@massimo-cassandro/minimo 1.40.2 → 1.41.0

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.
package/index.js CHANGED
@@ -1,5 +1,7 @@
1
+
1
2
  // utilities
2
3
  export { betterText } from './src/utilities/better-text.js';
4
+ export { betterTextWithPlaces } from './src/utilities/better-text-with-places.js';
3
5
  export { classnames, classnamesNull } from './src/utilities/classnames.js';
4
6
  export { createId } from './src/utilities/create-id.js';
5
7
  export { disableBtnsOnSubmit } from './src/utilities/disable-btns-on-submit.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "1.40.2",
3
+ "version": "1.41.0",
4
4
  "description": "Light css framework & utilities",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -0,0 +1,449 @@
1
+ // @ts-check
2
+ /*! minimo - Better Text with places */
3
+
4
+ import { betterText, NBSP_AFTER_PARTICLE_REGEX } from './better-text.js';
5
+
6
+ const places = [
7
+ // EUROPA
8
+ 'Europa',
9
+
10
+ // Italia
11
+ 'Italia',
12
+ // città
13
+ 'Roma', 'Milano', 'Napoli', 'Torino', 'Palermo', 'Bologna', 'Firenze', 'Venezia',
14
+ // fiumi
15
+ 'Po', 'Adige', 'Tevere', 'Arno',
16
+ // monti
17
+ 'Monte Bianco', 'Monte Rosa', 'Cervino', 'Etna', 'Vesuvio', 'Gran Sasso',
18
+ // località
19
+ 'Costiera Amalfitana', 'Cinque Terre', 'Pompei', 'Dolomiti', 'Val d’Orcia', 'Capri', 'Lago di Como',
20
+
21
+ // Francia
22
+ 'Francia',
23
+ // città
24
+ 'Parigi', 'Marsiglia', 'Lione', 'Tolosa', 'Nizza', 'Nantes', 'Strasburgo',
25
+ // fiumi
26
+ 'Senna', 'Loira', 'Rodano', 'Garonna',
27
+ // monti
28
+ 'Barre des Écrins', 'Pic du Midi de Bigorre',
29
+ // località
30
+ 'Mont Saint-Michel', 'Costa Azzurra', 'Valle della Loira', 'Chamonix', 'Versailles', 'Camargue',
31
+
32
+ // Germania
33
+ 'Germania',
34
+ // città
35
+ 'Berlino', 'Monaco di Baviera', 'Francoforte sul Meno', 'Amburgo', 'Colonia', 'Stoccarda',
36
+ // fiumi
37
+ 'Reno', 'Danubio', 'Elba', 'Meno', 'Weser',
38
+ // monti
39
+ 'Zugspitze', 'Watzmann', 'Feldberg',
40
+ // località
41
+ 'Castello di Neuschwanstein', 'Foresta Nera', 'Valle del Reno', 'Isola di Rügen', 'Rothenburg ob der Tauber',
42
+
43
+ // Spagna
44
+ 'Spagna',
45
+ // città
46
+ 'Madrid', 'Barcellona', 'Valencia', 'Siviglia', 'Saragozza', 'Malaga',
47
+ // fiumi
48
+ 'Tago', 'Ebro', 'Duero', 'Guadalquivir', 'Guadiana',
49
+ // monti
50
+ 'Mulhacén', 'Pico Aneto', 'Teide',
51
+ // località
52
+ 'Alhambra di Granada', 'Sagrada Família', 'Caminito del Rey', 'Ibiza', 'Ronda', 'Costa del Sol',
53
+
54
+ // Regno Unito
55
+ 'Regno Unito',
56
+ // città
57
+ 'Londra', 'Birmingham', 'Manchester', 'Glasgow', 'Edimburgo', 'Liverpool',
58
+ // fiumi
59
+ 'Tamigi', 'Severn', 'Trent', 'Clyde',
60
+ // monti
61
+ 'Ben Nevis', 'Scafell Pike', 'Snowdon',
62
+ // località
63
+ 'Stonehenge', 'Loch Ness', 'Giant\'s Causeway', 'Cotswolds', 'Highlands scozzesi', 'Windsor',
64
+
65
+ // Grecia
66
+ 'Grecia',
67
+ // città
68
+ 'Atene', 'Salonicco', 'Patrasso', 'Candia', 'Larissa',
69
+ // fiumi
70
+ 'Aliakmon', 'Achelous', 'Peneus',
71
+ // monti
72
+ 'Monte Olimpo', 'Monte Parnasso', 'Monte Athos',
73
+ // località
74
+ 'Meteora', 'Santorini', 'Mykonos', 'Delfi', 'Olimpia', 'Cnosso',
75
+
76
+ // Svizzera
77
+ 'Svizzera',
78
+ // città
79
+ 'Zurigo', 'Ginevra', 'Berna', 'Basilea', 'Losanna', 'Lucerna',
80
+ // fiumi
81
+ 'Aare', 'Ticino',
82
+ // monti
83
+ 'Dufourspitze', 'Eiger', 'Jungfrau',
84
+ // località
85
+ 'Zermatt', 'St. Moritz', 'Grindelwald', 'Cascate del Reno', 'Interlaken',
86
+
87
+
88
+ // AMERICA DEL NORD
89
+ 'America del Nord',
90
+
91
+ // Stati Uniti
92
+ 'Stati Uniti',
93
+ // città
94
+ 'New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix', 'Miami', 'San Francisco', 'Las Vegas',
95
+ // fiumi
96
+ 'Mississippi', 'Missouri', 'Colorado', 'Rio Grande', 'Hudson',
97
+ // monti
98
+ 'Denali', 'Monte Whitney', 'Monte Rainier', 'Monte Elbert',
99
+ // località
100
+ 'Grand Canyon', 'Parco di Yellowstone', 'Yosemite', 'Monument Valley', 'Cascate del Niagara', 'Key West',
101
+
102
+ // Canada
103
+ 'Canada',
104
+ // città
105
+ 'Toronto', 'Montreal', 'Vancouver', 'Calgary', 'Ottawa', 'Edmonton', 'Québec',
106
+ // fiumi
107
+ 'San Lorenzo', 'Mackenzie', 'Yukon', 'Fraser',
108
+ // monti
109
+ 'Monte Logan', 'Monte Robson', 'Monte Columbia',
110
+ // località
111
+ 'Parco Nazionale di Banff', 'Lago Louise', 'Whistler', 'Capilano Suspension Bridge',
112
+
113
+ // Messico
114
+ 'Messico',
115
+ // città
116
+ 'Città del Messico', 'Guadalajara', 'Monterrey', 'Puebla', 'Tijuana', 'Cancún',
117
+ // fiumi
118
+ 'Usumacinta', 'Grijalva',
119
+ // monti
120
+ 'Pico de Orizaba', 'Popocatépetl', 'Iztaccíhuatl',
121
+ // località
122
+ 'Chichén Itzá', 'Teotihuacan', 'Tulum', 'Cabo San Lucas', 'Oaxaca',
123
+
124
+
125
+ // AMERICA DEL SUD
126
+ 'America del Sud',
127
+
128
+ // Brasile
129
+ 'Brasile',
130
+ // città
131
+ 'San Paolo', 'Rio de Janeiro', 'Brasilia', 'Salvador', 'Fortaleza', 'Belo Horizonte',
132
+ // fiumi
133
+ 'Rio delle Amazzoni', 'Paraná', 'São Francisco', 'Tocantins',
134
+ // monti
135
+ 'Pico da Neblina', 'Pico 3 de Março', 'Pico da Bandeira',
136
+ // località
137
+ 'Cristo Redentore', 'Cascate dell\'Iguazú', 'Foresta Amazzonica', 'Lençóis Maranhenses', 'Fernando de Noronha',
138
+
139
+ // Argentina
140
+ 'Argentina',
141
+ // città
142
+ 'Buenos Aires', 'Córdoba', 'Rosario', 'Mendoza', 'La Plata', 'San Carlos de Bariloche',
143
+ // fiumi
144
+ 'Uruguay', 'Río de la Plata', 'Rio Negro',
145
+ // monti
146
+ 'Aconcagua', 'Fitz Roy', 'Monte Pissis',
147
+ // località
148
+ 'Ghiacciaio Perito Moreno', 'Patagonia', 'Ushuaia', 'Quebrada de Humahuaca',
149
+
150
+ // Perù
151
+ 'Perù',
152
+ // città
153
+ 'Lima', 'Arequipa', 'Trujillo', 'Chiclayo', 'Cusco', 'Iquitos',
154
+ // fiumi
155
+ 'Ucayali', 'Marañón',
156
+ // monti
157
+ 'Huascarán', 'Yerupajá', 'Ausangate',
158
+ // località
159
+ 'Machu Picchu', 'Valle Sacra degli Inca', 'Lago Titicaca', 'Linee di Nazca', 'Vinicunca',
160
+
161
+
162
+ // ASIA
163
+ 'Asia',
164
+
165
+ // Giappone
166
+ 'Giappone',
167
+ // città
168
+ 'Tokyo', 'Yokohama', 'Osaka', 'Nagoya', 'Sapporo', 'Kyoto', 'Fukuoka',
169
+ // fiumi
170
+ 'Shinano', 'Tone', 'Ishikari',
171
+ // monti
172
+ 'Monte Fuji', 'Monte Kita', 'Monte Hotaka',
173
+ // località
174
+ 'Fushimi Inari-taisha', 'Miyajima', 'Nara', 'Takayama', 'Shirakawa-go',
175
+
176
+ // Cina
177
+ 'Cina',
178
+ // città
179
+ 'Pechino', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Chengdu', 'Chongqing', 'Xi\'an',
180
+ // fiumi
181
+ 'Fiume Azzurro', 'Fiume Giallo', 'Fiume delle Perle',
182
+ // monti
183
+ 'Huangshan', 'Monte Tai', 'K2',
184
+ // località
185
+ 'Grande Muraglia Cinese', 'Città Proibita', 'Esercito di Terracotta', 'Guilin', 'Zhangjiajie',
186
+
187
+ // India
188
+ 'India',
189
+ // città
190
+ 'Mumbai', 'Nuova Delhi', 'Bangalore', 'Hyderabad', 'Ahmedabad', 'Calcutta', 'Jaipur',
191
+ // fiumi
192
+ 'Gange', 'Indo', 'Brahmaputra', 'Godavari',
193
+ // monti
194
+ 'Kangchenjunga', 'Nanda Devi', 'Kamet',
195
+ // località
196
+ 'Taj Mahal', 'Varanasi', 'Backwaters del Kerala', 'Khajuraho',
197
+
198
+ // Nepal
199
+ 'Nepal',
200
+ // città
201
+ 'Kathmandu', 'Pokhara', 'Lalitpur', 'Biratnagar',
202
+ // fiumi
203
+ 'Kosi', 'Gandaki', 'Karnali',
204
+ // monti
205
+ 'Everest', 'Lhotse', 'Makalu', 'Cho Oyu', 'Annapurna',
206
+ // località
207
+ 'Piazza Durbar', 'Campo Base dell\'Everest', 'Lago Phewa', 'Parco di Chitwan',
208
+
209
+
210
+ // AFRICA
211
+ 'Africa',
212
+
213
+ // Egitto
214
+ 'Egitto',
215
+ // città
216
+ 'Il Cairo', 'Alessandria', 'Giza', 'Sharm el-Sheikh', 'Luxor', 'Aswan',
217
+ // fiumi
218
+ 'Nilo',
219
+ // monti
220
+ 'Monte Caterina', 'Monte Sinai',
221
+ // località
222
+ 'Piramidi di Giza', 'Valle dei Re', 'Tempio di Abu Simbel', 'Karnak',
223
+
224
+ // Tanzania
225
+ 'Tanzania',
226
+ // città
227
+ 'Dar es Salaam', 'Dodoma', 'Mwanza', 'Arusha', 'Zanzibar City',
228
+ // fiumi
229
+ 'Rufiji', 'Ruvuma', 'Pangani',
230
+ // monti
231
+ 'Kilimangiaro', 'Monte Meru',
232
+ // località
233
+ 'Parco del Serengeti', 'Cratere di Ngorongoro', 'Zanzibar',
234
+
235
+ // Sudafrica
236
+ 'Sudafrica',
237
+ // città
238
+ 'Città del Capo', 'Johannesburg', 'Durban', 'Pretoria', 'Gqeberha',
239
+ // fiumi
240
+ 'Orange', 'Limpopo', 'Vaal',
241
+ // monti
242
+ 'Table Mountain', 'Mafadi',
243
+ // località
244
+ 'Parco Nazionale Kruger', 'Capo di Buona Speranza', 'Garden Route', 'Robben Island',
245
+
246
+
247
+ // OCEANIA
248
+ 'Oceania',
249
+
250
+ // Australia
251
+ 'Australia',
252
+ // città
253
+ 'Sydney', 'Melbourne', 'Brisbane', 'Perth', 'Adelaide', 'Canberra',
254
+ // fiumi
255
+ 'Murray', 'Darling', 'Murrumbidgee',
256
+ // monti
257
+ 'Monte Kosciuszko', 'Mawson Peak',
258
+ // località
259
+ 'Grande Barriera Corallina', 'Uluru', 'Opera House di Sydney', 'Twelve Apostles',
260
+
261
+ // Nuova Zelanda
262
+ 'Nuova Zelanda',
263
+ // città
264
+ 'Auckland', 'Wellington', 'Christchurch', 'Hamilton', 'Dunedin', 'Queenstown',
265
+ // fiumi
266
+ 'Waikato', 'Clutha', 'Whanganui',
267
+ // monti
268
+ 'Aoraki / Monte Cook', 'Monte Aspiring', 'Monte Ruapehu',
269
+ // località
270
+ 'Milford Sound', 'Hobbiton Movie Set', 'Rotorua', 'Waitomo Glowworm Caves',
271
+
272
+
273
+ // --------------------
274
+
275
+ // other countries
276
+ // EUROPA
277
+ 'Portogallo', 'Lisbona',
278
+ 'Paesi Bassi', 'Amsterdam',
279
+ 'Belgio', 'Bruxelles',
280
+ 'Austria', 'Vienna',
281
+ 'Polonia', 'Varsavia',
282
+ 'Svezia', 'Stoccolma',
283
+ 'Norvegia', 'Oslo',
284
+ 'Danimarca', 'Copenaghen',
285
+ 'Finlandia', 'Helsinki',
286
+ 'Irlanda', 'Dublino',
287
+ 'Repubblica Ceca', 'Praga',
288
+ 'Ungheria', 'Budapest',
289
+ 'Romania', 'Bucarest',
290
+ 'Croazia', 'Zagabria',
291
+ 'Turchia', 'Ankara',
292
+ 'Ucraina', 'Kiev',
293
+
294
+ // ASIA
295
+ 'Corea del Sud', 'Seoul',
296
+ 'Thailandia', 'Bangkok',
297
+ 'Vietnam', 'Hanoi',
298
+ 'Indonesia', 'Giacarta',
299
+ 'Filippine', 'Manila',
300
+ 'Malaysia', 'Kuala Lumpur',
301
+ 'Singapour', 'Singapore',
302
+ 'Emirati Arabi Uniti', 'Abu Dhabi', 'Dubai',
303
+ 'Arabia Saudita', 'Riad',
304
+ 'Israele', 'Gerusalemme',
305
+ 'Giordania', 'Amman',
306
+
307
+ // AFRICA
308
+ 'Marocco', 'Rabat',
309
+ 'Tunisia', 'Tunisi',
310
+ 'Kenya', 'Nairobi',
311
+ 'Senegal', 'Dakar',
312
+ 'Madagascar', 'Antananarivo',
313
+ 'Mauritius', 'Port Louis',
314
+ 'Etiopia', 'Addis Abeba',
315
+
316
+ // AMERICA DEL NORD E CARAIBI
317
+ 'Cuba', 'L’Avana',
318
+ 'Giamaica', 'Kingston',
319
+ 'Costa Rica', 'San José',
320
+ 'Panama', 'Città di Panama',
321
+ 'Repubblica Dominicana', 'Santo Domingo',
322
+
323
+ // AMERICA DEL SUD
324
+ 'Cile', 'Santiago del Cile',
325
+ 'Colombia', 'Bogotà',
326
+ 'Ecuador', 'Quito',
327
+ 'Uruguay', 'Montevideo',
328
+ 'Bolivia', 'La Paz',
329
+
330
+ // OCEANIA
331
+ 'Fiji', 'Suva',
332
+ 'Polinesia Francese', 'Papeete',
333
+
334
+ // -------------------------
335
+ // turistic places
336
+ // Europa
337
+ 'Alpi Svizzere', 'Plitvice Lakes', 'Isola di Skye', 'Algarve', 'Santorini Caldera',
338
+ 'Isola di Capri', 'Costa del Sol', 'Hallstatt', 'Bled', 'Fiordi Norvegesi',
339
+
340
+ // Asia e Medio Oriente
341
+ 'Petra', 'Taj Mahal Complex', 'Bagan', 'Halong Bay', 'Bali',
342
+ 'Cappadocia', 'Borobudur', 'Angkor Wat', 'Jeju Island', 'Maldivian Atolls',
343
+
344
+ // America del Nord e Caraibi
345
+ 'Punta Cana', 'Varadero', 'Bermuda Beaches', 'Monteverde Cloud Forest', 'San Blas Islands',
346
+
347
+ // America del Sud
348
+ 'Salar de Uyuni', 'Galapagos Islands', 'Torres del Paine', 'Cartagena Old Town', 'Atacama Desert',
349
+
350
+ // Africa
351
+ 'Chefchaouen', 'Okavango Delta', 'Praslin Island', 'Le Morne Brabant', 'Victoria Falls',
352
+
353
+ // Oceania
354
+ 'Bora Bora', 'Aoraki / Mount Cook Area', 'Whitsunday Islands', 'Matamata'
355
+ ];
356
+
357
+
358
+ /**
359
+ * Key used to match a place regardless of case, spacing and apostrophe style
360
+ * @param {string} str
361
+ * @returns {string}
362
+ */
363
+ const placeKey = str => str.toLowerCase().replace(/[ \u00A0]+/g, ' ').replace(/['‘’]/g, '’');
364
+
365
+ /**
366
+ * Builds the matcher for a list of places: a single regex (longest places first, so that
367
+ * e.g. "Lago di Como" wins over a shorter overlapping name) and a key → canonical form map.
368
+ * The canonical form uses the typographic apostrophe and non-breaking spaces after particles,
369
+ * consistently with betterText().
370
+ *
371
+ * @param {string[]} list - places list
372
+ * @returns {{regex: RegExp, canonical: Map<string, string>} | null} null if the list is empty
373
+ */
374
+ function buildPlacesMatcher(list) {
375
+ const canonical = new Map();
376
+
377
+ list.filter(Boolean).forEach(place => {
378
+ const key = placeKey(place);
379
+ if (!canonical.has(key)) {
380
+ canonical.set(
381
+ key,
382
+ place.trim()
383
+ .replace(/'/g, '’')
384
+ .replace(NBSP_AFTER_PARTICLE_REGEX, match => match.replace(/ +/g, '\u00A0'))
385
+ );
386
+ }
387
+ });
388
+
389
+ if (!canonical.size) {
390
+ return null;
391
+ }
392
+
393
+ const patterns = [...canonical.values()]
394
+ .sort((a, b) => b.length - a.length)
395
+ .map(place => place
396
+ .replace(/[.*+?^${}()|[\]\\/]/g, '\\$&')
397
+ .replace(/[ \u00A0]+/g, '[ \\u00A0]+')
398
+ .replace(/’/g, '[\'’‘]')
399
+ );
400
+
401
+ return {
402
+ // custom boundaries instead of \b, which doesn't work with accented edge letters (e.g. "Perù")
403
+ regex: new RegExp(`(?<![\\p{L}\\p{N}])(?:${patterns.join('|')})(?![\\p{L}\\p{N}])`, 'giu'),
404
+ canonical
405
+ };
406
+ }
407
+
408
+ const defaultMatcher = buildPlacesMatcher(places);
409
+
410
+ /**
411
+ * Version of betterText() that also normalizes the occurrences of known places
412
+ * (countries, cities, rivers, mountains, tourist locations) found in the text:
413
+ * matching is case-insensitive and tolerant to spacing and apostrophe style, and every
414
+ * match is replaced by the canonical form listed in `places` (casing, typographic
415
+ * apostrophe, non-breaking spaces after particles).
416
+ * Places replacement runs after betterText(), so it takes precedence over the casing
417
+ * enforced on particles and custom words.
418
+ *
419
+ * NOTE: places that are also common words (e.g. "Meno", "Po", "Reno") are capitalized
420
+ * wherever they appear.
421
+ *
422
+ * @param {string} str - input string to process
423
+ * @param {string[]} [custom_words] - list of words whose exact casing must be preserved (e.g. `['iPhone', 'macOS']`) (default: [])
424
+ * @param {string[]} [extra_places] - additional places, merged with the built-in list (default: [])
425
+ * @returns {string} processed string, or empty string if input is falsy
426
+ *
427
+ * @example
428
+ * betterTextWithPlaces("vacanza a new york e nel lago di como ,l'avana");
429
+ * // → "vacanza a New York e nel Lago di Como, L’Avana"
430
+ *
431
+ * betterTextWithPlaces('gita a monte cervino', ['iPhone'], ['Monte Cervino']);
432
+ * // → 'gita a Monte Cervino'
433
+ */
434
+ export function betterTextWithPlaces(str, custom_words = [], extra_places = []) {
435
+
436
+ str = betterText(str, custom_words);
437
+
438
+ if (!str) {
439
+ return str;
440
+ }
441
+
442
+ const matcher = extra_places.length
443
+ ? buildPlacesMatcher([...places, ...extra_places])
444
+ : defaultMatcher;
445
+
446
+ return matcher
447
+ ? str.replace(matcher.regex, match => matcher.canonical.get(placeKey(match)) ?? match)
448
+ : str;
449
+ }
@@ -1,6 +1,7 @@
1
1
  // @ts-check
2
2
  /*! minimo - Better Text */
3
3
 
4
+
4
5
  // Italian particles/articles (plus a few English and topographic terms) whose casing is
5
6
  // enforced and after which spaces are turned into non-breaking spaces. Hoisted to module
6
7
  // scope with the regexes/lookup built from it below, since none of this depends on the
@@ -29,7 +30,7 @@ const PARTICELLE = [
29
30
  ];
30
31
 
31
32
  // matches a particle followed by one-or-more spaces, to be turned into non-breaking spaces
32
- const NBSP_AFTER_PARTICLE_REGEX = new RegExp('\\b(' + PARTICELLE.join('|') + ')\\b +', 'gmi');
33
+ export const NBSP_AFTER_PARTICLE_REGEX =new RegExp('\\b(' + PARTICELLE.join('|') + ')\\b +', 'gmi');
33
34
 
34
35
  // matches any particle regardless of case, to enforce its exact casing in a single pass
35
36
  const PARTICLE_CASING_REGEX = new RegExp('\\b(' + PARTICELLE.join('|') + ')\\b', 'gmi');
@@ -59,6 +60,10 @@ export function betterText(str, custom_words = []) {
59
60
  str = str.replace(/ +(,|;|\.|:|!|\?)/g, '$1');
60
61
  str = str.replace(/(,|;|\.|:|!|\?)(?!$) +/g, '$1 ');
61
62
 
63
+ // add the missing space after , ; ! ? when directly followed by a letter or a quote;
64
+ // digits are skipped on purpose (decimals like 1,5), as are . and : (abbreviations, times, URLs)
65
+ str = str.replace(/([,;!?])(?=[\p{L}"'“‘])/gu, '$1 ');
66
+
62
67
  // collapse multiple spaces and tabs (including non-breaking spaces)
63
68
  str = str.replace(/[ \t\u00A0]+/g, ' ');
64
69
 
@@ -86,6 +91,12 @@ export function betterText(str, custom_words = []) {
86
91
  : exact;
87
92
  });
88
93
 
94
+ // capitalize the first letter after ! ? and ellipsis (... or …), optionally after an opening quote;
95
+ // runs after the particle casing so that a capital is not undone for particles like "e" or "di"
96
+ str = str.replace(/([!?]|\.{3}|…) +([“‘]?)(\p{Ll})/gu, (_match, punct, quote, letter) =>
97
+ `${punct} ${quote}${letter.toUpperCase()}`
98
+ );
99
+
89
100
  if(custom_words.length) {
90
101
  custom_words.forEach(item => {
91
102
  str = str.replace(new RegExp(`\\b${item}\\b`, 'gi'), item);