tscommons-esm-core 0.0.2

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.
Files changed (121) hide show
  1. package/dist/classes/commons-cache.d.mts +25 -0
  2. package/dist/classes/commons-cache.mjs +115 -0
  3. package/dist/classes/commons-cache.mjs.map +1 -0
  4. package/dist/classes/commons-cursor.d.mts +29 -0
  5. package/dist/classes/commons-cursor.mjs +108 -0
  6. package/dist/classes/commons-cursor.mjs.map +1 -0
  7. package/dist/classes/commons-fixed-date-range.d.mts +70 -0
  8. package/dist/classes/commons-fixed-date-range.mjs +232 -0
  9. package/dist/classes/commons-fixed-date-range.mjs.map +1 -0
  10. package/dist/classes/commons-fixed-date.d.mts +119 -0
  11. package/dist/classes/commons-fixed-date.mjs +588 -0
  12. package/dist/classes/commons-fixed-date.mjs.map +1 -0
  13. package/dist/classes/commons-fixed-duration.d.mts +96 -0
  14. package/dist/classes/commons-fixed-duration.mjs +478 -0
  15. package/dist/classes/commons-fixed-duration.mjs.map +1 -0
  16. package/dist/classes/commons-join-table.d.mts +29 -0
  17. package/dist/classes/commons-join-table.mjs +71 -0
  18. package/dist/classes/commons-join-table.mjs.map +1 -0
  19. package/dist/classes/commons-tally.d.mts +32 -0
  20. package/dist/classes/commons-tally.mjs +122 -0
  21. package/dist/classes/commons-tally.mjs.map +1 -0
  22. package/dist/classes/commons-timestamp-join-table.d.mts +11 -0
  23. package/dist/classes/commons-timestamp-join-table.mjs +25 -0
  24. package/dist/classes/commons-timestamp-join-table.mjs.map +1 -0
  25. package/dist/classes/commons-window-carousell.d.mts +15 -0
  26. package/dist/classes/commons-window-carousell.mjs +114 -0
  27. package/dist/classes/commons-window-carousell.mjs.map +1 -0
  28. package/dist/consts/commons-chars.d.mts +4 -0
  29. package/dist/consts/commons-chars.mjs +6 -0
  30. package/dist/consts/commons-chars.mjs.map +1 -0
  31. package/dist/consts/commons-const.d.mts +3 -0
  32. package/dist/consts/commons-const.mjs +5 -0
  33. package/dist/consts/commons-const.mjs.map +1 -0
  34. package/dist/consts/commons-regex.d.mts +41 -0
  35. package/dist/consts/commons-regex.mjs +44 -0
  36. package/dist/consts/commons-regex.mjs.map +1 -0
  37. package/dist/consts/commons-stopwords.d.mts +2 -0
  38. package/dist/consts/commons-stopwords.mjs +111 -0
  39. package/dist/consts/commons-stopwords.mjs.map +1 -0
  40. package/dist/enums/emap-rank-direction.d.mts +4 -0
  41. package/dist/enums/emap-rank-direction.mjs +6 -0
  42. package/dist/enums/emap-rank-direction.mjs.map +1 -0
  43. package/dist/helpers/commons-array.d.mts +22 -0
  44. package/dist/helpers/commons-array.mjs +363 -0
  45. package/dist/helpers/commons-array.mjs.map +1 -0
  46. package/dist/helpers/commons-base.d.mts +83 -0
  47. package/dist/helpers/commons-base.mjs +363 -0
  48. package/dist/helpers/commons-base.mjs.map +1 -0
  49. package/dist/helpers/commons-date.d.mts +78 -0
  50. package/dist/helpers/commons-date.mjs +775 -0
  51. package/dist/helpers/commons-date.mjs.map +1 -0
  52. package/dist/helpers/commons-encoding.d.mts +6 -0
  53. package/dist/helpers/commons-encoding.mjs +25 -0
  54. package/dist/helpers/commons-encoding.mjs.map +1 -0
  55. package/dist/helpers/commons-fixed-date.d.mts +10 -0
  56. package/dist/helpers/commons-fixed-date.mjs +67 -0
  57. package/dist/helpers/commons-fixed-date.mjs.map +1 -0
  58. package/dist/helpers/commons-fixed-duration.d.mts +3 -0
  59. package/dist/helpers/commons-fixed-duration.mjs +14 -0
  60. package/dist/helpers/commons-fixed-duration.mjs.map +1 -0
  61. package/dist/helpers/commons-map.d.mts +10 -0
  62. package/dist/helpers/commons-map.mjs +38 -0
  63. package/dist/helpers/commons-map.mjs.map +1 -0
  64. package/dist/helpers/commons-matrix.d.mts +5 -0
  65. package/dist/helpers/commons-matrix.mjs +46 -0
  66. package/dist/helpers/commons-matrix.mjs.map +1 -0
  67. package/dist/helpers/commons-number.d.mts +27 -0
  68. package/dist/helpers/commons-number.mjs +425 -0
  69. package/dist/helpers/commons-number.mjs.map +1 -0
  70. package/dist/helpers/commons-object.d.mts +4 -0
  71. package/dist/helpers/commons-object.mjs +44 -0
  72. package/dist/helpers/commons-object.mjs.map +1 -0
  73. package/dist/helpers/commons-string.d.mts +55 -0
  74. package/dist/helpers/commons-string.mjs +680 -0
  75. package/dist/helpers/commons-string.mjs.map +1 -0
  76. package/dist/helpers/commons-tree.d.mts +13 -0
  77. package/dist/helpers/commons-tree.mjs +81 -0
  78. package/dist/helpers/commons-tree.mjs.map +1 -0
  79. package/dist/helpers/commons-type.d.mts +308 -0
  80. package/dist/helpers/commons-type.mjs +1632 -0
  81. package/dist/helpers/commons-type.mjs.map +1 -0
  82. package/dist/index.d.mts +40 -0
  83. package/dist/index.mjs +33 -0
  84. package/dist/index.mjs.map +1 -0
  85. package/dist/types/tarray-with-errors.d.mts +4 -0
  86. package/dist/types/tarray-with-errors.mjs +2 -0
  87. package/dist/types/tarray-with-errors.mjs.map +1 -0
  88. package/dist/types/tdate-range.d.mts +5 -0
  89. package/dist/types/tdate-range.mjs +9 -0
  90. package/dist/types/tdate-range.mjs.map +1 -0
  91. package/dist/types/tdefined.d.mts +4 -0
  92. package/dist/types/tdefined.mjs +2 -0
  93. package/dist/types/tdefined.mjs.map +1 -0
  94. package/dist/types/tempty-object.d.mts +3 -0
  95. package/dist/types/tempty-object.mjs +2 -0
  96. package/dist/types/tempty-object.mjs.map +1 -0
  97. package/dist/types/tencoded.d.mts +6 -0
  98. package/dist/types/tencoded.mjs +2 -0
  99. package/dist/types/tencoded.mjs.map +1 -0
  100. package/dist/types/tenum-object.d.mts +3 -0
  101. package/dist/types/tenum-object.mjs +2 -0
  102. package/dist/types/tenum-object.mjs.map +1 -0
  103. package/dist/types/tinterquartile-model.d.mts +16 -0
  104. package/dist/types/tinterquartile-model.mjs +29 -0
  105. package/dist/types/tinterquartile-model.mjs.map +1 -0
  106. package/dist/types/tmap-rank.d.mts +4 -0
  107. package/dist/types/tmap-rank.mjs +2 -0
  108. package/dist/types/tmap-rank.mjs.map +1 -0
  109. package/dist/types/tmodules.d.mts +3 -0
  110. package/dist/types/tmodules.mjs +2 -0
  111. package/dist/types/tmodules.mjs.map +1 -0
  112. package/dist/types/tprimative.d.mts +4 -0
  113. package/dist/types/tprimative.mjs +2 -0
  114. package/dist/types/tprimative.mjs.map +1 -0
  115. package/dist/types/tproperty-object.d.mts +3 -0
  116. package/dist/types/tproperty-object.mjs +2 -0
  117. package/dist/types/tproperty-object.mjs.map +1 -0
  118. package/dist/types/tt-or-tarray.d.mts +2 -0
  119. package/dist/types/tt-or-tarray.mjs +9 -0
  120. package/dist/types/tt-or-tarray.mjs.map +1 -0
  121. package/package.json +27 -0
@@ -0,0 +1,680 @@
1
+ import { COMMONS_ALPHABET_CHARACTERS, COMMONS_CONSONANT_CHARACTERS, COMMONS_DEFAULT_PUNCTUATION_CHARACTERS, COMMONS_VOWEL_CHARACTERS } from '../consts/commons-chars.mjs';
2
+ import { commonsTypeIsString } from './commons-type.mjs';
3
+ // Casing methods
4
+ export function commonsStringUcWords(value) {
5
+ // easier to do this via a loop rather than a regex
6
+ let lastWord = false;
7
+ return value
8
+ .toString()
9
+ .split('')
10
+ .map((c) => {
11
+ const isWord = /^[A-Z]$/i.test(c);
12
+ try {
13
+ if (!isWord || lastWord)
14
+ return c;
15
+ return c.toUpperCase();
16
+ }
17
+ finally {
18
+ lastWord = isWord;
19
+ }
20
+ })
21
+ .join('');
22
+ }
23
+ export function commonsStringCamelCase(value, ucFirst = true) {
24
+ return value
25
+ .toString()
26
+ .replace(/([A-Z])/g, ' $1')
27
+ .replace(/[^a-z0-9]/ig, ' ')
28
+ .replace(/[ ]{2,}/, ' ')
29
+ .trim()
30
+ .split(' ')
31
+ .map((s) => s.trim())
32
+ .filter((s) => s !== '')
33
+ .map((s, index) => {
34
+ if (index === 0 && !ucFirst)
35
+ return s.toLowerCase();
36
+ if (s.length < 2)
37
+ return s.toUpperCase();
38
+ return s.substring(0, 1).toUpperCase() + s.substring(1);
39
+ })
40
+ .join('');
41
+ }
42
+ function delimeterCase(value, delimeter) {
43
+ return value
44
+ .toString()
45
+ .replace(/([A-Z])/g, ' $1')
46
+ .replace(/[^a-z0-9]/ig, ' ')
47
+ .replace(/[ ]{2,}/, ' ')
48
+ .trim()
49
+ .split(' ')
50
+ .map((s) => s.trim().toLowerCase())
51
+ .filter((s) => s !== '')
52
+ .join(delimeter);
53
+ }
54
+ export function commonsStringSnakeCase(value) {
55
+ return delimeterCase(value, '_');
56
+ }
57
+ export function commonsStringKebabCase(value) {
58
+ return delimeterCase(value, '-');
59
+ }
60
+ export function commonsStringDashedCase(value) {
61
+ return commonsStringKebabCase(value);
62
+ }
63
+ export function commonsStringRegexEscapeString(term) {
64
+ return term
65
+ .replace(/[.]/g, '\\.')
66
+ .replace(/[?]/g, '[?]')
67
+ .replace(/[*]/g, '[*]')
68
+ .replace(/[+]/g, '[+]')
69
+ .replace(/[(]/g, '\\(')
70
+ .replace(/[)]/g, '\\)')
71
+ .replace(/\[/g, '\\[)')
72
+ .replace(/\]/g, '\\]')
73
+ .replace(/[{]/g, '[{]')
74
+ .replace(/[}]/g, '[}]');
75
+ }
76
+ // Simple character, word and sentence methods
77
+ export function commonsStringIsAlphabet(c) {
78
+ return c.length === 1
79
+ && COMMONS_ALPHABET_CHARACTERS.includes(c.toLowerCase());
80
+ }
81
+ export function commonsStringIsVowel(c) {
82
+ return commonsStringIsAlphabet(c)
83
+ && COMMONS_VOWEL_CHARACTERS.includes(c.toLowerCase());
84
+ }
85
+ export function commonsStringIsConsonant(c) {
86
+ return commonsStringIsAlphabet(c)
87
+ && COMMONS_CONSONANT_CHARACTERS.includes(c.toLowerCase());
88
+ }
89
+ export function commonsStringRegexLike(term) {
90
+ return `^${commonsStringRegexEscapeString(term)}$`
91
+ .replace(/%/g, '(?:.|\\s)*');
92
+ }
93
+ export function commonsStringRtrim(value, characters = ' \r\n\0') {
94
+ const chars = characters.split('');
95
+ if (chars.length === 0)
96
+ return value;
97
+ while (value.length > 0 && chars.includes(value.substr(value.length - 1, 1))) {
98
+ value = value.substr(0, value.length - 1);
99
+ }
100
+ return value;
101
+ }
102
+ export function commonsStringLtrim(value, characters = ' \r\n\0') {
103
+ const chars = characters.split('');
104
+ if (chars.length === 0)
105
+ return value;
106
+ while (value.length > 0 && chars.includes(value.substr(0, 1))) {
107
+ value = value.substr(1);
108
+ }
109
+ return value;
110
+ }
111
+ export function commonsStringTrim(value, characters = ' \r\n\0') {
112
+ return commonsStringLtrim(commonsStringRtrim(value, characters), characters);
113
+ }
114
+ export function commonsStringSplitString(value, splitter = /[\r\n]/g, trim = true, excludeEmpty = true) {
115
+ return value
116
+ .split(splitter)
117
+ .map((s) => trim ? s.trim() : s)
118
+ .filter((s) => !excludeEmpty || s !== '');
119
+ }
120
+ // Complex word and sentence methods
121
+ export function commonsStringLimitLength(value, length = 128, soft = false) {
122
+ if (value.length <= length)
123
+ return value;
124
+ let hard = value.substr(0, length - 3); // -2 = make room for ...
125
+ if (!soft)
126
+ return `${hard}...`;
127
+ const fallback = hard;
128
+ while (hard.length > 1) {
129
+ if (/[^a-zA-Z0-9]/.test(hard.slice(-1)))
130
+ return `${hard.substr(0, hard.length - 1)}...`;
131
+ hard = hard.substr(0, hard.length - 1);
132
+ }
133
+ return `${fallback}...`;
134
+ }
135
+ export function commonsStringIsCapitalised(value) {
136
+ return /^[A-Z]+$/.test(value.replace(/[^a-z]/i, ''));
137
+ }
138
+ function capitaliseString(value, capitalised) {
139
+ return capitalised ? value.toUpperCase() : value;
140
+ }
141
+ export function commonsStringPluralise(singular, quantity = 2, autoDetectEndings = true) {
142
+ if (singular.length === 0)
143
+ return '';
144
+ if (quantity === 1)
145
+ return singular;
146
+ if (quantity === 0)
147
+ return commonsStringPluralise(singular, 2, autoDetectEndings);
148
+ const capitalised = commonsStringIsCapitalised(singular);
149
+ const last = singular.charAt(singular.length - 1);
150
+ if (!/[a-z]/i.test(last)) {
151
+ // doesn't end with a-z
152
+ return `${singular}${capitaliseString('s', capitalised)}`;
153
+ }
154
+ if (autoDetectEndings) {
155
+ const same = `
156
+ accommodation advice alms aluminum ammends
157
+ baggage barracks binoculars bison bourgeois breadfruit
158
+ cannon caribou cattle chalk chassis chinos clippers clothes clothing cod concrete corps correspondence crossroads
159
+ deer dice doldrums dozen dungarees
160
+ education eggfruit elk eyeglasses
161
+ flour food fruit furniture
162
+ gallows glasses goldfish grapefruit greenfly grouse gymnastics
163
+ haddock halibut headquarters help homework
164
+ ides information insignia
165
+ jackfruit jeans
166
+ kennels knickers knowledge kudos
167
+ leggings lego luggage
168
+ means monkfish moose mullet music
169
+ nailclippers news
170
+ offspring oxygen
171
+ pants passionfruit pike pliers police premises public pyjamas
172
+ reindeer rendezvous
173
+ salmon scenery scissors series shambles sheep shellfish shorts shrimp smithereens species squid staff starfruit sugar swine
174
+ tongs trousers trout tuna tweezers
175
+ wheat whitebait wood
176
+ you
177
+ `
178
+ .replace(/\s+/, ' ')
179
+ .split(' ')
180
+ .map((word) => commonsStringTrim(word))
181
+ .filter((word) => word !== '');
182
+ if (same.includes(singular.toLowerCase()))
183
+ return singular;
184
+ switch (singular.toLowerCase()) {
185
+ case 'cafe': return capitaliseString('cafes', capitalised);
186
+ case 'child': return capitaliseString('children', capitalised);
187
+ case 'woman': return capitaliseString('women', capitalised);
188
+ case 'man': return capitaliseString('men', capitalised);
189
+ case 'mouse': return capitaliseString('mice', capitalised);
190
+ case 'goose': return capitaliseString('geese', capitalised);
191
+ case 'potato': return capitaliseString('potatoes', capitalised);
192
+ case 'tomato': return capitaliseString('tomatoes', capitalised);
193
+ case 'fungus': return capitaliseString('fungae', capitalised);
194
+ case 'day':
195
+ case 'monday':
196
+ case 'tuesday':
197
+ case 'wednesday':
198
+ case 'thursday':
199
+ case 'friday':
200
+ case 'saturday':
201
+ case 'sunday':
202
+ return capitaliseString(`${singular.toLowerCase()}s`, capitalised);
203
+ }
204
+ if (/(craft|ies)$/.test(singular.toLowerCase()))
205
+ return singular;
206
+ if (/(ch|x|s|sh)$/i.test(singular))
207
+ return `${singular}${capitaliseString('es', capitalised)}`;
208
+ const regex1 = /^(.+)(f|fe)$/i.exec(singular);
209
+ if (regex1 !== null)
210
+ return `${regex1[1]}${capitaliseString('ves', capitalised)}`;
211
+ const regex2 = /^(.+[abcdfghjklmnpqrstvwxyz])y$/i.exec(singular);
212
+ if (regex2 !== null)
213
+ return `${regex2[1]}${capitaliseString('ies', capitalised)}`;
214
+ }
215
+ return `${singular}${capitaliseString('s', capitalised)}`;
216
+ }
217
+ export function commonsStringSingularise(plural) {
218
+ const capitalised = commonsStringIsCapitalised(plural);
219
+ const last = plural.charAt(plural.length - 1);
220
+ if (!/[a-z]/i.test(last)) {
221
+ // doesn't end with a-z
222
+ return plural;
223
+ }
224
+ if (plural.toLowerCase().endsWith('us'))
225
+ return plural;
226
+ if (plural.toLowerCase().endsWith('ess'))
227
+ return plural;
228
+ if (plural.toLowerCase().endsWith('is'))
229
+ return plural;
230
+ const same = `
231
+ accommodation advice alms aluminum ammends
232
+ baggage barracks binoculars bison bourgeois breadfruit
233
+ cannon caribou cattle chalk chassis chinos clippers clothes clothing cod concrete corps correspondence crossroads
234
+ deer dice doldrums dozen dungarees
235
+ education eggfruit elk eyeglasses
236
+ flour food fruit furniture
237
+ gallows glasses goldfish grapefruit greenfly grouse gymnastics
238
+ haddock halibut headquarters help homework
239
+ ides information insignia
240
+ jackfruit jeans
241
+ kennels knickers knowledge kudos
242
+ leggings lego luggage
243
+ means monkfish moose mullet music
244
+ nailclippers news
245
+ offspring oxygen
246
+ pants passionfruit pike pliers police premises public pyjamas
247
+ reindeer rendezvous
248
+ salmon scenery scissors series shambles sheep shellfish shorts shrimp smithereens species squid staff starfruit sugar swine
249
+ tongs trousers trout tuna tweezers
250
+ wheat whitebait wood
251
+ you
252
+ `
253
+ .replace(/\s+/, ' ')
254
+ .split(' ')
255
+ .map((word) => commonsStringTrim(word))
256
+ .filter((word) => word !== '');
257
+ if (same.includes(plural.toLowerCase()))
258
+ return plural;
259
+ switch (plural.toLowerCase()) {
260
+ case 'cafes': return capitaliseString('cafe', capitalised);
261
+ case 'children': return capitaliseString('child', capitalised);
262
+ case 'women': return capitaliseString('woman', capitalised);
263
+ case 'men': return capitaliseString('man', capitalised);
264
+ case 'mice': return capitaliseString('mouse', capitalised);
265
+ case 'geese': return capitaliseString('goose', capitalised);
266
+ case 'potatoes': return capitaliseString('potato', capitalised);
267
+ case 'tomatoes': return capitaliseString('tomato', capitalised);
268
+ case 'fungae': return capitaliseString('fungus', capitalised);
269
+ case 'days':
270
+ case 'mondays':
271
+ case 'tuesdays':
272
+ case 'wednesdays':
273
+ case 'thursdays':
274
+ case 'fridays':
275
+ case 'saturdays':
276
+ case 'sundays':
277
+ return capitaliseString(plural.substring(0, plural.length - 1).toLowerCase(), capitalised);
278
+ }
279
+ if (/(craft|ies)$/.test(plural.toLowerCase()))
280
+ return plural;
281
+ if (/(ch|x|s|sh)es$/i.test(plural))
282
+ return plural.substring(0, plural.length - 2);
283
+ const regex1 = /^(.+)ves$/i.exec(plural);
284
+ if (regex1 !== null)
285
+ return `${regex1[1]}${capitaliseString('f', capitalised)}`; // not ideal, as it conflates 'f' and 'fe' suffixes
286
+ const regex2 = /^(.+[abcdfghjklmnpqrstvwxyz])ies$/i.exec(plural);
287
+ if (regex2 !== null)
288
+ return `${regex2[1]}${capitaliseString('y', capitalised)}`;
289
+ if (!plural.toLowerCase().endsWith('s'))
290
+ return plural;
291
+ return plural.substring(0, plural.length - 1);
292
+ }
293
+ function noOrNumber(quantity, none = false, capitaliseNoNone = false) {
294
+ if (quantity === 0) {
295
+ const wording = none ? 'none' : 'no';
296
+ return capitaliseNoNone ? commonsStringUcWords(wording) : wording;
297
+ }
298
+ return quantity.toString();
299
+ }
300
+ export function commonsStringQuantify(singular, quantity, autoDetectEndings = true, capitaliseNoNone = false) {
301
+ if (singular.length === 0)
302
+ return noOrNumber(quantity, true, capitaliseNoNone);
303
+ const capitalised = commonsStringIsCapitalised(singular);
304
+ return capitaliseString(`${noOrNumber(quantity, false, capitaliseNoNone)} ${commonsStringPluralise(singular, quantity, autoDetectEndings)}`, capitalised);
305
+ }
306
+ function isVowelOrY(c) {
307
+ return commonsStringIsVowel(c) || c.toLowerCase() === 'y';
308
+ }
309
+ function isConsonantNotY(c) {
310
+ return commonsStringIsConsonant(c) && c.toLowerCase() !== 'y';
311
+ }
312
+ export function commonsStringSplitWords(sentence, allowHyphens = true, allowApostrophies = false) {
313
+ if (!allowHyphens)
314
+ sentence = sentence.replace('-', ' - ');
315
+ if (!allowApostrophies)
316
+ sentence = sentence.replace('\'', ' \' ');
317
+ return sentence
318
+ .split(/[^-'A-Za-z]/)
319
+ .map((word) => commonsStringTrim(word))
320
+ .filter((word) => word !== '');
321
+ }
322
+ export function commonsStringInternalRoughSyllables(word) {
323
+ // assumes that syllables consist of vowels in the center of each syllable
324
+ const chars = commonsStringTrim(word.toLowerCase()).split('');
325
+ const stack = [];
326
+ let allowConsume = false;
327
+ let build = '';
328
+ let reset = true;
329
+ while (true) {
330
+ const c = chars.shift();
331
+ if (c === undefined)
332
+ break;
333
+ if (!commonsStringIsAlphabet(c)) { // non-character
334
+ if (build.length > 0)
335
+ stack.push(build);
336
+ build = '';
337
+ reset = true;
338
+ allowConsume = false; // don't consume future single consonant
339
+ continue;
340
+ }
341
+ const isVowel = isVowelOrY(c);
342
+ if (allowConsume && isVowel) { // double vowel; concatinate with last
343
+ stack.push(`${stack.pop()}${c}`);
344
+ allowConsume = true; // consume future single consonant
345
+ continue;
346
+ }
347
+ if (allowConsume && !isVowel) {
348
+ // append to last stacked word
349
+ stack.push(`${stack.pop()}${c}`);
350
+ allowConsume = false; // don't consume future single consonant
351
+ continue;
352
+ }
353
+ if (isVowel) {
354
+ if (chars.length === 0 && stack.length > 0 && !reset) {
355
+ // absorb terminal vowels
356
+ stack.push(`${stack.pop()}${c}`);
357
+ break;
358
+ }
359
+ stack.push(`${build}${c}`);
360
+ build = '';
361
+ allowConsume = true;
362
+ continue;
363
+ }
364
+ build += c;
365
+ }
366
+ if (build !== '') {
367
+ if (build.length > 1) {
368
+ stack.push(build);
369
+ }
370
+ else {
371
+ stack.push(`${stack.pop()}${build}`);
372
+ }
373
+ }
374
+ // attempt to make syllables start with consonants where possible
375
+ for (let i = 1; i < stack.length; i++) {
376
+ if (stack[i - 1].length < 2)
377
+ continue;
378
+ if (isVowelOrY(stack[i].charAt(0)) && isConsonantNotY(stack[i - 1].slice(-1))) {
379
+ stack[i] = `${stack[i - 1].slice(-1)}${stack[i]}`;
380
+ stack[i - 1] = stack[i - 1].slice(0, stack[i - 1].length - 1);
381
+ }
382
+ }
383
+ return stack;
384
+ }
385
+ export function commonsStringRoughSyllables(wordOrWords) {
386
+ // assumes that syllables consist of vowels in the center of each syllable
387
+ // it gets complicated trying to cater for multiple words, so we just split and process for each
388
+ const total = [];
389
+ for (const word of commonsStringSplitWords(wordOrWords)) {
390
+ const syllables = commonsStringInternalRoughSyllables(word);
391
+ for (const syllable of syllables)
392
+ total.push(syllable);
393
+ }
394
+ return total;
395
+ }
396
+ export function commonsStringSplitSentences(paragraph, breakChars = /[.!?]/, allowDecimals = true, breakOnMultipleHyphens = true) {
397
+ if (breakOnMultipleHyphens) {
398
+ // multiple hyphens count as breaks; single count as hyphenated words
399
+ paragraph = paragraph.replace(/-{2,}/g, '. ');
400
+ }
401
+ if (!breakChars.test('\r')) {
402
+ paragraph = paragraph.replace(/\r/, ' ');
403
+ }
404
+ if (!breakChars.test('\n')) {
405
+ paragraph = paragraph.replace(/\n/, ' ');
406
+ }
407
+ // We don't use split, as we want to preserve the break characters
408
+ const chars = commonsStringTrim(paragraph).split('');
409
+ const sentences = [];
410
+ let build = '';
411
+ while (true) {
412
+ const c = chars.shift();
413
+ if (c === undefined)
414
+ break;
415
+ if (breakChars.test(c)) {
416
+ if (build === '' && sentences.length > 0) {
417
+ // concatenate multiple break characters onto the end of the last sentence
418
+ sentences.push(`${sentences.pop()}${c}`);
419
+ continue;
420
+ }
421
+ if (commonsStringTrim(build) === '') {
422
+ // nothing to push
423
+ build = '';
424
+ continue;
425
+ }
426
+ if (!allowDecimals
427
+ || !/[-0-9]/.test(build.slice(-1))
428
+ || chars.length === 0
429
+ || !/[0-9]/.test(chars[0])) {
430
+ sentences.push(`${commonsStringLtrim(build)}${c}`);
431
+ build = '';
432
+ continue;
433
+ }
434
+ }
435
+ build += c;
436
+ }
437
+ if (commonsStringTrim(build) !== '')
438
+ sentences.push(commonsStringTrim(build));
439
+ return sentences;
440
+ }
441
+ export function commonsStringFleschKincaidReadingEase(paragraph) {
442
+ const words = commonsStringSplitWords(paragraph);
443
+ const sentences = commonsStringSplitSentences(paragraph);
444
+ const syllables = commonsStringRoughSyllables(paragraph);
445
+ return 206.835 - (1.015 * (words.length / sentences.length)) - (84.6 * (syllables.length / words.length));
446
+ }
447
+ export function commonsStringAutomatedReadabilityIndex(paragraph) {
448
+ const words = commonsStringSplitWords(paragraph);
449
+ const sentences = commonsStringSplitSentences(paragraph);
450
+ const characters = [];
451
+ for (const word of words) {
452
+ for (const c of word.split('')) {
453
+ if (commonsStringIsAlphabet(c))
454
+ characters.push(c);
455
+ }
456
+ }
457
+ return (4.71 * (characters.length / words.length)) + (0.5 * (words.length / sentences.length)) - 21.43;
458
+ }
459
+ export function commonsStringSanitiseExtendedUnicodeChars(src, options = {}) {
460
+ options = {
461
+ trim: true,
462
+ dashes: true,
463
+ quotes: true,
464
+ backTick: true,
465
+ spaces: true,
466
+ ellipsis: true,
467
+ blank: true,
468
+ bullets: true,
469
+ ...options
470
+ };
471
+ if (options.trim)
472
+ src = src.trim();
473
+ if (options.dashes)
474
+ src = src.replace(/[-\u058a\u05be\u1400\u1806\u2010-\u2015\u2053\u207b\u208b\u2212\u2e17\u2e1a\u2e3a\u2e3b\u2e40\u2e5d\u301c\u3030\u30a0\ufe31\ufe32\ufe58\ufe63\uff0d]|\uD803\udead/g, '-');
475
+ if (options.quotes)
476
+ src = src.replace(/[\u2018\u2019\u201a\u201b]/g, '\'').replace(/[\u201c-\u201f]/g, '"');
477
+ if (options.backTick)
478
+ src = src.replace(/`/g, '\'');
479
+ if (options.spaces)
480
+ src = src.replace(/[\u00a0\u2000-\u200c\u202f\ufeff]/g, ' ');
481
+ if (options.ellipsis)
482
+ src = src.replace(/\u2026/, '...');
483
+ if (options.blank)
484
+ src = src.replace(/[\u200d\u2060]/g, '');
485
+ if (options.bullets)
486
+ src = src.replace(/[\u2022]/g, '*');
487
+ return src;
488
+ }
489
+ export function commonsStringBuildPunctuationRegexString(chars) {
490
+ const charsArray = commonsTypeIsString(chars) ? chars.split('') : [...chars];
491
+ const hyphenIndex = charsArray.indexOf('-');
492
+ if (hyphenIndex > -1) {
493
+ charsArray.splice(hyphenIndex, 1);
494
+ charsArray.unshift('-');
495
+ }
496
+ for (let i = charsArray.length; i-- > 0;) {
497
+ if (charsArray[i] === ']')
498
+ charsArray[i] = '\\]';
499
+ if (charsArray[i] === '\\')
500
+ charsArray[i] = '\\\\';
501
+ }
502
+ return `[${charsArray.join('')}]`;
503
+ }
504
+ export var ECommonsTokeniseHyphenSplit;
505
+ (function (ECommonsTokeniseHyphenSplit) {
506
+ ECommonsTokeniseHyphenSplit["ALL"] = "all";
507
+ ECommonsTokeniseHyphenSplit["NONE"] = "none";
508
+ ECommonsTokeniseHyphenSplit["MULTIPLE"] = "multiple"; // split on multiple, e.g. She said--because she was minded to--that they would go there later.
509
+ })(ECommonsTokeniseHyphenSplit || (ECommonsTokeniseHyphenSplit = {}));
510
+ export function commonsStringTokenise(text, puncChars = COMMONS_DEFAULT_PUNCTUATION_CHARACTERS, options = {}) {
511
+ options = {
512
+ hyphenSplit: ECommonsTokeniseHyphenSplit.ALL,
513
+ keepNonSpacedPunctuation: false,
514
+ returnPunctuationAsWords: true,
515
+ ...options
516
+ };
517
+ options.sanitiseExtendedUnicodeChars = {
518
+ dashes: false,
519
+ quotes: false,
520
+ backTick: false,
521
+ ellipsis: false,
522
+ blank: false,
523
+ ...options.sanitiseExtendedUnicodeChars
524
+ };
525
+ const PUNC_CHARS_ARRAY = commonsTypeIsString(puncChars) ? puncChars.split('') : [...puncChars];
526
+ switch (options.hyphenSplit) {
527
+ case ECommonsTokeniseHyphenSplit.ALL:
528
+ // add hyphens to the punctuation characters
529
+ PUNC_CHARS_ARRAY.push('-');
530
+ break;
531
+ case ECommonsTokeniseHyphenSplit.MULTIPLE:
532
+ // consider hyphens a non-punctuation character
533
+ // but pre-expand any multiples in the text
534
+ text = text.replace(/-{2,}/g, ' - ');
535
+ break;
536
+ default:
537
+ // consider hyphens a non-punctuation character
538
+ break;
539
+ }
540
+ const regexChars = commonsStringBuildPunctuationRegexString(puncChars);
541
+ const ANY_PUNC = new RegExp(`(${regexChars})`, 'g');
542
+ const START_PUNC = new RegExp(`(^|\\s)(${regexChars})`, 'g');
543
+ const END_PUNC = new RegExp(`(${regexChars})($|\\s)`, 'g');
544
+ text = commonsStringSanitiseExtendedUnicodeChars(text.replace(/\s/g, ' '), {
545
+ ...options.sanitiseExtendedUnicodeChars,
546
+ trim: true,
547
+ spaces: true
548
+ });
549
+ if (options.keepNonSpacedPunctuation) {
550
+ text = text
551
+ .replace(START_PUNC, ' $2 ') // space before punc
552
+ .replace(END_PUNC, ' $1 '); // space after punc
553
+ // have to correct for words that have multi-punctionation
554
+ const rebuild = [];
555
+ for (let word of text.split(' ')) {
556
+ const tail = [];
557
+ while (true) {
558
+ if (word === '')
559
+ break;
560
+ if (PUNC_CHARS_ARRAY.includes(word[0])) {
561
+ rebuild.push(word[0]);
562
+ word = word.substring(1);
563
+ continue;
564
+ }
565
+ if (PUNC_CHARS_ARRAY.includes(word[word.length - 1])) {
566
+ tail.unshift(word[word.length - 1]);
567
+ word = word.substring(0, word.length - 1);
568
+ continue;
569
+ }
570
+ break;
571
+ }
572
+ rebuild.push(word);
573
+ rebuild.push(...tail);
574
+ }
575
+ text = rebuild.join(' ');
576
+ }
577
+ else {
578
+ text = text
579
+ .replace(ANY_PUNC, ' $1 ');
580
+ }
581
+ return text
582
+ .split(' ')
583
+ .map((s) => s.trim())
584
+ .filter((s) => {
585
+ if (s === '')
586
+ return false;
587
+ if (PUNC_CHARS_ARRAY.includes(s))
588
+ return options.returnPunctuationAsWords || false;
589
+ return true;
590
+ });
591
+ }
592
+ export function commonsStringTokensToSentences(tokens, terminalPuncChars = '.?!', allowDotAfterAbbreviatedWords = []) {
593
+ const TERMINAL_CHARS_ARRAY = commonsTypeIsString(terminalPuncChars) ? terminalPuncChars.split('') : [...terminalPuncChars];
594
+ const sentences = [];
595
+ let current = [];
596
+ let lastWord;
597
+ while (true) {
598
+ const next = tokens.shift();
599
+ if (!next)
600
+ break;
601
+ if (TERMINAL_CHARS_ARRAY.includes(next)) {
602
+ if (next === '.' && lastWord && allowDotAfterAbbreviatedWords.includes(lastWord)) {
603
+ // ignore words like Mr. Smith
604
+ continue;
605
+ }
606
+ sentences.push([...current, next]);
607
+ current = [];
608
+ lastWord = undefined;
609
+ continue;
610
+ }
611
+ current.push(next);
612
+ lastWord = next;
613
+ }
614
+ if (current.length > 0)
615
+ sentences.push(current);
616
+ return sentences;
617
+ }
618
+ export function commonsStringNormaliseAccents(s) {
619
+ return s.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
620
+ }
621
+ export function commonsStringGobblePrefix(s, gobbleUntil, includeUntil = false) {
622
+ if (gobbleUntil instanceof RegExp) {
623
+ const clone = new RegExp(gobbleUntil);
624
+ let i = s.search(clone);
625
+ if (i === -1)
626
+ return s;
627
+ if (!includeUntil) {
628
+ const match = clone.exec(s.substring(i));
629
+ if (!match)
630
+ throw new Error('Regex search found a match, but subsequent exec did not match. This may be a regex specific error');
631
+ const matched = match[0];
632
+ i += matched.length;
633
+ }
634
+ return s.substring(i);
635
+ }
636
+ else {
637
+ let i = s.indexOf(gobbleUntil);
638
+ if (i === -1)
639
+ return s;
640
+ if (!includeUntil)
641
+ i += gobbleUntil.length;
642
+ return s.substring(i);
643
+ }
644
+ }
645
+ export function commonsStringGobbleSuffix(s, gobbleFrom, includeFrom = false) {
646
+ if (gobbleFrom instanceof RegExp) {
647
+ const clone = new RegExp(gobbleFrom);
648
+ // this is a nasty inefficient way of doing it, but struggling to come up with a better way
649
+ if (!clone.test(s))
650
+ return s;
651
+ let i = s.length;
652
+ while (true) {
653
+ if (clone.test(s.substring(i)))
654
+ break;
655
+ i--;
656
+ if (i < 0)
657
+ return s;
658
+ }
659
+ const match = clone.exec(s);
660
+ if (!match)
661
+ throw new Error('Test for suffix returned a gt 0 result but then that wasn\'t found in the regex exec. Possibly the regex is malformed?');
662
+ if (includeFrom)
663
+ i += match[0].length;
664
+ return s.substring(0, i);
665
+ }
666
+ else {
667
+ let i = s.lastIndexOf(gobbleFrom);
668
+ if (i === -1)
669
+ return s;
670
+ if (includeFrom)
671
+ i += gobbleFrom.length;
672
+ return s.substring(0, i);
673
+ }
674
+ }
675
+ export function commonsStringGobblePrefixAndSuffix(s, gobbleUntil, gobbleFrom, includeUntilAndFrom = false) {
676
+ s = commonsStringGobblePrefix(s, gobbleUntil, includeUntilAndFrom);
677
+ s = commonsStringGobbleSuffix(s, gobbleFrom, includeUntilAndFrom);
678
+ return s;
679
+ }
680
+ //# sourceMappingURL=commons-string.mjs.map