{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface NormalizeOptions {\n  /** Remove harakat/tashkeel diacritics (default: true) */\n  diacritics?: boolean;\n  /** Remove Quranic markers like sajdah, rub el hizb (default: true) */\n  markers?: boolean;\n  /** Remove verse numbers and their brackets (default: true) */\n  verseNumbers?: boolean;\n  /** Remove tatweel/kashida elongation (default: true) */\n  tatweel?: boolean;\n  /** Remove small/superscript letters (default: true) */\n  smallLetters?: boolean;\n  /** Remove punctuation like periods, commas, semicolons (default: true) */\n  punctuation?: boolean;\n  /** Collapse multiple whitespace to single space (default: true) */\n  collapseWhitespace?: boolean;\n  /**\n   * Strip hamza carriers entirely (default: false)\n   *\n   * Aggressively normalizes for Uthmani ↔ common Arabic matching:\n   * - Removes hamza carriers (أ إ ئ ء) and converts ؤ→و\n   * - Normalizes alef maqsura (ى→ي) and Farsi yeh (ی→ي)\n   * - Normalizes Uthmani spelling variants (الصلوة→الصلاة)\n   *\n   * Examples:\n   * - يسألونك → يسلونك (matches Uthmani يَسْـَٔلُونَكَ)\n   * - يؤوده → يوده (matches Uthmani يَـُٔودُهُ)\n   * - بشيء → بشي (matches Uthmani بِشَىْءٍ after ى→ي)\n   */\n  stripHamza?: boolean;\n}\n\n// Arabic tashkeel/harakat: U+064B-U+065F (includes shadda U+0651)\nconst DIACRITICS = /[\\u064B-\\u065F]/g;\n\n// Alif with madda above (آ U+0622) -> plain alif (ا U+0627)\nconst ALIF_MADDA = /\\u0622/g;\n\n// Alif wasla (ٱ U+0671) -> plain alif (ا U+0627)\nconst ALIF_WASLA = /\\u0671/g;\n\n// Alif variants: U+0672 (wavy hamza above), U+0673 (wavy hamza below) -> plain alif\nconst ALIF_VARIANTS = /[\\u0672\\u0673]/g;\n\n// Superscript alif (ٰ U+0670) -> plain alif (ا U+0627)\nconst SUPERSCRIPT_ALIF = /\\u0670/g;\n\n// Farsi/Urdu yeh variants -> Arabic yeh (ي U+064A)\n// ی (U+06CC Farsi yeh), ے (U+06D2 yeh barree) are common in LLM output\nconst FARSI_YEH = /[\\u06CC\\u06D2]/g;\n\n// Farsi/Urdu kaf (ک U+06A9) -> Arabic kaf (ك U+0643)\nconst FARSI_KAF = /\\u06A9/g;\n\n// Quranic annotation marks: U+06D6-U+06ED\nconst QURANIC_ANNOTATIONS = /[\\u06D6-\\u06ED]/g;\n\n// Small letters (superscript): small high letters used in Quranic text\n// U+06E5 (small waw), U+06E6 (small ya), etc. are in QURANIC_ANNOTATIONS range\n\n// End of ayah U+06DD, start of rub el hizb U+06DE, place of sajdah U+06E9\n// These are included in QURANIC_ANNOTATIONS range (U+06D6-U+06ED)\n\n// Tatweel/kashida: U+0640\nconst TATWEEL = /\\u0640/g;\n\n// Ornate parentheses: U+FD3E, U+FD3F\nconst ORNATE_PARENS = /[\\uFD3E\\uFD3F]/g;\n\n// Arabic-Indic digits: U+0660-U+0669\n// Extended Arabic-Indic digits: U+06F0-U+06F9\nconst ARABIC_DIGITS = /[\\u0660-\\u0669\\u06F0-\\u06F9]/g;\n\n// Common punctuation: periods, commas, colons, semicolons, exclamation, question marks, ellipsis\n// Arabic comma U+060C, Arabic semicolon U+061B, Arabic question mark U+061F\nconst PUNCTUATION = /[.,;:!?…\\u060C\\u061B\\u061F]/g;\n\n// Multiple whitespace\nconst MULTI_WHITESPACE = /\\s+/g;\n\n// Hamza forms that should be stripped to match Uthmani behavior:\n// أ (U+0623) alef-hamza above - Uthmani uses floating hamza on tatweel\n// إ (U+0625) alef-hamza below - Uthmani uses floating hamza on tatweel\n// ئ (U+0626) ya-hamza - Uthmani uses floating hamza on previous ya\n// ء (U+0621) standalone hamza\n// Note: ؤ (U+0624) is NOT stripped - it's represented the same in both common and Uthmani Arabic\nconst HAMZA_TO_STRIP = /[\\u0621\\u0623\\u0625\\u0626]/g;\n\n// Alef maqsura (ى U+0649) -> ya (ي U+064A) when stripHamza is true\nconst ALEF_MAQSURA = /\\u0649/g;\n\n// Uthmani spelling equivalents - normalize to modern Arabic form\n// These are archaic Quranic spellings that differ from modern standard Arabic:\n// - الصلوة/الصلاة (prayer) - Uthmani uses waw before taa marbuta\n// - الزكوة/الزكاة (charity) - Uthmani uses waw before taa marbuta\n// - الحيوة/الحياة (life) - Uthmani uses waw before taa marbuta\n// Pattern: وة or واة → اة (واة appears when superscript alef ٰ was already converted to alef)\nconst UTHMANI_WAW_TA = /وا?ة/g;\n\n// Double ya in modern Arabic vs single ya in Uthmani\n// النبيين (modern) vs النبين (Uthmani)\n// This pattern catches يي sequences\nconst DOUBLE_YA = /يي/g;\n\n// Sad/Sin equivalence in Uthmani orthography — specific known variants only\n// Certain Quranic words use ص in some manuscripts and س in others.\n// We normalize to the سين form for consistent matching:\n// Root ب-س-ط (to extend): بسطة/بصطة (2:247, 7:69), يبسط/يبصط (2:245)\n// Root س-ي-ط-ر (to control): المسيطرون/المصيطرون (52:37), بمسيطر/بمصيطر (88:22)\nconst SAD_SIN_VARIANTS: [RegExp, string][] = [\n  [/بصط/g, 'بسط'],     // ب-ص-ط → ب-س-ط\n  [/صيطر/g, 'سيطر'],   // ص-ي-ط-ر → س-ي-ط-ر\n];\n\nconst DEFAULT_OPTIONS: Required<NormalizeOptions> = {\n  diacritics: true,\n  markers: true,\n  verseNumbers: true,\n  tatweel: true,\n  smallLetters: true,\n  punctuation: true,\n  collapseWhitespace: true,\n  stripHamza: false,\n};\n\n/**\n * Normalize Arabic/Quranic text by removing diacritics, markers, and decorative characters.\n *\n * @param text - The Arabic text to normalize\n * @param options - Normalization options (all default to true for full normalization)\n * @returns Normalized plain Arabic text\n *\n * @example\n * ```ts\n * import { normalize } from 'arabic-text-normalizer';\n *\n * // Full normalization (default)\n * normalize('بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ');\n * // => 'بسم الله الرحمن الرحيم'\n *\n * // Keep diacritics\n * normalize('بِسْمِ', { diacritics: false });\n * // => 'بِسْمِ'\n * ```\n */\nexport function normalize(text: string, options: NormalizeOptions = {}): string {\n  const opts = { ...DEFAULT_OPTIONS, ...options };\n  let result = text;\n\n  if (opts.diacritics) {\n    // Strip all diacritics (tashkeel) including shadda\n    result = result.replace(DIACRITICS, \"\");\n    result = result.replace(ALIF_MADDA, \"\\u0627\"); // آ -> ا\n    result = result.replace(ALIF_WASLA, \"\\u0627\"); // ٱ -> ا\n    result = result.replace(ALIF_VARIANTS, \"\\u0627\"); // ٲ ٳ -> ا\n    // Strip superscript alef when preceded by regular alef (LLMs write اٰ\n    // but Uthmani has ـٰ; without this, اٰ→اا while ـٰ→ا after tatweel strip)\n    result = result.replace(/\\u0627\\u0670/g, \"\\u0627\"); // اٰ -> ا\n    result = result.replace(SUPERSCRIPT_ALIF, \"\\u0627\"); // remaining ٰ -> ا\n    // Normalize Farsi/Urdu character variants\n    result = result.replace(FARSI_YEH, \"\\u064A\"); // ی ے -> ي\n    result = result.replace(FARSI_KAF, \"\\u0643\"); // ک -> ك\n  }\n\n  if (opts.markers || opts.smallLetters) {\n    // QURANIC_ANNOTATIONS includes both markers and small letters\n    result = result.replace(QURANIC_ANNOTATIONS, \"\");\n  }\n\n  if (opts.verseNumbers) {\n    result = result.replace(ORNATE_PARENS, \"\");\n    result = result.replace(ARABIC_DIGITS, \"\");\n  }\n\n  if (opts.tatweel) {\n    result = result.replace(TATWEEL, \"\");\n  }\n\n  if (opts.punctuation) {\n    result = result.replace(PUNCTUATION, \"\");\n  }\n\n  if (opts.stripHamza) {\n    // Strip hamza forms that are represented differently in Uthmani\n    // (أ إ ئ ء are stripped; ؤ is preserved as it's the same in both)\n    result = result.replace(HAMZA_TO_STRIP, \"\");\n    // Normalize alef maqsura to ya for consistent matching\n    result = result.replace(ALEF_MAQSURA, \"\\u064A\"); // ى -> ي\n    // Normalize Uthmani spelling variants to modern form\n    // الصلوة → الصلاة, الزكوة → الزكاة, الزكواة → الزكاة\n    result = result.replace(UTHMANI_WAW_TA, \"اة\"); // وة/واة → اة\n    // Normalize double ya to single ya (النبيين → النبين)\n    result = result.replace(DOUBLE_YA, \"ي\");\n    // Normalize known ص/س Uthmani orthographic variants to سين form\n    for (const [pattern, replacement] of SAD_SIN_VARIANTS) {\n      result = result.replace(pattern, replacement);\n    }\n    // Collapse definite-article double-lam to match Uthmani لّ encoding\n    // LLM writes بالليل (2 lams), Uthmani بٱلّيل normalizes to باليل (1 lam)\n    result = result.replace(/([ا])لل/g, \"$1ل\");\n  }\n\n  if (opts.collapseWhitespace) {\n    result = result.replace(MULTI_WHITESPACE, \" \").trim();\n  }\n\n  return result;\n}\n\nexport default normalize;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCA,IAAM,aAAa;AAGnB,IAAM,aAAa;AAGnB,IAAM,aAAa;AAGnB,IAAM,gBAAgB;AAGtB,IAAM,mBAAmB;AAIzB,IAAM,YAAY;AAGlB,IAAM,YAAY;AAGlB,IAAM,sBAAsB;AAS5B,IAAM,UAAU;AAGhB,IAAM,gBAAgB;AAItB,IAAM,gBAAgB;AAItB,IAAM,cAAc;AAGpB,IAAM,mBAAmB;AAQzB,IAAM,iBAAiB;AAGvB,IAAM,eAAe;AAQrB,IAAM,iBAAiB;AAKvB,IAAM,YAAY;AAOlB,IAAM,mBAAuC;AAAA,EAC3C,CAAC,QAAQ,oBAAK;AAAA;AAAA,EACd,CAAC,SAAS,0BAAM;AAAA;AAClB;AAEA,IAAM,kBAA8C;AAAA,EAClD,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,cAAc;AAAA,EACd,SAAS;AAAA,EACT,cAAc;AAAA,EACd,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,YAAY;AACd;AAsBO,SAAS,UAAU,MAAc,UAA4B,CAAC,GAAW;AAC9E,QAAM,OAAO,EAAE,GAAG,iBAAiB,GAAG,QAAQ;AAC9C,MAAI,SAAS;AAEb,MAAI,KAAK,YAAY;AAEnB,aAAS,OAAO,QAAQ,YAAY,EAAE;AACtC,aAAS,OAAO,QAAQ,YAAY,QAAQ;AAC5C,aAAS,OAAO,QAAQ,YAAY,QAAQ;AAC5C,aAAS,OAAO,QAAQ,eAAe,QAAQ;AAG/C,aAAS,OAAO,QAAQ,iBAAiB,QAAQ;AACjD,aAAS,OAAO,QAAQ,kBAAkB,QAAQ;AAElD,aAAS,OAAO,QAAQ,WAAW,QAAQ;AAC3C,aAAS,OAAO,QAAQ,WAAW,QAAQ;AAAA,EAC7C;AAEA,MAAI,KAAK,WAAW,KAAK,cAAc;AAErC,aAAS,OAAO,QAAQ,qBAAqB,EAAE;AAAA,EACjD;AAEA,MAAI,KAAK,cAAc;AACrB,aAAS,OAAO,QAAQ,eAAe,EAAE;AACzC,aAAS,OAAO,QAAQ,eAAe,EAAE;AAAA,EAC3C;AAEA,MAAI,KAAK,SAAS;AAChB,aAAS,OAAO,QAAQ,SAAS,EAAE;AAAA,EACrC;AAEA,MAAI,KAAK,aAAa;AACpB,aAAS,OAAO,QAAQ,aAAa,EAAE;AAAA,EACzC;AAEA,MAAI,KAAK,YAAY;AAGnB,aAAS,OAAO,QAAQ,gBAAgB,EAAE;AAE1C,aAAS,OAAO,QAAQ,cAAc,QAAQ;AAG9C,aAAS,OAAO,QAAQ,gBAAgB,cAAI;AAE5C,aAAS,OAAO,QAAQ,WAAW,QAAG;AAEtC,eAAW,CAAC,SAAS,WAAW,KAAK,kBAAkB;AACrD,eAAS,OAAO,QAAQ,SAAS,WAAW;AAAA,IAC9C;AAGA,aAAS,OAAO,QAAQ,YAAY,UAAK;AAAA,EAC3C;AAEA,MAAI,KAAK,oBAAoB;AAC3B,aAAS,OAAO,QAAQ,kBAAkB,GAAG,EAAE,KAAK;AAAA,EACtD;AAEA,SAAO;AACT;AAEA,IAAO,gBAAQ;","names":[]}