@indodev/toolkit 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/{compare-B1MKSOWV.d.cts → compare-CZadJMGl.d.cts} +54 -1
  2. package/dist/{compare-B1MKSOWV.d.ts → compare-CZadJMGl.d.ts} +54 -1
  3. package/dist/currency/index.cjs +23 -0
  4. package/dist/currency/index.cjs.map +1 -1
  5. package/dist/currency/index.d.cts +367 -3
  6. package/dist/currency/index.d.ts +367 -3
  7. package/dist/currency/index.js +21 -1
  8. package/dist/currency/index.js.map +1 -1
  9. package/dist/index.cjs +1188 -0
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +7 -4
  12. package/dist/index.d.ts +7 -4
  13. package/dist/index.js +1165 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/nik/index.cjs +44 -0
  16. package/dist/nik/index.cjs.map +1 -1
  17. package/dist/nik/index.d.cts +44 -1
  18. package/dist/nik/index.d.ts +44 -1
  19. package/dist/nik/index.js +41 -1
  20. package/dist/nik/index.js.map +1 -1
  21. package/dist/npwp/index.cjs +95 -0
  22. package/dist/npwp/index.cjs.map +1 -0
  23. package/dist/npwp/index.d.cts +76 -0
  24. package/dist/npwp/index.d.ts +76 -0
  25. package/dist/npwp/index.js +90 -0
  26. package/dist/npwp/index.js.map +1 -0
  27. package/dist/phone/index.cjs +42 -0
  28. package/dist/phone/index.cjs.map +1 -1
  29. package/dist/phone/index.d.cts +57 -1
  30. package/dist/phone/index.d.ts +57 -1
  31. package/dist/phone/index.js +39 -1
  32. package/dist/phone/index.js.map +1 -1
  33. package/dist/plate/index.cjs +99 -0
  34. package/dist/plate/index.cjs.map +1 -0
  35. package/dist/plate/index.d.cts +8 -0
  36. package/dist/plate/index.d.ts +8 -0
  37. package/dist/plate/index.js +94 -0
  38. package/dist/plate/index.js.map +1 -0
  39. package/dist/text/index.cjs +811 -0
  40. package/dist/text/index.cjs.map +1 -1
  41. package/dist/text/index.d.cts +1 -1
  42. package/dist/text/index.d.ts +1 -1
  43. package/dist/text/index.js +808 -1
  44. package/dist/text/index.js.map +1 -1
  45. package/dist/types-i5e6R0AS.d.cts +39 -0
  46. package/dist/types-i5e6R0AS.d.ts +39 -0
  47. package/dist/utils-DDVlOusI.d.cts +30 -0
  48. package/dist/utils-DDVlOusI.d.ts +30 -0
  49. package/dist/vin/index.cjs +84 -0
  50. package/dist/vin/index.cjs.map +1 -0
  51. package/dist/vin/index.d.cts +39 -0
  52. package/dist/vin/index.d.ts +39 -0
  53. package/dist/vin/index.js +74 -0
  54. package/dist/vin/index.js.map +1 -0
  55. package/package.json +48 -18
  56. package/LICENCE +0 -21
  57. package/dist/words-Dy8iYkbv.d.cts +0 -333
  58. package/dist/words-Dy8iYkbv.d.ts +0 -333
package/dist/index.js CHANGED
@@ -208,6 +208,46 @@ function maskNIK(nik, options = {}) {
208
208
  return startPart + char.repeat(maskLength) + endPart;
209
209
  }
210
210
 
211
+ // src/nik/utils.ts
212
+ function getAge(nik, referenceDate = /* @__PURE__ */ new Date()) {
213
+ const info = parseNIK(nik);
214
+ if (!info || !info.birthDate) {
215
+ return null;
216
+ }
217
+ const birthDate = info.birthDate;
218
+ let age = referenceDate.getFullYear() - birthDate.getFullYear();
219
+ const m = referenceDate.getMonth() - birthDate.getMonth();
220
+ if (m < 0 || m === 0 && referenceDate.getDate() < birthDate.getDate()) {
221
+ age--;
222
+ }
223
+ return age;
224
+ }
225
+ function formatBirthDate(nik, options = {
226
+ day: "numeric",
227
+ month: "long",
228
+ year: "numeric"
229
+ }, locale = "id-ID") {
230
+ const info = parseNIK(nik);
231
+ if (!info || !info.birthDate) {
232
+ return null;
233
+ }
234
+ return new Intl.DateTimeFormat(locale, options).format(info.birthDate);
235
+ }
236
+ function isValidForGender(nik, gender) {
237
+ const info = parseNIK(nik);
238
+ if (!info) {
239
+ return false;
240
+ }
241
+ return info.gender === gender;
242
+ }
243
+ function isValidForBirthDate(nik, birthDate) {
244
+ const info = parseNIK(nik);
245
+ if (!info || !info.birthDate) {
246
+ return false;
247
+ }
248
+ return info.birthDate.getFullYear() === birthDate.getFullYear() && info.birthDate.getMonth() === birthDate.getMonth() && info.birthDate.getDate() === birthDate.getDate();
249
+ }
250
+
211
251
  // src/phone/constants.ts
212
252
  var OPERATOR_PREFIXES = {
213
253
  // Telkomsel (Halo, Simpati, by.U)
@@ -850,6 +890,37 @@ function maskPhoneNumber(phone, options = {}) {
850
890
  return masked;
851
891
  }
852
892
 
893
+ // src/phone/links.ts
894
+ function generateWALink(phone, message) {
895
+ if (!validatePhoneNumber(phone)) {
896
+ return "";
897
+ }
898
+ const e164 = toE164(phone);
899
+ let link = `https://wa.me/${e164}`;
900
+ if (message) {
901
+ link += `?text=${encodeURIComponent(message)}`;
902
+ }
903
+ return link;
904
+ }
905
+ function generateSmsLink(phone, body) {
906
+ if (!validatePhoneNumber(phone)) {
907
+ return "";
908
+ }
909
+ const e164 = toE164(phone);
910
+ let link = `sms:+${e164}`;
911
+ if (body) {
912
+ link += `?body=${encodeURIComponent(body)}`;
913
+ }
914
+ return link;
915
+ }
916
+ function generateTelLink(phone) {
917
+ if (!validatePhoneNumber(phone)) {
918
+ return "";
919
+ }
920
+ const e164 = toE164(phone);
921
+ return `tel:+${e164}`;
922
+ }
923
+
853
924
  // src/phone/parse.ts
854
925
  function parsePhoneNumber(phone) {
855
926
  if (!validatePhoneNumber(phone)) {
@@ -898,6 +969,13 @@ function getOperator(phone) {
898
969
  const prefix = normalized.substring(0, 4);
899
970
  return OPERATOR_PREFIXES[prefix] || null;
900
971
  }
972
+ function isProvider(phone, providerName) {
973
+ const operator = getOperator(phone);
974
+ if (!operator) {
975
+ return false;
976
+ }
977
+ return operator.toLowerCase() === providerName.toLowerCase();
978
+ }
901
979
  function getRegion(phone) {
902
980
  if (!phone.startsWith("0")) {
903
981
  return null;
@@ -923,6 +1001,254 @@ function normalizeToNational2(phone) {
923
1001
  return "";
924
1002
  }
925
1003
 
1004
+ // src/npwp/validate.ts
1005
+ function validateNPWP(npwp) {
1006
+ if (!npwp || typeof npwp !== "string") {
1007
+ return false;
1008
+ }
1009
+ const cleaned = npwp.replace(/[^\d]/g, "");
1010
+ if (cleaned.length !== 15 && cleaned.length !== 16) {
1011
+ return false;
1012
+ }
1013
+ if (!/^\d+$/.test(cleaned)) {
1014
+ return false;
1015
+ }
1016
+ return true;
1017
+ }
1018
+
1019
+ // src/npwp/format.ts
1020
+ function formatNPWP(npwp) {
1021
+ if (!validateNPWP(npwp)) {
1022
+ return npwp;
1023
+ }
1024
+ const cleaned = npwp.replace(/[^\d]/g, "");
1025
+ if (cleaned.length === 15) {
1026
+ return `${cleaned.substring(0, 2)}.${cleaned.substring(
1027
+ 2,
1028
+ 5
1029
+ )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(
1030
+ 9,
1031
+ 12
1032
+ )}.${cleaned.substring(12, 15)}`;
1033
+ }
1034
+ return cleaned;
1035
+ }
1036
+ function parseNPWP(npwp) {
1037
+ if (!validateNPWP(npwp)) {
1038
+ return null;
1039
+ }
1040
+ const cleaned = npwp.replace(/[^\d]/g, "");
1041
+ const isNikBased = cleaned.length === 16;
1042
+ if (isNikBased) {
1043
+ return {
1044
+ npwp: cleaned,
1045
+ type: cleaned.substring(0, 2),
1046
+ serial: cleaned.substring(2, 8),
1047
+ checksum: cleaned.substring(8, 9),
1048
+ taxOfficeCode: cleaned.substring(9, 12),
1049
+ branchCode: cleaned.substring(12, 16),
1050
+ isNikBased: true
1051
+ };
1052
+ }
1053
+ return {
1054
+ npwp: cleaned,
1055
+ type: cleaned.substring(0, 2),
1056
+ serial: cleaned.substring(2, 8),
1057
+ checksum: cleaned.substring(8, 9),
1058
+ taxOfficeCode: cleaned.substring(9, 12),
1059
+ branchCode: cleaned.substring(12, 15),
1060
+ isNikBased: false
1061
+ };
1062
+ }
1063
+ function maskNPWP(npwp, options) {
1064
+ if (!npwp) return "";
1065
+ const { visibleStart = 2, visibleEnd = 3, maskChar = "*" } = options || {};
1066
+ if (npwp.includes(".") || npwp.includes("-")) {
1067
+ let digitCount = 0;
1068
+ const digitsOnly = npwp.replace(/[^\d]/g, "");
1069
+ const totalDigits = digitsOnly.length;
1070
+ return npwp.split("").map((char) => {
1071
+ if (/\d/.test(char)) {
1072
+ digitCount++;
1073
+ if (digitCount <= visibleStart || digitCount > totalDigits - visibleEnd) {
1074
+ return char;
1075
+ }
1076
+ return maskChar;
1077
+ }
1078
+ return char;
1079
+ }).join("");
1080
+ }
1081
+ const cleaned = npwp.replace(/[^\d]/g, "");
1082
+ if (cleaned.length < visibleStart + visibleEnd) {
1083
+ return cleaned.replace(/./g, maskChar);
1084
+ }
1085
+ const start = cleaned.substring(0, visibleStart);
1086
+ const end = cleaned.substring(cleaned.length - visibleEnd);
1087
+ const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);
1088
+ return `${start}${middle}${end}`;
1089
+ }
1090
+
1091
+ // src/plate/regions.ts
1092
+ var PLATE_REGIONS = {
1093
+ A: "Banten",
1094
+ B: "Jakarta, Depok, Tangerang, Bekasi",
1095
+ D: "Bandung, Cimahi",
1096
+ E: "Cirebon, Indramayu, Majalengka, Kuningan",
1097
+ F: "Bogor, Cianjur, Sukabumi",
1098
+ G: "Pekalongan, Pemalang, Batang, Tegal, Brebes",
1099
+ H: "Semarang, Salatiga, Kendal, Demak",
1100
+ K: "Pati, Kudus, Jepara, Rembang, Blora, Grobogan",
1101
+ L: "Surabaya",
1102
+ M: "Madura",
1103
+ N: "Malang, Probolinggo, Pasuruan, Lumajang, Batu",
1104
+ P: "Besuki, Bondowoso, Situbondo, Jember, Banyuwangi",
1105
+ R: "Banyumas, Cilacap, Purbalinggo, Banjarnegara",
1106
+ S: "Bojonegoro, Tuban, Lamongan, Jombang, Mojokerto",
1107
+ T: "Purwakarta, Subang, Karawang",
1108
+ AA: "Kedu, Magelang, Purworejo, Kebumen, Temanggung, Wonosobo",
1109
+ AB: "Yogyakarta",
1110
+ AD: "Surakarta, Boyolali, Sukoharjo, Karanganyar, Wonogiri, Sragen, Klaten",
1111
+ AE: "Madiun, Ngawi, Magetan, Ponorogo, Pacitan",
1112
+ AG: "Kediri, Blitar, Tulungagung, Nganjuk, Trenggalek",
1113
+ BA: "Sumatera Barat",
1114
+ BB: "Sumatera Utara (Pantai Barat)",
1115
+ BD: "Bengkulu",
1116
+ BE: "Lampung",
1117
+ BG: "Sumatera Selatan",
1118
+ BH: "Jambi",
1119
+ BK: "Sumatera Utara (Pantai Timur)",
1120
+ BL: "Aceh",
1121
+ BM: "Riau",
1122
+ BN: "Kepulauan Bangka Belitung",
1123
+ BP: "Kepulauan Riau",
1124
+ DA: "Kalimantan Selatan",
1125
+ DB: "Sulawesi Utara (Daratan)",
1126
+ DC: "Sulawesi Barat",
1127
+ DD: "Sulawesi Selatan (Selatan)",
1128
+ DE: "Maluku",
1129
+ DF: "Timor Timur (Historical)",
1130
+ DG: "Maluku Utara",
1131
+ DH: "NTT (Timor)",
1132
+ DK: "Bali",
1133
+ DL: "Sulawesi Utara (Kepulauan)",
1134
+ DM: "Gorontalo",
1135
+ DN: "Sulawesi Tengah",
1136
+ DP: "Sulawesi Selatan (Utara)",
1137
+ DR: "NTB (Lombok)",
1138
+ DS: "Papua",
1139
+ DT: "Sulawesi Tenggara",
1140
+ EA: "NTB (Sumbawa)",
1141
+ EB: "NTT (Flores)",
1142
+ ED: "NTT (Sumba)",
1143
+ KB: "Kalimantan Barat",
1144
+ KH: "Kalimantan Tengah",
1145
+ KT: "Kalimantan Timur",
1146
+ KU: "Kalimantan Utara",
1147
+ PA: "Papua",
1148
+ PB: "Papua Barat"
1149
+ };
1150
+
1151
+ // src/plate/utils.ts
1152
+ function validatePlate(plate) {
1153
+ if (!plate || typeof plate !== "string") {
1154
+ return false;
1155
+ }
1156
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1157
+ const regex = /^[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$/;
1158
+ return regex.test(cleaned);
1159
+ }
1160
+ function getRegionFromPlate(plate) {
1161
+ if (!plate || typeof plate !== "string") {
1162
+ return null;
1163
+ }
1164
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1165
+ const match = cleaned.match(/^([A-Z]{1,2})/);
1166
+ if (!match) {
1167
+ return null;
1168
+ }
1169
+ const prefix = match[1];
1170
+ return PLATE_REGIONS[prefix] || null;
1171
+ }
1172
+ function formatPlate(plate) {
1173
+ if (!plate) return "";
1174
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1175
+ const match = cleaned.match(/^([A-Z]{1,2})(\d{1,4})([A-Z]{1,3})$/);
1176
+ if (!match) {
1177
+ return cleaned;
1178
+ }
1179
+ return `${match[1]} ${match[2]} ${match[3]}`;
1180
+ }
1181
+
1182
+ // src/vin/constants.ts
1183
+ var VIN_LENGTH = 17;
1184
+ var VIN_CHECK_DIGIT_INDEX = 8;
1185
+ var VIN_MODULUS = 11;
1186
+ var VIN_CHECK_DIGIT_X = "X";
1187
+ var VIN_WEIGHTS = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];
1188
+ var VIN_CHAR_VALUES = {
1189
+ "0": 0,
1190
+ "1": 1,
1191
+ "2": 2,
1192
+ "3": 3,
1193
+ "4": 4,
1194
+ "5": 5,
1195
+ "6": 6,
1196
+ "7": 7,
1197
+ "8": 8,
1198
+ "9": 9,
1199
+ "A": 1,
1200
+ "B": 2,
1201
+ "C": 3,
1202
+ "D": 4,
1203
+ "E": 5,
1204
+ "F": 6,
1205
+ "G": 7,
1206
+ "H": 8,
1207
+ "J": 1,
1208
+ "K": 2,
1209
+ "L": 3,
1210
+ "M": 4,
1211
+ "N": 5,
1212
+ "P": 7,
1213
+ "R": 9,
1214
+ "S": 2,
1215
+ "T": 3,
1216
+ "U": 4,
1217
+ "V": 5,
1218
+ "W": 6,
1219
+ "X": 7,
1220
+ "Y": 8,
1221
+ "Z": 9
1222
+ };
1223
+ var EXCLUDED_VIN_CHARS = ["I", "O", "Q"];
1224
+
1225
+ // src/vin/validate.ts
1226
+ function validateVIN(vin) {
1227
+ if (!vin || vin.length !== VIN_LENGTH) {
1228
+ return false;
1229
+ }
1230
+ const normalizedVIN = vin.toUpperCase();
1231
+ for (const char of EXCLUDED_VIN_CHARS) {
1232
+ if (normalizedVIN.includes(char)) {
1233
+ return false;
1234
+ }
1235
+ }
1236
+ let sum = 0;
1237
+ for (let i = 0; i < VIN_LENGTH; i++) {
1238
+ const char = normalizedVIN[i];
1239
+ const weight = VIN_WEIGHTS[i];
1240
+ const val = VIN_CHAR_VALUES[char];
1241
+ if (val === void 0) {
1242
+ return false;
1243
+ }
1244
+ sum += val * weight;
1245
+ }
1246
+ const checkDigitValue = sum % VIN_MODULUS;
1247
+ const expectedCheckDigit = checkDigitValue === 10 ? VIN_CHECK_DIGIT_X : checkDigitValue.toString();
1248
+ const actualCheckDigit = normalizedVIN[VIN_CHECK_DIGIT_INDEX];
1249
+ return actualCheckDigit === expectedCheckDigit;
1250
+ }
1251
+
926
1252
  // src/currency/format.ts
927
1253
  function formatRupiah(amount, options) {
928
1254
  const {
@@ -1148,6 +1474,37 @@ function capitalize(str) {
1148
1474
  return str.charAt(0).toUpperCase() + str.slice(1);
1149
1475
  }
1150
1476
 
1477
+ // src/currency/utils.ts
1478
+ function roundToClean(amount, unit = "ribu") {
1479
+ const divisors = {
1480
+ ribu: 1e3,
1481
+ "ratus-ribu": 1e5,
1482
+ juta: 1e6
1483
+ };
1484
+ const divisor = divisors[unit];
1485
+ return Math.round(amount / divisor) * divisor;
1486
+ }
1487
+ function formatAccounting(amount, options) {
1488
+ const isNegative = amount < 0;
1489
+ const formatted = formatRupiah(Math.abs(amount), options);
1490
+ if (isNegative) {
1491
+ return `(${formatted})`;
1492
+ }
1493
+ return formatted;
1494
+ }
1495
+ function calculateTax(amount, rate = 0.11) {
1496
+ return amount * rate;
1497
+ }
1498
+ function addRupiahSymbol(amount) {
1499
+ if (typeof amount === "number") {
1500
+ return `Rp ${amount.toLocaleString("id-ID")}`;
1501
+ }
1502
+ if (amount.trim().startsWith("Rp")) {
1503
+ return amount;
1504
+ }
1505
+ return `Rp ${amount.trim()}`;
1506
+ }
1507
+
1151
1508
  // src/text/constants.ts
1152
1509
  var LOWERCASE_WORDS = [
1153
1510
  // Indonesian prepositions (kata depan)
@@ -1598,6 +1955,741 @@ var ABBREVIATIONS = {
1598
1955
  "m3.": "meter kubik",
1599
1956
  "ha.": "hektar"
1600
1957
  };
1958
+ var PROFANITY = [
1959
+ "anjing",
1960
+ "babi",
1961
+ "bangsat",
1962
+ "bajingan",
1963
+ "brengsek",
1964
+ "goblok",
1965
+ "tolol",
1966
+ "idiot",
1967
+ "perek",
1968
+ "jablay",
1969
+ "kontol",
1970
+ "memek",
1971
+ "ngewe",
1972
+ "puki",
1973
+ "jembut",
1974
+ "asu",
1975
+ "itil",
1976
+ "lanjiao",
1977
+ "pantek",
1978
+ "anying",
1979
+ "anjrit"
1980
+ ];
1981
+ var STOPWORDS = [
1982
+ "ada",
1983
+ "adalah",
1984
+ "adanya",
1985
+ "adapun",
1986
+ "agak",
1987
+ "agaknya",
1988
+ "agar",
1989
+ "akan",
1990
+ "akankah",
1991
+ "akhir",
1992
+ "akhiri",
1993
+ "akhirnya",
1994
+ "aku",
1995
+ "akulah",
1996
+ "amat",
1997
+ "amatlah",
1998
+ "anda",
1999
+ "andalah",
2000
+ "antar",
2001
+ "antara",
2002
+ "antaranya",
2003
+ "apa",
2004
+ "apaan",
2005
+ "apabila",
2006
+ "apakah",
2007
+ "apalagi",
2008
+ "apatah",
2009
+ "artinya",
2010
+ "asal",
2011
+ "asalkan",
2012
+ "atas",
2013
+ "atau",
2014
+ "ataukah",
2015
+ "ataupun",
2016
+ "awal",
2017
+ "awalnya",
2018
+ "bagai",
2019
+ "bagaikan",
2020
+ "bagaimana",
2021
+ "bagaimanakah",
2022
+ "bagaimanapun",
2023
+ "bagi",
2024
+ "bagian",
2025
+ "bahkan",
2026
+ "bahwa",
2027
+ "bahwasanya",
2028
+ "baik",
2029
+ "bakal",
2030
+ "bakalan",
2031
+ "balik",
2032
+ "banyak",
2033
+ "bapak",
2034
+ "baru",
2035
+ "bawah",
2036
+ "beberapa",
2037
+ "begini",
2038
+ "beginian",
2039
+ "beginikah",
2040
+ "beginilah",
2041
+ "begitu",
2042
+ "begitukah",
2043
+ "begitulah",
2044
+ "begitupun",
2045
+ "bekerja",
2046
+ "belakang",
2047
+ "belakangan",
2048
+ "belum",
2049
+ "belumlah",
2050
+ "benar",
2051
+ "benarkah",
2052
+ "benarlah",
2053
+ "berada",
2054
+ "berakhir",
2055
+ "berakhirlah",
2056
+ "berakhirnya",
2057
+ "berapa",
2058
+ "berapakah",
2059
+ "berapalah",
2060
+ "berapapun",
2061
+ "berarti",
2062
+ "berawal",
2063
+ "berbagai",
2064
+ "berikut",
2065
+ "berikutnya",
2066
+ "berjumlah",
2067
+ "berkali-kali",
2068
+ "berkata",
2069
+ "berkeinginan",
2070
+ "berkenaan",
2071
+ "berlainan",
2072
+ "berlalu",
2073
+ "berlangsung",
2074
+ "berlebihan",
2075
+ "bermacam",
2076
+ "bermacam-macam",
2077
+ "bermaksud",
2078
+ "bermula",
2079
+ "bersama",
2080
+ "bersama-sama",
2081
+ "bersiap",
2082
+ "bersiap-siap",
2083
+ "bertanya",
2084
+ "bertanya-tanya",
2085
+ "berturut",
2086
+ "berturut-turut",
2087
+ "bertutur",
2088
+ "berujar",
2089
+ "berupa",
2090
+ "besar",
2091
+ "betul",
2092
+ "betulkah",
2093
+ "biasa",
2094
+ "biasanya",
2095
+ "bila",
2096
+ "bilakah",
2097
+ "bisa",
2098
+ "bisakah",
2099
+ "boleh",
2100
+ "bolehkah",
2101
+ "bolehlah",
2102
+ "buat",
2103
+ "bukan",
2104
+ "bukankah",
2105
+ "bukanlah",
2106
+ "bukannya",
2107
+ "bulan",
2108
+ "bung",
2109
+ "cara",
2110
+ "caranya",
2111
+ "cukup",
2112
+ "cukupkah",
2113
+ "cukuplah",
2114
+ "cuma",
2115
+ "dahulu",
2116
+ "dalam",
2117
+ "dan",
2118
+ "dapat",
2119
+ "dari",
2120
+ "daripada",
2121
+ "datang",
2122
+ "dekat",
2123
+ "demi",
2124
+ "demikian",
2125
+ "demikianlah",
2126
+ "dengan",
2127
+ "depan",
2128
+ "di",
2129
+ "dia",
2130
+ "diakhiri",
2131
+ "diakhirinya",
2132
+ "dialah",
2133
+ "diantara",
2134
+ "diantaranya",
2135
+ "diberi",
2136
+ "diberikan",
2137
+ "diberikannya",
2138
+ "dibuat",
2139
+ "dibuatnya",
2140
+ "didapat",
2141
+ "didatangkan",
2142
+ "digunakan",
2143
+ "diibaratkan",
2144
+ "diingat",
2145
+ "diingatkan",
2146
+ "diinginkan",
2147
+ "dijawab",
2148
+ "dijelaskan",
2149
+ "dijelaskannya",
2150
+ "dikarenakan",
2151
+ "dikatakan",
2152
+ "dikatakannya",
2153
+ "dikerjakan",
2154
+ "diketahui",
2155
+ "diketahuinya",
2156
+ "dikira",
2157
+ "dilakukan",
2158
+ "dilalui",
2159
+ "dilihat",
2160
+ "dimaksud",
2161
+ "dimaksudkan",
2162
+ "dimaksudkannya",
2163
+ "dimana",
2164
+ "dimanalah",
2165
+ "dimulai",
2166
+ "dimulailah",
2167
+ "dimulainya",
2168
+ "diminta",
2169
+ "dimintai",
2170
+ "dimisalkan",
2171
+ "dimungkinkan",
2172
+ "dini",
2173
+ "dipastikan",
2174
+ "diperbuat",
2175
+ "diperbuatnya",
2176
+ "dipergunakan",
2177
+ "diperkirakan",
2178
+ "diperlihatkan",
2179
+ "diperlukan",
2180
+ "diperlukannya",
2181
+ "dipersoalkan",
2182
+ "dipertanyakan",
2183
+ "dipunyai",
2184
+ "diri",
2185
+ "dirinya",
2186
+ "disampaikan",
2187
+ "disebut",
2188
+ "disebutkan",
2189
+ "disebutkannya",
2190
+ "disini",
2191
+ "disinilah",
2192
+ "disitulah",
2193
+ "diterangkan",
2194
+ "diterangkannya",
2195
+ "diteruskan",
2196
+ "ditujukan",
2197
+ "ditunjuk",
2198
+ "ditunjuki",
2199
+ "ditunjukkan",
2200
+ "ditunjukkannya",
2201
+ "ditunjuknya",
2202
+ "dituturkan",
2203
+ "dituturkannya",
2204
+ "diucapkan",
2205
+ "diucapkannya",
2206
+ "diungkapkan",
2207
+ "dua",
2208
+ "dulu",
2209
+ "empat",
2210
+ "enggak",
2211
+ "enggaknya",
2212
+ "entah",
2213
+ "entahlah",
2214
+ "guna",
2215
+ "gunakan",
2216
+ "hal",
2217
+ "hampir",
2218
+ "hanya",
2219
+ "hanyalah",
2220
+ "hari",
2221
+ "harus",
2222
+ "haruslah",
2223
+ "harusnya",
2224
+ "hendak",
2225
+ "hendaklah",
2226
+ "hendaknya",
2227
+ "hingga",
2228
+ "ia",
2229
+ "ialah",
2230
+ "ibarat",
2231
+ "ibaratkan",
2232
+ "ibaratnya",
2233
+ "ibu",
2234
+ "ikut",
2235
+ "ingat",
2236
+ "ingat-ingat",
2237
+ "ingin",
2238
+ "inginkah",
2239
+ "inginkan",
2240
+ "ini",
2241
+ "inikah",
2242
+ "inilah",
2243
+ "itu",
2244
+ "itukah",
2245
+ "itulah",
2246
+ "jadi",
2247
+ "jadilah",
2248
+ "jadinya",
2249
+ "jangan",
2250
+ "jangankan",
2251
+ "janganlah",
2252
+ "jauh",
2253
+ "jawab",
2254
+ "jawaban",
2255
+ "jawabnya",
2256
+ "jelas",
2257
+ "jelaskan",
2258
+ "jelaslah",
2259
+ "jelasnya",
2260
+ "jika",
2261
+ "jikalau",
2262
+ "juga",
2263
+ "jumlah",
2264
+ "jumlahnya",
2265
+ "justru",
2266
+ "kala",
2267
+ "kalau",
2268
+ "kalaulah",
2269
+ "kalaupun",
2270
+ "kali",
2271
+ "kalian",
2272
+ "kami",
2273
+ "kamilah",
2274
+ "kamu",
2275
+ "kamulah",
2276
+ "kan",
2277
+ "kapan",
2278
+ "kapankah",
2279
+ "kapanpun",
2280
+ "karena",
2281
+ "karenanya",
2282
+ "ke",
2283
+ "keadaan",
2284
+ "kebetulan",
2285
+ "kecil",
2286
+ "kedua",
2287
+ "keduanya",
2288
+ "keinginan",
2289
+ "kelak",
2290
+ "kelihatan",
2291
+ "kelihatannya",
2292
+ "kelima",
2293
+ "keluar",
2294
+ "kembali",
2295
+ "kemudian",
2296
+ "kemungkinan",
2297
+ "kemungkinannya",
2298
+ "kenapa",
2299
+ "kepada",
2300
+ "kepadanya",
2301
+ "kesampaian",
2302
+ "keseluruhan",
2303
+ "keseluruhannya",
2304
+ "keterlaluan",
2305
+ "ketika",
2306
+ "khususnya",
2307
+ "kini",
2308
+ "kinilah",
2309
+ "kira",
2310
+ "kira-kira",
2311
+ "kiranya",
2312
+ "kita",
2313
+ "kitalah",
2314
+ "kok",
2315
+ "kurang",
2316
+ "lagi",
2317
+ "lagian",
2318
+ "lah",
2319
+ "lain",
2320
+ "lainnya",
2321
+ "lalu",
2322
+ "lama",
2323
+ "lamanya",
2324
+ "lanjut",
2325
+ "lanjutnya",
2326
+ "lebih",
2327
+ "lewat",
2328
+ "luar",
2329
+ "macam",
2330
+ "maka",
2331
+ "makanya",
2332
+ "makin",
2333
+ "malah",
2334
+ "malahan",
2335
+ "mampu",
2336
+ "mampukah",
2337
+ "mana",
2338
+ "manakala",
2339
+ "manalagi",
2340
+ "masih",
2341
+ "masihkah",
2342
+ "masing",
2343
+ "masing-masing",
2344
+ "mau",
2345
+ "maupun",
2346
+ "melainkan",
2347
+ "melakukan",
2348
+ "melalui",
2349
+ "melihat",
2350
+ "melihatnya",
2351
+ "memang",
2352
+ "memastikan",
2353
+ "memberi",
2354
+ "memberikan",
2355
+ "membuat",
2356
+ "memerlukan",
2357
+ "memihak",
2358
+ "meminta",
2359
+ "memisalkan",
2360
+ "memperbuat",
2361
+ "mempergunakan",
2362
+ "memperkirakan",
2363
+ "memperlihatkan",
2364
+ "mempersiapkan",
2365
+ "mempersoalkan",
2366
+ "mempertanyakan",
2367
+ "mempunyai",
2368
+ "memulai",
2369
+ "memungkinkan",
2370
+ "memutuskan",
2371
+ "menanti",
2372
+ "menanti-nanti",
2373
+ "menantikan",
2374
+ "menunjuk",
2375
+ "menunjuknya",
2376
+ "menuju",
2377
+ "menurut",
2378
+ "menurutnya",
2379
+ "menurutmu",
2380
+ "menurutku",
2381
+ "menurutnya",
2382
+ "menurut mereka",
2383
+ "menyampaikan",
2384
+ "menyebut",
2385
+ "menyebutkan",
2386
+ "menjelaskan",
2387
+ "menjadi",
2388
+ "menjadikan",
2389
+ "menjalani",
2390
+ "menjelang",
2391
+ "menjawab",
2392
+ "menunjukkan",
2393
+ "menuangkan",
2394
+ "menulis",
2395
+ "menyatakan",
2396
+ "merupakan",
2397
+ "mereka",
2398
+ "merekalah",
2399
+ "meski",
2400
+ "meskipun",
2401
+ "mula",
2402
+ "mulai",
2403
+ "mulailah",
2404
+ "mulanya",
2405
+ "mungkin",
2406
+ "mungkinkah",
2407
+ "nah",
2408
+ "naik",
2409
+ "namun",
2410
+ "nanti",
2411
+ "nantinya",
2412
+ "nyaris",
2413
+ "oleh",
2414
+ "olehnya",
2415
+ "orang",
2416
+ "pada",
2417
+ "padahal",
2418
+ "padanya",
2419
+ "pakai",
2420
+ "paling",
2421
+ "panjang",
2422
+ "pantas",
2423
+ "para",
2424
+ "pasti",
2425
+ "pastilah",
2426
+ "pagi",
2427
+ "per",
2428
+ "pernah",
2429
+ "persoalan",
2430
+ "pertama",
2431
+ "pertama-tama",
2432
+ "perlu",
2433
+ "perlukah",
2434
+ "perlulah",
2435
+ "pernah",
2436
+ "pihak",
2437
+ "pihaknya",
2438
+ "pukul",
2439
+ "pula",
2440
+ "pun",
2441
+ "punya",
2442
+ "rasa",
2443
+ "rasanya",
2444
+ "rata",
2445
+ "rupanya",
2446
+ "saat",
2447
+ "saatnya",
2448
+ "saja",
2449
+ "sajalah",
2450
+ "salam",
2451
+ "saling",
2452
+ "sama",
2453
+ "sama-sama",
2454
+ "sambil",
2455
+ "sampai",
2456
+ "sampai-sampai",
2457
+ "sampaikan",
2458
+ "sana",
2459
+ "sangat",
2460
+ "sangatlah",
2461
+ "satu",
2462
+ "saya",
2463
+ "sayalah",
2464
+ "sayang",
2465
+ "seperti",
2466
+ "seperti-itu",
2467
+ "sepura",
2468
+ "sebab",
2469
+ "sebabnya",
2470
+ "sebagai",
2471
+ "sebagaimana",
2472
+ "sebagainya",
2473
+ "sebagian",
2474
+ "sebaik",
2475
+ "sebaik-baiknya",
2476
+ "sebaiknya",
2477
+ "sebaliknya",
2478
+ "sebanyak",
2479
+ "sebegini",
2480
+ "sebegitu",
2481
+ "sebelum",
2482
+ "sebelumnya",
2483
+ "sebenarnya",
2484
+ "seberapa",
2485
+ "sebesar",
2486
+ "sebetulnya",
2487
+ "sebisanya",
2488
+ "sebuah",
2489
+ "sebut",
2490
+ "sebutkan",
2491
+ "sebutnya",
2492
+ "secara",
2493
+ "secukupnya",
2494
+ "sedang",
2495
+ "sedangkan",
2496
+ "sedikit",
2497
+ "sedikitnya",
2498
+ "sedemikian",
2499
+ "sediakala",
2500
+ "sedikit",
2501
+ "sedikitnya",
2502
+ "segala",
2503
+ "segalanya",
2504
+ "segera",
2505
+ "seharusnya",
2506
+ "sehingga",
2507
+ "seingat",
2508
+ "sejak",
2509
+ "sejauh",
2510
+ "sejenak",
2511
+ "sejumlah",
2512
+ "sekali",
2513
+ "sekali-kali",
2514
+ "sekalian",
2515
+ "sekaligus",
2516
+ "sekalipun",
2517
+ "sekarang",
2518
+ "sekaranglah",
2519
+ "sekecil",
2520
+ "seketika",
2521
+ "sekiranya",
2522
+ "sekitar",
2523
+ "sekitarnya",
2524
+ "sekurang",
2525
+ "sekurangnya",
2526
+ "sela",
2527
+ "selalu",
2528
+ "selama",
2529
+ "selama-lamanya",
2530
+ "selamanya",
2531
+ "selanjutnya",
2532
+ "seluruh",
2533
+ "seluruhnya",
2534
+ "semacam",
2535
+ "semakin",
2536
+ "semampu",
2537
+ "semampunya",
2538
+ "semasa",
2539
+ "semata",
2540
+ "semata-mata",
2541
+ "semaunya",
2542
+ "sementara",
2543
+ "semisal",
2544
+ "semisalnya",
2545
+ "sempat",
2546
+ "semua",
2547
+ "semuanya",
2548
+ "semula",
2549
+ "sendiri",
2550
+ "sendirinya",
2551
+ "seolah",
2552
+ "seolah-olah",
2553
+ "seorang",
2554
+ "sepanjang",
2555
+ "sepantasnya",
2556
+ "sepantasnyalah",
2557
+ "seperempat",
2558
+ "seperti",
2559
+ "sepertinya",
2560
+ "sepihak",
2561
+ "sepuluh",
2562
+ "seratus",
2563
+ "seribu",
2564
+ "sering",
2565
+ "seringnya",
2566
+ "serta",
2567
+ "serupa",
2568
+ "sesaat",
2569
+ "sesama",
2570
+ "sesampai",
2571
+ "sesampainya",
2572
+ "sesegera",
2573
+ "sesekali",
2574
+ "seseorang",
2575
+ "sesuatu",
2576
+ "sesuatunya",
2577
+ "sesudah",
2578
+ "sesudahnya",
2579
+ "setelah",
2580
+ "setempat",
2581
+ "setengah",
2582
+ "seterusnya",
2583
+ "setiap",
2584
+ "setidaknya",
2585
+ "setinggi",
2586
+ "seusai",
2587
+ "sewaktu",
2588
+ "siap",
2589
+ "siapa",
2590
+ "siapakah",
2591
+ "siapapun",
2592
+ "sini",
2593
+ "sinilah",
2594
+ "situ",
2595
+ "situlah",
2596
+ "suatu",
2597
+ "sudah",
2598
+ "sudahkah",
2599
+ "sudahlah",
2600
+ "supaya",
2601
+ "tadi",
2602
+ "tadinya",
2603
+ "tahu",
2604
+ "tak",
2605
+ "tambah",
2606
+ "tambahnya",
2607
+ "tampak",
2608
+ "tampaknya",
2609
+ "tandas",
2610
+ "tandasnya",
2611
+ "tanpa",
2612
+ "tanya",
2613
+ "tanyakan",
2614
+ "tanyanya",
2615
+ "tapi",
2616
+ "tegas",
2617
+ "tegasnya",
2618
+ "telah",
2619
+ "tempat",
2620
+ "tengah",
2621
+ "tentang",
2622
+ "tentu",
2623
+ "tentulah",
2624
+ "tentunya",
2625
+ "tepat",
2626
+ "terakhir",
2627
+ "terasa",
2628
+ "terbanyak",
2629
+ "terdahulu",
2630
+ "terdapat",
2631
+ "terdiri",
2632
+ "terdiri-dari",
2633
+ "terhadap",
2634
+ "terhadapnya",
2635
+ "teringat",
2636
+ "teringat-ingat",
2637
+ "terjadi",
2638
+ "terjadilah",
2639
+ "terjadinya",
2640
+ "terkira",
2641
+ "terlalu",
2642
+ "terlebih",
2643
+ "terlihat",
2644
+ "termasuk",
2645
+ "ternyata",
2646
+ "tersampaikan",
2647
+ "tersebut",
2648
+ "tersebutlah",
2649
+ "tertentu",
2650
+ "tertuju",
2651
+ "terus",
2652
+ "terutama",
2653
+ "tetap",
2654
+ "tetapi",
2655
+ "tiap",
2656
+ "tiba",
2657
+ "tiba-tiba",
2658
+ "tidak",
2659
+ "tidakkah",
2660
+ "tidaklah",
2661
+ "tiga",
2662
+ "tadi",
2663
+ "tadinya",
2664
+ "tinggi",
2665
+ "toh",
2666
+ "tuju",
2667
+ "tunjuk",
2668
+ "turut",
2669
+ "tutur",
2670
+ "tuturnya",
2671
+ "ucap",
2672
+ "ucapnya",
2673
+ "ujar",
2674
+ "ujarnya",
2675
+ "umumnya",
2676
+ "ungkap",
2677
+ "ungkapnya",
2678
+ "untuk",
2679
+ "untaian",
2680
+ "usai",
2681
+ "usah",
2682
+ "waduh",
2683
+ "wah",
2684
+ "wahai",
2685
+ "walau",
2686
+ "walaupun",
2687
+ "wong",
2688
+ "yaitu",
2689
+ "yakin",
2690
+ "yakni",
2691
+ "yang"
2692
+ ];
1601
2693
 
1602
2694
  // src/text/capitalization.ts
1603
2695
  function capitalize2(text) {
@@ -1935,6 +3027,78 @@ function contractAbbreviation(text, options) {
1935
3027
  return result;
1936
3028
  }
1937
3029
 
3030
+ // src/text/filter.ts
3031
+ function profanityFilter(text, mask = "*") {
3032
+ let filtered = text;
3033
+ PROFANITY.forEach((word) => {
3034
+ const regex = new RegExp(`\\b${word}\\b`, "gi");
3035
+ filtered = filtered.replace(regex, mask.repeat(word.length));
3036
+ });
3037
+ return filtered;
3038
+ }
3039
+ function removeStopwords(text) {
3040
+ const words = text.split(/\s+/);
3041
+ const filtered = words.filter(
3042
+ (word) => !STOPWORDS.includes(word.toLowerCase())
3043
+ );
3044
+ return filtered.join(" ");
3045
+ }
3046
+
3047
+ // src/text/normalization.ts
3048
+ var INFORMAL_MAP = {
3049
+ gw: "saya",
3050
+ gua: "saya",
3051
+ lu: "kamu",
3052
+ lo: "kamu",
3053
+ elo: "kamu",
3054
+ lagi: "sedang",
3055
+ gue: "saya",
3056
+ gwe: "saya",
3057
+ gak: "tidak",
3058
+ ga: "tidak",
3059
+ nggak: "tidak",
3060
+ kalo: "kalau",
3061
+ karna: "karena",
3062
+ tapi: "tetapi",
3063
+ udah: "sudah",
3064
+ dah: "sudah",
3065
+ aja: "saja",
3066
+ banget: "sekali",
3067
+ emang: "memang",
3068
+ pake: "pakai",
3069
+ bikin: "membuat",
3070
+ kasih: "memberi",
3071
+ dapet: "dapat",
3072
+ liat: "lihat",
3073
+ ngasih: "memberi",
3074
+ nyari: "mencari",
3075
+ nanya: "bertanya",
3076
+ bilang: "berkata"
3077
+ };
3078
+ function toFormal(text) {
3079
+ const words = text.split(/\s+/);
3080
+ const formalized = words.map((word) => {
3081
+ const lower = word.toLowerCase().replace(/[^\w]/g, "");
3082
+ const formal = INFORMAL_MAP[lower];
3083
+ if (formal) {
3084
+ if (word[0] === word[0].toUpperCase()) {
3085
+ return formal.charAt(0).toUpperCase() + formal.slice(1);
3086
+ }
3087
+ return formal;
3088
+ }
3089
+ return word;
3090
+ });
3091
+ return formalized.join(" ");
3092
+ }
3093
+ function isAlay(text) {
3094
+ if (!text) return false;
3095
+ const alternatingCaps = /([a-z][A-Z][a-z]|[A-Z][a-z][A-Z])/.test(text);
3096
+ const numberSub = /\b\w*[0431572]\w*\b/.test(text);
3097
+ const qSub = /q/i.test(text) && !/u/i.test(text);
3098
+ const excessiveChars = /(.)\1{2,}/.test(text);
3099
+ return alternatingCaps || numberSub || qSub || excessiveChars;
3100
+ }
3101
+
1938
3102
  // src/text/extract.ts
1939
3103
  function truncate(text, maxLength, options) {
1940
3104
  if (!text || maxLength <= 0) {
@@ -2043,6 +3207,6 @@ function similarity(str1, str2) {
2043
3207
  return 1 - distance / maxLength;
2044
3208
  }
2045
3209
 
2046
- export { capitalize2 as capitalize, cleanPhoneNumber, compareStrings, contractAbbreviation, expandAbbreviation, extractWords, formatCompact, formatNIK, formatPhoneNumber, formatRupiah, getOperator, isLandlineNumber, isMobileNumber, maskNIK, maskPhoneNumber, normalizeWhitespace, parseNIK, parsePhoneNumber, parseRupiah, removeAccents, sanitize, similarity, slugify, toE164, toInternational, toNational, toSentenceCase, toTitleCase, toWords, truncate, validateNIK, validatePhoneNumber };
3210
+ export { addRupiahSymbol, calculateTax, capitalize2 as capitalize, cleanPhoneNumber, compareStrings, contractAbbreviation, expandAbbreviation, extractWords, formatAccounting, formatBirthDate, formatCompact, formatNIK, formatNPWP, formatPhoneNumber, formatPlate, formatRupiah, generateSmsLink, generateTelLink, generateWALink, getAge, getOperator, getRegionFromPlate, isAlay, isLandlineNumber, isMobileNumber, isProvider, isValidForBirthDate, isValidForGender, maskNIK, maskNPWP, maskPhoneNumber, normalizeWhitespace, parseNIK, parseNPWP, parsePhoneNumber, parseRupiah, profanityFilter, removeAccents, removeStopwords, roundToClean, sanitize, similarity, slugify, toE164, toFormal, toInternational, toNational, toSentenceCase, toTitleCase, toWords, truncate, validateNIK, validateNPWP, validatePhoneNumber, validatePlate, validateVIN };
2047
3211
  //# sourceMappingURL=index.js.map
2048
3212
  //# sourceMappingURL=index.js.map