urdu-text-utils 0.1.6 → 0.1.7
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/CHANGELOG.md +7 -0
- package/README.md +25 -0
- package/dist/index.cjs +202 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -1
- package/dist/index.d.ts +97 -1
- package/dist/index.iife.js +1 -1
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +196 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.7
|
|
4
|
+
|
|
5
|
+
- Add Urdu date & time formatting module (`formatUrduDate`, `timeAgoUrdu`, `getUrduMonthName`, `getUrduWeekdayName`).
|
|
6
|
+
- Add pattern token replacement (`YYYY`, `MMMM`, `DD`, `dddd`, `hh:mm A`) with automatic Urdu numerals and day period indicators (`صبح`, `دوپہر`, `شام`, `رات`).
|
|
7
|
+
- Add localized natural relative time formatting for past and future dates (*"ابھی"*, *"۵ منٹ پہلے"*, *"۳ گھنٹے پہلے"*, *"کل"*, *"پرسوں"*, *"۲ ہفتے بعد"*).
|
|
8
|
+
- Add canonical constants `URDU_MONTHS_GREGORIAN`, `URDU_MONTHS_HIJRI`, and `URDU_WEEKDAYS`.
|
|
9
|
+
|
|
3
10
|
## 0.1.6
|
|
4
11
|
|
|
5
12
|
- Add dedicated minified IIFE browser bundle (`dist/index.iife.js`) exposing `window.UrduTextUtils` for seamless jsDelivr and unpkg CDN usage without a bundler.
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# urdu-text-utils — Urdu Text Processing Toolkit for JavaScript & TypeScript
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/urdu-text-utils)
|
|
4
|
+
[](https://www.jsdelivr.com/package/npm/urdu-text-utils)
|
|
5
|
+
[](https://unpkg.com/urdu-text-utils/)
|
|
4
6
|
[](https://github.com/Zaid-maker/urdu-text-utils/actions/workflows/ci.yml)
|
|
5
7
|
[](https://bundlejs.com/?q=urdu-text-utils)
|
|
6
8
|
[](https://www.npmjs.com/package/urdu-text-utils?activeTab=dependencies)
|
|
@@ -49,6 +51,8 @@ import {
|
|
|
49
51
|
urduSlug,
|
|
50
52
|
isStopWord,
|
|
51
53
|
removeStopWords,
|
|
54
|
+
formatUrduDate,
|
|
55
|
+
timeAgoUrdu,
|
|
52
56
|
isUrdu,
|
|
53
57
|
countWords,
|
|
54
58
|
splitSentences,
|
|
@@ -147,6 +151,27 @@ parseUrduNumber("۳٫۱۴"); // 3.14
|
|
|
147
151
|
numberToUrduWords(100000); // "ایک لاکھ" — South Asian scale, @experimental
|
|
148
152
|
```
|
|
149
153
|
|
|
154
|
+
## Urdu dates & relative time
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { formatUrduDate, timeAgoUrdu } from "urdu-text-utils";
|
|
158
|
+
|
|
159
|
+
// Format date with Urdu month and numerals
|
|
160
|
+
formatUrduDate(new Date(), "DD MMMM YYYY");
|
|
161
|
+
// "۲۲ اگست ۲۰۲۶"
|
|
162
|
+
|
|
163
|
+
// Date with weekday and 12-hour period
|
|
164
|
+
formatUrduDate(new Date(), "dddd، D MMMM YYYY، hh:mm A");
|
|
165
|
+
// "ہفتہ، ۲۲ اگست ۲۰۲۶، ۰۲:۳۰ دوپہر"
|
|
166
|
+
|
|
167
|
+
// Natural relative time (time ago)
|
|
168
|
+
timeAgoUrdu(Date.now() - 5 * 60 * 1000); // "۵ منٹ پہلے"
|
|
169
|
+
timeAgoUrdu(Date.now() - 3 * 3600 * 1000); // "۳ گھنٹے پہلے"
|
|
170
|
+
timeAgoUrdu(Date.now() - 86400 * 1000); // "کل"
|
|
171
|
+
timeAgoUrdu(Date.now() - 2 * 86400 * 1000);// "پرسوں"
|
|
172
|
+
timeAgoUrdu(Date.now() + 10 * 60 * 1000); // "۱۰ منٹ بعد"
|
|
173
|
+
```
|
|
174
|
+
|
|
150
175
|
## Diacritics
|
|
151
176
|
|
|
152
177
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -3508,7 +3508,205 @@ function urduSlug(input, options = {}) {
|
|
|
3508
3508
|
return slug;
|
|
3509
3509
|
}
|
|
3510
3510
|
|
|
3511
|
+
// src/date.ts
|
|
3512
|
+
var URDU_MONTHS_GREGORIAN = [
|
|
3513
|
+
"\u062C\u0646\u0648\u0631\u06CC",
|
|
3514
|
+
"\u0641\u0631\u0648\u0631\u06CC",
|
|
3515
|
+
"\u0645\u0627\u0631\u0686",
|
|
3516
|
+
"\u0627\u067E\u0631\u06CC\u0644",
|
|
3517
|
+
"\u0645\u0626\u06CC",
|
|
3518
|
+
"\u062C\u0648\u0646",
|
|
3519
|
+
"\u062C\u0648\u0644\u0627\u0626\u06CC",
|
|
3520
|
+
"\u0627\u06AF\u0633\u062A",
|
|
3521
|
+
"\u0633\u062A\u0645\u0628\u0631",
|
|
3522
|
+
"\u0627\u06A9\u062A\u0648\u0628\u0631",
|
|
3523
|
+
"\u0646\u0648\u0645\u0628\u0631",
|
|
3524
|
+
"\u062F\u0633\u0645\u0628\u0631"
|
|
3525
|
+
];
|
|
3526
|
+
var URDU_MONTHS_HIJRI = [
|
|
3527
|
+
"\u0645\u062D\u0631\u0645",
|
|
3528
|
+
"\u0635\u0641\u0631",
|
|
3529
|
+
"\u0631\u0628\u06CC\u0639 \u0627\u0644\u0627\u0648\u0644",
|
|
3530
|
+
"\u0631\u0628\u06CC\u0639 \u0627\u0644\u062B\u0627\u0646\u06CC",
|
|
3531
|
+
"\u062C\u0645\u0627\u062F\u06CC \u0627\u0644\u0627\u0648\u0644",
|
|
3532
|
+
"\u062C\u0645\u0627\u062F\u06CC \u0627\u0644\u062B\u0627\u0646\u06CC",
|
|
3533
|
+
"\u0631\u062C\u0628",
|
|
3534
|
+
"\u0634\u0639\u0628\u0627\u0646",
|
|
3535
|
+
"\u0631\u0645\u0636\u0627\u0646 \u0627\u0644\u0645\u0628\u0627\u0631\u06A9",
|
|
3536
|
+
"\u0634\u0648\u0627\u0644",
|
|
3537
|
+
"\u0630\u06CC \u0627\u0644\u0642\u0639\u062F\u06C1",
|
|
3538
|
+
"\u0630\u06CC \u0627\u0644\u062D\u062C\u06C1"
|
|
3539
|
+
];
|
|
3540
|
+
var URDU_WEEKDAYS = [
|
|
3541
|
+
"\u0627\u062A\u0648\u0627\u0631",
|
|
3542
|
+
"\u067E\u06CC\u0631",
|
|
3543
|
+
"\u0645\u0646\u06AF\u0644",
|
|
3544
|
+
"\u0628\u062F\u06BE",
|
|
3545
|
+
"\u062C\u0645\u0639\u0631\u0627\u062A",
|
|
3546
|
+
"\u062C\u0645\u0639\u06C1",
|
|
3547
|
+
"\u06C1\u0641\u062A\u06C1"
|
|
3548
|
+
];
|
|
3549
|
+
function parseDateInput(input) {
|
|
3550
|
+
if (input instanceof Date) {
|
|
3551
|
+
return isNaN(input.getTime()) ? null : input;
|
|
3552
|
+
}
|
|
3553
|
+
const date = new Date(input);
|
|
3554
|
+
return isNaN(date.getTime()) ? null : date;
|
|
3555
|
+
}
|
|
3556
|
+
function getUrduMonthName(monthIndex, calendar = "gregorian") {
|
|
3557
|
+
const normalizedIndex = Math.floor(monthIndex) % 12;
|
|
3558
|
+
const idx = normalizedIndex < 0 ? normalizedIndex + 12 : normalizedIndex;
|
|
3559
|
+
return calendar === "hijri" ? URDU_MONTHS_HIJRI[idx] : URDU_MONTHS_GREGORIAN[idx];
|
|
3560
|
+
}
|
|
3561
|
+
function getUrduWeekdayName(dayIndex) {
|
|
3562
|
+
const normalizedIndex = Math.floor(dayIndex) % 7;
|
|
3563
|
+
const idx = normalizedIndex < 0 ? normalizedIndex + 7 : normalizedIndex;
|
|
3564
|
+
return URDU_WEEKDAYS[idx];
|
|
3565
|
+
}
|
|
3566
|
+
function formatUrduDate(date, pattern = "DD MMMM YYYY", options = {}) {
|
|
3567
|
+
const d = parseDateInput(date);
|
|
3568
|
+
if (!d) return "";
|
|
3569
|
+
const digits = options.digits ?? "urdu";
|
|
3570
|
+
const calendar = options.calendar ?? "gregorian";
|
|
3571
|
+
const year = d.getFullYear();
|
|
3572
|
+
const month = d.getMonth();
|
|
3573
|
+
const dayOfMonth = d.getDate();
|
|
3574
|
+
const dayOfWeek = d.getDay();
|
|
3575
|
+
const hours24 = d.getHours();
|
|
3576
|
+
const hours12 = hours24 % 12 || 12;
|
|
3577
|
+
const minutes = d.getMinutes();
|
|
3578
|
+
const seconds = d.getSeconds();
|
|
3579
|
+
const pad = (n) => n < 10 ? `0${n}` : `${n}`;
|
|
3580
|
+
let periodDetailed;
|
|
3581
|
+
let periodSimple;
|
|
3582
|
+
if (hours24 >= 4 && hours24 < 12) {
|
|
3583
|
+
periodDetailed = "\u0635\u0628\u062D";
|
|
3584
|
+
periodSimple = "\u0635\u0628\u062D";
|
|
3585
|
+
} else if (hours24 >= 12 && hours24 < 16) {
|
|
3586
|
+
periodDetailed = "\u062F\u0648\u067E\u06C1\u0631";
|
|
3587
|
+
periodSimple = "\u0634\u0627\u0645";
|
|
3588
|
+
} else if (hours24 >= 16 && hours24 < 20) {
|
|
3589
|
+
periodDetailed = "\u0634\u0627\u0645";
|
|
3590
|
+
periodSimple = "\u0634\u0627\u0645";
|
|
3591
|
+
} else {
|
|
3592
|
+
periodDetailed = "\u0631\u0627\u062A";
|
|
3593
|
+
periodSimple = "\u0631\u0627\u062A";
|
|
3594
|
+
}
|
|
3595
|
+
const tokenValues = {
|
|
3596
|
+
YYYY: `${year}`,
|
|
3597
|
+
YY: `${year}`.slice(-2),
|
|
3598
|
+
MMMM: getUrduMonthName(month, calendar),
|
|
3599
|
+
MMM: getUrduMonthName(month, calendar),
|
|
3600
|
+
MM: pad(month + 1),
|
|
3601
|
+
M: `${month + 1}`,
|
|
3602
|
+
DD: pad(dayOfMonth),
|
|
3603
|
+
D: `${dayOfMonth}`,
|
|
3604
|
+
dddd: getUrduWeekdayName(dayOfWeek),
|
|
3605
|
+
ddd: getUrduWeekdayName(dayOfWeek),
|
|
3606
|
+
HH: pad(hours24),
|
|
3607
|
+
H: `${hours24}`,
|
|
3608
|
+
hh: pad(hours12),
|
|
3609
|
+
h: `${hours12}`,
|
|
3610
|
+
mm: pad(minutes),
|
|
3611
|
+
m: `${minutes}`,
|
|
3612
|
+
ss: pad(seconds),
|
|
3613
|
+
s: `${seconds}`,
|
|
3614
|
+
A: periodDetailed,
|
|
3615
|
+
a: periodSimple
|
|
3616
|
+
};
|
|
3617
|
+
const regex = /YYYY|YY|MMMM|MMM|MM|M|DD|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|A|a/g;
|
|
3618
|
+
const result = pattern.replace(regex, (match) => {
|
|
3619
|
+
const val = tokenValues[match];
|
|
3620
|
+
if (val === void 0) return match;
|
|
3621
|
+
if (digits === "urdu" && /^\d+$/.test(val)) {
|
|
3622
|
+
return toUrduDigits(val);
|
|
3623
|
+
}
|
|
3624
|
+
return val;
|
|
3625
|
+
});
|
|
3626
|
+
return result;
|
|
3627
|
+
}
|
|
3628
|
+
function timeAgoUrdu(date, relativeTo = /* @__PURE__ */ new Date(), options = {}) {
|
|
3629
|
+
const d = parseDateInput(date);
|
|
3630
|
+
const now = parseDateInput(relativeTo);
|
|
3631
|
+
if (!d || !now) return "";
|
|
3632
|
+
const digits = options.digits ?? "urdu";
|
|
3633
|
+
const addSuffix = options.addSuffix ?? true;
|
|
3634
|
+
const formatNum = (num) => {
|
|
3635
|
+
const s = `${num}`;
|
|
3636
|
+
return digits === "urdu" ? toUrduDigits(s) : s;
|
|
3637
|
+
};
|
|
3638
|
+
const diffMs = now.getTime() - d.getTime();
|
|
3639
|
+
const isPast = diffMs >= 0;
|
|
3640
|
+
const absDiffSeconds = Math.round(Math.abs(diffMs) / 1e3);
|
|
3641
|
+
if (absDiffSeconds < 45) {
|
|
3642
|
+
return isPast ? "\u0627\u0628\u06BE\u06CC" : "\u0686\u0646\u062F \u0644\u0645\u062D\u06D2 \u0628\u0639\u062F";
|
|
3643
|
+
}
|
|
3644
|
+
const minutes = Math.round(absDiffSeconds / 60);
|
|
3645
|
+
if (minutes <= 45) {
|
|
3646
|
+
if (minutes === 1) {
|
|
3647
|
+
if (!addSuffix) return "\u0627\u06CC\u06A9 \u0645\u0646\u0679";
|
|
3648
|
+
return isPast ? "\u0627\u06CC\u06A9 \u0645\u0646\u0679 \u067E\u06C1\u0644\u06D2" : "\u0627\u06CC\u06A9 \u0645\u0646\u0679 \u0628\u0639\u062F";
|
|
3649
|
+
}
|
|
3650
|
+
const count2 = formatNum(minutes);
|
|
3651
|
+
if (!addSuffix) return `${count2} \u0645\u0646\u0679`;
|
|
3652
|
+
return isPast ? `${count2} \u0645\u0646\u0679 \u067E\u06C1\u0644\u06D2` : `${count2} \u0645\u0646\u0679 \u0628\u0639\u062F`;
|
|
3653
|
+
}
|
|
3654
|
+
const hours = Math.round(minutes / 60);
|
|
3655
|
+
if (hours <= 22) {
|
|
3656
|
+
if (hours === 1) {
|
|
3657
|
+
if (!addSuffix) return "\u0627\u06CC\u06A9 \u06AF\u06BE\u0646\u0679\u06C1";
|
|
3658
|
+
return isPast ? "\u0627\u06CC\u06A9 \u06AF\u06BE\u0646\u0679\u06C1 \u067E\u06C1\u0644\u06D2" : "\u0627\u06CC\u06A9 \u06AF\u06BE\u0646\u0679\u06C1 \u0628\u0639\u062F";
|
|
3659
|
+
}
|
|
3660
|
+
const count2 = formatNum(hours);
|
|
3661
|
+
if (!addSuffix) return `${count2} \u06AF\u06BE\u0646\u0679\u06D2`;
|
|
3662
|
+
return isPast ? `${count2} \u06AF\u06BE\u0646\u0679\u06D2 \u067E\u06C1\u0644\u06D2` : `${count2} \u06AF\u06BE\u0646\u0679\u06D2 \u0628\u0639\u062F`;
|
|
3663
|
+
}
|
|
3664
|
+
const days = Math.round(hours / 24);
|
|
3665
|
+
if (days === 1) {
|
|
3666
|
+
return isPast ? "\u06A9\u0644" : "\u06A9\u0644";
|
|
3667
|
+
}
|
|
3668
|
+
if (days === 2) {
|
|
3669
|
+
return isPast ? "\u067E\u0631\u0633\u0648\u06BA" : "\u067E\u0631\u0633\u0648\u06BA";
|
|
3670
|
+
}
|
|
3671
|
+
if (days <= 6) {
|
|
3672
|
+
const count2 = formatNum(days);
|
|
3673
|
+
if (!addSuffix) return `${count2} \u062F\u0646`;
|
|
3674
|
+
return isPast ? `${count2} \u062F\u0646 \u067E\u06C1\u0644\u06D2` : `${count2} \u062F\u0646 \u0628\u0639\u062F`;
|
|
3675
|
+
}
|
|
3676
|
+
const weeks = Math.round(days / 7);
|
|
3677
|
+
if (days <= 28) {
|
|
3678
|
+
if (weeks === 1) {
|
|
3679
|
+
if (!addSuffix) return "\u0627\u06CC\u06A9 \u06C1\u0641\u062A\u06C1";
|
|
3680
|
+
return isPast ? "\u0627\u06CC\u06A9 \u06C1\u0641\u062A\u06C1 \u067E\u06C1\u0644\u06D2" : "\u0627\u06CC\u06A9 \u06C1\u0641\u062A\u06C1 \u0628\u0639\u062F";
|
|
3681
|
+
}
|
|
3682
|
+
const count2 = formatNum(weeks);
|
|
3683
|
+
if (!addSuffix) return `${count2} \u06C1\u0641\u062A\u06D2`;
|
|
3684
|
+
return isPast ? `${count2} \u06C1\u0641\u062A\u06D2 \u067E\u06C1\u0644\u06D2` : `${count2} \u06C1\u0641\u062A\u06D2 \u0628\u0639\u062F`;
|
|
3685
|
+
}
|
|
3686
|
+
const months = Math.round(days / 30.44);
|
|
3687
|
+
if (days <= 320) {
|
|
3688
|
+
if (months <= 1) {
|
|
3689
|
+
if (!addSuffix) return "\u0627\u06CC\u06A9 \u0645\u0627\u06C1";
|
|
3690
|
+
return isPast ? "\u0627\u06CC\u06A9 \u0645\u0627\u06C1 \u067E\u06C1\u0644\u06D2" : "\u0627\u06CC\u06A9 \u0645\u0627\u06C1 \u0628\u0639\u062F";
|
|
3691
|
+
}
|
|
3692
|
+
const count2 = formatNum(months);
|
|
3693
|
+
if (!addSuffix) return `${count2} \u0645\u0627\u06C1`;
|
|
3694
|
+
return isPast ? `${count2} \u0645\u0627\u06C1 \u067E\u06C1\u0644\u06D2` : `${count2} \u0645\u0627\u06C1 \u0628\u0639\u062F`;
|
|
3695
|
+
}
|
|
3696
|
+
const years = Math.round(days / 365.25);
|
|
3697
|
+
if (years <= 1) {
|
|
3698
|
+
if (!addSuffix) return "\u0627\u06CC\u06A9 \u0633\u0627\u0644";
|
|
3699
|
+
return isPast ? "\u0627\u06CC\u06A9 \u0633\u0627\u0644 \u067E\u06C1\u0644\u06D2" : "\u0627\u06CC\u06A9 \u0633\u0627\u0644 \u0628\u0639\u062F";
|
|
3700
|
+
}
|
|
3701
|
+
const count = formatNum(years);
|
|
3702
|
+
if (!addSuffix) return `${count} \u0633\u0627\u0644`;
|
|
3703
|
+
return isPast ? `${count} \u0633\u0627\u0644 \u067E\u06C1\u0644\u06D2` : `${count} \u0633\u0627\u0644 \u0628\u0639\u062F`;
|
|
3704
|
+
}
|
|
3705
|
+
|
|
3706
|
+
exports.URDU_MONTHS_GREGORIAN = URDU_MONTHS_GREGORIAN;
|
|
3707
|
+
exports.URDU_MONTHS_HIJRI = URDU_MONTHS_HIJRI;
|
|
3511
3708
|
exports.URDU_STOP_WORDS = URDU_STOP_WORDS;
|
|
3709
|
+
exports.URDU_WEEKDAYS = URDU_WEEKDAYS;
|
|
3512
3710
|
exports.analyzeUrdu = analyzeUrdu;
|
|
3513
3711
|
exports.compareUrdu = compareUrdu;
|
|
3514
3712
|
exports.convertNumbers = convertNumbers;
|
|
@@ -3517,6 +3715,9 @@ exports.countWords = countWords;
|
|
|
3517
3715
|
exports.editDistance = editDistance;
|
|
3518
3716
|
exports.filterStopWords = filterStopWords;
|
|
3519
3717
|
exports.foldUrdu = foldUrdu;
|
|
3718
|
+
exports.formatUrduDate = formatUrduDate;
|
|
3719
|
+
exports.getUrduMonthName = getUrduMonthName;
|
|
3720
|
+
exports.getUrduWeekdayName = getUrduWeekdayName;
|
|
3520
3721
|
exports.hasUrduSpecificLetters = hasUrduSpecificLetters;
|
|
3521
3722
|
exports.highlightUrdu = highlightUrdu;
|
|
3522
3723
|
exports.isStopWord = isStopWord;
|
|
@@ -3533,6 +3734,7 @@ exports.searchUrduRanked = searchUrduRanked;
|
|
|
3533
3734
|
exports.sortUrdu = sortUrdu;
|
|
3534
3735
|
exports.splitSentences = splitSentences;
|
|
3535
3736
|
exports.splitWords = splitWords;
|
|
3737
|
+
exports.timeAgoUrdu = timeAgoUrdu;
|
|
3536
3738
|
exports.toArabicIndicDigits = toArabicIndicDigits;
|
|
3537
3739
|
exports.toEnglishDigits = toEnglishDigits;
|
|
3538
3740
|
exports.toUrduDigits = toUrduDigits;
|