@indodev/toolkit 0.1.5 → 0.3.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/dist/index.cjs CHANGED
@@ -210,6 +210,46 @@ function maskNIK(nik, options = {}) {
210
210
  return startPart + char.repeat(maskLength) + endPart;
211
211
  }
212
212
 
213
+ // src/nik/utils.ts
214
+ function getAge(nik, referenceDate = /* @__PURE__ */ new Date()) {
215
+ const info = parseNIK(nik);
216
+ if (!info || !info.birthDate) {
217
+ return null;
218
+ }
219
+ const birthDate = info.birthDate;
220
+ let age = referenceDate.getFullYear() - birthDate.getFullYear();
221
+ const m = referenceDate.getMonth() - birthDate.getMonth();
222
+ if (m < 0 || m === 0 && referenceDate.getDate() < birthDate.getDate()) {
223
+ age--;
224
+ }
225
+ return age;
226
+ }
227
+ function formatBirthDate(nik, options = {
228
+ day: "numeric",
229
+ month: "long",
230
+ year: "numeric"
231
+ }, locale = "id-ID") {
232
+ const info = parseNIK(nik);
233
+ if (!info || !info.birthDate) {
234
+ return null;
235
+ }
236
+ return new Intl.DateTimeFormat(locale, options).format(info.birthDate);
237
+ }
238
+ function isValidForGender(nik, gender) {
239
+ const info = parseNIK(nik);
240
+ if (!info) {
241
+ return false;
242
+ }
243
+ return info.gender === gender;
244
+ }
245
+ function isValidForBirthDate(nik, birthDate) {
246
+ const info = parseNIK(nik);
247
+ if (!info || !info.birthDate) {
248
+ return false;
249
+ }
250
+ return info.birthDate.getFullYear() === birthDate.getFullYear() && info.birthDate.getMonth() === birthDate.getMonth() && info.birthDate.getDate() === birthDate.getDate();
251
+ }
252
+
213
253
  // src/phone/constants.ts
214
254
  var OPERATOR_PREFIXES = {
215
255
  // Telkomsel (Halo, Simpati, by.U)
@@ -852,6 +892,37 @@ function maskPhoneNumber(phone, options = {}) {
852
892
  return masked;
853
893
  }
854
894
 
895
+ // src/phone/links.ts
896
+ function generateWALink(phone, message) {
897
+ if (!validatePhoneNumber(phone)) {
898
+ return "";
899
+ }
900
+ const e164 = toE164(phone);
901
+ let link = `https://wa.me/${e164}`;
902
+ if (message) {
903
+ link += `?text=${encodeURIComponent(message)}`;
904
+ }
905
+ return link;
906
+ }
907
+ function generateSmsLink(phone, body) {
908
+ if (!validatePhoneNumber(phone)) {
909
+ return "";
910
+ }
911
+ const e164 = toE164(phone);
912
+ let link = `sms:+${e164}`;
913
+ if (body) {
914
+ link += `?body=${encodeURIComponent(body)}`;
915
+ }
916
+ return link;
917
+ }
918
+ function generateTelLink(phone) {
919
+ if (!validatePhoneNumber(phone)) {
920
+ return "";
921
+ }
922
+ const e164 = toE164(phone);
923
+ return `tel:+${e164}`;
924
+ }
925
+
855
926
  // src/phone/parse.ts
856
927
  function parsePhoneNumber(phone) {
857
928
  if (!validatePhoneNumber(phone)) {
@@ -900,6 +971,13 @@ function getOperator(phone) {
900
971
  const prefix = normalized.substring(0, 4);
901
972
  return OPERATOR_PREFIXES[prefix] || null;
902
973
  }
974
+ function isProvider(phone, providerName) {
975
+ const operator = getOperator(phone);
976
+ if (!operator) {
977
+ return false;
978
+ }
979
+ return operator.toLowerCase() === providerName.toLowerCase();
980
+ }
903
981
  function getRegion(phone) {
904
982
  if (!phone.startsWith("0")) {
905
983
  return null;
@@ -925,6 +1003,184 @@ function normalizeToNational2(phone) {
925
1003
  return "";
926
1004
  }
927
1005
 
1006
+ // src/npwp/validate.ts
1007
+ function validateNPWP(npwp) {
1008
+ if (!npwp || typeof npwp !== "string") {
1009
+ return false;
1010
+ }
1011
+ const cleaned = npwp.replace(/[^\d]/g, "");
1012
+ if (cleaned.length !== 15 && cleaned.length !== 16) {
1013
+ return false;
1014
+ }
1015
+ if (!/^\d+$/.test(cleaned)) {
1016
+ return false;
1017
+ }
1018
+ return true;
1019
+ }
1020
+
1021
+ // src/npwp/format.ts
1022
+ function formatNPWP(npwp) {
1023
+ if (!validateNPWP(npwp)) {
1024
+ return npwp;
1025
+ }
1026
+ const cleaned = npwp.replace(/[^\d]/g, "");
1027
+ if (cleaned.length === 15) {
1028
+ return `${cleaned.substring(0, 2)}.${cleaned.substring(
1029
+ 2,
1030
+ 5
1031
+ )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(
1032
+ 9,
1033
+ 12
1034
+ )}.${cleaned.substring(12, 15)}`;
1035
+ }
1036
+ return cleaned;
1037
+ }
1038
+ function parseNPWP(npwp) {
1039
+ if (!validateNPWP(npwp)) {
1040
+ return null;
1041
+ }
1042
+ const cleaned = npwp.replace(/[^\d]/g, "");
1043
+ const isNikBased = cleaned.length === 16;
1044
+ if (isNikBased) {
1045
+ return {
1046
+ npwp: cleaned,
1047
+ type: cleaned.substring(0, 2),
1048
+ serial: cleaned.substring(2, 8),
1049
+ checksum: cleaned.substring(8, 9),
1050
+ taxOfficeCode: cleaned.substring(9, 12),
1051
+ branchCode: cleaned.substring(12, 16),
1052
+ isNikBased: true
1053
+ };
1054
+ }
1055
+ return {
1056
+ npwp: cleaned,
1057
+ type: cleaned.substring(0, 2),
1058
+ serial: cleaned.substring(2, 8),
1059
+ checksum: cleaned.substring(8, 9),
1060
+ taxOfficeCode: cleaned.substring(9, 12),
1061
+ branchCode: cleaned.substring(12, 15),
1062
+ isNikBased: false
1063
+ };
1064
+ }
1065
+ function maskNPWP(npwp, options) {
1066
+ if (!npwp) return "";
1067
+ const { visibleStart = 2, visibleEnd = 3, maskChar = "*" } = options || {};
1068
+ if (npwp.includes(".") || npwp.includes("-")) {
1069
+ let digitCount = 0;
1070
+ const digitsOnly = npwp.replace(/[^\d]/g, "");
1071
+ const totalDigits = digitsOnly.length;
1072
+ return npwp.split("").map((char) => {
1073
+ if (/\d/.test(char)) {
1074
+ digitCount++;
1075
+ if (digitCount <= visibleStart || digitCount > totalDigits - visibleEnd) {
1076
+ return char;
1077
+ }
1078
+ return maskChar;
1079
+ }
1080
+ return char;
1081
+ }).join("");
1082
+ }
1083
+ const cleaned = npwp.replace(/[^\d]/g, "");
1084
+ if (cleaned.length < visibleStart + visibleEnd) {
1085
+ return cleaned.replace(/./g, maskChar);
1086
+ }
1087
+ const start = cleaned.substring(0, visibleStart);
1088
+ const end = cleaned.substring(cleaned.length - visibleEnd);
1089
+ const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);
1090
+ return `${start}${middle}${end}`;
1091
+ }
1092
+
1093
+ // src/plate/regions.ts
1094
+ var PLATE_REGIONS = {
1095
+ A: "Banten",
1096
+ B: "Jakarta, Depok, Tangerang, Bekasi",
1097
+ D: "Bandung, Cimahi",
1098
+ E: "Cirebon, Indramayu, Majalengka, Kuningan",
1099
+ F: "Bogor, Cianjur, Sukabumi",
1100
+ G: "Pekalongan, Pemalang, Batang, Tegal, Brebes",
1101
+ H: "Semarang, Salatiga, Kendal, Demak",
1102
+ K: "Pati, Kudus, Jepara, Rembang, Blora, Grobogan",
1103
+ L: "Surabaya",
1104
+ M: "Madura",
1105
+ N: "Malang, Probolinggo, Pasuruan, Lumajang, Batu",
1106
+ P: "Besuki, Bondowoso, Situbondo, Jember, Banyuwangi",
1107
+ R: "Banyumas, Cilacap, Purbalinggo, Banjarnegara",
1108
+ S: "Bojonegoro, Tuban, Lamongan, Jombang, Mojokerto",
1109
+ T: "Purwakarta, Subang, Karawang",
1110
+ AA: "Kedu, Magelang, Purworejo, Kebumen, Temanggung, Wonosobo",
1111
+ AB: "Yogyakarta",
1112
+ AD: "Surakarta, Boyolali, Sukoharjo, Karanganyar, Wonogiri, Sragen, Klaten",
1113
+ AE: "Madiun, Ngawi, Magetan, Ponorogo, Pacitan",
1114
+ AG: "Kediri, Blitar, Tulungagung, Nganjuk, Trenggalek",
1115
+ BA: "Sumatera Barat",
1116
+ BB: "Sumatera Utara (Pantai Barat)",
1117
+ BD: "Bengkulu",
1118
+ BE: "Lampung",
1119
+ BG: "Sumatera Selatan",
1120
+ BH: "Jambi",
1121
+ BK: "Sumatera Utara (Pantai Timur)",
1122
+ BL: "Aceh",
1123
+ BM: "Riau",
1124
+ BN: "Kepulauan Bangka Belitung",
1125
+ BP: "Kepulauan Riau",
1126
+ DA: "Kalimantan Selatan",
1127
+ DB: "Sulawesi Utara (Daratan)",
1128
+ DC: "Sulawesi Barat",
1129
+ DD: "Sulawesi Selatan (Selatan)",
1130
+ DE: "Maluku",
1131
+ DF: "Timor Timur (Historical)",
1132
+ DG: "Maluku Utara",
1133
+ DH: "NTT (Timor)",
1134
+ DK: "Bali",
1135
+ DL: "Sulawesi Utara (Kepulauan)",
1136
+ DM: "Gorontalo",
1137
+ DN: "Sulawesi Tengah",
1138
+ DP: "Sulawesi Selatan (Utara)",
1139
+ DR: "NTB (Lombok)",
1140
+ DS: "Papua",
1141
+ DT: "Sulawesi Tenggara",
1142
+ EA: "NTB (Sumbawa)",
1143
+ EB: "NTT (Flores)",
1144
+ ED: "NTT (Sumba)",
1145
+ KB: "Kalimantan Barat",
1146
+ KH: "Kalimantan Tengah",
1147
+ KT: "Kalimantan Timur",
1148
+ KU: "Kalimantan Utara",
1149
+ PA: "Papua",
1150
+ PB: "Papua Barat"
1151
+ };
1152
+
1153
+ // src/plate/utils.ts
1154
+ function validatePlate(plate) {
1155
+ if (!plate || typeof plate !== "string") {
1156
+ return false;
1157
+ }
1158
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1159
+ const regex = /^[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$/;
1160
+ return regex.test(cleaned);
1161
+ }
1162
+ function getRegionFromPlate(plate) {
1163
+ if (!plate || typeof plate !== "string") {
1164
+ return null;
1165
+ }
1166
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1167
+ const match = cleaned.match(/^([A-Z]{1,2})/);
1168
+ if (!match) {
1169
+ return null;
1170
+ }
1171
+ const prefix = match[1];
1172
+ return PLATE_REGIONS[prefix] || null;
1173
+ }
1174
+ function formatPlate(plate) {
1175
+ if (!plate) return "";
1176
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1177
+ const match = cleaned.match(/^([A-Z]{1,2})(\d{1,4})([A-Z]{1,3})$/);
1178
+ if (!match) {
1179
+ return cleaned;
1180
+ }
1181
+ return `${match[1]} ${match[2]} ${match[3]}`;
1182
+ }
1183
+
928
1184
  // src/currency/format.ts
929
1185
  function formatRupiah(amount, options) {
930
1186
  const {
@@ -1150,24 +1406,1793 @@ function capitalize(str) {
1150
1406
  return str.charAt(0).toUpperCase() + str.slice(1);
1151
1407
  }
1152
1408
 
1409
+ // src/currency/utils.ts
1410
+ function roundToClean(amount, unit = "ribu") {
1411
+ const divisors = {
1412
+ ribu: 1e3,
1413
+ "ratus-ribu": 1e5,
1414
+ juta: 1e6
1415
+ };
1416
+ const divisor = divisors[unit];
1417
+ return Math.round(amount / divisor) * divisor;
1418
+ }
1419
+ function formatAccounting(amount, options) {
1420
+ const isNegative = amount < 0;
1421
+ const formatted = formatRupiah(Math.abs(amount), options);
1422
+ if (isNegative) {
1423
+ return `(${formatted})`;
1424
+ }
1425
+ return formatted;
1426
+ }
1427
+ function calculateTax(amount, rate = 0.11) {
1428
+ return amount * rate;
1429
+ }
1430
+ function addRupiahSymbol(amount) {
1431
+ if (typeof amount === "number") {
1432
+ return `Rp ${amount.toLocaleString("id-ID")}`;
1433
+ }
1434
+ if (amount.trim().startsWith("Rp")) {
1435
+ return amount;
1436
+ }
1437
+ return `Rp ${amount.trim()}`;
1438
+ }
1439
+
1440
+ // src/text/constants.ts
1441
+ var LOWERCASE_WORDS = [
1442
+ // Indonesian prepositions (kata depan)
1443
+ "di",
1444
+ "ke",
1445
+ "dari",
1446
+ "pada",
1447
+ "dalam",
1448
+ "untuk",
1449
+ "dengan",
1450
+ "oleh",
1451
+ "kepada",
1452
+ "terhadap",
1453
+ "tentang",
1454
+ "tanpa",
1455
+ "hingga",
1456
+ "sampai",
1457
+ "sejak",
1458
+ "menuju",
1459
+ "melalui",
1460
+ // Indonesian conjunctions (kata hubung)
1461
+ "dan",
1462
+ "atau",
1463
+ "tetapi",
1464
+ "namun",
1465
+ "serta",
1466
+ "maupun",
1467
+ "melainkan",
1468
+ "sedangkan",
1469
+ // Indonesian articles/particles
1470
+ "yang",
1471
+ "sebagai",
1472
+ "adalah",
1473
+ "ialah",
1474
+ "yaitu",
1475
+ "bahwa",
1476
+ "akan",
1477
+ "telah",
1478
+ "sudah",
1479
+ "belum",
1480
+ // English articles
1481
+ "a",
1482
+ "an",
1483
+ "the",
1484
+ // English conjunctions
1485
+ "and",
1486
+ "or",
1487
+ "but",
1488
+ "nor",
1489
+ "for",
1490
+ "yet",
1491
+ "so",
1492
+ "as",
1493
+ // English prepositions (short ones, < 5 letters)
1494
+ "at",
1495
+ "by",
1496
+ "in",
1497
+ "of",
1498
+ "on",
1499
+ "to",
1500
+ "up",
1501
+ "via",
1502
+ "per",
1503
+ "off",
1504
+ "out"
1505
+ // English prepositions (5+ letters - optional, some style guides capitalize these)
1506
+ // 'about',
1507
+ // 'above',
1508
+ // 'across',
1509
+ // 'after',
1510
+ // 'among',
1511
+ // 'below',
1512
+ // 'under',
1513
+ // 'until',
1514
+ // 'with',
1515
+ ];
1516
+ var ACRONYMS = [
1517
+ // Indonesian government & military
1518
+ "DKI",
1519
+ // Daerah Khusus Ibukota
1520
+ "DIY",
1521
+ // Daerah Istimewa Yogyakarta
1522
+ "TNI",
1523
+ // Tentara Nasional Indonesia
1524
+ "POLRI",
1525
+ // Kepolisian Republik Indonesia
1526
+ "ABRI",
1527
+ // Angkatan Bersenjata Republik Indonesia
1528
+ "MPR",
1529
+ // Majelis Permusyawaratan Rakyat
1530
+ "DPR",
1531
+ // Dewan Perwakilan Rakyat
1532
+ "KPK",
1533
+ // Komisi Pemberantasan Korupsi
1534
+ "BIN",
1535
+ // Badan Intelijen Negara
1536
+ // Indonesian business entities
1537
+ "PT",
1538
+ // Perseroan Terbatas
1539
+ "CV",
1540
+ // Commanditaire Vennootschap
1541
+ "UD",
1542
+ // Usaha Dagang
1543
+ "PD",
1544
+ // Perusahaan Daerah
1545
+ "Tbk",
1546
+ // Terbuka (publicly traded)
1547
+ "BUMN",
1548
+ // Badan Usaha Milik Negara
1549
+ "BUMD",
1550
+ // Badan Usaha Milik Daerah
1551
+ // Indonesian banks
1552
+ "BCA",
1553
+ // Bank Central Asia
1554
+ "BRI",
1555
+ // Bank Rakyat Indonesia
1556
+ "BNI",
1557
+ // Bank Negara Indonesia
1558
+ "BTN",
1559
+ // Bank Tabungan Negara
1560
+ "BSI",
1561
+ // Bank Syariah Indonesia
1562
+ "BPD",
1563
+ // Bank Pembangunan Daerah
1564
+ // Indonesian government services
1565
+ "KTP",
1566
+ // Kartu Tanda Penduduk
1567
+ "NIK",
1568
+ // Nomor Induk Kependudukan
1569
+ "NPWP",
1570
+ // Nomor Pokok Wajib Pajak
1571
+ "SIM",
1572
+ // Surat Izin Mengemudi
1573
+ "STNK",
1574
+ // Surat Tanda Nomor Kendaraan
1575
+ "BPJS",
1576
+ // Badan Penyelenggara Jaminan Sosial
1577
+ "KIS",
1578
+ // Kartu Indonesia Sehat
1579
+ "KIP",
1580
+ // Kartu Indonesia Pintar
1581
+ "PKH",
1582
+ // Program Keluarga Harapan
1583
+ // Indonesian utilities & infrastructure
1584
+ "PLN",
1585
+ // Perusahaan Listrik Negara
1586
+ "PDAM",
1587
+ // Perusahaan Daerah Air Minum
1588
+ "PGN",
1589
+ // Perusahaan Gas Negara
1590
+ "KAI",
1591
+ // Kereta Api Indonesia
1592
+ "MRT",
1593
+ // Mass Rapid Transit
1594
+ "LRT",
1595
+ // Light Rail Transit
1596
+ // Indonesian taxes & fees
1597
+ "PBB",
1598
+ // Pajak Bumi dan Bangunan
1599
+ "PPh",
1600
+ // Pajak Penghasilan
1601
+ "PPN",
1602
+ // Pajak Pertambahan Nilai
1603
+ "BPHTB",
1604
+ // Bea Perolehan Hak atas Tanah dan Bangunan
1605
+ // Indonesian education
1606
+ "UI",
1607
+ // Universitas Indonesia
1608
+ "ITB",
1609
+ // Institut Teknologi Bandung
1610
+ "UGM",
1611
+ // Universitas Gadjah Mada
1612
+ "IPB",
1613
+ // Institut Pertanian Bogor
1614
+ "ITS",
1615
+ // Institut Teknologi Sepuluh Nopember
1616
+ "UNPAD",
1617
+ // Universitas Padjadjaran
1618
+ "UNDIP",
1619
+ // Universitas Diponegoro
1620
+ "UNAIR",
1621
+ // Universitas Airlangga
1622
+ "UNS",
1623
+ // Universitas Sebelas Maret
1624
+ // Indonesian degrees (gelar)
1625
+ "S.Pd",
1626
+ // Sarjana Pendidikan
1627
+ "S.H",
1628
+ // Sarjana Hukum
1629
+ "S.E",
1630
+ // Sarjana Ekonomi
1631
+ "S.T",
1632
+ // Sarjana Teknik
1633
+ "S.Kom",
1634
+ // Sarjana Komputer
1635
+ "S.Si",
1636
+ // Sarjana Sains
1637
+ "S.Sos",
1638
+ // Sarjana Sosial
1639
+ "M.Pd",
1640
+ // Magister Pendidikan
1641
+ "M.M",
1642
+ // Magister Manajemen
1643
+ "M.T",
1644
+ // Magister Teknik
1645
+ "M.Kom",
1646
+ // Magister Komputer
1647
+ // Common services
1648
+ "ATM",
1649
+ // Automated Teller Machine
1650
+ "POS",
1651
+ // Point of Sale
1652
+ "SMS",
1653
+ // Short Message Service
1654
+ "GPS",
1655
+ // Global Positioning System
1656
+ "WiFi",
1657
+ // Wireless Fidelity (technically Wi-Fi)
1658
+ "USB",
1659
+ // Universal Serial Bus
1660
+ "PIN",
1661
+ // Personal Identification Number
1662
+ "OTP",
1663
+ // One Time Password
1664
+ "QR",
1665
+ // Quick Response
1666
+ // Technology & IT
1667
+ "IT",
1668
+ // Information Technology
1669
+ "AI",
1670
+ // Artificial Intelligence
1671
+ "ML",
1672
+ // Machine Learning
1673
+ "API",
1674
+ // Application Programming Interface
1675
+ "UI",
1676
+ // User Interface (duplicate with Universitas Indonesia, context matters)
1677
+ "UX",
1678
+ // User Experience
1679
+ "SEO",
1680
+ // Search Engine Optimization
1681
+ "SaaS",
1682
+ // Software as a Service
1683
+ "CRM",
1684
+ // Customer Relationship Management
1685
+ "ERP",
1686
+ // Enterprise Resource Planning
1687
+ // Business titles
1688
+ "CEO",
1689
+ // Chief Executive Officer
1690
+ "CFO",
1691
+ // Chief Financial Officer
1692
+ "CTO",
1693
+ // Chief Technology Officer
1694
+ "COO",
1695
+ // Chief Operating Officer
1696
+ "CMO",
1697
+ // Chief Marketing Officer
1698
+ "HR",
1699
+ // Human Resources
1700
+ "PR",
1701
+ // Public Relations
1702
+ "VP",
1703
+ // Vice President
1704
+ "GM",
1705
+ // General Manager
1706
+ // International organizations
1707
+ "UN",
1708
+ // United Nations
1709
+ "WHO",
1710
+ // World Health Organization
1711
+ "UNESCO",
1712
+ // United Nations Educational, Scientific and Cultural Organization
1713
+ "NATO",
1714
+ // North Atlantic Treaty Organization
1715
+ "ASEAN",
1716
+ // Association of Southeast Asian Nations
1717
+ "APEC",
1718
+ // Asia-Pacific Economic Cooperation
1719
+ "WTO",
1720
+ // World Trade Organization
1721
+ "IMF",
1722
+ // International Monetary Fund
1723
+ // Medical
1724
+ "ICU",
1725
+ // Intensive Care Unit
1726
+ "ER",
1727
+ // Emergency Room
1728
+ "MRI",
1729
+ // Magnetic Resonance Imaging
1730
+ "CT",
1731
+ // Computed Tomography
1732
+ "DNA",
1733
+ // Deoxyribonucleic Acid
1734
+ "RNA",
1735
+ // Ribonucleic Acid
1736
+ "HIV",
1737
+ // Human Immunodeficiency Virus
1738
+ "AIDS",
1739
+ // Acquired Immunodeficiency Syndrome
1740
+ "COVID",
1741
+ // Coronavirus Disease
1742
+ // Measurements & units
1743
+ "KM",
1744
+ // Kilometer
1745
+ "CM",
1746
+ // Centimeter
1747
+ "MM",
1748
+ // Millimeter
1749
+ "KG",
1750
+ // Kilogram
1751
+ "RPM",
1752
+ // Revolutions Per Minute
1753
+ "MPH",
1754
+ // Miles Per Hour
1755
+ "KPH",
1756
+ // Kilometers Per Hour
1757
+ // Finance
1758
+ "IPO",
1759
+ // Initial Public Offering
1760
+ "ATM",
1761
+ // Automated Teller Machine (duplicate)
1762
+ "ROI",
1763
+ // Return on Investment
1764
+ "GDP",
1765
+ // Gross Domestic Product
1766
+ "VAT"
1767
+ // Value Added Tax
1768
+ ];
1769
+ var ABBREVIATIONS = {
1770
+ // ========== Address Abbreviations ==========
1771
+ "Jl.": "Jalan",
1772
+ "Gg.": "Gang",
1773
+ "No.": "Nomor",
1774
+ "Kp.": "Kampung",
1775
+ "Ds.": "Desa",
1776
+ "Kel.": "Kelurahan",
1777
+ "Kec.": "Kecamatan",
1778
+ "Kab.": "Kabupaten",
1779
+ Kota: "Kota",
1780
+ "Prov.": "Provinsi",
1781
+ "Prop.": "Provinsi",
1782
+ "Rt.": "Rukun Tetangga",
1783
+ "Rw.": "Rukun Warga",
1784
+ Blok: "Blok",
1785
+ "Komp.": "Kompleks",
1786
+ Perumahan: "Perumahan",
1787
+ "Perum.": "Perumahan",
1788
+ // ========== Academic Titles ==========
1789
+ "Dr.": "Doktor",
1790
+ "Ir.": "Insinyur",
1791
+ "Prof.": "Profesor",
1792
+ "Drs.": "Doktorandus",
1793
+ "Dra.": "Doktoranda",
1794
+ // Bachelor degrees
1795
+ "S.Pd.": "Sarjana Pendidikan",
1796
+ "S.H.": "Sarjana Hukum",
1797
+ "S.E.": "Sarjana Ekonomi",
1798
+ "S.T.": "Sarjana Teknik",
1799
+ "S.Kom.": "Sarjana Komputer",
1800
+ "S.Si.": "Sarjana Sains",
1801
+ "S.Sos.": "Sarjana Sosial",
1802
+ "S.I.Kom.": "Sarjana Ilmu Komunikasi",
1803
+ "S.S.": "Sarjana Sastra",
1804
+ "S.Psi.": "Sarjana Psikologi",
1805
+ "S.Farm.": "Sarjana Farmasi",
1806
+ "S.Ked.": "Sarjana Kedokteran",
1807
+ // Master degrees
1808
+ "M.Sc.": "Master of Science",
1809
+ "M.M.": "Magister Manajemen",
1810
+ "M.Pd.": "Magister Pendidikan",
1811
+ "M.T.": "Magister Teknik",
1812
+ "M.Kom.": "Magister Komputer",
1813
+ "M.Si.": "Magister Sains",
1814
+ "M.H.": "Magister Hukum",
1815
+ "M.A.": "Master of Arts",
1816
+ MBA: "Master of Business Administration",
1817
+ // ========== Honorifics ==========
1818
+ "Bpk.": "Bapak",
1819
+ Ibu: "Ibu",
1820
+ "Sdr.": "Saudara",
1821
+ "Sdri.": "Saudari",
1822
+ "Yth.": "Yang Terhormat",
1823
+ "H.": "Haji",
1824
+ "Hj.": "Hajjah",
1825
+ "Tn.": "Tuan",
1826
+ "Ny.": "Nyonya",
1827
+ "Nn.": "Nona",
1828
+ // ========== Organizations ==========
1829
+ "PT.": "Perseroan Terbatas",
1830
+ "CV.": "Commanditaire Vennootschap",
1831
+ "UD.": "Usaha Dagang",
1832
+ "PD.": "Perusahaan Daerah",
1833
+ "Tbk.": "Terbuka",
1834
+ Koperasi: "Koperasi",
1835
+ Yayasan: "Yayasan",
1836
+ // ========== Common Abbreviations ==========
1837
+ "dst.": "dan seterusnya",
1838
+ "dsb.": "dan sebagainya",
1839
+ "dll.": "dan lain-lain",
1840
+ "dkk.": "dan kawan-kawan",
1841
+ "a.n.": "atas nama",
1842
+ "u.p.": "untuk perhatian",
1843
+ "u.b.": "untuk beliau",
1844
+ "c.q.": "casu quo",
1845
+ "hlm.": "halaman",
1846
+ "tgl.": "tanggal",
1847
+ "bln.": "bulan",
1848
+ "thn.": "tahun",
1849
+ "ttd.": "tertanda",
1850
+ // ========== Contact Information ==========
1851
+ "Tlp.": "Telepon",
1852
+ "Telp.": "Telepon",
1853
+ "HP.": "Handphone",
1854
+ Fax: "Faksimile",
1855
+ Email: "Email",
1856
+ Website: "Website",
1857
+ // ========== Days (Indonesian) ==========
1858
+ "Sen.": "Senin",
1859
+ "Sel.": "Selasa",
1860
+ "Rab.": "Rabu",
1861
+ "Kam.": "Kamis",
1862
+ "Jum.": "Jumat",
1863
+ "Sab.": "Sabtu",
1864
+ "Min.": "Minggu",
1865
+ // ========== Months (Indonesian) ==========
1866
+ "Jan.": "Januari",
1867
+ "Feb.": "Februari",
1868
+ "Mar.": "Maret",
1869
+ "Apr.": "April",
1870
+ Mei: "Mei",
1871
+ "Jun.": "Juni",
1872
+ "Jul.": "Juli",
1873
+ "Agt.": "Agustus",
1874
+ "Sep.": "September",
1875
+ "Okt.": "Oktober",
1876
+ "Nov.": "November",
1877
+ "Des.": "Desember",
1878
+ // ========== Units & Measurements ==========
1879
+ "kg.": "kilogram",
1880
+ "gr.": "gram",
1881
+ "lt.": "liter",
1882
+ "ml.": "mililiter",
1883
+ "km.": "kilometer",
1884
+ "cm.": "sentimeter",
1885
+ "mm.": "milimeter",
1886
+ "m2.": "meter persegi",
1887
+ "m3.": "meter kubik",
1888
+ "ha.": "hektar"
1889
+ };
1890
+ var PROFANITY = [
1891
+ "anjing",
1892
+ "babi",
1893
+ "bangsat",
1894
+ "bajingan",
1895
+ "brengsek",
1896
+ "goblok",
1897
+ "tolol",
1898
+ "idiot",
1899
+ "perek",
1900
+ "jablay",
1901
+ "kontol",
1902
+ "memek",
1903
+ "ngewe",
1904
+ "puki",
1905
+ "jembut",
1906
+ "asu",
1907
+ "itil",
1908
+ "lanjiao",
1909
+ "pantek",
1910
+ "anying",
1911
+ "anjrit"
1912
+ ];
1913
+ var STOPWORDS = [
1914
+ "ada",
1915
+ "adalah",
1916
+ "adanya",
1917
+ "adapun",
1918
+ "agak",
1919
+ "agaknya",
1920
+ "agar",
1921
+ "akan",
1922
+ "akankah",
1923
+ "akhir",
1924
+ "akhiri",
1925
+ "akhirnya",
1926
+ "aku",
1927
+ "akulah",
1928
+ "amat",
1929
+ "amatlah",
1930
+ "anda",
1931
+ "andalah",
1932
+ "antar",
1933
+ "antara",
1934
+ "antaranya",
1935
+ "apa",
1936
+ "apaan",
1937
+ "apabila",
1938
+ "apakah",
1939
+ "apalagi",
1940
+ "apatah",
1941
+ "artinya",
1942
+ "asal",
1943
+ "asalkan",
1944
+ "atas",
1945
+ "atau",
1946
+ "ataukah",
1947
+ "ataupun",
1948
+ "awal",
1949
+ "awalnya",
1950
+ "bagai",
1951
+ "bagaikan",
1952
+ "bagaimana",
1953
+ "bagaimanakah",
1954
+ "bagaimanapun",
1955
+ "bagi",
1956
+ "bagian",
1957
+ "bahkan",
1958
+ "bahwa",
1959
+ "bahwasanya",
1960
+ "baik",
1961
+ "bakal",
1962
+ "bakalan",
1963
+ "balik",
1964
+ "banyak",
1965
+ "bapak",
1966
+ "baru",
1967
+ "bawah",
1968
+ "beberapa",
1969
+ "begini",
1970
+ "beginian",
1971
+ "beginikah",
1972
+ "beginilah",
1973
+ "begitu",
1974
+ "begitukah",
1975
+ "begitulah",
1976
+ "begitupun",
1977
+ "bekerja",
1978
+ "belakang",
1979
+ "belakangan",
1980
+ "belum",
1981
+ "belumlah",
1982
+ "benar",
1983
+ "benarkah",
1984
+ "benarlah",
1985
+ "berada",
1986
+ "berakhir",
1987
+ "berakhirlah",
1988
+ "berakhirnya",
1989
+ "berapa",
1990
+ "berapakah",
1991
+ "berapalah",
1992
+ "berapapun",
1993
+ "berarti",
1994
+ "berawal",
1995
+ "berbagai",
1996
+ "berikut",
1997
+ "berikutnya",
1998
+ "berjumlah",
1999
+ "berkali-kali",
2000
+ "berkata",
2001
+ "berkeinginan",
2002
+ "berkenaan",
2003
+ "berlainan",
2004
+ "berlalu",
2005
+ "berlangsung",
2006
+ "berlebihan",
2007
+ "bermacam",
2008
+ "bermacam-macam",
2009
+ "bermaksud",
2010
+ "bermula",
2011
+ "bersama",
2012
+ "bersama-sama",
2013
+ "bersiap",
2014
+ "bersiap-siap",
2015
+ "bertanya",
2016
+ "bertanya-tanya",
2017
+ "berturut",
2018
+ "berturut-turut",
2019
+ "bertutur",
2020
+ "berujar",
2021
+ "berupa",
2022
+ "besar",
2023
+ "betul",
2024
+ "betulkah",
2025
+ "biasa",
2026
+ "biasanya",
2027
+ "bila",
2028
+ "bilakah",
2029
+ "bisa",
2030
+ "bisakah",
2031
+ "boleh",
2032
+ "bolehkah",
2033
+ "bolehlah",
2034
+ "buat",
2035
+ "bukan",
2036
+ "bukankah",
2037
+ "bukanlah",
2038
+ "bukannya",
2039
+ "bulan",
2040
+ "bung",
2041
+ "cara",
2042
+ "caranya",
2043
+ "cukup",
2044
+ "cukupkah",
2045
+ "cukuplah",
2046
+ "cuma",
2047
+ "dahulu",
2048
+ "dalam",
2049
+ "dan",
2050
+ "dapat",
2051
+ "dari",
2052
+ "daripada",
2053
+ "datang",
2054
+ "dekat",
2055
+ "demi",
2056
+ "demikian",
2057
+ "demikianlah",
2058
+ "dengan",
2059
+ "depan",
2060
+ "di",
2061
+ "dia",
2062
+ "diakhiri",
2063
+ "diakhirinya",
2064
+ "dialah",
2065
+ "diantara",
2066
+ "diantaranya",
2067
+ "diberi",
2068
+ "diberikan",
2069
+ "diberikannya",
2070
+ "dibuat",
2071
+ "dibuatnya",
2072
+ "didapat",
2073
+ "didatangkan",
2074
+ "digunakan",
2075
+ "diibaratkan",
2076
+ "diingat",
2077
+ "diingatkan",
2078
+ "diinginkan",
2079
+ "dijawab",
2080
+ "dijelaskan",
2081
+ "dijelaskannya",
2082
+ "dikarenakan",
2083
+ "dikatakan",
2084
+ "dikatakannya",
2085
+ "dikerjakan",
2086
+ "diketahui",
2087
+ "diketahuinya",
2088
+ "dikira",
2089
+ "dilakukan",
2090
+ "dilalui",
2091
+ "dilihat",
2092
+ "dimaksud",
2093
+ "dimaksudkan",
2094
+ "dimaksudkannya",
2095
+ "dimana",
2096
+ "dimanalah",
2097
+ "dimulai",
2098
+ "dimulailah",
2099
+ "dimulainya",
2100
+ "diminta",
2101
+ "dimintai",
2102
+ "dimisalkan",
2103
+ "dimungkinkan",
2104
+ "dini",
2105
+ "dipastikan",
2106
+ "diperbuat",
2107
+ "diperbuatnya",
2108
+ "dipergunakan",
2109
+ "diperkirakan",
2110
+ "diperlihatkan",
2111
+ "diperlukan",
2112
+ "diperlukannya",
2113
+ "dipersoalkan",
2114
+ "dipertanyakan",
2115
+ "dipunyai",
2116
+ "diri",
2117
+ "dirinya",
2118
+ "disampaikan",
2119
+ "disebut",
2120
+ "disebutkan",
2121
+ "disebutkannya",
2122
+ "disini",
2123
+ "disinilah",
2124
+ "disitulah",
2125
+ "diterangkan",
2126
+ "diterangkannya",
2127
+ "diteruskan",
2128
+ "ditujukan",
2129
+ "ditunjuk",
2130
+ "ditunjuki",
2131
+ "ditunjukkan",
2132
+ "ditunjukkannya",
2133
+ "ditunjuknya",
2134
+ "dituturkan",
2135
+ "dituturkannya",
2136
+ "diucapkan",
2137
+ "diucapkannya",
2138
+ "diungkapkan",
2139
+ "dua",
2140
+ "dulu",
2141
+ "empat",
2142
+ "enggak",
2143
+ "enggaknya",
2144
+ "entah",
2145
+ "entahlah",
2146
+ "guna",
2147
+ "gunakan",
2148
+ "hal",
2149
+ "hampir",
2150
+ "hanya",
2151
+ "hanyalah",
2152
+ "hari",
2153
+ "harus",
2154
+ "haruslah",
2155
+ "harusnya",
2156
+ "hendak",
2157
+ "hendaklah",
2158
+ "hendaknya",
2159
+ "hingga",
2160
+ "ia",
2161
+ "ialah",
2162
+ "ibarat",
2163
+ "ibaratkan",
2164
+ "ibaratnya",
2165
+ "ibu",
2166
+ "ikut",
2167
+ "ingat",
2168
+ "ingat-ingat",
2169
+ "ingin",
2170
+ "inginkah",
2171
+ "inginkan",
2172
+ "ini",
2173
+ "inikah",
2174
+ "inilah",
2175
+ "itu",
2176
+ "itukah",
2177
+ "itulah",
2178
+ "jadi",
2179
+ "jadilah",
2180
+ "jadinya",
2181
+ "jangan",
2182
+ "jangankan",
2183
+ "janganlah",
2184
+ "jauh",
2185
+ "jawab",
2186
+ "jawaban",
2187
+ "jawabnya",
2188
+ "jelas",
2189
+ "jelaskan",
2190
+ "jelaslah",
2191
+ "jelasnya",
2192
+ "jika",
2193
+ "jikalau",
2194
+ "juga",
2195
+ "jumlah",
2196
+ "jumlahnya",
2197
+ "justru",
2198
+ "kala",
2199
+ "kalau",
2200
+ "kalaulah",
2201
+ "kalaupun",
2202
+ "kali",
2203
+ "kalian",
2204
+ "kami",
2205
+ "kamilah",
2206
+ "kamu",
2207
+ "kamulah",
2208
+ "kan",
2209
+ "kapan",
2210
+ "kapankah",
2211
+ "kapanpun",
2212
+ "karena",
2213
+ "karenanya",
2214
+ "ke",
2215
+ "keadaan",
2216
+ "kebetulan",
2217
+ "kecil",
2218
+ "kedua",
2219
+ "keduanya",
2220
+ "keinginan",
2221
+ "kelak",
2222
+ "kelihatan",
2223
+ "kelihatannya",
2224
+ "kelima",
2225
+ "keluar",
2226
+ "kembali",
2227
+ "kemudian",
2228
+ "kemungkinan",
2229
+ "kemungkinannya",
2230
+ "kenapa",
2231
+ "kepada",
2232
+ "kepadanya",
2233
+ "kesampaian",
2234
+ "keseluruhan",
2235
+ "keseluruhannya",
2236
+ "keterlaluan",
2237
+ "ketika",
2238
+ "khususnya",
2239
+ "kini",
2240
+ "kinilah",
2241
+ "kira",
2242
+ "kira-kira",
2243
+ "kiranya",
2244
+ "kita",
2245
+ "kitalah",
2246
+ "kok",
2247
+ "kurang",
2248
+ "lagi",
2249
+ "lagian",
2250
+ "lah",
2251
+ "lain",
2252
+ "lainnya",
2253
+ "lalu",
2254
+ "lama",
2255
+ "lamanya",
2256
+ "lanjut",
2257
+ "lanjutnya",
2258
+ "lebih",
2259
+ "lewat",
2260
+ "luar",
2261
+ "macam",
2262
+ "maka",
2263
+ "makanya",
2264
+ "makin",
2265
+ "malah",
2266
+ "malahan",
2267
+ "mampu",
2268
+ "mampukah",
2269
+ "mana",
2270
+ "manakala",
2271
+ "manalagi",
2272
+ "masih",
2273
+ "masihkah",
2274
+ "masing",
2275
+ "masing-masing",
2276
+ "mau",
2277
+ "maupun",
2278
+ "melainkan",
2279
+ "melakukan",
2280
+ "melalui",
2281
+ "melihat",
2282
+ "melihatnya",
2283
+ "memang",
2284
+ "memastikan",
2285
+ "memberi",
2286
+ "memberikan",
2287
+ "membuat",
2288
+ "memerlukan",
2289
+ "memihak",
2290
+ "meminta",
2291
+ "memisalkan",
2292
+ "memperbuat",
2293
+ "mempergunakan",
2294
+ "memperkirakan",
2295
+ "memperlihatkan",
2296
+ "mempersiapkan",
2297
+ "mempersoalkan",
2298
+ "mempertanyakan",
2299
+ "mempunyai",
2300
+ "memulai",
2301
+ "memungkinkan",
2302
+ "memutuskan",
2303
+ "menanti",
2304
+ "menanti-nanti",
2305
+ "menantikan",
2306
+ "menunjuk",
2307
+ "menunjuknya",
2308
+ "menuju",
2309
+ "menurut",
2310
+ "menurutnya",
2311
+ "menurutmu",
2312
+ "menurutku",
2313
+ "menurutnya",
2314
+ "menurut mereka",
2315
+ "menyampaikan",
2316
+ "menyebut",
2317
+ "menyebutkan",
2318
+ "menjelaskan",
2319
+ "menjadi",
2320
+ "menjadikan",
2321
+ "menjalani",
2322
+ "menjelang",
2323
+ "menjawab",
2324
+ "menunjukkan",
2325
+ "menuangkan",
2326
+ "menulis",
2327
+ "menyatakan",
2328
+ "merupakan",
2329
+ "mereka",
2330
+ "merekalah",
2331
+ "meski",
2332
+ "meskipun",
2333
+ "mula",
2334
+ "mulai",
2335
+ "mulailah",
2336
+ "mulanya",
2337
+ "mungkin",
2338
+ "mungkinkah",
2339
+ "nah",
2340
+ "naik",
2341
+ "namun",
2342
+ "nanti",
2343
+ "nantinya",
2344
+ "nyaris",
2345
+ "oleh",
2346
+ "olehnya",
2347
+ "orang",
2348
+ "pada",
2349
+ "padahal",
2350
+ "padanya",
2351
+ "pakai",
2352
+ "paling",
2353
+ "panjang",
2354
+ "pantas",
2355
+ "para",
2356
+ "pasti",
2357
+ "pastilah",
2358
+ "pagi",
2359
+ "per",
2360
+ "pernah",
2361
+ "persoalan",
2362
+ "pertama",
2363
+ "pertama-tama",
2364
+ "perlu",
2365
+ "perlukah",
2366
+ "perlulah",
2367
+ "pernah",
2368
+ "pihak",
2369
+ "pihaknya",
2370
+ "pukul",
2371
+ "pula",
2372
+ "pun",
2373
+ "punya",
2374
+ "rasa",
2375
+ "rasanya",
2376
+ "rata",
2377
+ "rupanya",
2378
+ "saat",
2379
+ "saatnya",
2380
+ "saja",
2381
+ "sajalah",
2382
+ "salam",
2383
+ "saling",
2384
+ "sama",
2385
+ "sama-sama",
2386
+ "sambil",
2387
+ "sampai",
2388
+ "sampai-sampai",
2389
+ "sampaikan",
2390
+ "sana",
2391
+ "sangat",
2392
+ "sangatlah",
2393
+ "satu",
2394
+ "saya",
2395
+ "sayalah",
2396
+ "sayang",
2397
+ "seperti",
2398
+ "seperti-itu",
2399
+ "sepura",
2400
+ "sebab",
2401
+ "sebabnya",
2402
+ "sebagai",
2403
+ "sebagaimana",
2404
+ "sebagainya",
2405
+ "sebagian",
2406
+ "sebaik",
2407
+ "sebaik-baiknya",
2408
+ "sebaiknya",
2409
+ "sebaliknya",
2410
+ "sebanyak",
2411
+ "sebegini",
2412
+ "sebegitu",
2413
+ "sebelum",
2414
+ "sebelumnya",
2415
+ "sebenarnya",
2416
+ "seberapa",
2417
+ "sebesar",
2418
+ "sebetulnya",
2419
+ "sebisanya",
2420
+ "sebuah",
2421
+ "sebut",
2422
+ "sebutkan",
2423
+ "sebutnya",
2424
+ "secara",
2425
+ "secukupnya",
2426
+ "sedang",
2427
+ "sedangkan",
2428
+ "sedikit",
2429
+ "sedikitnya",
2430
+ "sedemikian",
2431
+ "sediakala",
2432
+ "sedikit",
2433
+ "sedikitnya",
2434
+ "segala",
2435
+ "segalanya",
2436
+ "segera",
2437
+ "seharusnya",
2438
+ "sehingga",
2439
+ "seingat",
2440
+ "sejak",
2441
+ "sejauh",
2442
+ "sejenak",
2443
+ "sejumlah",
2444
+ "sekali",
2445
+ "sekali-kali",
2446
+ "sekalian",
2447
+ "sekaligus",
2448
+ "sekalipun",
2449
+ "sekarang",
2450
+ "sekaranglah",
2451
+ "sekecil",
2452
+ "seketika",
2453
+ "sekiranya",
2454
+ "sekitar",
2455
+ "sekitarnya",
2456
+ "sekurang",
2457
+ "sekurangnya",
2458
+ "sela",
2459
+ "selalu",
2460
+ "selama",
2461
+ "selama-lamanya",
2462
+ "selamanya",
2463
+ "selanjutnya",
2464
+ "seluruh",
2465
+ "seluruhnya",
2466
+ "semacam",
2467
+ "semakin",
2468
+ "semampu",
2469
+ "semampunya",
2470
+ "semasa",
2471
+ "semata",
2472
+ "semata-mata",
2473
+ "semaunya",
2474
+ "sementara",
2475
+ "semisal",
2476
+ "semisalnya",
2477
+ "sempat",
2478
+ "semua",
2479
+ "semuanya",
2480
+ "semula",
2481
+ "sendiri",
2482
+ "sendirinya",
2483
+ "seolah",
2484
+ "seolah-olah",
2485
+ "seorang",
2486
+ "sepanjang",
2487
+ "sepantasnya",
2488
+ "sepantasnyalah",
2489
+ "seperempat",
2490
+ "seperti",
2491
+ "sepertinya",
2492
+ "sepihak",
2493
+ "sepuluh",
2494
+ "seratus",
2495
+ "seribu",
2496
+ "sering",
2497
+ "seringnya",
2498
+ "serta",
2499
+ "serupa",
2500
+ "sesaat",
2501
+ "sesama",
2502
+ "sesampai",
2503
+ "sesampainya",
2504
+ "sesegera",
2505
+ "sesekali",
2506
+ "seseorang",
2507
+ "sesuatu",
2508
+ "sesuatunya",
2509
+ "sesudah",
2510
+ "sesudahnya",
2511
+ "setelah",
2512
+ "setempat",
2513
+ "setengah",
2514
+ "seterusnya",
2515
+ "setiap",
2516
+ "setidaknya",
2517
+ "setinggi",
2518
+ "seusai",
2519
+ "sewaktu",
2520
+ "siap",
2521
+ "siapa",
2522
+ "siapakah",
2523
+ "siapapun",
2524
+ "sini",
2525
+ "sinilah",
2526
+ "situ",
2527
+ "situlah",
2528
+ "suatu",
2529
+ "sudah",
2530
+ "sudahkah",
2531
+ "sudahlah",
2532
+ "supaya",
2533
+ "tadi",
2534
+ "tadinya",
2535
+ "tahu",
2536
+ "tak",
2537
+ "tambah",
2538
+ "tambahnya",
2539
+ "tampak",
2540
+ "tampaknya",
2541
+ "tandas",
2542
+ "tandasnya",
2543
+ "tanpa",
2544
+ "tanya",
2545
+ "tanyakan",
2546
+ "tanyanya",
2547
+ "tapi",
2548
+ "tegas",
2549
+ "tegasnya",
2550
+ "telah",
2551
+ "tempat",
2552
+ "tengah",
2553
+ "tentang",
2554
+ "tentu",
2555
+ "tentulah",
2556
+ "tentunya",
2557
+ "tepat",
2558
+ "terakhir",
2559
+ "terasa",
2560
+ "terbanyak",
2561
+ "terdahulu",
2562
+ "terdapat",
2563
+ "terdiri",
2564
+ "terdiri-dari",
2565
+ "terhadap",
2566
+ "terhadapnya",
2567
+ "teringat",
2568
+ "teringat-ingat",
2569
+ "terjadi",
2570
+ "terjadilah",
2571
+ "terjadinya",
2572
+ "terkira",
2573
+ "terlalu",
2574
+ "terlebih",
2575
+ "terlihat",
2576
+ "termasuk",
2577
+ "ternyata",
2578
+ "tersampaikan",
2579
+ "tersebut",
2580
+ "tersebutlah",
2581
+ "tertentu",
2582
+ "tertuju",
2583
+ "terus",
2584
+ "terutama",
2585
+ "tetap",
2586
+ "tetapi",
2587
+ "tiap",
2588
+ "tiba",
2589
+ "tiba-tiba",
2590
+ "tidak",
2591
+ "tidakkah",
2592
+ "tidaklah",
2593
+ "tiga",
2594
+ "tadi",
2595
+ "tadinya",
2596
+ "tinggi",
2597
+ "toh",
2598
+ "tuju",
2599
+ "tunjuk",
2600
+ "turut",
2601
+ "tutur",
2602
+ "tuturnya",
2603
+ "ucap",
2604
+ "ucapnya",
2605
+ "ujar",
2606
+ "ujarnya",
2607
+ "umumnya",
2608
+ "ungkap",
2609
+ "ungkapnya",
2610
+ "untuk",
2611
+ "untaian",
2612
+ "usai",
2613
+ "usah",
2614
+ "waduh",
2615
+ "wah",
2616
+ "wahai",
2617
+ "walau",
2618
+ "walaupun",
2619
+ "wong",
2620
+ "yaitu",
2621
+ "yakin",
2622
+ "yakni",
2623
+ "yang"
2624
+ ];
2625
+
2626
+ // src/text/capitalization.ts
2627
+ function capitalize2(text) {
2628
+ if (!text) return text;
2629
+ return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
2630
+ }
2631
+ function toTitleCase(text, options) {
2632
+ if (!text) return text;
2633
+ const {
2634
+ preserveAcronyms = true,
2635
+ strict = false,
2636
+ exceptions = []
2637
+ } = options || {};
2638
+ const lowercaseSet = /* @__PURE__ */ new Set([...LOWERCASE_WORDS, ...exceptions]);
2639
+ const acronymSet = new Set(ACRONYMS);
2640
+ const normalized = normalizeSpaces(text);
2641
+ const words = normalized.split(" ");
2642
+ return words.map((word, index) => {
2643
+ if (!word) return word;
2644
+ if (word.includes("-")) {
2645
+ return processHyphenatedWord(word, index === 0, {
2646
+ lowercaseSet,
2647
+ acronymSet,
2648
+ preserveAcronyms,
2649
+ strict
2650
+ });
2651
+ }
2652
+ return processWord(word, index === 0, {
2653
+ lowercaseSet,
2654
+ acronymSet,
2655
+ preserveAcronyms,
2656
+ strict
2657
+ });
2658
+ }).join(" ");
2659
+ }
2660
+ function normalizeSpaces(text) {
2661
+ return text.trim().replace(/\s+/g, " ");
2662
+ }
2663
+ function processWord(word, isFirstWord, context) {
2664
+ const { lowercaseSet, acronymSet, preserveAcronyms, strict } = context;
2665
+ const lowerWord = word.toLowerCase();
2666
+ const upperWord = word.toUpperCase();
2667
+ if (preserveAcronyms && acronymSet.has(upperWord)) {
2668
+ return upperWord;
2669
+ }
2670
+ if (!isFirstWord && lowercaseSet.has(lowerWord)) {
2671
+ return lowerWord;
2672
+ }
2673
+ if (strict) {
2674
+ return capitalizeFirstLetter(lowerWord);
2675
+ }
2676
+ return capitalizeFirstLetter(word.toLowerCase());
2677
+ }
2678
+ function processHyphenatedWord(word, isFirstWord, context) {
2679
+ return word.split("-").map(
2680
+ (part, index) => processWord(part, isFirstWord && index === 0, context)
2681
+ ).join("-");
2682
+ }
2683
+ function capitalizeFirstLetter(word) {
2684
+ if (!word) return word;
2685
+ return word.charAt(0).toUpperCase() + word.slice(1);
2686
+ }
2687
+ function toSentenceCase(text) {
2688
+ if (!text) return text;
2689
+ const normalized = text.trim().replace(/\s+/g, " ");
2690
+ let result = "";
2691
+ let shouldCapitalize = true;
2692
+ for (let i = 0; i < normalized.length; i++) {
2693
+ const char = normalized[i];
2694
+ if (shouldCapitalize && /[a-zA-ZÀ-ÿ]/.test(char)) {
2695
+ result += char.toUpperCase();
2696
+ shouldCapitalize = false;
2697
+ } else {
2698
+ result += char.toLowerCase();
2699
+ }
2700
+ if (isSentenceEnd(char)) {
2701
+ shouldCapitalize = true;
2702
+ }
2703
+ if (char === "." && i + 1 < normalized.length) {
2704
+ const nextChar = normalized[i + 1];
2705
+ if (nextChar !== " " && !/[.!?]/.test(nextChar)) {
2706
+ shouldCapitalize = false;
2707
+ }
2708
+ }
2709
+ }
2710
+ return result;
2711
+ }
2712
+ function isSentenceEnd(char) {
2713
+ return char === "." || char === "!" || char === "?";
2714
+ }
2715
+
2716
+ // src/text/slug.ts
2717
+ function slugify(text, options) {
2718
+ if (!text) return "";
2719
+ const {
2720
+ separator = "-",
2721
+ lowercase = true,
2722
+ replacements = {},
2723
+ trim = true
2724
+ } = options || {};
2725
+ let result = text;
2726
+ for (const [search, replace] of Object.entries(replacements)) {
2727
+ result = result.replace(new RegExp(escapeRegex(search), "g"), replace);
2728
+ }
2729
+ result = result.replace(/&/g, " dan ");
2730
+ result = result.replace(/\//g, " atau ");
2731
+ if (lowercase) {
2732
+ result = result.toLowerCase();
2733
+ }
2734
+ result = result.replace(/[.'@éèêëàâäôöûüùïîçñ™®©]/g, "");
2735
+ result = result.replace(/[^\w\s-]+/g, separator);
2736
+ result = result.replace(/\s+/g, separator);
2737
+ if (separator !== "-") {
2738
+ result = result.replace(/-/g, separator);
2739
+ }
2740
+ if (trim) {
2741
+ const separatorRegex = new RegExp(`\\${separator}+`, "g");
2742
+ result = result.replace(separatorRegex, separator);
2743
+ const trimRegex = new RegExp(`^\\${separator}+|\\${separator}+$`, "g");
2744
+ result = result.replace(trimRegex, "");
2745
+ }
2746
+ return result;
2747
+ }
2748
+ function escapeRegex(str) {
2749
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2750
+ }
2751
+
2752
+ // src/text/sanitize.ts
2753
+ function normalizeWhitespace(text) {
2754
+ if (!text) return text;
2755
+ return text.trim().replace(/\s+/g, " ");
2756
+ }
2757
+ function sanitize(text, options) {
2758
+ if (!text) return text;
2759
+ const {
2760
+ removeNewlines = false,
2761
+ removeExtraSpaces = true,
2762
+ removePunctuation = false,
2763
+ allowedChars,
2764
+ trim = true
2765
+ } = options || {};
2766
+ let result = text;
2767
+ if (removeNewlines) {
2768
+ result = result.replace(/[\n\r]/g, " ");
2769
+ }
2770
+ if (removePunctuation) {
2771
+ result = result.replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/g, "");
2772
+ }
2773
+ if (allowedChars) {
2774
+ const allowedRegex = new RegExp(`[^${allowedChars}]`, "g");
2775
+ result = result.replace(allowedRegex, "");
2776
+ }
2777
+ if (removeExtraSpaces) {
2778
+ if (trim) {
2779
+ if (removeNewlines) {
2780
+ result = result.replace(/\s+/g, " ");
2781
+ } else {
2782
+ result = result.replace(/[ \t]+/g, " ");
2783
+ }
2784
+ } else {
2785
+ const leadingMatch = result.match(/^([ \t]*)/);
2786
+ const trailingMatch = result.match(/([ \t]*)$/);
2787
+ const leading = leadingMatch ? leadingMatch[1] : "";
2788
+ const trailing = trailingMatch ? trailingMatch[1] : "";
2789
+ const middle = result.slice(
2790
+ leading.length,
2791
+ result.length - trailing.length
2792
+ );
2793
+ const normalizedMiddle = removeNewlines ? middle.replace(/\s+/g, " ") : middle.replace(/[ \t]+/g, " ");
2794
+ result = leading + normalizedMiddle + trailing;
2795
+ }
2796
+ }
2797
+ if (trim) {
2798
+ result = result.trim();
2799
+ }
2800
+ return result;
2801
+ }
2802
+ function removeAccents(text) {
2803
+ if (!text) return text;
2804
+ const specialChars = {
2805
+ \u00D8: "O",
2806
+ \u00F8: "o",
2807
+ \u00C6: "AE",
2808
+ \u00E6: "ae",
2809
+ \u00C5: "A",
2810
+ \u00E5: "a",
2811
+ \u0110: "D",
2812
+ \u0111: "d",
2813
+ \u0141: "L",
2814
+ \u0142: "l",
2815
+ \u00DE: "TH",
2816
+ \u00FE: "th",
2817
+ \u00DF: "ss"
2818
+ };
2819
+ let result = text;
2820
+ for (const [accented, plain] of Object.entries(specialChars)) {
2821
+ result = result.replace(new RegExp(accented, "g"), plain);
2822
+ }
2823
+ return result.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
2824
+ }
2825
+
2826
+ // src/text/abbreviation.ts
2827
+ function expandAbbreviation(text, options) {
2828
+ if (!text) return text;
2829
+ const { mode = "all", customMap = {}, preserveCase = false } = options || {};
2830
+ const abbreviationsMap = {
2831
+ ...getAbbreviationsByMode(mode),
2832
+ ...customMap
2833
+ };
2834
+ let result = text;
2835
+ const sortedAbbrevs = Object.keys(abbreviationsMap).sort(
2836
+ (a, b) => b.length - a.length
2837
+ );
2838
+ for (const abbrev of sortedAbbrevs) {
2839
+ const expansion = abbreviationsMap[abbrev];
2840
+ const startBoundary = /^\w/.test(abbrev) ? "\\b" : "";
2841
+ const endBoundary = /\w$/.test(abbrev) ? "\\b" : "";
2842
+ const regex = new RegExp(
2843
+ `${startBoundary}${escapeRegex2(abbrev)}${endBoundary}`,
2844
+ "gi"
2845
+ );
2846
+ result = result.replace(regex, (match) => {
2847
+ if (!preserveCase) {
2848
+ return expansion;
2849
+ }
2850
+ return matchCase(match, expansion);
2851
+ });
2852
+ }
2853
+ return result;
2854
+ }
2855
+ function getAbbreviationsByMode(mode) {
2856
+ if (mode === "all") {
2857
+ return ABBREVIATIONS;
2858
+ }
2859
+ const filtered = {};
2860
+ const addressAbbrevs = [
2861
+ "Jl.",
2862
+ "Gg.",
2863
+ "No.",
2864
+ "Kp.",
2865
+ "Ds.",
2866
+ "Kel.",
2867
+ "Kec.",
2868
+ "Kab.",
2869
+ "Kota",
2870
+ "Prov.",
2871
+ "Prop.",
2872
+ "Rt.",
2873
+ "Rw.",
2874
+ "Blok",
2875
+ "Komp.",
2876
+ "Perumahan",
2877
+ "Perum."
2878
+ ];
2879
+ const titleAbbrevs = [
2880
+ "Dr.",
2881
+ "Ir.",
2882
+ "Prof.",
2883
+ "Drs.",
2884
+ "Dra.",
2885
+ "S.Pd.",
2886
+ "S.H.",
2887
+ "S.E.",
2888
+ "S.T.",
2889
+ "S.Kom.",
2890
+ "S.Si.",
2891
+ "S.Sos.",
2892
+ "S.I.Kom.",
2893
+ "S.S.",
2894
+ "S.Psi.",
2895
+ "S.Farm.",
2896
+ "S.Ked.",
2897
+ "M.Sc.",
2898
+ "M.M.",
2899
+ "M.Pd.",
2900
+ "M.T.",
2901
+ "M.Kom.",
2902
+ "M.Si.",
2903
+ "M.H.",
2904
+ "M.A.",
2905
+ "MBA"
2906
+ ];
2907
+ const orgAbbrevs = [
2908
+ "PT.",
2909
+ "CV.",
2910
+ "UD.",
2911
+ "PD.",
2912
+ "Tbk.",
2913
+ "Koperasi",
2914
+ "Yayasan"
2915
+ ];
2916
+ for (const [abbrev, expansion] of Object.entries(ABBREVIATIONS)) {
2917
+ if (mode === "address" && addressAbbrevs.includes(abbrev)) {
2918
+ filtered[abbrev] = expansion;
2919
+ } else if (mode === "title" && titleAbbrevs.includes(abbrev)) {
2920
+ filtered[abbrev] = expansion;
2921
+ } else if (mode === "org" && orgAbbrevs.includes(abbrev)) {
2922
+ filtered[abbrev] = expansion;
2923
+ }
2924
+ }
2925
+ return filtered;
2926
+ }
2927
+ function escapeRegex2(str) {
2928
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2929
+ }
2930
+ function matchCase(original, replacement) {
2931
+ if (original === original.toUpperCase()) {
2932
+ return replacement.toUpperCase();
2933
+ }
2934
+ if (original === original.toLowerCase()) {
2935
+ return replacement.toLowerCase();
2936
+ }
2937
+ if (original.charAt(0) === original.charAt(0).toUpperCase()) {
2938
+ return replacement.charAt(0).toUpperCase() + replacement.slice(1).toLowerCase();
2939
+ }
2940
+ return replacement;
2941
+ }
2942
+ function contractAbbreviation(text, options) {
2943
+ if (!text) return text;
2944
+ const { mode = "all" } = options || {};
2945
+ const abbreviationsMap = getAbbreviationsByMode(mode);
2946
+ const reverseMap = {};
2947
+ for (const [abbrev, expansion] of Object.entries(abbreviationsMap)) {
2948
+ reverseMap[expansion] = abbrev;
2949
+ }
2950
+ let result = text;
2951
+ const sortedExpansions = Object.keys(reverseMap).sort(
2952
+ (a, b) => b.length - a.length
2953
+ );
2954
+ for (const expansion of sortedExpansions) {
2955
+ const abbrev = reverseMap[expansion];
2956
+ const regex = new RegExp(`\\b${escapeRegex2(expansion)}\\b`, "gi");
2957
+ result = result.replace(regex, abbrev);
2958
+ }
2959
+ return result;
2960
+ }
2961
+
2962
+ // src/text/filter.ts
2963
+ function profanityFilter(text, mask = "*") {
2964
+ let filtered = text;
2965
+ PROFANITY.forEach((word) => {
2966
+ const regex = new RegExp(`\\b${word}\\b`, "gi");
2967
+ filtered = filtered.replace(regex, mask.repeat(word.length));
2968
+ });
2969
+ return filtered;
2970
+ }
2971
+ function removeStopwords(text) {
2972
+ const words = text.split(/\s+/);
2973
+ const filtered = words.filter(
2974
+ (word) => !STOPWORDS.includes(word.toLowerCase())
2975
+ );
2976
+ return filtered.join(" ");
2977
+ }
2978
+
2979
+ // src/text/normalization.ts
2980
+ var INFORMAL_MAP = {
2981
+ gw: "saya",
2982
+ gua: "saya",
2983
+ lu: "kamu",
2984
+ lo: "kamu",
2985
+ elo: "kamu",
2986
+ lagi: "sedang",
2987
+ gue: "saya",
2988
+ gwe: "saya",
2989
+ gak: "tidak",
2990
+ ga: "tidak",
2991
+ nggak: "tidak",
2992
+ kalo: "kalau",
2993
+ karna: "karena",
2994
+ tapi: "tetapi",
2995
+ udah: "sudah",
2996
+ dah: "sudah",
2997
+ aja: "saja",
2998
+ banget: "sekali",
2999
+ emang: "memang",
3000
+ pake: "pakai",
3001
+ bikin: "membuat",
3002
+ kasih: "memberi",
3003
+ dapet: "dapat",
3004
+ liat: "lihat",
3005
+ ngasih: "memberi",
3006
+ nyari: "mencari",
3007
+ nanya: "bertanya",
3008
+ bilang: "berkata"
3009
+ };
3010
+ function toFormal(text) {
3011
+ const words = text.split(/\s+/);
3012
+ const formalized = words.map((word) => {
3013
+ const lower = word.toLowerCase().replace(/[^\w]/g, "");
3014
+ const formal = INFORMAL_MAP[lower];
3015
+ if (formal) {
3016
+ if (word[0] === word[0].toUpperCase()) {
3017
+ return formal.charAt(0).toUpperCase() + formal.slice(1);
3018
+ }
3019
+ return formal;
3020
+ }
3021
+ return word;
3022
+ });
3023
+ return formalized.join(" ");
3024
+ }
3025
+ function isAlay(text) {
3026
+ if (!text) return false;
3027
+ const alternatingCaps = /([a-z][A-Z][a-z]|[A-Z][a-z][A-Z])/.test(text);
3028
+ const numberSub = /\b\w*[0431572]\w*\b/.test(text);
3029
+ const qSub = /q/i.test(text) && !/u/i.test(text);
3030
+ const excessiveChars = /(.)\1{2,}/.test(text);
3031
+ return alternatingCaps || numberSub || qSub || excessiveChars;
3032
+ }
3033
+
3034
+ // src/text/extract.ts
3035
+ function truncate(text, maxLength, options) {
3036
+ if (!text || maxLength <= 0) {
3037
+ return "";
3038
+ }
3039
+ const { ellipsis = "...", wordBoundary = true } = options || {};
3040
+ if (text.length <= maxLength) {
3041
+ return text;
3042
+ }
3043
+ const availableLength = maxLength - ellipsis.length;
3044
+ if (availableLength <= 0) {
3045
+ return ellipsis.slice(0, maxLength);
3046
+ }
3047
+ let truncated = text.slice(0, availableLength);
3048
+ if (wordBoundary) {
3049
+ const lastSpaceIndex = truncated.lastIndexOf(" ");
3050
+ if (lastSpaceIndex > 0) {
3051
+ truncated = truncated.slice(0, lastSpaceIndex);
3052
+ }
3053
+ }
3054
+ truncated = truncated.trimEnd();
3055
+ return truncated + ellipsis;
3056
+ }
3057
+ function extractWords(text, options) {
3058
+ if (!text || !text.trim()) {
3059
+ return [];
3060
+ }
3061
+ const {
3062
+ minLength = 0,
3063
+ includeHyphenated = true,
3064
+ lowercase = false
3065
+ } = options || {};
3066
+ let cleaned = text;
3067
+ if (includeHyphenated) {
3068
+ cleaned = text.replace(/[^\w\s-]/g, " ");
3069
+ } else {
3070
+ cleaned = text.replace(/[^\w\s]/g, " ");
3071
+ }
3072
+ const words = cleaned.split(/\s+/).map((word) => word.trim()).filter((word) => word.length > 0).filter((word) => !/^-+$/.test(word));
3073
+ let result = words;
3074
+ if (minLength > 0) {
3075
+ result = result.filter((word) => word.length >= minLength);
3076
+ }
3077
+ if (lowercase) {
3078
+ result = result.map((word) => word.toLowerCase());
3079
+ }
3080
+ return result;
3081
+ }
3082
+
3083
+ // src/text/compare.ts
3084
+ function compareStrings(str1, str2, options) {
3085
+ if (str1 === str2) {
3086
+ return true;
3087
+ }
3088
+ const s1 = str1 || "";
3089
+ const s2 = str2 || "";
3090
+ const {
3091
+ caseSensitive = false,
3092
+ ignoreWhitespace = false,
3093
+ ignoreAccents = false
3094
+ } = options || {};
3095
+ let normalized1 = s1;
3096
+ let normalized2 = s2;
3097
+ if (ignoreWhitespace) {
3098
+ normalized1 = normalizeWhitespace(normalized1);
3099
+ normalized2 = normalizeWhitespace(normalized2);
3100
+ }
3101
+ if (ignoreAccents) {
3102
+ normalized1 = removeAccents(normalized1);
3103
+ normalized2 = removeAccents(normalized2);
3104
+ }
3105
+ if (!caseSensitive) {
3106
+ normalized1 = normalized1.toLowerCase();
3107
+ normalized2 = normalized2.toLowerCase();
3108
+ }
3109
+ return normalized1 === normalized2;
3110
+ }
3111
+ function similarity(str1, str2) {
3112
+ if (str1 === str2) return 1;
3113
+ if (str1.length === 0) return str2.length === 0 ? 1 : 0;
3114
+ if (str2.length === 0) return 0;
3115
+ const len1 = str1.length;
3116
+ const len2 = str2.length;
3117
+ let prevRow = Array(len2 + 1).fill(0);
3118
+ let currentRow = Array(len2 + 1).fill(0);
3119
+ for (let j = 0; j <= len2; j++) {
3120
+ prevRow[j] = j;
3121
+ }
3122
+ for (let i = 1; i <= len1; i++) {
3123
+ currentRow[0] = i;
3124
+ for (let j = 1; j <= len2; j++) {
3125
+ const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
3126
+ currentRow[j] = Math.min(
3127
+ currentRow[j - 1] + 1,
3128
+ // Insertion
3129
+ prevRow[j] + 1,
3130
+ // Deletion
3131
+ prevRow[j - 1] + cost
3132
+ // Substitution
3133
+ );
3134
+ }
3135
+ [prevRow, currentRow] = [currentRow, prevRow];
3136
+ }
3137
+ const distance = prevRow[len2];
3138
+ const maxLength = Math.max(len1, len2);
3139
+ return 1 - distance / maxLength;
3140
+ }
3141
+
3142
+ exports.addRupiahSymbol = addRupiahSymbol;
3143
+ exports.calculateTax = calculateTax;
3144
+ exports.capitalize = capitalize2;
1153
3145
  exports.cleanPhoneNumber = cleanPhoneNumber;
3146
+ exports.compareStrings = compareStrings;
3147
+ exports.contractAbbreviation = contractAbbreviation;
3148
+ exports.expandAbbreviation = expandAbbreviation;
3149
+ exports.extractWords = extractWords;
3150
+ exports.formatAccounting = formatAccounting;
3151
+ exports.formatBirthDate = formatBirthDate;
1154
3152
  exports.formatCompact = formatCompact;
1155
3153
  exports.formatNIK = formatNIK;
3154
+ exports.formatNPWP = formatNPWP;
1156
3155
  exports.formatPhoneNumber = formatPhoneNumber;
3156
+ exports.formatPlate = formatPlate;
1157
3157
  exports.formatRupiah = formatRupiah;
3158
+ exports.generateSmsLink = generateSmsLink;
3159
+ exports.generateTelLink = generateTelLink;
3160
+ exports.generateWALink = generateWALink;
3161
+ exports.getAge = getAge;
1158
3162
  exports.getOperator = getOperator;
3163
+ exports.getRegionFromPlate = getRegionFromPlate;
3164
+ exports.isAlay = isAlay;
1159
3165
  exports.isLandlineNumber = isLandlineNumber;
1160
3166
  exports.isMobileNumber = isMobileNumber;
3167
+ exports.isProvider = isProvider;
3168
+ exports.isValidForBirthDate = isValidForBirthDate;
3169
+ exports.isValidForGender = isValidForGender;
1161
3170
  exports.maskNIK = maskNIK;
3171
+ exports.maskNPWP = maskNPWP;
1162
3172
  exports.maskPhoneNumber = maskPhoneNumber;
3173
+ exports.normalizeWhitespace = normalizeWhitespace;
1163
3174
  exports.parseNIK = parseNIK;
3175
+ exports.parseNPWP = parseNPWP;
1164
3176
  exports.parsePhoneNumber = parsePhoneNumber;
1165
3177
  exports.parseRupiah = parseRupiah;
3178
+ exports.profanityFilter = profanityFilter;
3179
+ exports.removeAccents = removeAccents;
3180
+ exports.removeStopwords = removeStopwords;
3181
+ exports.roundToClean = roundToClean;
3182
+ exports.sanitize = sanitize;
3183
+ exports.similarity = similarity;
3184
+ exports.slugify = slugify;
1166
3185
  exports.toE164 = toE164;
3186
+ exports.toFormal = toFormal;
1167
3187
  exports.toInternational = toInternational;
1168
3188
  exports.toNational = toNational;
3189
+ exports.toSentenceCase = toSentenceCase;
3190
+ exports.toTitleCase = toTitleCase;
1169
3191
  exports.toWords = toWords;
3192
+ exports.truncate = truncate;
1170
3193
  exports.validateNIK = validateNIK;
3194
+ exports.validateNPWP = validateNPWP;
1171
3195
  exports.validatePhoneNumber = validatePhoneNumber;
3196
+ exports.validatePlate = validatePlate;
1172
3197
  //# sourceMappingURL=index.cjs.map
1173
3198
  //# sourceMappingURL=index.cjs.map