@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/README.md +91 -183
- package/dist/compare-BIodyGn7.d.cts +991 -0
- package/dist/compare-BIodyGn7.d.ts +991 -0
- package/dist/currency/index.cjs +23 -0
- package/dist/currency/index.cjs.map +1 -1
- package/dist/currency/index.d.cts +367 -3
- package/dist/currency/index.d.ts +367 -3
- package/dist/currency/index.js +21 -1
- package/dist/currency/index.js.map +1 -1
- package/dist/index.cjs +2025 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -3
- package/dist/index.d.ts +110 -3
- package/dist/index.js +1990 -1
- package/dist/index.js.map +1 -1
- package/dist/nik/index.cjs +44 -0
- package/dist/nik/index.cjs.map +1 -1
- package/dist/nik/index.d.cts +44 -1
- package/dist/nik/index.d.ts +44 -1
- package/dist/nik/index.js +41 -1
- package/dist/nik/index.js.map +1 -1
- package/dist/phone/index.cjs +42 -0
- package/dist/phone/index.cjs.map +1 -1
- package/dist/phone/index.d.cts +57 -1
- package/dist/phone/index.d.ts +57 -1
- package/dist/phone/index.js +39 -1
- package/dist/phone/index.js.map +1 -1
- package/dist/text/index.cjs +1726 -0
- package/dist/text/index.cjs.map +1 -0
- package/dist/text/index.d.cts +284 -0
- package/dist/text/index.d.ts +284 -0
- package/dist/text/index.js +1705 -0
- package/dist/text/index.js.map +1 -0
- package/package.json +54 -17
- package/LICENCE +0 -21
- package/dist/words-Dy8iYkbv.d.cts +0 -333
- package/dist/words-Dy8iYkbv.d.ts +0 -333
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
|