@kashi-ui/persian 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/iban.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Bank } from "./card.js";
2
+ /** ۲۴ رقم شبا بدون IR؛ «IR12 0170…» یا «۱۲۰۱۷۰…» را می‌پذیرد */
3
+ export declare function ibanDigits(value: string): string;
4
+ /** اعتبارسنجی شماره شبا (IBAN ایران): IR + ۲۴ رقم با رقم‌های کنترل ISO 13616 */
5
+ export declare function isValidIban(value: string): boolean;
6
+ /** نام بانک از روی شبا؛ اگر شناخته نشود null */
7
+ export declare function getBankByIban(value: string): Bank | null;
8
+ /** IR + گروه‌های چهارتایی: IR06 0170 0000 … */
9
+ export declare function formatIban(value: string): string;
package/dist/iban.js ADDED
@@ -0,0 +1,62 @@
1
+ import { toEnDigits } from "./digits.js";
2
+ // کد سه‌رقمی بانک در شبا (رقم‌های ۵ تا ۷ پس از IR). فهرست ممکن است کامل نباشد.
3
+ const BANK_CODES = {
4
+ "010": { name: "بانک مرکزی", slug: "markazi" },
5
+ "011": { name: "بانک صنعت و معدن", slug: "bim" },
6
+ "012": { name: "بانک ملت", slug: "mellat" },
7
+ "013": { name: "بانک رفاه", slug: "refah" },
8
+ "014": { name: "بانک مسکن", slug: "maskan" },
9
+ "015": { name: "بانک سپه", slug: "sepah" },
10
+ "016": { name: "بانک کشاورزی", slug: "keshavarzi" },
11
+ "017": { name: "بانک ملی", slug: "melli" },
12
+ "018": { name: "بانک تجارت", slug: "tejarat" },
13
+ "019": { name: "بانک صادرات", slug: "saderat" },
14
+ "020": { name: "بانک توسعه صادرات", slug: "edbi" },
15
+ "021": { name: "پست بانک", slug: "postbank" },
16
+ "022": { name: "بانک توسعه تعاون", slug: "tosee-taavon" },
17
+ "053": { name: "بانک کارآفرین", slug: "karafarin" },
18
+ "054": { name: "بانک پارسیان", slug: "parsian" },
19
+ "055": { name: "بانک اقتصاد نوین", slug: "eghtesad-novin" },
20
+ "056": { name: "بانک سامان", slug: "saman" },
21
+ "057": { name: "بانک پاسارگاد", slug: "pasargad" },
22
+ "058": { name: "بانک سرمایه", slug: "sarmayeh" },
23
+ "059": { name: "بانک سینا", slug: "sina" },
24
+ "060": { name: "بانک قرض‌الحسنه مهر ایران", slug: "mehr-iran" },
25
+ "061": { name: "بانک شهر", slug: "shahr" },
26
+ "062": { name: "بانک آینده", slug: "ayandeh" },
27
+ "064": { name: "بانک گردشگری", slug: "gardeshgari" },
28
+ "066": { name: "بانک دی", slug: "dey" },
29
+ "069": { name: "بانک ایران زمین", slug: "iran-zamin" },
30
+ "070": { name: "بانک قرض‌الحسنه رسالت", slug: "resalat" },
31
+ "078": { name: "بانک خاورمیانه", slug: "khavarmianeh" },
32
+ };
33
+ /** ۲۴ رقم شبا بدون IR؛ «IR12 0170…» یا «۱۲۰۱۷۰…» را می‌پذیرد */
34
+ export function ibanDigits(value) {
35
+ return toEnDigits(value).toUpperCase().replace(/^\s*IR/, "").replace(/\D/g, "").slice(0, 24);
36
+ }
37
+ /** باقیماندهٔ تقسیم یک عدد بلند (به‌صورت رشته) بر ۹۷ */
38
+ function mod97(numeric) {
39
+ let r = 0;
40
+ for (let i = 0; i < numeric.length; i += 7)
41
+ r = Number(String(r) + numeric.slice(i, i + 7)) % 97;
42
+ return r;
43
+ }
44
+ /** اعتبارسنجی شماره شبا (IBAN ایران): IR + ۲۴ رقم با رقم‌های کنترل ISO 13616 */
45
+ export function isValidIban(value) {
46
+ const raw = toEnDigits(value).toUpperCase().replace(/[\s-]/g, "");
47
+ const digits = raw.startsWith("IR") ? raw.slice(2) : raw;
48
+ if (!/^\d{24}$/.test(digits))
49
+ return false;
50
+ // I=18، R=27؛ دو حرف و رقم‌های کنترل به انتهای شماره منتقل می‌شوند
51
+ return mod97(digits.slice(2) + "1827" + digits.slice(0, 2)) === 1;
52
+ }
53
+ /** نام بانک از روی شبا؛ اگر شناخته نشود null */
54
+ export function getBankByIban(value) {
55
+ const d = ibanDigits(value);
56
+ return d.length >= 5 ? (BANK_CODES[d.slice(2, 5)] ?? null) : null;
57
+ }
58
+ /** IR + گروه‌های چهارتایی: IR06 0170 0000 … */
59
+ export function formatIban(value) {
60
+ const d = ibanDigits(value);
61
+ return d ? `IR${d}`.replace(/(.{4})(?=.)/g, "$1 ") : "";
62
+ }
package/dist/index.d.ts CHANGED
@@ -5,3 +5,9 @@ export type { JalaliDate, FormatJalaliOptions } from "./jalali.js";
5
5
  export { isValidNationalId } from "./national-id.js";
6
6
  export { isValidCardNumber, getBankByCard, formatCardNumber } from "./card.js";
7
7
  export type { Bank } from "./card.js";
8
+ export { isValidIban, getBankByIban, formatIban, ibanDigits } from "./iban.js";
9
+ export { normalizeMobile, isValidMobile, getMobileOperator, formatMobile } from "./mobile.js";
10
+ export type { Operator } from "./mobile.js";
11
+ export { numberToWords } from "./words.js";
12
+ export { normalizePersian } from "./text.js";
13
+ export type { NormalizeOptions } from "./text.js";
package/dist/index.js CHANGED
@@ -2,3 +2,7 @@ export { toFaDigits, toEnDigits, onlyDigits, formatNumber } from "./digits.js";
2
2
  export { JALALI_MONTHS, WEEKDAYS, WEEKDAYS_SHORT, toJalali, toGregorian, isLeapJalaliYear, jalaliMonthLength, isValidJalaliDate, jalaliWeekday, formatJalali, parseJalali, toISODate, fromISODate, } from "./jalali.js";
3
3
  export { isValidNationalId } from "./national-id.js";
4
4
  export { isValidCardNumber, getBankByCard, formatCardNumber } from "./card.js";
5
+ export { isValidIban, getBankByIban, formatIban, ibanDigits } from "./iban.js";
6
+ export { normalizeMobile, isValidMobile, getMobileOperator, formatMobile } from "./mobile.js";
7
+ export { numberToWords } from "./words.js";
8
+ export { normalizePersian } from "./text.js";
@@ -0,0 +1,15 @@
1
+ export interface Operator {
2
+ name: string;
3
+ slug: "mci" | "irancell" | "rightel";
4
+ }
5
+ /**
6
+ * شماره موبایل را به شکل استاندارد ۰۹xxxxxxxxx درمی‌آورد.
7
+ * +98912…، 0098912…، 98912… و 912… پذیرفته می‌شوند. اگر ساختار درست نباشد، ارقام همان‌طور برمی‌گردند.
8
+ */
9
+ export declare function normalizeMobile(value: string): string;
10
+ /** شماره موبایل ایران: ۱۱ رقم که با ۰۹ شروع می‌شود */
11
+ export declare function isValidMobile(value: string): boolean;
12
+ /** اپراتور از روی پیش‌شماره؛ اگر شناخته نشود null */
13
+ export declare function getMobileOperator(value: string): Operator | null;
14
+ /** ۰۹۱۲ ۳۴۵ ۶۷۸۹ */
15
+ export declare function formatMobile(value: string): string;
package/dist/mobile.js ADDED
@@ -0,0 +1,38 @@
1
+ import { onlyDigits } from "./digits.js";
2
+ const MCI = { name: "همراه اول", slug: "mci" };
3
+ const IRANCELL = { name: "ایرانسل", slug: "irancell" };
4
+ const RIGHTEL = { name: "رایتل", slug: "rightel" };
5
+ // پیش‌شماره‌ها پس از ۰۹؛ فهرست اپراتورهای اصلی، ممکن است کامل نباشد
6
+ const PREFIXES = {
7
+ ...Object.fromEntries(["10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "90", "91", "92", "93", "94"].map((p) => [p, MCI])),
8
+ ...Object.fromEntries(["01", "02", "03", "04", "05", "30", "33", "35", "36", "37", "38", "39", "41"].map((p) => [p, IRANCELL])),
9
+ ...Object.fromEntries(["20", "21", "22"].map((p) => [p, RIGHTEL])),
10
+ };
11
+ /**
12
+ * شماره موبایل را به شکل استاندارد ۰۹xxxxxxxxx درمی‌آورد.
13
+ * +98912…، 0098912…، 98912… و 912… پذیرفته می‌شوند. اگر ساختار درست نباشد، ارقام همان‌طور برمی‌گردند.
14
+ */
15
+ export function normalizeMobile(value) {
16
+ let d = onlyDigits(value);
17
+ if (d.startsWith("0098"))
18
+ d = "0" + d.slice(4);
19
+ else if (d.startsWith("98") && d.length === 12)
20
+ d = "0" + d.slice(2);
21
+ else if (d.startsWith("9") && d.length === 10)
22
+ d = "0" + d;
23
+ return d;
24
+ }
25
+ /** شماره موبایل ایران: ۱۱ رقم که با ۰۹ شروع می‌شود */
26
+ export function isValidMobile(value) {
27
+ return /^09\d{9}$/.test(normalizeMobile(value));
28
+ }
29
+ /** اپراتور از روی پیش‌شماره؛ اگر شناخته نشود null */
30
+ export function getMobileOperator(value) {
31
+ const d = normalizeMobile(value);
32
+ return d.length >= 4 && d.startsWith("09") ? (PREFIXES[d.slice(2, 4)] ?? null) : null;
33
+ }
34
+ /** ۰۹۱۲ ۳۴۵ ۶۷۸۹ */
35
+ export function formatMobile(value) {
36
+ const d = normalizeMobile(value).slice(0, 11);
37
+ return [d.slice(0, 4), d.slice(4, 7), d.slice(7, 11)].filter(Boolean).join(" ");
38
+ }
package/dist/text.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export interface NormalizeOptions {
2
+ /** خط ارقام خروجی؛ undefined یعنی بدون تغییر */
3
+ digits?: "fa" | "latin";
4
+ }
5
+ /**
6
+ * یکدست‌سازی متن فارسی برای ذخیره و جستجو:
7
+ * «ي» و «ى» عربی ← «ی»، «ك» ← «ک»، «ة» ← «ه»، حذف اعراب و کشیده (ـ)،
8
+ * و جمع کردن فاصله‌ها و نیم‌فاصله‌های تکراری.
9
+ */
10
+ export declare function normalizePersian(text: string, { digits }?: NormalizeOptions): string;
package/dist/text.js ADDED
@@ -0,0 +1,23 @@
1
+ import { toEnDigits, toFaDigits } from "./digits.js";
2
+ /**
3
+ * یکدست‌سازی متن فارسی برای ذخیره و جستجو:
4
+ * «ي» و «ى» عربی ← «ی»، «ك» ← «ک»، «ة» ← «ه»، حذف اعراب و کشیده (ـ)،
5
+ * و جمع کردن فاصله‌ها و نیم‌فاصله‌های تکراری.
6
+ */
7
+ export function normalizePersian(text, { digits } = {}) {
8
+ let out = text
9
+ .replace(/[يى]/g, "ی")
10
+ .replace(/ك/g, "ک")
11
+ .replace(/ة/g, "ه")
12
+ .replace(/[ً-ٰٟ]/g, "") // اعراب
13
+ .replace(/ـ/g, "") // کشیده
14
+ .replace(/‌{2,}/g, "‌")
15
+ .replace(/ *‌ */g, "‌")
16
+ .replace(/[ \t]{2,}/g, " ")
17
+ .trim();
18
+ if (digits === "fa")
19
+ out = toFaDigits(toEnDigits(out));
20
+ if (digits === "latin")
21
+ out = toEnDigits(out);
22
+ return out;
23
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * عدد به حروف فارسی: 1250000 → «یک میلیون و دویست و پنجاه هزار».
3
+ * برای اعداد صحیح تا ۹۹۹ تریلیون. «هزار» بدون «یک» خوانده می‌شود (۱۰۰۰ → هزار).
4
+ */
5
+ export declare function numberToWords(value: number | bigint): string;
package/dist/words.js ADDED
@@ -0,0 +1,44 @@
1
+ const ONES = ["", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", "نه"];
2
+ const TEENS = ["ده", "یازده", "دوازده", "سیزده", "چهارده", "پانزده", "شانزده", "هفده", "هجده", "نوزده"];
3
+ const TENS = ["", "", "بیست", "سی", "چهل", "پنجاه", "شصت", "هفتاد", "هشتاد", "نود"];
4
+ const HUNDREDS = ["", "صد", "دویست", "سیصد", "چهارصد", "پانصد", "ششصد", "هفتصد", "هشتصد", "نهصد"];
5
+ const SCALES = ["", "هزار", "میلیون", "میلیارد", "تریلیون"];
6
+ function under1000(n) {
7
+ const parts = [];
8
+ const h = Math.floor(n / 100);
9
+ const rest = n % 100;
10
+ if (h)
11
+ parts.push(HUNDREDS[h]);
12
+ if (rest >= 10 && rest < 20)
13
+ parts.push(TEENS[rest - 10]);
14
+ else {
15
+ if (rest >= 20)
16
+ parts.push(TENS[Math.floor(rest / 10)]);
17
+ if (rest % 10)
18
+ parts.push(ONES[rest % 10]);
19
+ }
20
+ return parts.join(" و ");
21
+ }
22
+ /**
23
+ * عدد به حروف فارسی: 1250000 → «یک میلیون و دویست و پنجاه هزار».
24
+ * برای اعداد صحیح تا ۹۹۹ تریلیون. «هزار» بدون «یک» خوانده می‌شود (۱۰۰۰ → هزار).
25
+ */
26
+ export function numberToWords(value) {
27
+ let n = typeof value === "bigint" ? value : BigInt(Math.trunc(value));
28
+ if (n === 0n)
29
+ return "صفر";
30
+ const negative = n < 0n;
31
+ if (negative)
32
+ n = -n;
33
+ if (n >= 10n ** 15n)
34
+ throw new RangeError("عدد بزرگ‌تر از حد پشتیبانی‌شده است");
35
+ const groups = [];
36
+ for (let i = 0; n > 0n; i++, n /= 1000n) {
37
+ const g = Number(n % 1000n);
38
+ if (!g)
39
+ continue;
40
+ const words = i === 1 && g === 1 ? "" : under1000(g);
41
+ groups.unshift([words, SCALES[i]].filter(Boolean).join(" "));
42
+ }
43
+ return (negative ? "منفی " : "") + groups.join(" و ");
44
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kashi-ui/persian",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "ابزارهای فارسی کاشی: تاریخ شمسی، اعتبارسنجی کد ملی و شماره کارت، ارقام فارسی",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",