cizgile 0.1.0 → 0.2.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.
@@ -0,0 +1,595 @@
1
+ //#region src/transliterate/latin.ts
2
+ /** Latin letters with no decomposition (`ß`, `Æ`, `Ł`, `Þ`, `Ə`, ...) and the modifier letters that are dropped. */
3
+ const latin = {
4
+ Æ: "AE",
5
+ æ: "ae",
6
+ Ø: "O",
7
+ ø: "o",
8
+ Ǿ: "O",
9
+ ǿ: "o",
10
+ Ð: "D",
11
+ ð: "d",
12
+ Þ: "TH",
13
+ þ: "th",
14
+ ß: "ss",
15
+ ẞ: "SS",
16
+ Œ: "OE",
17
+ œ: "oe",
18
+ Ł: "L",
19
+ ł: "l",
20
+ Đ: "D",
21
+ đ: "d",
22
+ ı: "i",
23
+ İ: "I",
24
+ Ħ: "H",
25
+ ħ: "h",
26
+ Ŧ: "T",
27
+ ŧ: "t",
28
+ Ŋ: "NG",
29
+ ŋ: "ng",
30
+ ĸ: "k",
31
+ ſ: "s",
32
+ IJ: "IJ",
33
+ ij: "ij",
34
+ Ə: "E",
35
+ ə: "e",
36
+ Ɛ: "E",
37
+ ɛ: "e",
38
+ Ɔ: "O",
39
+ ɔ: "o",
40
+ Ƶ: "Z",
41
+ ƶ: "z",
42
+ Ǥ: "G",
43
+ ǥ: "g",
44
+ Ƀ: "B",
45
+ ƀ: "b",
46
+ Ɨ: "I",
47
+ ɨ: "i",
48
+ Ʉ: "U",
49
+ ʉ: "u",
50
+ Ɍ: "R",
51
+ ɍ: "r",
52
+ Ⱥ: "A",
53
+ ⱥ: "a",
54
+ Ȼ: "C",
55
+ ȼ: "c",
56
+ Ɇ: "E",
57
+ ɇ: "e",
58
+ Ꝺ: "D",
59
+ ꝺ: "d",
60
+ Ƒ: "F",
61
+ ƒ: "f",
62
+ Ɓ: "B",
63
+ ɓ: "b",
64
+ Ɗ: "D",
65
+ ɗ: "d",
66
+ Ƙ: "K",
67
+ ƙ: "k",
68
+ Ƴ: "Y",
69
+ ƴ: "y",
70
+ Ʃ: "SH",
71
+ ʃ: "sh",
72
+ Ʒ: "ZH",
73
+ ʒ: "zh",
74
+ Ǝ: "E",
75
+ ǝ: "e",
76
+ Ɣ: "GH",
77
+ ɣ: "gh",
78
+ Ɩ: "I",
79
+ ɩ: "i",
80
+ Ʊ: "U",
81
+ ʊ: "u",
82
+ ʔ: "",
83
+ ʼ: "",
84
+ ʻ: "",
85
+ ʹ: "",
86
+ ʺ: "",
87
+ ʽ: "",
88
+ ʾ: "",
89
+ ʿ: "",
90
+ ˈ: "",
91
+ ˌ: ""
92
+ };
93
+
94
+ //#endregion
95
+ //#region src/transliterate/symbols.ts
96
+ /** Symbols spelled out in English (`&`, `©`, currency signs) or turned into separators (dashes, quotes, bullets). */
97
+ const symbols = {
98
+ "&": " and ",
99
+ "©": " c ",
100
+ "®": " r ",
101
+ "™": " tm ",
102
+ "℠": " sm ",
103
+ "♥": " love ",
104
+ "❤": " love ",
105
+ "🦄": " unicorn ",
106
+ "€": " euro ",
107
+ "£": " pound ",
108
+ "¥": " yen ",
109
+ "¢": " cent ",
110
+ "₺": " lira ",
111
+ "₹": " rupee ",
112
+ "₽": " ruble ",
113
+ "₩": " won ",
114
+ "₪": " shekel ",
115
+ "₫": " dong ",
116
+ "₴": " hryvnia ",
117
+ "₦": " naira ",
118
+ "฿": " baht ",
119
+ "₿": " bitcoin ",
120
+ "₱": " peso ",
121
+ "₸": " tenge ",
122
+ "₾": " lari ",
123
+ "₮": " tugrik ",
124
+ "₼": " manat ",
125
+ "₡": " colon ",
126
+ "₲": " guarani ",
127
+ "₭": " kip ",
128
+ "₨": " rupee ",
129
+ "‰": " permille ",
130
+ "°": " deg ",
131
+ "№": " no ",
132
+ µ: " u ",
133
+ "×": " x ",
134
+ "∞": " infinity ",
135
+ "∑": " sum ",
136
+ "√": " sqrt ",
137
+ π: " pi ",
138
+ "§": " section ",
139
+ "¶": " paragraph ",
140
+ "†": " ",
141
+ "‡": " ",
142
+ "•": " ",
143
+ "…": " ",
144
+ "–": " ",
145
+ "—": " ",
146
+ "«": " ",
147
+ "»": " ",
148
+ "“": " ",
149
+ "”": " ",
150
+ "„": " ",
151
+ "‘": "",
152
+ "’": "",
153
+ "‚": "",
154
+ "‛": "",
155
+ "‹": " ",
156
+ "›": " ",
157
+ "¿": " ",
158
+ "¡": " ",
159
+ "′": " ",
160
+ "″": " "
161
+ };
162
+
163
+ //#endregion
164
+ //#region src/transliterate/core.ts
165
+ /** The tables every call consults last: `latin`, then `symbols`. */
166
+ const DEFAULT_TABLES = [latin, symbols];
167
+ const NON_ASCII = /[^\x00-\x7F]/;
168
+ let tableIds;
169
+ let nextTableId = 0;
170
+ let compiledByArray;
171
+ let compiledByKey;
172
+ function codePointCount(text) {
173
+ let count = 0;
174
+ for (const _ of text) count += 1;
175
+ return count;
176
+ }
177
+ function tableId(table) {
178
+ tableIds ??= /* @__PURE__ */ new WeakMap();
179
+ let id = tableIds.get(table);
180
+ if (id === void 0) {
181
+ id = nextTableId;
182
+ nextTableId += 1;
183
+ tableIds.set(table, id);
184
+ }
185
+ return id;
186
+ }
187
+ function build(tables) {
188
+ const map = /* @__PURE__ */ new Map();
189
+ const multi = [];
190
+ for (const table of tables) for (const key of Object.keys(table)) {
191
+ if (map.has(key)) continue;
192
+ const value = table[key] ?? "";
193
+ map.set(key, value);
194
+ if (codePointCount(key) > 1) multi.push([key, value]);
195
+ }
196
+ multi.sort((a, b) => b[0].length - a[0].length);
197
+ const asciiKeys = [...map.keys()].filter((key) => key.length === 1 && (key.codePointAt(0) ?? 0) < 128);
198
+ return {
199
+ map,
200
+ sequences: multi,
201
+ ascii: asciiKeys.length === 0 ? void 0 : new RegExp(`[${asciiKeys.map((k) => k.replace(/[\]\\^-]/g, "\\$&")).join("")}]`, "g"),
202
+ folded: /* @__PURE__ */ new Map()
203
+ };
204
+ }
205
+ function compileTables(tables) {
206
+ compiledByArray ??= /* @__PURE__ */ new WeakMap();
207
+ const byArray = compiledByArray.get(tables);
208
+ if (byArray !== void 0) return byArray;
209
+ compiledByKey ??= /* @__PURE__ */ new Map();
210
+ const key = tables.map(tableId).join(",");
211
+ let compiled = compiledByKey.get(key);
212
+ if (compiled === void 0) {
213
+ compiled = build(tables);
214
+ if (compiledByKey.size > 256) compiledByKey.clear();
215
+ compiledByKey.set(key, compiled);
216
+ }
217
+ compiledByArray.set(tables, compiled);
218
+ return compiled;
219
+ }
220
+ /** The table list a `transliterate` call would consult, in lookup order. */
221
+ function resolveTables(options) {
222
+ const out = [];
223
+ if (options.locale !== void 0) {
224
+ out.push(options.locale.table);
225
+ if (options.locale.tables !== void 0) out.push(...options.locale.tables);
226
+ }
227
+ if (options.tables !== void 0) out.push(...options.tables);
228
+ out.push(...DEFAULT_TABLES);
229
+ return out;
230
+ }
231
+ /** The first table value for `key`, or `undefined`. */
232
+ function lookup(tables, key) {
233
+ for (const table of tables) {
234
+ const value = table[key];
235
+ if (value !== void 0) return value;
236
+ }
237
+ }
238
+ /** Removes combining marks: `"é"` becomes `"e"`, `"ǿ"` becomes `"ø"`. */
239
+ function stripMarks(input) {
240
+ return input.normalize("NFD").replace(/\p{M}+/gu, "").normalize("NFC");
241
+ }
242
+ const MARK = /^\p{M}+$/u;
243
+ function foldPieces(ch, map) {
244
+ const decomposed = ch.normalize("NFD");
245
+ if (decomposed !== ch) {
246
+ let out = "";
247
+ let complete = true;
248
+ for (const piece of decomposed) {
249
+ const value = map.get(piece);
250
+ if (value === void 0) {
251
+ complete = false;
252
+ break;
253
+ }
254
+ out += value;
255
+ }
256
+ if (complete) return out;
257
+ }
258
+ const base = stripMarks(ch);
259
+ if (base === ch) return null;
260
+ const mapped = map.get(base);
261
+ if (mapped !== void 0) return mapped;
262
+ return (base.codePointAt(0) ?? 128) < 128 ? base : null;
263
+ }
264
+ function foldChar(ch, compiled) {
265
+ const cached = compiled.folded.get(ch);
266
+ if (cached !== void 0) return cached;
267
+ const value = foldPieces(ch, compiled.map);
268
+ if (compiled.folded.size > 8192) compiled.folded.clear();
269
+ compiled.folded.set(ch, value);
270
+ return value;
271
+ }
272
+ /** The transliteration core: applies `tables` to NFC text, folding marks unless told not to. */
273
+ function fold(input, tables, dropUnknown, foldMarks = true) {
274
+ const compiled = "sequences" in tables ? tables : compileTables(tables);
275
+ const map = compiled.map;
276
+ let text = input;
277
+ if (!NON_ASCII.test(text)) return compiled.ascii === void 0 ? text : text.replace(compiled.ascii, (m) => map.get(m) ?? m);
278
+ if (compiled.sequences.length > 0) {
279
+ for (const [key, value] of compiled.sequences) if (text.includes(key)) text = text.split(key).join(value);
280
+ }
281
+ let out = "";
282
+ let kept = false;
283
+ for (const ch of text) {
284
+ const direct = map.get(ch);
285
+ if (direct !== void 0) {
286
+ out += direct;
287
+ kept = false;
288
+ continue;
289
+ }
290
+ if ((ch.codePointAt(0) ?? 0) < 128) {
291
+ out += ch;
292
+ kept = false;
293
+ continue;
294
+ }
295
+ if (foldMarks && MARK.test(ch)) {
296
+ if (kept && !dropUnknown) out += ch;
297
+ continue;
298
+ }
299
+ const folded = foldMarks ? foldChar(ch, compiled) : null;
300
+ if (folded !== null) {
301
+ out += folded;
302
+ kept = false;
303
+ continue;
304
+ }
305
+ if (!dropUnknown) out += ch;
306
+ kept = !dropUnknown;
307
+ }
308
+ return out;
309
+ }
310
+ let compatCache;
311
+ function compatEntries(table) {
312
+ compatCache ??= /* @__PURE__ */ new WeakMap();
313
+ const cached = compatCache.get(table);
314
+ if (cached !== void 0) return cached;
315
+ const out = [];
316
+ for (const [key, value] of Object.entries(table)) if (key.normalize("NFKC") !== key) out.push([key, value]);
317
+ compatCache.set(table, out);
318
+ return out;
319
+ }
320
+ /** Applies the table entries whose keys NFKC would split, so a ligature gets its table value before normalisation. */
321
+ function applyCompat(text, tables) {
322
+ let out = text;
323
+ for (const table of tables) for (const [key, value] of compatEntries(table)) if (out.includes(key)) out = out.split(key).join(value);
324
+ return out;
325
+ }
326
+ /** Replaces non-ASCII letters with ASCII from the tables and the mark-stripping fallback. Characters no table knows are kept whole, marks included, or dropped with `unknown: "drop"`. */
327
+ function transliterate(input, options = {}) {
328
+ const tables = resolveTables(options);
329
+ let text = input.normalize("NFC");
330
+ if (options.nfkc === true && NON_ASCII.test(text)) text = applyCompat(text, tables).normalize("NFKC");
331
+ return fold(text, tables, options.unknown === "drop");
332
+ }
333
+
334
+ //#endregion
335
+ //#region src/transliterate/locales-latin.ts
336
+ function turkishLowercase(input) {
337
+ return input.toLocaleLowerCase("tr");
338
+ }
339
+ /** German: `ä ö ü` become `ae oe ue`, `ß` becomes `ss`, `&` becomes `und`. */
340
+ const de = {
341
+ id: "de",
342
+ table: {
343
+ Ä: "Ae",
344
+ ä: "ae",
345
+ Ö: "Oe",
346
+ ö: "oe",
347
+ Ü: "Ue",
348
+ ü: "ue",
349
+ ß: "ss",
350
+ ẞ: "SS",
351
+ "&": " und "
352
+ }
353
+ };
354
+ /** Turkish: dotted and dotless i, `ğ ş ç ö ü` stripped, `&` becomes `ve`; lowercases with the Turkish rules. */
355
+ const tr = {
356
+ id: "tr",
357
+ table: {
358
+ ı: "i",
359
+ İ: "I",
360
+ Ğ: "G",
361
+ ğ: "g",
362
+ Ş: "S",
363
+ ş: "s",
364
+ Ç: "C",
365
+ ç: "c",
366
+ Ö: "O",
367
+ ö: "o",
368
+ Ü: "U",
369
+ ü: "u",
370
+ "&": " ve "
371
+ },
372
+ lowercase: turkishLowercase
373
+ };
374
+ /** Azerbaijani: the Turkish letters plus `ə`, `&` becomes `ve`. */
375
+ const az = {
376
+ id: "az",
377
+ table: {
378
+ ı: "i",
379
+ İ: "I",
380
+ Ğ: "G",
381
+ ğ: "g",
382
+ Ş: "S",
383
+ ş: "s",
384
+ Ç: "C",
385
+ ç: "c",
386
+ Ö: "O",
387
+ ö: "o",
388
+ Ü: "U",
389
+ ü: "u",
390
+ Ə: "E",
391
+ ə: "e",
392
+ "&": " ve "
393
+ },
394
+ lowercase: turkishLowercase
395
+ };
396
+ /** Danish: `ø å æ` become `oe aa ae`, `&` becomes `og`. */
397
+ const da = {
398
+ id: "da",
399
+ table: {
400
+ Ø: "Oe",
401
+ ø: "oe",
402
+ Å: "Aa",
403
+ å: "aa",
404
+ Æ: "Ae",
405
+ æ: "ae",
406
+ "&": " og "
407
+ }
408
+ };
409
+ /** Norwegian Bokmål: `ø å æ` become `oe aa ae`, `&` becomes `og`. */
410
+ const nb = {
411
+ id: "nb",
412
+ table: {
413
+ Ø: "Oe",
414
+ ø: "oe",
415
+ Å: "Aa",
416
+ å: "aa",
417
+ Æ: "Ae",
418
+ æ: "ae",
419
+ "&": " og "
420
+ }
421
+ };
422
+ /** Swedish: `ä ö å` become `ae oe aa`, `&` becomes `och`. */
423
+ const sv = {
424
+ id: "sv",
425
+ table: {
426
+ Ä: "Ae",
427
+ ä: "ae",
428
+ Ö: "Oe",
429
+ ö: "oe",
430
+ Å: "Aa",
431
+ å: "aa",
432
+ "&": " och "
433
+ }
434
+ };
435
+ /** Finnish: `ä ö å` become `ae oe aa`, `&` becomes `ja`. */
436
+ const fi = {
437
+ id: "fi",
438
+ table: {
439
+ Ä: "Ae",
440
+ ä: "ae",
441
+ Ö: "Oe",
442
+ ö: "oe",
443
+ Å: "Aa",
444
+ å: "aa",
445
+ "&": " ja "
446
+ }
447
+ };
448
+ /** Hungarian: `&` becomes `es`. */
449
+ const hu = {
450
+ id: "hu",
451
+ table: { "&": " es " }
452
+ };
453
+ /** Vietnamese: `đ` becomes `d`, `&` becomes `va`. */
454
+ const vi = {
455
+ id: "vi",
456
+ table: {
457
+ Đ: "D",
458
+ đ: "d",
459
+ "&": " va "
460
+ }
461
+ };
462
+ /** Spanish: `ñ` becomes `n`, `&` becomes `y`. */
463
+ const es = {
464
+ id: "es",
465
+ table: {
466
+ Ñ: "N",
467
+ ñ: "n",
468
+ "&": " y "
469
+ }
470
+ };
471
+ /** French: `œ æ` become `oe ae`, `&` becomes `et`. */
472
+ const fr = {
473
+ id: "fr",
474
+ table: {
475
+ Œ: "Oe",
476
+ œ: "oe",
477
+ Æ: "Ae",
478
+ æ: "ae",
479
+ "&": " et "
480
+ }
481
+ };
482
+ /** Portuguese: `&` becomes `e`. */
483
+ const pt = {
484
+ id: "pt",
485
+ table: { "&": " e " }
486
+ };
487
+ /** Italian: `&` becomes `e`. */
488
+ const it = {
489
+ id: "it",
490
+ table: { "&": " e " }
491
+ };
492
+ /** Dutch: `ij` becomes `ij`, `&` becomes `en`. */
493
+ const nl = {
494
+ id: "nl",
495
+ table: {
496
+ IJ: "IJ",
497
+ ij: "ij",
498
+ "&": " en "
499
+ }
500
+ };
501
+ /** Polish: `&` becomes `i`. */
502
+ const pl = {
503
+ id: "pl",
504
+ table: { "&": " i " }
505
+ };
506
+ /** Romanian: `&` becomes `si`. */
507
+ const ro = {
508
+ id: "ro",
509
+ table: { "&": " si " }
510
+ };
511
+ /** Czech: `&` becomes `a`. */
512
+ const cs = {
513
+ id: "cs",
514
+ table: { "&": " a " }
515
+ };
516
+ /** Slovak: `&` becomes `a`. */
517
+ const sk = {
518
+ id: "sk",
519
+ table: { "&": " a " }
520
+ };
521
+ /** Slovenian: `&` becomes `in`. */
522
+ const sl = {
523
+ id: "sl",
524
+ table: { "&": " in " }
525
+ };
526
+ /** Croatian: `&` becomes `i`. */
527
+ const hr = {
528
+ id: "hr",
529
+ table: { "&": " i " }
530
+ };
531
+ /** Icelandic: `þ ð` become `th d`, `&` becomes `og`. */
532
+ const is = {
533
+ id: "is",
534
+ table: {
535
+ Þ: "Th",
536
+ þ: "th",
537
+ Ð: "D",
538
+ ð: "d",
539
+ "&": " og "
540
+ }
541
+ };
542
+ /** Estonian: `&` becomes `ja`. */
543
+ const et = {
544
+ id: "et",
545
+ table: { "&": " ja " }
546
+ };
547
+ /** Latvian: `&` becomes `un`. */
548
+ const lv = {
549
+ id: "lv",
550
+ table: { "&": " un " }
551
+ };
552
+ /** Lithuanian: `&` becomes `ir`. */
553
+ const lt = {
554
+ id: "lt",
555
+ table: { "&": " ir " }
556
+ };
557
+ /** Catalan: the punt volat in `l·l` is dropped, `&` becomes `i`. */
558
+ const ca = {
559
+ id: "ca",
560
+ table: {
561
+ "·": "",
562
+ "&": " i "
563
+ }
564
+ };
565
+ /** The Latin-script locales by id; these ship with the main entry. */
566
+ const latinLocales = {
567
+ az,
568
+ ca,
569
+ cs,
570
+ da,
571
+ de,
572
+ es,
573
+ et,
574
+ fi,
575
+ fr,
576
+ hr,
577
+ hu,
578
+ is,
579
+ it,
580
+ lt,
581
+ lv,
582
+ nb,
583
+ nl,
584
+ pl,
585
+ pt,
586
+ ro,
587
+ sk,
588
+ sl,
589
+ sv,
590
+ tr,
591
+ vi
592
+ };
593
+
594
+ //#endregion
595
+ export { fold as A, sl as C, DEFAULT_TABLES as D, vi as E, symbols as F, latin as I, resolveTables as M, stripMarks as N, applyCompat as O, transliterate as P, sk as S, tr as T, nb as _, de as a, pt as b, fi as c, hu as d, is as f, lv as g, lt as h, da as i, lookup as j, compileTables as k, fr as l, latinLocales as m, ca as n, es as o, it as p, cs as r, et as s, az as t, hr as u, nl as v, sv as w, ro as x, pl as y };