bitaboom 1.2.0 → 1.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 CHANGED
@@ -654,3 +654,57 @@ stripZeroWidthCharacters('يَخْلُوَ ‏.');
654
654
  ```
655
655
 
656
656
  ---
657
+
658
+ ### `truncate`
659
+
660
+ Truncates a string to a specified length, adding an ellipsis if truncated.
661
+
662
+ #### Example:
663
+
664
+ ```javascript
665
+ truncate('The quick brown fox jumps over the lazy dog', 20);
666
+ // Output: 'The quick brown fox…'
667
+
668
+ truncate('Short text', 50);
669
+ // Output: 'Short text'
670
+ ```
671
+
672
+ ---
673
+
674
+ ### `truncateMiddle`
675
+
676
+ Truncates a string from the middle, preserving both the beginning and end portions.
677
+
678
+ #### Example:
679
+
680
+ ```javascript
681
+ truncateMiddle('The quick brown fox jumps right over the lazy dog', 20);
682
+ // Output: 'The quick bro…zy dog'
683
+
684
+ truncateMiddle('The quick brown fox jumps right over the lazy dog', 25, 8);
685
+ // Output: 'The quick brown …lazy dog'
686
+
687
+ truncateMiddle('Short text', 50);
688
+ // Output: 'Short text'
689
+ ```
690
+
691
+ ---
692
+
693
+ ### `unescapeSpaces`
694
+
695
+ Unescapes backslash-escaped spaces and trims whitespace from both ends. Commonly used to clean file paths that have been escaped when pasted into terminals.
696
+
697
+ #### Example:
698
+
699
+ ```javascript
700
+ unescapeSpaces('My\\ Folder\\ Name');
701
+ // Output: 'My Folder Name'
702
+
703
+ unescapeSpaces(' /path/to/My\\ Document.txt ');
704
+ // Output: '/path/to/My Document.txt'
705
+
706
+ unescapeSpaces('regular text');
707
+ // Output: 'regular text'
708
+ ```
709
+
710
+ ---
package/dist/index.d.ts CHANGED
@@ -428,6 +428,64 @@ export const removeSingleDigitReferences: (text: string) => string;
428
428
  * @returns {string} - The modified text with URLs removed.
429
429
  */
430
430
  export const removeUrls: (text: string) => string;
431
+ /**
432
+ * Truncates a string to a specified length, adding an ellipsis if truncated.
433
+ *
434
+ * @param val - The string to truncate
435
+ * @param n - Maximum length of the string (default: 150)
436
+ * @returns The truncated string with ellipsis if needed, otherwise the original string
437
+ *
438
+ * @example
439
+ * ```javascript
440
+ * truncate('The quick brown fox jumps over the lazy dog', 20);
441
+ * // Output: 'The quick brown fox…'
442
+ *
443
+ * truncate('Short text', 50);
444
+ * // Output: 'Short text'
445
+ * ```
446
+ */
447
+ export const truncate: (val: string, n?: number) => string;
448
+ /**
449
+ * Truncates a string from the middle, preserving both the beginning and end portions.
450
+ *
451
+ * @param text - The string to truncate
452
+ * @param maxLength - Maximum length of the resulting string (default: 50)
453
+ * @param endLength - Number of characters to preserve at the end (default: 1/3 of maxLength, minimum 3)
454
+ * @returns The truncated string with ellipsis in the middle if needed, otherwise the original string
455
+ *
456
+ * @example
457
+ * ```javascript
458
+ * truncateMiddle('The quick brown fox jumps right over the lazy dog', 20);
459
+ * // Output: 'The quick bro…zy dog'
460
+ *
461
+ * truncateMiddle('The quick brown fox jumps right over the lazy dog', 25, 8);
462
+ * // Output: 'The quick brown …lazy dog'
463
+ *
464
+ * truncateMiddle('Short text', 50);
465
+ * // Output: 'Short text'
466
+ * ```
467
+ */
468
+ export const truncateMiddle: (text: string, maxLength?: number, endLength?: number) => string;
469
+ /**
470
+ * Unescapes backslash-escaped spaces and trims whitespace from both ends.
471
+ * Commonly used to clean file paths that have been escaped when pasted into terminals.
472
+ *
473
+ * @param input - The string to unescape and clean
474
+ * @returns The cleaned string with escaped spaces converted to regular spaces and trimmed
475
+ *
476
+ * @example
477
+ * ```javascript
478
+ * unescapeSpaces('My\\ Folder\\ Name');
479
+ * // Output: 'My Folder Name'
480
+ *
481
+ * unescapeSpaces(' /path/to/My\\ Document.txt ');
482
+ * // Output: '/path/to/My Document.txt'
483
+ *
484
+ * unescapeSpaces('regular text');
485
+ * // Output: 'regular text'
486
+ * ```
487
+ */
488
+ export const unescapeSpaces: (input: string) => string;
431
489
  /**
432
490
  * Replaces common Arabic prefixes (like 'Al-', 'Ar-', 'Ash-', etc.) with 'al-' in the text.
433
491
  * Handles different variations of prefixes such as Ash- and Al- but not when the second word
package/dist/main.js CHANGED
@@ -406,13 +406,16 @@ $parcel$export($15eb38b546e8440a$exports, "removeDeathYear", () => $15eb38b546e8
406
406
  $parcel$export($15eb38b546e8440a$exports, "removeNumbersAndDashes", () => $15eb38b546e8440a$export$c8e7d4d7d9f46256);
407
407
  $parcel$export($15eb38b546e8440a$exports, "removeSingleDigitReferences", () => $15eb38b546e8440a$export$8e7f001aa315ad82);
408
408
  $parcel$export($15eb38b546e8440a$exports, "removeUrls", () => $15eb38b546e8440a$export$e4a0bb7881a4591a);
409
+ $parcel$export($15eb38b546e8440a$exports, "truncate", () => $15eb38b546e8440a$export$6a506b36fdea397d);
410
+ $parcel$export($15eb38b546e8440a$exports, "truncateMiddle", () => $15eb38b546e8440a$export$f3a88d5244308057);
411
+ $parcel$export($15eb38b546e8440a$exports, "unescapeSpaces", () => $15eb38b546e8440a$export$1791d17c7d9c448);
409
412
  /**
410
413
  * Removes various symbols, part references, and numerical markers from the text.
411
414
  * Example: '(1) (2/3)' becomes ''.
412
415
  * @param {string} text - The input text to apply the rule to.
413
416
  * @returns {string} - The modified text with symbols and part references removed.
414
417
  */ const $15eb38b546e8440a$export$70476c4e7ef0b147 = (text)=>{
415
- return text.replace(/ *\(?:\d+(?:\/\d+){0,2}\)? *| *\[\d+(?:\/\d+)?\] *| *«\d+» *|\d+\/\d+(?:\/\d+)?|[،§{}۝؍‎﴿﴾<>;_؟»«:!،؛\[\]…ـ¬\.\\\/\*\(\)"]/g, ' ');
418
+ return text.replace(/ *\(?:\d+(?:\/\d+){0,2}\)? *| *\[\d+(?:\/\d+)?\] *| *«\d+» *|\d+\/\d+(?:\/\d+)?|[،§{}۝؍‎﴿﴾<>;_؟»«:!،؛[\]…ـ¬.\\/*()"]/g, ' ');
416
419
  };
417
420
  const $15eb38b546e8440a$export$9f81734a6223638b = (text)=>{
418
421
  return text.replace(/-\[\d+\]-/g, '');
@@ -435,6 +438,24 @@ const $15eb38b546e8440a$export$8e7f001aa315ad82 = (text)=>{
435
438
  const $15eb38b546e8440a$export$e4a0bb7881a4591a = (text)=>{
436
439
  return text.replace(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g, '');
437
440
  };
441
+ const $15eb38b546e8440a$export$6a506b36fdea397d = (val, n = 150)=>val.length > n ? `${val.substring(0, n - 1)}\u{2026}` : val;
442
+ const $15eb38b546e8440a$export$f3a88d5244308057 = (text, maxLength = 50, endLength)=>{
443
+ if (text.length <= maxLength) return text;
444
+ // Default end length is roughly 1/3 of max length, minimum 3 characters
445
+ const defaultEndLength = Math.max(3, Math.floor(maxLength / 3));
446
+ const actualEndLength = endLength ?? defaultEndLength;
447
+ // Reserve space for the ellipsis character (1 char)
448
+ const availableLength = maxLength - 1;
449
+ // Calculate start length (remaining space after end portion)
450
+ const startLength = availableLength - actualEndLength;
451
+ // Ensure we have at least some characters at the start
452
+ if (startLength < 1) // If we can't fit both start and end, just truncate normally
453
+ return `${text.substring(0, maxLength - 1)}\u{2026}`;
454
+ const startPortion = text.substring(0, startLength);
455
+ const endPortion = text.substring(text.length - actualEndLength);
456
+ return `${startPortion}\u{2026}${endPortion}`;
457
+ };
458
+ const $15eb38b546e8440a$export$1791d17c7d9c448 = (input)=>input.replace(/\\ /g, ' ').trim();
438
459
 
439
460
 
440
461
  var $0c91e05aa031e32a$exports = {};
@@ -477,5 +498,5 @@ const $0c91e05aa031e32a$export$d421e6fd95c29a67 = (fullName)=>{
477
498
 
478
499
 
479
500
 
480
- export {$798f85a7713a6ff1$export$60dc7fb96c441688 as cleanExtremeArabicUnderscores, $798f85a7713a6ff1$export$dcf00cfaf31fd188 as convertUrduSymbolsToArabic, $798f85a7713a6ff1$export$6c58e29008d10c1d as fixTrailingWow, $798f85a7713a6ff1$export$cf81487e80b00e26 as addSpaceBetweenArabicTextAndNumbers, $798f85a7713a6ff1$export$df81ab2e9352ca65 as stripEnglishCharactersAndSymbols, $798f85a7713a6ff1$export$d580a3cb14401529 as removeNonIndexSignatures, $798f85a7713a6ff1$export$84d849da647fa2e5 as removeSingularCodes, $798f85a7713a6ff1$export$7dedbc726019ed0f as removeSolitaryArabicLetters, $798f85a7713a6ff1$export$9571c9c2c203652d as removeTatwil, $798f85a7713a6ff1$export$f95230335378ec58 as replaceTaMarbutahWithHa, $798f85a7713a6ff1$export$b5bee4b27048330b as stripDiacritics, $798f85a7713a6ff1$export$8696bb09194c5fb5 as stripZeroWidthCharacters, $798f85a7713a6ff1$export$b1d6cb321dee12ad as replaceAlifMaqsurah, $798f85a7713a6ff1$export$db0c96cd03237332 as replaceEnglishPunctuationWithArabic, $798f85a7713a6ff1$export$1d28b07894af8a98 as normalizeAlifVariants, $86c5c45def76a44f$export$814bebc253f2e5df as insertLineBreaksAfterPunctuation, $86c5c45def76a44f$export$f0306841cd6b95d5 as addSpaceBeforeAndAfterPunctuation, $86c5c45def76a44f$export$42f47e081bfe828c as applySmartQuotes, $86c5c45def76a44f$export$b4922cc8c111eae2 as cleanLiteralNewLines, $86c5c45def76a44f$export$95680a0d9bdd5dba as cleanMultilines, $86c5c45def76a44f$export$20a121a9317a6ed4 as hasWordInSingleLine, $86c5c45def76a44f$export$d936e191dd6a8e06 as isOnlyPunctuation, $86c5c45def76a44f$export$38e1db3c2502e6cc as cleanJunkFromText, $86c5c45def76a44f$export$e65ff0050dc4971d as cleanSpacesBeforePeriod, $86c5c45def76a44f$export$6e89dcbda2f1dcad as condenseAsterisks, $86c5c45def76a44f$export$64ee6721b5d4cefa as condenseColons, $86c5c45def76a44f$export$9f873c000de6f69a as condenseDashes, $86c5c45def76a44f$export$35abf980a52dfe44 as condenseEllipsis, $86c5c45def76a44f$export$660f127778d3db20 as reduceMultilineBreaksToDouble, $86c5c45def76a44f$export$7b984b558843c423 as reduceMultilineBreaksToSingle, $86c5c45def76a44f$export$3468167fbf4483d7 as condensePeriods, $86c5c45def76a44f$export$a299139a27d861bb as condenseUnderscores, $86c5c45def76a44f$export$55102718dfa8db7e as doubleToSingleBrackets, $86c5c45def76a44f$export$803cc4592448c009 as replaceDoubleBracketsWithArrows, $86c5c45def76a44f$export$748703bb362bd52c as formatStringBySentence, $86c5c45def76a44f$export$9027754b4b9f4cf4 as normalizeSlashInReferences, $86c5c45def76a44f$export$85f748ccc2d3e888 as normalizeSpaces, $86c5c45def76a44f$export$5c77851c03e0da0a as ensureSpaceBeforeBrackets, $86c5c45def76a44f$export$a97ebab70a927fe1 as removeRedundantPunctuation, $86c5c45def76a44f$export$6726e05a22c5d4c9 as removeSpaceInsideBrackets, $86c5c45def76a44f$export$6db2c5d62fd5ffe9 as stripBoldStyling, $86c5c45def76a44f$export$9340b5fbcad6fe5a as stripItalicsStyling, $86c5c45def76a44f$export$e166e222302a97bd as stripStyling, $86c5c45def76a44f$export$eedf7f8c32995e56 as trimSpaceInsideQuotes, $045191e51bf3eda2$export$62c7e2fbc3880e40 as normalizeJsonSyntax, $045191e51bf3eda2$export$70726570eaa51acb as isJsonStructureValid, $045191e51bf3eda2$export$ae2dc619900afbaa as splitByQuotes, $045191e51bf3eda2$export$1e23eb8d8fab7cc as isBalanced, $15eb38b546e8440a$export$70476c4e7ef0b147 as cleanSymbolsAndPartReferences, $15eb38b546e8440a$export$9f81734a6223638b as cleanTrailingPageNumbers, $15eb38b546e8440a$export$631d05f860fc7118 as replaceLineBreaksWithSpaces, $15eb38b546e8440a$export$edd6c3bb8fa3bc01 as stripAllDigits, $15eb38b546e8440a$export$a537ffbd78859923 as removeDeathYear, $15eb38b546e8440a$export$c8e7d4d7d9f46256 as removeNumbersAndDashes, $15eb38b546e8440a$export$8e7f001aa315ad82 as removeSingleDigitReferences, $15eb38b546e8440a$export$e4a0bb7881a4591a as removeUrls, $0c91e05aa031e32a$export$2a02c946f8bfe63e as normalizeArabicPrefixesToAl, $0c91e05aa031e32a$export$bdee7fc4cb327c1a as normalizeDoubleApostrophes, $0c91e05aa031e32a$export$a0f0be7fbc73baaa as replaceSalutationsWithSymbol, $0c91e05aa031e32a$export$a3295358bff77e as normalize, $0c91e05aa031e32a$export$a4e89c859f54cbf3 as normalizeApostrophes, $0c91e05aa031e32a$export$dcfbf7d1ecba5f64 as removeArabicPrefixes, $0c91e05aa031e32a$export$17df925670d0176a as normalizeTransliteratedEnglish, $0c91e05aa031e32a$export$d421e6fd95c29a67 as extractInitials};
501
+ export {$798f85a7713a6ff1$export$60dc7fb96c441688 as cleanExtremeArabicUnderscores, $798f85a7713a6ff1$export$dcf00cfaf31fd188 as convertUrduSymbolsToArabic, $798f85a7713a6ff1$export$6c58e29008d10c1d as fixTrailingWow, $798f85a7713a6ff1$export$cf81487e80b00e26 as addSpaceBetweenArabicTextAndNumbers, $798f85a7713a6ff1$export$df81ab2e9352ca65 as stripEnglishCharactersAndSymbols, $798f85a7713a6ff1$export$d580a3cb14401529 as removeNonIndexSignatures, $798f85a7713a6ff1$export$84d849da647fa2e5 as removeSingularCodes, $798f85a7713a6ff1$export$7dedbc726019ed0f as removeSolitaryArabicLetters, $798f85a7713a6ff1$export$9571c9c2c203652d as removeTatwil, $798f85a7713a6ff1$export$f95230335378ec58 as replaceTaMarbutahWithHa, $798f85a7713a6ff1$export$b5bee4b27048330b as stripDiacritics, $798f85a7713a6ff1$export$8696bb09194c5fb5 as stripZeroWidthCharacters, $798f85a7713a6ff1$export$b1d6cb321dee12ad as replaceAlifMaqsurah, $798f85a7713a6ff1$export$db0c96cd03237332 as replaceEnglishPunctuationWithArabic, $798f85a7713a6ff1$export$1d28b07894af8a98 as normalizeAlifVariants, $86c5c45def76a44f$export$814bebc253f2e5df as insertLineBreaksAfterPunctuation, $86c5c45def76a44f$export$f0306841cd6b95d5 as addSpaceBeforeAndAfterPunctuation, $86c5c45def76a44f$export$42f47e081bfe828c as applySmartQuotes, $86c5c45def76a44f$export$b4922cc8c111eae2 as cleanLiteralNewLines, $86c5c45def76a44f$export$95680a0d9bdd5dba as cleanMultilines, $86c5c45def76a44f$export$20a121a9317a6ed4 as hasWordInSingleLine, $86c5c45def76a44f$export$d936e191dd6a8e06 as isOnlyPunctuation, $86c5c45def76a44f$export$38e1db3c2502e6cc as cleanJunkFromText, $86c5c45def76a44f$export$e65ff0050dc4971d as cleanSpacesBeforePeriod, $86c5c45def76a44f$export$6e89dcbda2f1dcad as condenseAsterisks, $86c5c45def76a44f$export$64ee6721b5d4cefa as condenseColons, $86c5c45def76a44f$export$9f873c000de6f69a as condenseDashes, $86c5c45def76a44f$export$35abf980a52dfe44 as condenseEllipsis, $86c5c45def76a44f$export$660f127778d3db20 as reduceMultilineBreaksToDouble, $86c5c45def76a44f$export$7b984b558843c423 as reduceMultilineBreaksToSingle, $86c5c45def76a44f$export$3468167fbf4483d7 as condensePeriods, $86c5c45def76a44f$export$a299139a27d861bb as condenseUnderscores, $86c5c45def76a44f$export$55102718dfa8db7e as doubleToSingleBrackets, $86c5c45def76a44f$export$803cc4592448c009 as replaceDoubleBracketsWithArrows, $86c5c45def76a44f$export$748703bb362bd52c as formatStringBySentence, $86c5c45def76a44f$export$9027754b4b9f4cf4 as normalizeSlashInReferences, $86c5c45def76a44f$export$85f748ccc2d3e888 as normalizeSpaces, $86c5c45def76a44f$export$5c77851c03e0da0a as ensureSpaceBeforeBrackets, $86c5c45def76a44f$export$a97ebab70a927fe1 as removeRedundantPunctuation, $86c5c45def76a44f$export$6726e05a22c5d4c9 as removeSpaceInsideBrackets, $86c5c45def76a44f$export$6db2c5d62fd5ffe9 as stripBoldStyling, $86c5c45def76a44f$export$9340b5fbcad6fe5a as stripItalicsStyling, $86c5c45def76a44f$export$e166e222302a97bd as stripStyling, $86c5c45def76a44f$export$eedf7f8c32995e56 as trimSpaceInsideQuotes, $045191e51bf3eda2$export$62c7e2fbc3880e40 as normalizeJsonSyntax, $045191e51bf3eda2$export$70726570eaa51acb as isJsonStructureValid, $045191e51bf3eda2$export$ae2dc619900afbaa as splitByQuotes, $045191e51bf3eda2$export$1e23eb8d8fab7cc as isBalanced, $15eb38b546e8440a$export$70476c4e7ef0b147 as cleanSymbolsAndPartReferences, $15eb38b546e8440a$export$9f81734a6223638b as cleanTrailingPageNumbers, $15eb38b546e8440a$export$631d05f860fc7118 as replaceLineBreaksWithSpaces, $15eb38b546e8440a$export$edd6c3bb8fa3bc01 as stripAllDigits, $15eb38b546e8440a$export$a537ffbd78859923 as removeDeathYear, $15eb38b546e8440a$export$c8e7d4d7d9f46256 as removeNumbersAndDashes, $15eb38b546e8440a$export$8e7f001aa315ad82 as removeSingleDigitReferences, $15eb38b546e8440a$export$e4a0bb7881a4591a as removeUrls, $15eb38b546e8440a$export$6a506b36fdea397d as truncate, $15eb38b546e8440a$export$f3a88d5244308057 as truncateMiddle, $15eb38b546e8440a$export$1791d17c7d9c448 as unescapeSpaces, $0c91e05aa031e32a$export$2a02c946f8bfe63e as normalizeArabicPrefixesToAl, $0c91e05aa031e32a$export$bdee7fc4cb327c1a as normalizeDoubleApostrophes, $0c91e05aa031e32a$export$a0f0be7fbc73baaa as replaceSalutationsWithSymbol, $0c91e05aa031e32a$export$a3295358bff77e as normalize, $0c91e05aa031e32a$export$a4e89c859f54cbf3 as normalizeApostrophes, $0c91e05aa031e32a$export$dcfbf7d1ecba5f64 as removeArabicPrefixes, $0c91e05aa031e32a$export$17df925670d0176a as normalizeTransliteratedEnglish, $0c91e05aa031e32a$export$d421e6fd95c29a67 as extractInitials};
481
502
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["src/index.ts","src/arabic.ts","src/formatting.ts","src/parsing.ts","src/sanitization.ts","src/transliteration.ts"],"sourcesContent":["export * from './arabic';\nexport * from './formatting';\nexport * from './parsing';\nexport * from './sanitization';\nexport * from './transliteration';\n","/**\n * Removes extreme Arabic underscores (ـ) that appear at the beginning or end of a line or in text.\n * Does not affect Hijri dates (e.g., 1424هـ) or specific Arabic terms.\n * Example: \"ـThis is a textـ\" will be changed to \"This is a text\".\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with extreme underscores removed.\n */\nexport const cleanExtremeArabicUnderscores = (text: string): string => {\n return text.replace(/(?<!\\d ?ه|اه)ـ(?=\\r?$)|^ـ(?!اهـ)/gm, '');\n};\n\n/**\n * Converts Urdu symbols to their Arabic equivalents.\n * Example: 'ھذا' will be changed to 'هذا', 'ی' to 'ي'.\n * @param {string} text - The input text containing Urdu symbols.\n * @returns {string} - The modified text with Urdu symbols converted to Arabic symbols.\n */\nexport const convertUrduSymbolsToArabic = (text: string): string => {\n return text.replace(/ھ/g, 'ه').replace(/ی/g, 'ي');\n};\n\n/**\n * Fixes the trailing \"و\" (wow) in phrases such as \"عليكم و رحمة\" to \"عليكم ورحمة\".\n * This function attempts to correct phrases where \"و\" appears unnecessarily, particularly in greetings.\n * Example: 'السلام عليكم و رحمة' will be changed to 'السلام عليكم ورحمة'.\n * @param {string} text - The input text containing the \"و\" character.\n * @returns {string} - The modified text with unnecessary trailing \"و\" characters corrected.\n */\nexport const fixTrailingWow = (text: string): string => {\n return text.replace(/ و /g, ' و');\n};\n\n/**\n * Inserts a space between Arabic text and numbers.\n * Example: 'الآية37' will be changed to 'الآية 37'.\n * @param {string} text - The input text containing Arabic text followed by numbers.\n * @returns {string} - The modified text with spaces inserted between Arabic text and numbers.\n */\nexport const addSpaceBetweenArabicTextAndNumbers = (text: string): string => {\n return text.replace(/([\\u0600-\\u06FF]+)(\\d+)/g, '$1 $2');\n};\n\n/**\n * Removes English letters and symbols from the text, including ampersands, slashes, and other symbols.\n * Example: 'أحب & لنفسي' will be changed to 'أحب لنفسي'.\n * @param {string} text - The input text containing English letters and symbols.\n * @returns {string} - The modified text with English letters and symbols removed.\n */\nexport const stripEnglishCharactersAndSymbols = (text: string): string => {\n return text.replace(/[a-zA-Z]+[0-9]*|[¬§`ﷺ=]|\\/{2,}|&/g, ' ');\n};\n\n/**\n * Removes single-digit numbers surrounded by Arabic text. Also removes dashes (-) not followed by a number.\n * For example, removes '3' from 'وهب 3 وقال' but does not remove '121' from 'لوحه 121 الجرح'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with non-index numbers and dashes removed.\n */\nexport const removeNonIndexSignatures = (text: string): string => {\n return text\n .replace(/(?<![0-9] ?)-|(?<=[\\u0600-\\u06FF])\\s?\\d\\s?(?=[\\u0600-\\u06FF])/g, ' ')\n .replace(/(?<=[\\u0600-\\u06FF]\\s)(\\d+\\s)+\\d+(?=(\\s[\\u0600-\\u06FF]|$))/g, ' ');\n};\n\n/**\n * Removes characters enclosed in square brackets [] or parentheses () if they are Arabic letters or Arabic-Indic numerals.\n * Example: '[س]' or '(س)' will be removed.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with singular codes removed.\n */\nexport const removeSingularCodes = (text: string): string => {\n return text.replace(/[[({][\\u0621-\\u064A\\u0660-\\u0669][\\])}]/g, '');\n};\n\n/**\n * Removes solitary Arabic letters unless they are the 'ha' letter, which is used in Hijri years.\n * Example: \"ب ا الكلمات ت\" will be changed to \"ا الكلمات\".\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with solitary Arabic letters removed.\n */\nexport const removeSolitaryArabicLetters = (text: string): string => {\n return text.replace(/(^| )[\\u0621-\\u064A]( |$)/g, ' ');\n};\n\n/**\n * Removes tatweel characters while preserving dates references and numbered list items.\n * Example: \"1435/3/29 هـ\" remains as \"1435/3/29 هـ\" but \"أبـــتِـــكَةُ\" becomes \"أبتِكَةُ\"\n * @param text The text to format.\n * @returns The modified text with the tatweel characters removed.\n */\nexport const removeTatwil = (text: string) => {\n // Don't remove tatweel if:\n // 1. Immediately preceded by a number or ه (for dates like \"1435هـ\")\n // 2. Preceded by a number with optional spaces (for list items like \"3 ـ\")\n return text.replace(/(?<![0-9ه])(?<![0-9]\\s*)ـ/g, '');\n};\n\n/**\n * Replaces the 'tah marbutah' (ة) character with 'ha' (ه).\n * Example: 'مدرسة' will be changed to 'مدرسه'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with 'ta marbutah' replaced by 'ha'.\n */\nexport const replaceTaMarbutahWithHa = (text: string): string => {\n return text.replace(/[ة]/g, 'ه');\n};\n\n/**\n * Removes Arabic diacritics (tashkeel) and the tatweel (elongation) character.\n * Example: 'مُحَمَّدٌ' will be changed to 'محمد'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with diacritics and tatweel removed.\n */\nexport const stripDiacritics = (text: string): string => {\n return text.replace(\n /[\\u0610\\u0611\\u0612\\u0613\\u0614\\u0615\\u0616\\u0617\\u0618\\u0619\\u061A\\u064B\\u064C\\u064D\\u064E\\u064F\\u0650\\u0651\\u0652\\u0653\\u0654\\u0655\\u0656\\u0657\\u0658\\u065A\\u065B\\u065C\\u065D\\u065E\\u0640]/g,\n '',\n );\n};\n\n/**\n * Removes zero-width joiners (ZWJ) and other zero-width characters from the input text.\n * Zero-width characters include U+200B to U+200F, U+202A to U+202E, U+2060 to U+2064, and U+FEFF.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with zero-width characters removed.\n */\nexport const stripZeroWidthCharacters = (text: string): string => {\n return text.replace(/[\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u2064\\uFEFF]/g, ' ');\n};\n\n/**\n * Replaces the 'alif maqsurah' (ى) character with the regular 'ya' (ي).\n * Example: 'رؤيى' will be changed to 'رؤيي'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with 'alif maqsurah' replaced by 'ya'.\n */\nexport const replaceAlifMaqsurah = (text: string): string => {\n return text.replace(/[ىي]/g, 'ي');\n};\n\n/**\n * Replaces English punctuation (question mark and semicolon) with their Arabic equivalents.\n * Example: '?' will be replaced with '؟', and ';' with '؛'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with English punctuation replaced by Arabic punctuation.\n */\nexport const replaceEnglishPunctuationWithArabic = (text: string): string => {\n return text\n .replace(/\\?|؟\\./g, '؟')\n .replace(/(;|؛)\\s*(\\1\\s*)*/g, '؛')\n .replace(/,|-،/g, '،');\n};\n\n/**\n * Simplifies all forms of 'alif' (أ, إ, and آ) to the basic 'ا'.\n * Example: 'أنا إلى الآفاق' will be changed to 'انا الى الافاق'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with simplified 'alif' characters.\n */\nexport const normalizeAlifVariants = (text: string): string => {\n return text.replace(/[أإآ]/g, 'ا');\n};\n","/**\n * Adds line breaks after punctuation marks such as periods, exclamation points, and question marks.\n * Example: 'Text.' becomes 'Text.\\n'.\n * @param {string} text - The input text containing punctuation.\n * @returns {string} - The modified text with line breaks added after punctuation.\n */\nexport const insertLineBreaksAfterPunctuation = (text: string): string => {\n // Define the punctuation marks that should trigger a new line\n const punctuation = /([.?!؟])/g;\n\n // Replace occurrences of punctuation marks followed by a space with the punctuation mark, a newline, and the space\n const formattedText = text.replace(punctuation, '$1\\n').replace(/\\n\\s+/g, '\\n').trim();\n\n return formattedText;\n};\n\n/**\n * Adds spaces before and after punctuation, except for certain cases like quoted text or ayah references.\n * Example: 'Text,word' becomes 'Text, word'.\n * @param {string} text - The input text containing punctuation.\n * @returns {string} - The modified text with spaces added before and after punctuation.\n */\nexport const addSpaceBeforeAndAfterPunctuation = (text: string): string => {\n return text\n .replace(/( ?)([.!?,،؟;؛])((?![ '”“)\"\\]\\n])|(?=\\s{2,}))/g, '$1$2 ')\n .replace(/\\s([.!?,،؟;؛])\\s*([ '”“)\"\\]\\n])/g, '$1$2')\n .replace(/([^\\s\\w\\d'”“)\"\\]]+)\\s+([.!?,،؟;؛])|([.!?,،؟;؛])\\s+$/g, '$1$2$3')\n .replace(/(?<=\\D)( ?: ?)(?!(\\d+:)|(:\\d+))|(?<=\\d) ?: ?(?=\\D)|(?<=\\D) ?: ?(?=\\d)/g, ': ');\n};\n\n/**\n * Turns regular double quotes surrounding a body of text into smart quotes.\n * Also fixes incorrect starting quotes by ensuring the string starts with an opening quote if needed.\n * Example: 'The \"quick brown\" fox' becomes 'The “quick brown” fox'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with smart quotes applied.\n */\nexport const applySmartQuotes = (text: string): string => {\n return text\n .replace(/[“”]/g, '\"')\n .replace(/\"([^\"]*)\"/g, '“$1”')\n .replace(/^”/g, '“');\n};\n\n/**\n * Replaces literal new line characters (\\n) and carriage returns (\\r) with actual line breaks.\n * Example: 'A\\\\nB' becomes 'A\\nB'.\n * @param {string} text - The input text containing literal new lines.\n * @returns {string} - The modified text with actual line breaks.\n */\nexport const cleanLiteralNewLines = (text: string): string => {\n return text.replace(/\\\\n|\\r/g, '\\n');\n};\n\n/**\n * Removes trailing spaces from each line in a multiline string.\n * Example: \" This is a line \\nAnother line \" becomes \"This is a line\\nAnother line\".\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with trailing spaces removed.\n */\nexport const cleanMultilines = (text: string): string => {\n return text.replace(/^ +| +$/gm, '');\n};\n\n/**\n * Detects if a word is by itself in a line.\n * @param text The text to check.\n * @returns true if there exists a word in any of the lines in the text that is by itself.\n */\nexport const hasWordInSingleLine = (text: string): boolean => {\n return /^\\s*\\S+\\s*$/gm.test(text);\n};\n\n/**\n * Checks if the input string consists of only punctuation characters.\n * @param {string} text - The input text to check.\n * @returns {boolean} - Returns true if the string contains only punctuation, false otherwise.\n */\nexport const isOnlyPunctuation = (text: string): boolean => {\n const regex = /^[\\u0020-\\u002f\\u003a-\\u0040\\u005b-\\u0060\\u007b-\\u007e0-9٠-٩]+$/;\n return regex.test(text);\n};\n\nexport const cleanJunkFromText = (text: string): string => {\n const newBody = cleanMultilines(text);\n const lines = newBody.split('\\n').filter((line) => {\n return !line || (line.length > 1 && !isOnlyPunctuation(line));\n });\n\n return lines.join('\\n').trim();\n};\n\n/**\n * Cleans unnecessary spaces before punctuation marks such as periods, commas, and question marks.\n * Example: 'This is a sentence , with extra space .' becomes 'This is a sentence, with extra space.'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with cleaned spaces before punctuation.\n */\nexport const cleanSpacesBeforePeriod = (text: string): string => {\n return text.replace(/\\s+([.؟!,،؛:?])/g, '$1');\n};\n\n/**\n * Condenses multiple asterisks (*) into a single one.\n * Example: '***' becomes '*'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed asterisks.\n */\nexport const condenseAsterisks = (text: string): string => {\n return text.replace(/(\\*\\s*)+/g, '*');\n};\n\n/**\n * Replaces occurrences of colons surrounded by periods (e.g., '.:.' or ':') with a single colon.\n * Example: 'This.:. is a test' becomes 'This: is a test'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed colons.\n */\nexport const condenseColons = (text: string): string => {\n return text.replace(/[.-]?:[.-]?/g, ':');\n};\n\n/**\n * Condenses two or more dashes (--) into a single dash (-).\n * Example: 'This is some ---- text' becomes 'This is some - text'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed dashes.\n */\nexport const condenseDashes = (text: string): string => {\n return text.replace(/-{2,}/g, '-');\n};\n\n/**\n * Replaces sequences of two or more periods (e.g., '...') with an ellipsis character (…).\n * Example: 'This is a test...' becomes 'This is a test…'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with ellipses condensed.\n */\nexport const condenseEllipsis = (text: string): string => {\n return text.replace(/\\.{2,}/g, '…');\n};\n\n/**\n * Reduces multiple consecutive line breaks (3 or more) to exactly 2 line breaks.\n * Example: 'This is line 1\\n\\n\\n\\nThis is line 2' becomes 'This is line 1\\n\\nThis is line 2'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed line breaks.\n */\nexport const reduceMultilineBreaksToDouble = (text: string): string => {\n return text.replace(/(\\n\\s*){3,}/g, '\\n\\n');\n};\n\n/**\n * Reduces multiple consecutive line breaks (2 or more) to exactly 1 line break.\n * Example: 'This is line 1\\n\\nThis is line 2' becomes 'This is line 1\\nThis is line 2'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed line breaks.\n */\nexport const reduceMultilineBreaksToSingle = (text: string): string => {\n return text.replace(/(\\n\\s*){2,}/g, '\\n');\n};\n\n/**\n * Condenses multiple periods separated by spaces (e.g., '. . .') into a single period.\n * Example: 'This . . . is a test' becomes 'This. is a test'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed periods.\n */\nexport const condensePeriods = (text: string): string => {\n return text.replace(/\\. +\\./g, '.');\n};\n\n/**\n * Condenses multiple underscores (__) or Arabic Tatweel characters (ـــــ) into a single underscore or Tatweel.\n * Example: 'This is ـــ some text __' becomes 'This is ـ some text _'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed underscores.\n */\nexport const condenseUnderscores = (text: string): string => {\n return text.replace(/ـ{2,}/g, 'ـ').replace(/_+/g, '_');\n};\n\n/**\n * Replaces double parentheses or brackets with single ones.\n * Example: '((text))' becomes '(text)'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed brackets.\n */\nexport const doubleToSingleBrackets = (text: string): string => {\n return text.replace(/(\\(|\\)){2,}|(\\[|\\]){2,}/g, '$1$2');\n};\n\n/**\n * Replaces double parentheses single a single arrow variation.\n * Example: '((text))' becomes '«text»'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed brackets.\n */\nexport const replaceDoubleBracketsWithArrows = (text: string) => {\n return text.replace(/\\(\\(\\s?/g, '«').replace(/\\s?\\)\\)/g, '»');\n};\n\n/**\n * Formats a multiline string by joining sentences and maintaining footnotes on their own lines.\n * Footnotes are identified by Arabic and English numerals.\n * Example: 'Sentence one.\\n(1) A footnote.\\nSentence two.' remains the same, while regular sentences are joined.\n * @param {string} input - The input text containing sentences and footnotes.\n * @returns {string} - The formatted text.\n */\nexport const formatStringBySentence = (input: string): string => {\n const footnoteRegex = /^\\((?:\\d+|۱|۲|۳|۴|۵|۶|۷|۸|۹)\\)\\s/;\n const sentences: string[] = [];\n const lines = input.split('\\n');\n let currentSentence = '';\n\n lines.forEach((line) => {\n const trimmedLine = line.trim();\n const isFootnote = footnoteRegex.test(trimmedLine);\n const isNumber = /^\\(\\d+\\/\\d+\\)/.test(trimmedLine);\n\n if (isFootnote && !isNumber) {\n if (currentSentence) {\n sentences.push(currentSentence.trim());\n currentSentence = '';\n }\n sentences.push(trimmedLine);\n } else {\n currentSentence += `${trimmedLine} `;\n const lastChar = currentSentence.trim().slice(-1);\n if (/[.!؟]/.test(lastChar)) {\n sentences.push(currentSentence.trim());\n currentSentence = '';\n }\n }\n });\n\n // Add any remaining text to the output\n if (currentSentence) {\n sentences.push(currentSentence.trim());\n }\n\n return sentences.join('\\n');\n};\n\n/**\n * Removes unnecessary spaces around slashes in references.\n * Example: '127 / 11' becomes '127/11'.\n * @param {string} text - The input text containing references.\n * @returns {string} - The modified text with spaces removed around slashes.\n */\nexport const normalizeSlashInReferences = (text: string): string => {\n return text.replace(/(\\d+)\\s?\\/\\s?(\\d+)/g, '$1/$2');\n};\n\n/**\n * Reduces multiple spaces or tabs to a single space.\n * Example: 'This is a text' becomes 'This is a text'.\n * @param {string} text - The input text containing extra spaces.\n * @returns {string} - The modified text with reduced spaces.\n */\nexport const normalizeSpaces = (text: string): string => {\n return text.replace(/[ \\t]+/g, ' ');\n};\n\n/**\n * Ensures at most 1 space exists before any word before brackets.\n * Adds a space if there isn't one, or reduces multiple spaces to one.\n * @param {string} text - The input text to modify\n * @returns {string} - The modified text with proper spacing before brackets\n */\nexport const ensureSpaceBeforeBrackets = (text: string): string => {\n return text.replace(/(\\S) *(\\([^)]*\\))/g, '$1 $2');\n};\n\n/**\n * Removes redundant punctuation marks that follow Arabic question marks or exclamation marks.\n * This function cleans up text by removing periods (.) or Arabic commas (،) that immediately\n * follow Arabic question marks (؟) or exclamation marks (!), as they are considered redundant\n * in proper Arabic punctuation.\n *\n * @param text - The Arabic text to clean up\n * @returns The text with redundant punctuation removed\n *\n * @example\n * ```typescript\n * removeRedundantPunctuation('كيف حالك؟.') // Returns: 'كيف حالك؟'\n * removeRedundantPunctuation('ممتاز!،') // Returns: 'ممتاز!'\n * removeRedundantPunctuation('هذا جيد.') // Returns: 'هذا جيد.' (unchanged)\n * ```\n */\nexport const removeRedundantPunctuation = (text: string) => {\n return text.replace(/([؟!])[.،]/g, '$1');\n};\n\n/**\n * Removes spaces inside brackets, parentheses, or square brackets.\n * Example: '( a b )' becomes '(a b)'.\n * @param {string} text - The input text with spaces inside brackets.\n * @returns {string} - The modified text with spaces removed inside brackets.\n */\nexport const removeSpaceInsideBrackets = (text: string): string => {\n return text.replace(/([[(])\\s*(.*?)\\s*([\\])])/g, '$1$2$3');\n};\n\n/**\n * Removes bold styling from text by normalizing the string and removing stylistic characters.\n * @param {string} text - The input text containing bold characters.\n * @returns {string} - The modified text with bold styling removed.\n */\nexport const stripBoldStyling = (text: string): string => {\n // Normalize the string to NFKD form\n const normalizedString = text.normalize('NFKD');\n\n // Remove combining marks (diacritics) and stylistic characters from the string\n return normalizedString.replace(/[\\u0300-\\u036f]/g, '').trim();\n};\n\n/**\n * Removes italicized characters by replacing italic Unicode characters with their normal counterparts.\n * Example: '𝘼𝘽𝘾' becomes 'ABC'.\n * @param {string} text - The input text containing italicized characters.\n * @returns {string} - The modified text with italics removed.\n */\nexport const stripItalicsStyling = (text: string): string => {\n const italicMap: Record<string, string> = {\n '\\uD835\\uDC4E': 'I',\n '\\uD835\\uDC68': 'g',\n '\\u{1D63C}': '!',\n '\\uD835\\uDC4F': 'J',\n '\\uD835\\uDC69': 'h',\n '\\u{1D63D}': '?',\n '\\uD835\\uDC50': 'K',\n '\\uD835\\uDC6A': 'i',\n '\\uD835\\uDC51': 'L',\n '\\uD835\\uDC6B': 'j',\n '\\u{1D63F}': ',',\n '\\uD835\\uDC52': 'M',\n '\\uD835\\uDC6C': 'k',\n '\\u{1D640}': '.',\n '\\uD835\\uDC53': 'N',\n '\\uD835\\uDC6D': 'l',\n '\\uD835\\uDC54': 'O',\n '\\uD835\\uDC6E': 'm',\n '\\uD835\\uDC6F': 'n',\n '\\uD835\\uDC56': 'Q',\n '\\uD835\\uDC70': 'o',\n '\\uD835\\uDC57': 'R',\n '\\uD835\\uDC71': 'p',\n '\\uD835\\uDC58': 'S',\n '\\uD835\\uDC72': 'q',\n '\\uD835\\uDC59': 'T',\n '\\uD835\\uDC73': 'r',\n '\\u{1D647}': '-',\n '\\uD835\\uDC5A': 'U',\n '\\uD835\\uDC74': 's',\n '\\uD835\\uDC5B': 'V',\n '\\uD835\\uDC75': 't',\n '\\uD835\\uDC5C': 'W',\n '\\uD835\\uDC76': 'u',\n '\\uD835\\uDC5D': 'X',\n '\\uD835\\uDC77': 'v',\n '\\uD835\\uDC5E': 'Y',\n '\\uD835\\uDC78': 'w',\n '\\uD835\\uDC5F': 'Z',\n '\\uD835\\uDC79': 'x',\n '\\uD835\\uDC46': 'A',\n '\\uD835\\uDC7A': 'y',\n '\\uD835\\uDC47': 'B',\n '\\uD835\\uDC7B': 'z',\n '\\uD835\\uDC62': 'a',\n '\\uD835\\uDC48': 'C',\n '\\uD835\\uDC63': 'b',\n '\\uD835\\uDC49': 'D',\n '\\uD835\\uDC64': 'c',\n '\\uD835\\uDC4A': 'E',\n '\\uD835\\uDC65': 'd',\n '\\uD835\\uDC4B': 'F',\n '\\uD835\\uDC66': 'e',\n '\\uD835\\uDC4C': 'G',\n '\\uD835\\uDC67': 'f',\n '\\uD835\\uDC4D': 'H',\n '\\uD835\\uDC55': 'P',\n };\n\n return text.replace(/[\\uD835\\uDC62-\\uD835\\uDC7B\\uD835\\uDC46-\\uD835\\uDC5F\\u{1D63C}-\\u{1D647}]/gu, (match) => {\n return italicMap[match] || match;\n });\n};\n\n/**\n * Removes all bold and italic styling from the input text.\n * @param {string} text - The input text to remove styling from.\n * @returns {string} - The modified text with all styling removed.\n */\nexport const stripStyling = (text: string): string => {\n return stripItalicsStyling(stripBoldStyling(text));\n};\n\n/**\n * Removes unnecessary spaces inside quotes.\n * Example: '“ Text ”' becomes '“Text”'.\n * @param {string} text - The input text with spaces inside quotes.\n * @returns {string} - The modified text with spaces removed inside quotes.\n */\nexport const trimSpaceInsideQuotes = (text: string): string => {\n return text.replace(/([“”\"]|«) *(.*?) *([“”\"]|»)/g, '$1$2$3');\n};\n","/**\n * Converts a string that resembles JSON but with numeric keys and single-quoted values\n * into valid JSON format. This function replaces numeric keys with quoted numeric keys\n * and ensures all values are double-quoted as required by JSON.\n *\n * @param {string} str - The input string that needs to be fixed into valid JSON.\n * @returns {string} - A valid JSON string.\n *\n * @example\n * const result = normalizeJsonSyntax(\"{10: 'abc', 20: 'def'}\");\n * console.log(result); // '{\"10\": \"abc\", \"20\": \"def\"}'\n */\nexport const normalizeJsonSyntax = (str: string): string => {\n let input = str.replace(/(\\b\\d+\\b)(?=:)/g, '\"$1\"');\n input = input.replace(/:\\s*'([^']+)'/g, ': \"$1\"');\n input = input.replace(/:\\s*\"([^\"]+)\"/g, ': \"$1\"');\n\n return JSON.stringify(JSON.parse(input));\n};\n\n/**\n * Checks if a given string resembles a JSON object with numeric or quoted keys and values\n * that are single or double quoted. This is useful for detecting malformed JSON-like\n * structures that can be fixed by the `normalizeJsonSyntax` function.\n *\n * @param {string} str - The input string to check.\n * @returns {boolean} - Returns true if the string is JSON-like, false otherwise.\n *\n * @example\n * const result = isJsonStructureValid(\"{10: 'abc', 'key': 'value'}\");\n * console.log(result); // true\n */\nexport const isJsonStructureValid = (str: string): boolean => {\n // Checks for a pattern with numeric keys or quoted keys and values in quotes\n const jsonLikePattern =\n /^{(\\s*(\\d+|'[^']*'|\"[^\"]*\")\\s*:\\s*('|\")[^'\"]*\\3\\s*,)*(?:\\s*(\\d+|'[^']*'|\"[^\"]*\")\\s*:\\s*('|\")[^'\"]*\\5\\s*)}$/;\n return jsonLikePattern.test(str.trim());\n};\n\n/**\n * Splits a string by spaces and quoted substrings.\n *\n * This function takes an input string and splits it into parts where substrings\n * enclosed in double quotes are treated as a single part. Other substrings\n * separated by spaces are split normally.\n *\n * @param {string} query - The input string to be split.\n * @returns {string[]} An array of strings, with quoted substrings kept intact.\n *\n * @example\n * const result = splitByQuotes('\"This is\" \"a part of the\" \"string and\"');\n * console.log(result); // [\"This is\", \"a part of the\", \"string and\"]\n */\nexport const splitByQuotes = (query: string): string[] => {\n const regex = /(?:[^\\s\"]+|\"(.*?)\")+/g;\n return (query.match(regex) || []).map((s: string) => (s.startsWith('\"') ? s.slice(1, -1) : s));\n};\n\n/**\n * Checks if all double quotes in a string are balanced (even count).\n * A string has balanced quotes if every opening quote has a corresponding closing quote.\n *\n * @param str - The string to check for balanced quotes\n * @returns True if quotes are balanced (even count), false otherwise\n *\n * @example\n * ```typescript\n * areQuotesBalanced('Hello \"world\"') // Returns: true\n * areQuotesBalanced('Hello \"world') // Returns: false\n * areQuotesBalanced('No quotes') // Returns: true\n * ```\n */\nconst areQuotesBalanced = (str: string): boolean => {\n let quoteCount = 0;\n for (const char of str) {\n if (char === '\"') {\n quoteCount++;\n }\n }\n return quoteCount % 2 === 0;\n};\n\nconst brackets = { '(': ')', '[': ']', '{': '}' };\nconst openBrackets = new Set(['(', '[', '{']);\nconst closeBrackets = new Set([')', ']', '}']);\n\n/**\n * Checks if all brackets in a string are properly balanced and matched.\n * This function validates that every opening bracket has a corresponding closing bracket\n * in the correct order and of the matching type.\n *\n * Supported bracket types: parentheses (), square brackets [], curly braces {}\n *\n * @param str - The string to check for balanced brackets\n * @returns True if all brackets are properly balanced and matched, false otherwise\n *\n * @example\n * ```typescript\n * areBracketsBalanced('(hello [world])') // Returns: true\n * areBracketsBalanced('(hello [world)') // Returns: false (mismatched)\n * areBracketsBalanced('((hello))') // Returns: true\n * areBracketsBalanced('(hello') // Returns: false (unclosed)\n * ```\n */\n\nconst areBracketsBalanced = (str: string): boolean => {\n const stack: string[] = [];\n\n for (const char of str) {\n if (openBrackets.has(char)) {\n stack.push(char);\n } else if (closeBrackets.has(char)) {\n const lastOpen = stack.pop();\n if (!lastOpen || brackets[lastOpen as keyof typeof brackets] !== char) {\n return false;\n }\n }\n }\n\n return stack.length === 0;\n};\n\n/**\n * Checks if both quotes and brackets are balanced in a string.\n * This function combines quote balance checking and bracket balance checking\n * to ensure the entire string has properly balanced punctuation.\n *\n * A string is considered balanced when:\n * - All double quotes have matching pairs (even count)\n * - All brackets (parentheses, square brackets, curly braces) are properly matched and nested\n *\n * @param str - The string to check for balanced quotes and brackets\n * @returns True if both quotes and brackets are balanced, false otherwise\n *\n * @example\n * ```typescript\n * isBalanced('He said \"Hello (world)!\"') // Returns: true\n * isBalanced('He said \"Hello (world!\"') // Returns: false (unbalanced quote)\n * isBalanced('He said \"Hello (world)\"') // Returns: false (unbalanced quote)\n * isBalanced('Hello (world) [test]') // Returns: true\n * ```\n */\nexport const isBalanced = (str: string): boolean => {\n return areQuotesBalanced(str) && areBracketsBalanced(str);\n};\n","/**\n * Removes various symbols, part references, and numerical markers from the text.\n * Example: '(1) (2/3)' becomes ''.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with symbols and part references removed.\n */\nexport const cleanSymbolsAndPartReferences = (text: string): string => {\n return text.replace(\n / *\\(?:\\d+(?:\\/\\d+){0,2}\\)? *| *\\[\\d+(?:\\/\\d+)?\\] *| *«\\d+» *|\\d+\\/\\d+(?:\\/\\d+)?|[،§{}۝؍‎﴿﴾<>;_؟»«:!،؛\\[\\]…ـ¬\\.\\\\\\/\\*\\(\\)\"]/g,\n ' ',\n );\n};\n\n/**\n * Removes trailing page numbers formatted as '-[46]-' from the text.\n * Example: 'This is some -[46]- text' becomes 'This is some text'.\n * @param {string} text - The input text with trailing page numbers.\n * @returns {string} - The modified text with page numbers removed.\n */\nexport const cleanTrailingPageNumbers = (text: string): string => {\n return text.replace(/-\\[\\d+\\]-/g, '');\n};\n\n/**\n * Replaces consecutive line breaks and whitespace characters with a single space.\n * Example: 'a\\nb' becomes 'a b'.\n * @param {string} text - The input text containing line breaks or multiple spaces.\n * @returns {string} - The modified text with spaces.\n */\nexport const replaceLineBreaksWithSpaces = (text: string): string => {\n return text.replace(/\\s+/g, ' ');\n};\n\n/**\n * Removes all numeric digits from the text.\n * Example: 'abc123' becomes 'abc'.\n * @param {string} text - The input text containing digits.\n * @returns {string} - The modified text with digits removed.\n */\nexport const stripAllDigits = (text: string): string => {\n return text.replace(/[0-9]/g, '');\n};\n\n/**\n * Removes death year references like \"(d. 390H)\" and \"[d. 100h]\" from the text.\n * Example: 'Sufyān ibn ‘Uyaynah (d. 198h)' becomes 'Sufyān ibn ‘Uyaynah'.\n * @param {string} text - The input text containing death year references.\n * @returns {string} - The modified text with death years removed.\n */\nexport const removeDeathYear = (text: string): string => {\n return text.replace(/\\[(d)\\.\\s*\\d{1,4}[hH]\\]\\s*|\\((d)\\.\\s*\\d{1,4}[hH]\\)\\s*/g, '');\n};\n\n/**\n * Removes numeric digits and dashes from the text.\n * Example: 'ABC 123-Xyz' becomes 'ABC Xyz'.\n * @param {string} text - The input text containing digits and dashes.\n * @returns {string} - The modified text with numbers and dashes removed.\n */\nexport const removeNumbersAndDashes = (text: string): string => {\n return text.replace(/[\\d-]/g, '');\n};\n\n/**\n * Removes single digit references like (1), «2», [3] from the text.\n * Example: 'Ref (1), Ref «2», Ref [3]' becomes 'Ref , Ref , Ref '.\n * @param {string} text - The input text containing single digit references.\n * @returns {string} - The modified text with single digit references removed.\n */\nexport const removeSingleDigitReferences = (text: string): string => {\n return text.replace(/\\(\\d{1}\\)|\\[\\d{1}\\]|«\\d»/g, '');\n};\n\n/**\n * Removes URLs from the text.\n * Example: 'Visit https://example.com' becomes 'Visit '.\n * @param {string} text - The input text containing URLs.\n * @returns {string} - The modified text with URLs removed.\n */\nexport const removeUrls = (text: string): string => {\n return text.replace(\n /https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g,\n '',\n );\n};\n","import { normalizeSpaces } from './formatting';\n\n/**\n * Replaces common Arabic prefixes (like 'Al-', 'Ar-', 'Ash-', etc.) with 'al-' in the text.\n * Handles different variations of prefixes such as Ash- and Al- but not when the second word\n * does not start with 'S'.\n * Example: 'Ash-Shafiee' becomes 'al-Shafiee'.\n *\n * @param {string} text - The input text containing Arabic prefixes.\n * @returns {string} - The modified text with standardized 'al-' prefixes.\n */\nexport const normalizeArabicPrefixesToAl = (text: string): string => {\n return text\n .replace(/(\\b|\\W)(Al |Al-|Ar-|As-|Adh-|Ad-|Ats-|Ath |Ath-|Az |Az-|az-|adh-|as-|ar-)/g, '$1al-')\n .replace(/(\\b|\\W)(Ash-S|ash-S)/g, '$1al-S')\n .replace(/al- (.+?)\\b/g, 'al-$1');\n};\n\n/**\n * Removes double occurrences of Arabic apostrophes such as ʿʿ or ʾʾ in the text.\n * Example: 'ʿulamāʾʾ' becomes 'ʿulamāʾ'.\n *\n * @param {string} text - The input text containing double apostrophes.\n * @returns {string} - The modified text with condensed apostrophes.\n */\nexport const normalizeDoubleApostrophes = (text: string): string => {\n return text.replace(/ʿʿ/g, 'ʿ').replace(/ʾʾ/g, 'ʾ');\n};\n\n/**\n * Replaces common salutations such as \"sallahu alayhi wasallam\" with \"ﷺ\" in the text.\n * It also handles variations of the salutation phrase, including 'peace and blessings be upon him'.\n * Example: 'Then Muḥammad (sallahu alayhi wasallam)' becomes 'Then Muḥammad ﷺ'.\n *\n * @param {string} text - The input text containing salutations.\n * @returns {string} - The modified text with salutations replaced.\n */\nexport const replaceSalutationsWithSymbol = (text: string): string => {\n return text\n .replace(\n /\\(peace be upon him\\)|(Messenger of (Allah|Allāh)|Messenger|Prophet|Mu[hḥ]ammad) *\\((s[^)]*m|peace[^)]*him|May[^)]*him|may[^)]*him)\\)*/gi,\n '$1 ﷺ',\n )\n .replace(/,\\s*ﷺ\\s*,/g, ' ﷺ');\n};\n\n/**\n * Normalizes the text by removing diacritics, apostrophes, and dashes.\n * Example: 'Al-Jadwal' becomes 'AlJadwal'.\n *\n * @param {string} input - The input text to normalize.\n * @returns {string} - The normalized text.\n */\nexport const normalize = (input: string) => {\n return input\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/`|ʾ|ʿ|-/g, '');\n};\n\n/**\n * Replaces various apostrophe characters (‛, ’, ‘) with the standard apostrophe (').\n * Example: '‛ulama’ al-su‘' becomes ''ulama' al-su''.\n *\n * @param {string} text - The input text containing different apostrophe characters.\n * @returns {string} - The modified text with normalized apostrophes.\n */\nexport const normalizeApostrophes = (text: string): string => {\n return text.replace(/‛|’|‘/g, \"'\");\n};\n\n/**\n * Strips common Arabic prefixes like 'al-', 'bi-', 'fī', 'wa-', etc. from the beginning of words.\n * Example: 'al-Bukhari' becomes 'Bukhari'.\n *\n * @param {string} text - The input text containing Arabic prefixes.\n * @returns {string} - The modified text with prefixes stripped.\n */\nexport const removeArabicPrefixes = (text: string): string => {\n return normalizeSpaces(text.replace(/(\\bal-|\\bli-|\\bbi-|\\bfī|\\bwa[-\\s]+|\\bl-|\\bliʿl|\\Bʿalá|\\Bʿan|\\bb\\.)/gi, ''));\n};\n\n/**\n * Simplifies English transliterations by removing diacritics, apostrophes, and common prefixes.\n * Example: 'Al-Jadwal' becomes 'Jadwal', and 'āḍġḥīṣṭū' becomes 'adghistu'.\n *\n * @param {string} text - The input text to simplify.\n * @returns {string} - The simplified text.\n */\nexport const normalizeTransliteratedEnglish = (text: string): string => normalize(removeArabicPrefixes(text));\n\n/**\n * Extracts the initials from the input string, typically used for names or titles.\n * Example: 'Nayl al-Awtar' becomes 'NA'.\n *\n * @param {string} text - The input text to extract initials from.\n * @returns {string} - The extracted initials.\n */\nexport const extractInitials = (fullName: string) => {\n const initials = normalizeTransliteratedEnglish(fullName)\n .trim()\n .split(/[ -]/)\n .slice(0, 2)\n .map((word) => {\n return word.charAt(0).toUpperCase();\n })\n .join('');\n return initials;\n};\n"],"names":[],"version":3,"file":"main.js.map","sourceRoot":"../"}
1
+ {"mappings":";;;;;;;;;;;;;;;;;;;;;ACAA;;;;;;CAMC,GACM,MAAM,4CAAgC,CAAC;IAC1C,OAAO,KAAK,OAAO,CAAC,sCAAsC;AAC9D;AAQO,MAAM,4CAA6B,CAAC;IACvC,OAAO,KAAK,OAAO,CAAC,MAAM,UAAK,OAAO,CAAC,MAAM;AACjD;AASO,MAAM,4CAAiB,CAAC;IAC3B,OAAO,KAAK,OAAO,CAAC,QAAQ;AAChC;AAQO,MAAM,4CAAsC,CAAC;IAChD,OAAO,KAAK,OAAO,CAAC,4BAA4B;AACpD;AAQO,MAAM,4CAAmC,CAAC;IAC7C,OAAO,KAAK,OAAO,CAAC,yCAAyC;AACjE;AAQO,MAAM,4CAA2B,CAAC;IACrC,OAAO,KACF,OAAO,CAAC,kEAAkE,KAC1E,OAAO,CAAC,+DAA+D;AAChF;AAQO,MAAM,4CAAsB,CAAC;IAChC,OAAO,KAAK,OAAO,CAAC,4CAA4C;AACpE;AAQO,MAAM,4CAA8B,CAAC;IACxC,OAAO,KAAK,OAAO,CAAC,8BAA8B;AACtD;AAQO,MAAM,4CAAe,CAAC;IACzB,2BAA2B;IAC3B,qEAAqE;IACrE,2EAA2E;IAC3E,OAAO,KAAK,OAAO,CAAC,8BAA8B;AACtD;AAQO,MAAM,4CAA0B,CAAC;IACpC,OAAO,KAAK,OAAO,CAAC,QAAQ;AAChC;AAQO,MAAM,4CAAkB,CAAC;IAC5B,OAAO,KAAK,OAAO,CACf,iMACA;AAER;AAQO,MAAM,4CAA2B,CAAC;IACrC,OAAO,KAAK,OAAO,CAAC,oDAAoD;AAC5E;AAQO,MAAM,4CAAsB,CAAC;IAChC,OAAO,KAAK,OAAO,CAAC,SAAS;AACjC;AAQO,MAAM,4CAAsC,CAAC;IAChD,OAAO,KACF,OAAO,CAAC,WAAW,UACnB,OAAO,CAAC,qBAAqB,UAC7B,OAAO,CAAC,SAAS;AAC1B;AAQO,MAAM,4CAAwB,CAAC;IAClC,OAAO,KAAK,OAAO,CAAC,UAAU;AAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjKA;;;;;CAKC,GACM,MAAM,4CAAmC,CAAC;IAC7C,8DAA8D;IAC9D,MAAM,cAAc;IAEpB,mHAAmH;IACnH,MAAM,gBAAgB,KAAK,OAAO,CAAC,aAAa,QAAQ,OAAO,CAAC,UAAU,MAAM,IAAI;IAEpF,OAAO;AACX;AAQO,MAAM,4CAAoC,CAAC;IAC9C,OAAO,KACF,OAAO,CAAC,kDAAkD,SAC1D,OAAO,CAAC,oCAAoC,QAC5C,OAAO,CAAC,wDAAwD,UAChE,OAAO,CAAC,0EAA0E;AAC3F;AASO,MAAM,4CAAmB,CAAC;IAC7B,OAAO,KACF,OAAO,CAAC,SAAS,KACjB,OAAO,CAAC,cAAc,kBACtB,OAAO,CAAC,OAAO;AACxB;AAQO,MAAM,4CAAuB,CAAC;IACjC,OAAO,KAAK,OAAO,CAAC,WAAW;AACnC;AAQO,MAAM,4CAAkB,CAAC;IAC5B,OAAO,KAAK,OAAO,CAAC,aAAa;AACrC;AAOO,MAAM,4CAAsB,CAAC;IAChC,OAAO,gBAAgB,IAAI,CAAC;AAChC;AAOO,MAAM,4CAAoB,CAAC;IAC9B,MAAM,QAAQ;IACd,OAAO,MAAM,IAAI,CAAC;AACtB;AAEO,MAAM,4CAAoB,CAAC;IAC9B,MAAM,UAAU,0CAAgB;IAChC,MAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,MAAM,CAAC,CAAC;QACtC,OAAO,CAAC,QAAS,KAAK,MAAM,GAAG,KAAK,CAAC,0CAAkB;IAC3D;IAEA,OAAO,MAAM,IAAI,CAAC,MAAM,IAAI;AAChC;AAQO,MAAM,4CAA0B,CAAC;IACpC,OAAO,KAAK,OAAO,CAAC,oBAAoB;AAC5C;AAQO,MAAM,4CAAoB,CAAC;IAC9B,OAAO,KAAK,OAAO,CAAC,aAAa;AACrC;AAQO,MAAM,4CAAiB,CAAC;IAC3B,OAAO,KAAK,OAAO,CAAC,gBAAgB;AACxC;AAQO,MAAM,4CAAiB,CAAC;IAC3B,OAAO,KAAK,OAAO,CAAC,UAAU;AAClC;AAQO,MAAM,4CAAmB,CAAC;IAC7B,OAAO,KAAK,OAAO,CAAC,WAAW;AACnC;AAQO,MAAM,4CAAgC,CAAC;IAC1C,OAAO,KAAK,OAAO,CAAC,gBAAgB;AACxC;AAQO,MAAM,4CAAgC,CAAC;IAC1C,OAAO,KAAK,OAAO,CAAC,gBAAgB;AACxC;AAQO,MAAM,4CAAkB,CAAC;IAC5B,OAAO,KAAK,OAAO,CAAC,WAAW;AACnC;AAQO,MAAM,4CAAsB,CAAC;IAChC,OAAO,KAAK,OAAO,CAAC,UAAU,UAAK,OAAO,CAAC,OAAO;AACtD;AAQO,MAAM,4CAAyB,CAAC;IACnC,OAAO,KAAK,OAAO,CAAC,4BAA4B;AACpD;AAQO,MAAM,4CAAkC,CAAC;IAC5C,OAAO,KAAK,OAAO,CAAC,YAAY,QAAK,OAAO,CAAC,YAAY;AAC7D;AASO,MAAM,4CAAyB,CAAC;IACnC,MAAM,gBAAgB;IACtB,MAAM,YAAsB,EAAE;IAC9B,MAAM,QAAQ,MAAM,KAAK,CAAC;IAC1B,IAAI,kBAAkB;IAEtB,MAAM,OAAO,CAAC,CAAC;QACX,MAAM,cAAc,KAAK,IAAI;QAC7B,MAAM,aAAa,cAAc,IAAI,CAAC;QACtC,MAAM,WAAW,gBAAgB,IAAI,CAAC;QAEtC,IAAI,cAAc,CAAC,UAAU;YACzB,IAAI,iBAAiB;gBACjB,UAAU,IAAI,CAAC,gBAAgB,IAAI;gBACnC,kBAAkB;YACtB;YACA,UAAU,IAAI,CAAC;QACnB,OAAO;YACH,mBAAmB,GAAG,YAAY,CAAC,CAAC;YACpC,MAAM,WAAW,gBAAgB,IAAI,GAAG,KAAK,CAAC;YAC9C,IAAI,QAAQ,IAAI,CAAC,WAAW;gBACxB,UAAU,IAAI,CAAC,gBAAgB,IAAI;gBACnC,kBAAkB;YACtB;QACJ;IACJ;IAEA,uCAAuC;IACvC,IAAI,iBACA,UAAU,IAAI,CAAC,gBAAgB,IAAI;IAGvC,OAAO,UAAU,IAAI,CAAC;AAC1B;AAQO,MAAM,4CAA6B,CAAC;IACvC,OAAO,KAAK,OAAO,CAAC,uBAAuB;AAC/C;AAQO,MAAM,4CAAkB,CAAC;IAC5B,OAAO,KAAK,OAAO,CAAC,WAAW;AACnC;AAQO,MAAM,4CAA4B,CAAC;IACtC,OAAO,KAAK,OAAO,CAAC,sBAAsB;AAC9C;AAkBO,MAAM,4CAA6B,CAAC;IACvC,OAAO,KAAK,OAAO,CAAC,eAAe;AACvC;AAQO,MAAM,4CAA4B,CAAC;IACtC,OAAO,KAAK,OAAO,CAAC,6BAA6B;AACrD;AAOO,MAAM,4CAAmB,CAAC;IAC7B,oCAAoC;IACpC,MAAM,mBAAmB,KAAK,SAAS,CAAC;IAExC,+EAA+E;IAC/E,OAAO,iBAAiB,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAChE;AAQO,MAAM,4CAAsB,CAAC;IAChC,MAAM,YAAoC;QACtC,gBAAgB;QAChB,gBAAgB;QAChB,gBAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,gBAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,gBAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;IACpB;IAEA,OAAO,KAAK,OAAO,CAAC,6EAA6E,CAAC;QAC9F,OAAO,SAAS,CAAC,MAAM,IAAI;IAC/B;AACJ;AAOO,MAAM,4CAAe,CAAC;IACzB,OAAO,0CAAoB,0CAAiB;AAChD;AAQO,MAAM,4CAAwB,CAAC;IAClC,OAAO,KAAK,OAAO,CAAC,gCAAgC;AACxD;;;;;;;;;ACtZA;;;;;;;;;;;CAWC,GACM,MAAM,4CAAsB,CAAC;IAChC,IAAI,QAAQ,IAAI,OAAO,CAAC,mBAAmB;IAC3C,QAAQ,MAAM,OAAO,CAAC,kBAAkB;IACxC,QAAQ,MAAM,OAAO,CAAC,kBAAkB;IAExC,OAAO,KAAK,SAAS,CAAC,KAAK,KAAK,CAAC;AACrC;AAcO,MAAM,4CAAuB,CAAC;IACjC,6EAA6E;IAC7E,MAAM,kBACF;IACJ,OAAO,gBAAgB,IAAI,CAAC,IAAI,IAAI;AACxC;AAgBO,MAAM,4CAAgB,CAAC;IAC1B,MAAM,QAAQ;IACd,OAAO,AAAC,CAAA,MAAM,KAAK,CAAC,UAAU,EAAE,AAAD,EAAG,GAAG,CAAC,CAAC,IAAe,EAAE,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/F;AAEA;;;;;;;;;;;;;CAaC,GACD,MAAM,0CAAoB,CAAC;IACvB,IAAI,aAAa;IACjB,KAAK,MAAM,QAAQ,IACf,IAAI,SAAS,KACT;IAGR,OAAO,aAAa,MAAM;AAC9B;AAEA,MAAM,iCAAW;IAAE,KAAK;IAAK,KAAK;IAAK,KAAK;AAAI;AAChD,MAAM,qCAAe,IAAI,IAAI;IAAC;IAAK;IAAK;CAAI;AAC5C,MAAM,sCAAgB,IAAI,IAAI;IAAC;IAAK;IAAK;CAAI;AAE7C;;;;;;;;;;;;;;;;;CAiBC,GAED,MAAM,4CAAsB,CAAC;IACzB,MAAM,QAAkB,EAAE;IAE1B,KAAK,MAAM,QAAQ,IAAK;QACpB,IAAI,mCAAa,GAAG,CAAC,OACjB,MAAM,IAAI,CAAC;aACR,IAAI,oCAAc,GAAG,CAAC,OAAO;YAChC,MAAM,WAAW,MAAM,GAAG;YAC1B,IAAI,CAAC,YAAY,8BAAQ,CAAC,SAAkC,KAAK,MAC7D,OAAO;QAEf;IACJ;IAEA,OAAO,MAAM,MAAM,KAAK;AAC5B;AAsBO,MAAM,2CAAa,CAAC;IACvB,OAAO,wCAAkB,QAAQ,0CAAoB;AACzD;;;;;;;;;;;;;;;;AChJA;;;;;CAKC,GACM,MAAM,4CAAgC,CAAC;IAC1C,OAAO,KAAK,OAAO,CACf,yHACA;AAER;AAQO,MAAM,4CAA2B,CAAC;IACrC,OAAO,KAAK,OAAO,CAAC,cAAc;AACtC;AAQO,MAAM,4CAA8B,CAAC;IACxC,OAAO,KAAK,OAAO,CAAC,QAAQ;AAChC;AAQO,MAAM,4CAAiB,CAAC;IAC3B,OAAO,KAAK,OAAO,CAAC,UAAU;AAClC;AAQO,MAAM,4CAAkB,CAAC;IAC5B,OAAO,KAAK,OAAO,CAAC,0DAA0D;AAClF;AAQO,MAAM,4CAAyB,CAAC;IACnC,OAAO,KAAK,OAAO,CAAC,UAAU;AAClC;AAQO,MAAM,4CAA8B,CAAC;IACxC,OAAO,KAAK,OAAO,CAAC,6BAA6B;AACrD;AAQO,MAAM,4CAAa,CAAC;IACvB,OAAO,KAAK,OAAO,CACf,wGACA;AAER;AAkBO,MAAM,4CAAW,CAAC,KAAa,IAAI,GAAG,GAAc,IAAI,MAAM,GAAG,IAAI,GAAG,IAAI,SAAS,CAAC,GAAG,IAAI,GAAG,QAAC,CAAC,GAAG;AAsBrG,MAAM,4CAAiB,CAAC,MAAc,YAAoB,EAAE,EAAE;IACjE,IAAI,KAAK,MAAM,IAAI,WACf,OAAO;IAGX,wEAAwE;IACxE,MAAM,mBAAmB,KAAK,GAAG,CAAC,GAAG,KAAK,KAAK,CAAC,YAAY;IAC5D,MAAM,kBAAkB,aAAa;IAErC,oDAAoD;IACpD,MAAM,kBAAkB,YAAY;IAEpC,6DAA6D;IAC7D,MAAM,cAAc,kBAAkB;IAEtC,uDAAuD;IACvD,IAAI,cAAc,GACd,6DAA6D;IAC7D,OAAO,GAAG,KAAK,SAAS,CAAC,GAAG,YAAY,GAAG,QAAC,CAAC;IAGjD,MAAM,eAAe,KAAK,SAAS,CAAC,GAAG;IACvC,MAAM,aAAa,KAAK,SAAS,CAAC,KAAK,MAAM,GAAG;IAEhD,OAAO,GAAG,aAAa,QAAC,EAAE,YAAY;AAC1C;AAqBO,MAAM,2CAAiB,CAAC,QAAkB,MAAM,OAAO,CAAC,QAAQ,KAAK,IAAI;;;;;;;;;;;;;;AC/JzE,MAAM,4CAA8B,CAAC;IACxC,OAAO,KACF,OAAO,CAAC,8EAA8E,SACtF,OAAO,CAAC,yBAAyB,UACjC,OAAO,CAAC,gBAAgB;AACjC;AASO,MAAM,4CAA6B,CAAC;IACvC,OAAO,KAAK,OAAO,CAAC,OAAO,UAAK,OAAO,CAAC,OAAO;AACnD;AAUO,MAAM,4CAA+B,CAAC;IACzC,OAAO,KACF,OAAO,CACJ,4IACA,aAEH,OAAO,CAAC,cAAc;AAC/B;AASO,MAAM,0CAAY,CAAC;IACtB,OAAO,MACF,SAAS,CAAC,QACV,OAAO,CAAC,oBAAoB,IAC5B,OAAO,CAAC,YAAY;AAC7B;AASO,MAAM,4CAAuB,CAAC;IACjC,OAAO,KAAK,OAAO,CAAC,UAAU;AAClC;AASO,MAAM,4CAAuB,CAAC;IACjC,OAAO,CAAA,GAAA,yCAAc,EAAE,KAAK,OAAO,CAAC,wEAAwE;AAChH;AASO,MAAM,4CAAiC,CAAC,OAAiB,wCAAU,0CAAqB;AASxF,MAAM,4CAAkB,CAAC;IAC5B,MAAM,WAAW,0CAA+B,UAC3C,IAAI,GACJ,KAAK,CAAC,QACN,KAAK,CAAC,GAAG,GACT,GAAG,CAAC,CAAC;QACF,OAAO,KAAK,MAAM,CAAC,GAAG,WAAW;IACrC,GACC,IAAI,CAAC;IACV,OAAO;AACX;","sources":["src/index.ts","src/arabic.ts","src/formatting.ts","src/parsing.ts","src/sanitization.ts","src/transliteration.ts"],"sourcesContent":["export * from './arabic';\nexport * from './formatting';\nexport * from './parsing';\nexport * from './sanitization';\nexport * from './transliteration';\n","/**\n * Removes extreme Arabic underscores (ـ) that appear at the beginning or end of a line or in text.\n * Does not affect Hijri dates (e.g., 1424هـ) or specific Arabic terms.\n * Example: \"ـThis is a textـ\" will be changed to \"This is a text\".\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with extreme underscores removed.\n */\nexport const cleanExtremeArabicUnderscores = (text: string) => {\n return text.replace(/(?<!\\d ?ه|اه)ـ(?=\\r?$)|^ـ(?!اهـ)/gm, '');\n};\n\n/**\n * Converts Urdu symbols to their Arabic equivalents.\n * Example: 'ھذا' will be changed to 'هذا', 'ی' to 'ي'.\n * @param {string} text - The input text containing Urdu symbols.\n * @returns {string} - The modified text with Urdu symbols converted to Arabic symbols.\n */\nexport const convertUrduSymbolsToArabic = (text: string) => {\n return text.replace(/ھ/g, 'ه').replace(/ی/g, 'ي');\n};\n\n/**\n * Fixes the trailing \"و\" (wow) in phrases such as \"عليكم و رحمة\" to \"عليكم ورحمة\".\n * This function attempts to correct phrases where \"و\" appears unnecessarily, particularly in greetings.\n * Example: 'السلام عليكم و رحمة' will be changed to 'السلام عليكم ورحمة'.\n * @param {string} text - The input text containing the \"و\" character.\n * @returns {string} - The modified text with unnecessary trailing \"و\" characters corrected.\n */\nexport const fixTrailingWow = (text: string) => {\n return text.replace(/ و /g, ' و');\n};\n\n/**\n * Inserts a space between Arabic text and numbers.\n * Example: 'الآية37' will be changed to 'الآية 37'.\n * @param {string} text - The input text containing Arabic text followed by numbers.\n * @returns {string} - The modified text with spaces inserted between Arabic text and numbers.\n */\nexport const addSpaceBetweenArabicTextAndNumbers = (text: string) => {\n return text.replace(/([\\u0600-\\u06FF]+)(\\d+)/g, '$1 $2');\n};\n\n/**\n * Removes English letters and symbols from the text, including ampersands, slashes, and other symbols.\n * Example: 'أحب & لنفسي' will be changed to 'أحب لنفسي'.\n * @param {string} text - The input text containing English letters and symbols.\n * @returns {string} - The modified text with English letters and symbols removed.\n */\nexport const stripEnglishCharactersAndSymbols = (text: string) => {\n return text.replace(/[a-zA-Z]+[0-9]*|[¬§`ﷺ=]|\\/{2,}|&/g, ' ');\n};\n\n/**\n * Removes single-digit numbers surrounded by Arabic text. Also removes dashes (-) not followed by a number.\n * For example, removes '3' from 'وهب 3 وقال' but does not remove '121' from 'لوحه 121 الجرح'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with non-index numbers and dashes removed.\n */\nexport const removeNonIndexSignatures = (text: string) => {\n return text\n .replace(/(?<![0-9] ?)-|(?<=[\\u0600-\\u06FF])\\s?\\d\\s?(?=[\\u0600-\\u06FF])/g, ' ')\n .replace(/(?<=[\\u0600-\\u06FF]\\s)(\\d+\\s)+\\d+(?=(\\s[\\u0600-\\u06FF]|$))/g, ' ');\n};\n\n/**\n * Removes characters enclosed in square brackets [] or parentheses () if they are Arabic letters or Arabic-Indic numerals.\n * Example: '[س]' or '(س)' will be removed.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with singular codes removed.\n */\nexport const removeSingularCodes = (text: string) => {\n return text.replace(/[[({][\\u0621-\\u064A\\u0660-\\u0669][\\])}]/g, '');\n};\n\n/**\n * Removes solitary Arabic letters unless they are the 'ha' letter, which is used in Hijri years.\n * Example: \"ب ا الكلمات ت\" will be changed to \"ا الكلمات\".\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with solitary Arabic letters removed.\n */\nexport const removeSolitaryArabicLetters = (text: string) => {\n return text.replace(/(^| )[\\u0621-\\u064A]( |$)/g, ' ');\n};\n\n/**\n * Removes tatweel characters while preserving dates references and numbered list items.\n * Example: \"1435/3/29 هـ\" remains as \"1435/3/29 هـ\" but \"أبـــتِـــكَةُ\" becomes \"أبتِكَةُ\"\n * @param text The text to format.\n * @returns The modified text with the tatweel characters removed.\n */\nexport const removeTatwil = (text: string) => {\n // Don't remove tatweel if:\n // 1. Immediately preceded by a number or ه (for dates like \"1435هـ\")\n // 2. Preceded by a number with optional spaces (for list items like \"3 ـ\")\n return text.replace(/(?<![0-9ه])(?<![0-9]\\s*)ـ/g, '');\n};\n\n/**\n * Replaces the 'tah marbutah' (ة) character with 'ha' (ه).\n * Example: 'مدرسة' will be changed to 'مدرسه'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with 'ta marbutah' replaced by 'ha'.\n */\nexport const replaceTaMarbutahWithHa = (text: string) => {\n return text.replace(/[ة]/g, 'ه');\n};\n\n/**\n * Removes Arabic diacritics (tashkeel) and the tatweel (elongation) character.\n * Example: 'مُحَمَّدٌ' will be changed to 'محمد'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with diacritics and tatweel removed.\n */\nexport const stripDiacritics = (text: string) => {\n return text.replace(\n /[\\u0610\\u0611\\u0612\\u0613\\u0614\\u0615\\u0616\\u0617\\u0618\\u0619\\u061A\\u064B\\u064C\\u064D\\u064E\\u064F\\u0650\\u0651\\u0652\\u0653\\u0654\\u0655\\u0656\\u0657\\u0658\\u065A\\u065B\\u065C\\u065D\\u065E\\u0640]/g,\n '',\n );\n};\n\n/**\n * Removes zero-width joiners (ZWJ) and other zero-width characters from the input text.\n * Zero-width characters include U+200B to U+200F, U+202A to U+202E, U+2060 to U+2064, and U+FEFF.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with zero-width characters removed.\n */\nexport const stripZeroWidthCharacters = (text: string) => {\n return text.replace(/[\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u2064\\uFEFF]/g, ' ');\n};\n\n/**\n * Replaces the 'alif maqsurah' (ى) character with the regular 'ya' (ي).\n * Example: 'رؤيى' will be changed to 'رؤيي'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with 'alif maqsurah' replaced by 'ya'.\n */\nexport const replaceAlifMaqsurah = (text: string) => {\n return text.replace(/[ىي]/g, 'ي');\n};\n\n/**\n * Replaces English punctuation (question mark and semicolon) with their Arabic equivalents.\n * Example: '?' will be replaced with '؟', and ';' with '؛'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with English punctuation replaced by Arabic punctuation.\n */\nexport const replaceEnglishPunctuationWithArabic = (text: string) => {\n return text\n .replace(/\\?|؟\\./g, '؟')\n .replace(/(;|؛)\\s*(\\1\\s*)*/g, '؛')\n .replace(/,|-،/g, '،');\n};\n\n/**\n * Simplifies all forms of 'alif' (أ, إ, and آ) to the basic 'ا'.\n * Example: 'أنا إلى الآفاق' will be changed to 'انا الى الافاق'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with simplified 'alif' characters.\n */\nexport const normalizeAlifVariants = (text: string) => {\n return text.replace(/[أإآ]/g, 'ا');\n};\n","/**\n * Adds line breaks after punctuation marks such as periods, exclamation points, and question marks.\n * Example: 'Text.' becomes 'Text.\\n'.\n * @param {string} text - The input text containing punctuation.\n * @returns {string} - The modified text with line breaks added after punctuation.\n */\nexport const insertLineBreaksAfterPunctuation = (text: string) => {\n // Define the punctuation marks that should trigger a new line\n const punctuation = /([.?!؟])/g;\n\n // Replace occurrences of punctuation marks followed by a space with the punctuation mark, a newline, and the space\n const formattedText = text.replace(punctuation, '$1\\n').replace(/\\n\\s+/g, '\\n').trim();\n\n return formattedText;\n};\n\n/**\n * Adds spaces before and after punctuation, except for certain cases like quoted text or ayah references.\n * Example: 'Text,word' becomes 'Text, word'.\n * @param {string} text - The input text containing punctuation.\n * @returns {string} - The modified text with spaces added before and after punctuation.\n */\nexport const addSpaceBeforeAndAfterPunctuation = (text: string) => {\n return text\n .replace(/( ?)([.!?,،؟;؛])((?![ '”“)\"\\]\\n])|(?=\\s{2,}))/g, '$1$2 ')\n .replace(/\\s([.!?,،؟;؛])\\s*([ '”“)\"\\]\\n])/g, '$1$2')\n .replace(/([^\\s\\w\\d'”“)\"\\]]+)\\s+([.!?,،؟;؛])|([.!?,،؟;؛])\\s+$/g, '$1$2$3')\n .replace(/(?<=\\D)( ?: ?)(?!(\\d+:)|(:\\d+))|(?<=\\d) ?: ?(?=\\D)|(?<=\\D) ?: ?(?=\\d)/g, ': ');\n};\n\n/**\n * Turns regular double quotes surrounding a body of text into smart quotes.\n * Also fixes incorrect starting quotes by ensuring the string starts with an opening quote if needed.\n * Example: 'The \"quick brown\" fox' becomes 'The “quick brown” fox'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with smart quotes applied.\n */\nexport const applySmartQuotes = (text: string) => {\n return text\n .replace(/[“”]/g, '\"')\n .replace(/\"([^\"]*)\"/g, '“$1”')\n .replace(/^”/g, '“');\n};\n\n/**\n * Replaces literal new line characters (\\n) and carriage returns (\\r) with actual line breaks.\n * Example: 'A\\\\nB' becomes 'A\\nB'.\n * @param {string} text - The input text containing literal new lines.\n * @returns {string} - The modified text with actual line breaks.\n */\nexport const cleanLiteralNewLines = (text: string) => {\n return text.replace(/\\\\n|\\r/g, '\\n');\n};\n\n/**\n * Removes trailing spaces from each line in a multiline string.\n * Example: \" This is a line \\nAnother line \" becomes \"This is a line\\nAnother line\".\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with trailing spaces removed.\n */\nexport const cleanMultilines = (text: string) => {\n return text.replace(/^ +| +$/gm, '');\n};\n\n/**\n * Detects if a word is by itself in a line.\n * @param text The text to check.\n * @returns true if there exists a word in any of the lines in the text that is by itself.\n */\nexport const hasWordInSingleLine = (text: string): boolean => {\n return /^\\s*\\S+\\s*$/gm.test(text);\n};\n\n/**\n * Checks if the input string consists of only punctuation characters.\n * @param {string} text - The input text to check.\n * @returns {boolean} - Returns true if the string contains only punctuation, false otherwise.\n */\nexport const isOnlyPunctuation = (text: string): boolean => {\n const regex = /^[\\u0020-\\u002f\\u003a-\\u0040\\u005b-\\u0060\\u007b-\\u007e0-9٠-٩]+$/;\n return regex.test(text);\n};\n\nexport const cleanJunkFromText = (text: string) => {\n const newBody = cleanMultilines(text);\n const lines = newBody.split('\\n').filter((line) => {\n return !line || (line.length > 1 && !isOnlyPunctuation(line));\n });\n\n return lines.join('\\n').trim();\n};\n\n/**\n * Cleans unnecessary spaces before punctuation marks such as periods, commas, and question marks.\n * Example: 'This is a sentence , with extra space .' becomes 'This is a sentence, with extra space.'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with cleaned spaces before punctuation.\n */\nexport const cleanSpacesBeforePeriod = (text: string) => {\n return text.replace(/\\s+([.؟!,،؛:?])/g, '$1');\n};\n\n/**\n * Condenses multiple asterisks (*) into a single one.\n * Example: '***' becomes '*'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed asterisks.\n */\nexport const condenseAsterisks = (text: string) => {\n return text.replace(/(\\*\\s*)+/g, '*');\n};\n\n/**\n * Replaces occurrences of colons surrounded by periods (e.g., '.:.' or ':') with a single colon.\n * Example: 'This.:. is a test' becomes 'This: is a test'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed colons.\n */\nexport const condenseColons = (text: string) => {\n return text.replace(/[.-]?:[.-]?/g, ':');\n};\n\n/**\n * Condenses two or more dashes (--) into a single dash (-).\n * Example: 'This is some ---- text' becomes 'This is some - text'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed dashes.\n */\nexport const condenseDashes = (text: string) => {\n return text.replace(/-{2,}/g, '-');\n};\n\n/**\n * Replaces sequences of two or more periods (e.g., '...') with an ellipsis character (…).\n * Example: 'This is a test...' becomes 'This is a test…'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with ellipses condensed.\n */\nexport const condenseEllipsis = (text: string) => {\n return text.replace(/\\.{2,}/g, '…');\n};\n\n/**\n * Reduces multiple consecutive line breaks (3 or more) to exactly 2 line breaks.\n * Example: 'This is line 1\\n\\n\\n\\nThis is line 2' becomes 'This is line 1\\n\\nThis is line 2'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed line breaks.\n */\nexport const reduceMultilineBreaksToDouble = (text: string) => {\n return text.replace(/(\\n\\s*){3,}/g, '\\n\\n');\n};\n\n/**\n * Reduces multiple consecutive line breaks (2 or more) to exactly 1 line break.\n * Example: 'This is line 1\\n\\nThis is line 2' becomes 'This is line 1\\nThis is line 2'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed line breaks.\n */\nexport const reduceMultilineBreaksToSingle = (text: string) => {\n return text.replace(/(\\n\\s*){2,}/g, '\\n');\n};\n\n/**\n * Condenses multiple periods separated by spaces (e.g., '. . .') into a single period.\n * Example: 'This . . . is a test' becomes 'This. is a test'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed periods.\n */\nexport const condensePeriods = (text: string) => {\n return text.replace(/\\. +\\./g, '.');\n};\n\n/**\n * Condenses multiple underscores (__) or Arabic Tatweel characters (ـــــ) into a single underscore or Tatweel.\n * Example: 'This is ـــ some text __' becomes 'This is ـ some text _'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed underscores.\n */\nexport const condenseUnderscores = (text: string) => {\n return text.replace(/ـ{2,}/g, 'ـ').replace(/_+/g, '_');\n};\n\n/**\n * Replaces double parentheses or brackets with single ones.\n * Example: '((text))' becomes '(text)'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed brackets.\n */\nexport const doubleToSingleBrackets = (text: string) => {\n return text.replace(/(\\(|\\)){2,}|(\\[|\\]){2,}/g, '$1$2');\n};\n\n/**\n * Replaces double parentheses single a single arrow variation.\n * Example: '((text))' becomes '«text»'.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with condensed brackets.\n */\nexport const replaceDoubleBracketsWithArrows = (text: string) => {\n return text.replace(/\\(\\(\\s?/g, '«').replace(/\\s?\\)\\)/g, '»');\n};\n\n/**\n * Formats a multiline string by joining sentences and maintaining footnotes on their own lines.\n * Footnotes are identified by Arabic and English numerals.\n * Example: 'Sentence one.\\n(1) A footnote.\\nSentence two.' remains the same, while regular sentences are joined.\n * @param {string} input - The input text containing sentences and footnotes.\n * @returns {string} - The formatted text.\n */\nexport const formatStringBySentence = (input: string) => {\n const footnoteRegex = /^\\((?:\\d+|۱|۲|۳|۴|۵|۶|۷|۸|۹)\\)\\s/;\n const sentences: string[] = [];\n const lines = input.split('\\n');\n let currentSentence = '';\n\n lines.forEach((line) => {\n const trimmedLine = line.trim();\n const isFootnote = footnoteRegex.test(trimmedLine);\n const isNumber = /^\\(\\d+\\/\\d+\\)/.test(trimmedLine);\n\n if (isFootnote && !isNumber) {\n if (currentSentence) {\n sentences.push(currentSentence.trim());\n currentSentence = '';\n }\n sentences.push(trimmedLine);\n } else {\n currentSentence += `${trimmedLine} `;\n const lastChar = currentSentence.trim().slice(-1);\n if (/[.!؟]/.test(lastChar)) {\n sentences.push(currentSentence.trim());\n currentSentence = '';\n }\n }\n });\n\n // Add any remaining text to the output\n if (currentSentence) {\n sentences.push(currentSentence.trim());\n }\n\n return sentences.join('\\n');\n};\n\n/**\n * Removes unnecessary spaces around slashes in references.\n * Example: '127 / 11' becomes '127/11'.\n * @param {string} text - The input text containing references.\n * @returns {string} - The modified text with spaces removed around slashes.\n */\nexport const normalizeSlashInReferences = (text: string) => {\n return text.replace(/(\\d+)\\s?\\/\\s?(\\d+)/g, '$1/$2');\n};\n\n/**\n * Reduces multiple spaces or tabs to a single space.\n * Example: 'This is a text' becomes 'This is a text'.\n * @param {string} text - The input text containing extra spaces.\n * @returns {string} - The modified text with reduced spaces.\n */\nexport const normalizeSpaces = (text: string) => {\n return text.replace(/[ \\t]+/g, ' ');\n};\n\n/**\n * Ensures at most 1 space exists before any word before brackets.\n * Adds a space if there isn't one, or reduces multiple spaces to one.\n * @param {string} text - The input text to modify\n * @returns {string} - The modified text with proper spacing before brackets\n */\nexport const ensureSpaceBeforeBrackets = (text: string) => {\n return text.replace(/(\\S) *(\\([^)]*\\))/g, '$1 $2');\n};\n\n/**\n * Removes redundant punctuation marks that follow Arabic question marks or exclamation marks.\n * This function cleans up text by removing periods (.) or Arabic commas (،) that immediately\n * follow Arabic question marks (؟) or exclamation marks (!), as they are considered redundant\n * in proper Arabic punctuation.\n *\n * @param text - The Arabic text to clean up\n * @returns The text with redundant punctuation removed\n *\n * @example\n * ```typescript\n * removeRedundantPunctuation('كيف حالك؟.') // Returns: 'كيف حالك؟'\n * removeRedundantPunctuation('ممتاز!،') // Returns: 'ممتاز!'\n * removeRedundantPunctuation('هذا جيد.') // Returns: 'هذا جيد.' (unchanged)\n * ```\n */\nexport const removeRedundantPunctuation = (text: string) => {\n return text.replace(/([؟!])[.،]/g, '$1');\n};\n\n/**\n * Removes spaces inside brackets, parentheses, or square brackets.\n * Example: '( a b )' becomes '(a b)'.\n * @param {string} text - The input text with spaces inside brackets.\n * @returns {string} - The modified text with spaces removed inside brackets.\n */\nexport const removeSpaceInsideBrackets = (text: string) => {\n return text.replace(/([[(])\\s*(.*?)\\s*([\\])])/g, '$1$2$3');\n};\n\n/**\n * Removes bold styling from text by normalizing the string and removing stylistic characters.\n * @param {string} text - The input text containing bold characters.\n * @returns {string} - The modified text with bold styling removed.\n */\nexport const stripBoldStyling = (text: string) => {\n // Normalize the string to NFKD form\n const normalizedString = text.normalize('NFKD');\n\n // Remove combining marks (diacritics) and stylistic characters from the string\n return normalizedString.replace(/[\\u0300-\\u036f]/g, '').trim();\n};\n\n/**\n * Removes italicized characters by replacing italic Unicode characters with their normal counterparts.\n * Example: '𝘼𝘽𝘾' becomes 'ABC'.\n * @param {string} text - The input text containing italicized characters.\n * @returns {string} - The modified text with italics removed.\n */\nexport const stripItalicsStyling = (text: string) => {\n const italicMap: Record<string, string> = {\n '\\uD835\\uDC4E': 'I',\n '\\uD835\\uDC68': 'g',\n '\\u{1D63C}': '!',\n '\\uD835\\uDC4F': 'J',\n '\\uD835\\uDC69': 'h',\n '\\u{1D63D}': '?',\n '\\uD835\\uDC50': 'K',\n '\\uD835\\uDC6A': 'i',\n '\\uD835\\uDC51': 'L',\n '\\uD835\\uDC6B': 'j',\n '\\u{1D63F}': ',',\n '\\uD835\\uDC52': 'M',\n '\\uD835\\uDC6C': 'k',\n '\\u{1D640}': '.',\n '\\uD835\\uDC53': 'N',\n '\\uD835\\uDC6D': 'l',\n '\\uD835\\uDC54': 'O',\n '\\uD835\\uDC6E': 'm',\n '\\uD835\\uDC6F': 'n',\n '\\uD835\\uDC56': 'Q',\n '\\uD835\\uDC70': 'o',\n '\\uD835\\uDC57': 'R',\n '\\uD835\\uDC71': 'p',\n '\\uD835\\uDC58': 'S',\n '\\uD835\\uDC72': 'q',\n '\\uD835\\uDC59': 'T',\n '\\uD835\\uDC73': 'r',\n '\\u{1D647}': '-',\n '\\uD835\\uDC5A': 'U',\n '\\uD835\\uDC74': 's',\n '\\uD835\\uDC5B': 'V',\n '\\uD835\\uDC75': 't',\n '\\uD835\\uDC5C': 'W',\n '\\uD835\\uDC76': 'u',\n '\\uD835\\uDC5D': 'X',\n '\\uD835\\uDC77': 'v',\n '\\uD835\\uDC5E': 'Y',\n '\\uD835\\uDC78': 'w',\n '\\uD835\\uDC5F': 'Z',\n '\\uD835\\uDC79': 'x',\n '\\uD835\\uDC46': 'A',\n '\\uD835\\uDC7A': 'y',\n '\\uD835\\uDC47': 'B',\n '\\uD835\\uDC7B': 'z',\n '\\uD835\\uDC62': 'a',\n '\\uD835\\uDC48': 'C',\n '\\uD835\\uDC63': 'b',\n '\\uD835\\uDC49': 'D',\n '\\uD835\\uDC64': 'c',\n '\\uD835\\uDC4A': 'E',\n '\\uD835\\uDC65': 'd',\n '\\uD835\\uDC4B': 'F',\n '\\uD835\\uDC66': 'e',\n '\\uD835\\uDC4C': 'G',\n '\\uD835\\uDC67': 'f',\n '\\uD835\\uDC4D': 'H',\n '\\uD835\\uDC55': 'P',\n };\n\n return text.replace(/[\\uD835\\uDC62-\\uD835\\uDC7B\\uD835\\uDC46-\\uD835\\uDC5F\\u{1D63C}-\\u{1D647}]/gu, (match) => {\n return italicMap[match] || match;\n });\n};\n\n/**\n * Removes all bold and italic styling from the input text.\n * @param {string} text - The input text to remove styling from.\n * @returns {string} - The modified text with all styling removed.\n */\nexport const stripStyling = (text: string) => {\n return stripItalicsStyling(stripBoldStyling(text));\n};\n\n/**\n * Removes unnecessary spaces inside quotes.\n * Example: '“ Text ”' becomes '“Text”'.\n * @param {string} text - The input text with spaces inside quotes.\n * @returns {string} - The modified text with spaces removed inside quotes.\n */\nexport const trimSpaceInsideQuotes = (text: string) => {\n return text.replace(/([“”\"]|«) *(.*?) *([“”\"]|»)/g, '$1$2$3');\n};\n","/**\n * Converts a string that resembles JSON but with numeric keys and single-quoted values\n * into valid JSON format. This function replaces numeric keys with quoted numeric keys\n * and ensures all values are double-quoted as required by JSON.\n *\n * @param {string} str - The input string that needs to be fixed into valid JSON.\n * @returns {string} - A valid JSON string.\n *\n * @example\n * const result = normalizeJsonSyntax(\"{10: 'abc', 20: 'def'}\");\n * console.log(result); // '{\"10\": \"abc\", \"20\": \"def\"}'\n */\nexport const normalizeJsonSyntax = (str: string) => {\n let input = str.replace(/(\\b\\d+\\b)(?=:)/g, '\"$1\"');\n input = input.replace(/:\\s*'([^']+)'/g, ': \"$1\"');\n input = input.replace(/:\\s*\"([^\"]+)\"/g, ': \"$1\"');\n\n return JSON.stringify(JSON.parse(input));\n};\n\n/**\n * Checks if a given string resembles a JSON object with numeric or quoted keys and values\n * that are single or double quoted. This is useful for detecting malformed JSON-like\n * structures that can be fixed by the `normalizeJsonSyntax` function.\n *\n * @param {string} str - The input string to check.\n * @returns {boolean} - Returns true if the string is JSON-like, false otherwise.\n *\n * @example\n * const result = isJsonStructureValid(\"{10: 'abc', 'key': 'value'}\");\n * console.log(result); // true\n */\nexport const isJsonStructureValid = (str: string) => {\n // Checks for a pattern with numeric keys or quoted keys and values in quotes\n const jsonLikePattern =\n /^{(\\s*(\\d+|'[^']*'|\"[^\"]*\")\\s*:\\s*('|\")[^'\"]*\\3\\s*,)*(?:\\s*(\\d+|'[^']*'|\"[^\"]*\")\\s*:\\s*('|\")[^'\"]*\\5\\s*)}$/;\n return jsonLikePattern.test(str.trim());\n};\n\n/**\n * Splits a string by spaces and quoted substrings.\n *\n * This function takes an input string and splits it into parts where substrings\n * enclosed in double quotes are treated as a single part. Other substrings\n * separated by spaces are split normally.\n *\n * @param {string} query - The input string to be split.\n * @returns {string[]} An array of strings, with quoted substrings kept intact.\n *\n * @example\n * const result = splitByQuotes('\"This is\" \"a part of the\" \"string and\"');\n * console.log(result); // [\"This is\", \"a part of the\", \"string and\"]\n */\nexport const splitByQuotes = (query: string): string[] => {\n const regex = /(?:[^\\s\"]+|\"(.*?)\")+/g;\n return (query.match(regex) || []).map((s: string) => (s.startsWith('\"') ? s.slice(1, -1) : s));\n};\n\n/**\n * Checks if all double quotes in a string are balanced (even count).\n * A string has balanced quotes if every opening quote has a corresponding closing quote.\n *\n * @param str - The string to check for balanced quotes\n * @returns True if quotes are balanced (even count), false otherwise\n *\n * @example\n * ```typescript\n * areQuotesBalanced('Hello \"world\"') // Returns: true\n * areQuotesBalanced('Hello \"world') // Returns: false\n * areQuotesBalanced('No quotes') // Returns: true\n * ```\n */\nconst areQuotesBalanced = (str: string) => {\n let quoteCount = 0;\n for (const char of str) {\n if (char === '\"') {\n quoteCount++;\n }\n }\n return quoteCount % 2 === 0;\n};\n\nconst brackets = { '(': ')', '[': ']', '{': '}' };\nconst openBrackets = new Set(['(', '[', '{']);\nconst closeBrackets = new Set([')', ']', '}']);\n\n/**\n * Checks if all brackets in a string are properly balanced and matched.\n * This function validates that every opening bracket has a corresponding closing bracket\n * in the correct order and of the matching type.\n *\n * Supported bracket types: parentheses (), square brackets [], curly braces {}\n *\n * @param str - The string to check for balanced brackets\n * @returns True if all brackets are properly balanced and matched, false otherwise\n *\n * @example\n * ```typescript\n * areBracketsBalanced('(hello [world])') // Returns: true\n * areBracketsBalanced('(hello [world)') // Returns: false (mismatched)\n * areBracketsBalanced('((hello))') // Returns: true\n * areBracketsBalanced('(hello') // Returns: false (unclosed)\n * ```\n */\n\nconst areBracketsBalanced = (str: string) => {\n const stack: string[] = [];\n\n for (const char of str) {\n if (openBrackets.has(char)) {\n stack.push(char);\n } else if (closeBrackets.has(char)) {\n const lastOpen = stack.pop();\n if (!lastOpen || brackets[lastOpen as keyof typeof brackets] !== char) {\n return false;\n }\n }\n }\n\n return stack.length === 0;\n};\n\n/**\n * Checks if both quotes and brackets are balanced in a string.\n * This function combines quote balance checking and bracket balance checking\n * to ensure the entire string has properly balanced punctuation.\n *\n * A string is considered balanced when:\n * - All double quotes have matching pairs (even count)\n * - All brackets (parentheses, square brackets, curly braces) are properly matched and nested\n *\n * @param str - The string to check for balanced quotes and brackets\n * @returns True if both quotes and brackets are balanced, false otherwise\n *\n * @example\n * ```typescript\n * isBalanced('He said \"Hello (world)!\"') // Returns: true\n * isBalanced('He said \"Hello (world!\"') // Returns: false (unbalanced quote)\n * isBalanced('He said \"Hello (world)\"') // Returns: false (unbalanced quote)\n * isBalanced('Hello (world) [test]') // Returns: true\n * ```\n */\nexport const isBalanced = (str: string) => {\n return areQuotesBalanced(str) && areBracketsBalanced(str);\n};\n","/**\n * Removes various symbols, part references, and numerical markers from the text.\n * Example: '(1) (2/3)' becomes ''.\n * @param {string} text - The input text to apply the rule to.\n * @returns {string} - The modified text with symbols and part references removed.\n */\nexport const cleanSymbolsAndPartReferences = (text: string) => {\n return text.replace(\n / *\\(?:\\d+(?:\\/\\d+){0,2}\\)? *| *\\[\\d+(?:\\/\\d+)?\\] *| *«\\d+» *|\\d+\\/\\d+(?:\\/\\d+)?|[،§{}۝؍‎﴿﴾<>;_؟»«:!،؛[\\]…ـ¬.\\\\/*()\"]/g,\n ' ',\n );\n};\n\n/**\n * Removes trailing page numbers formatted as '-[46]-' from the text.\n * Example: 'This is some -[46]- text' becomes 'This is some text'.\n * @param {string} text - The input text with trailing page numbers.\n * @returns {string} - The modified text with page numbers removed.\n */\nexport const cleanTrailingPageNumbers = (text: string) => {\n return text.replace(/-\\[\\d+\\]-/g, '');\n};\n\n/**\n * Replaces consecutive line breaks and whitespace characters with a single space.\n * Example: 'a\\nb' becomes 'a b'.\n * @param {string} text - The input text containing line breaks or multiple spaces.\n * @returns {string} - The modified text with spaces.\n */\nexport const replaceLineBreaksWithSpaces = (text: string) => {\n return text.replace(/\\s+/g, ' ');\n};\n\n/**\n * Removes all numeric digits from the text.\n * Example: 'abc123' becomes 'abc'.\n * @param {string} text - The input text containing digits.\n * @returns {string} - The modified text with digits removed.\n */\nexport const stripAllDigits = (text: string) => {\n return text.replace(/[0-9]/g, '');\n};\n\n/**\n * Removes death year references like \"(d. 390H)\" and \"[d. 100h]\" from the text.\n * Example: 'Sufyān ibn ‘Uyaynah (d. 198h)' becomes 'Sufyān ibn ‘Uyaynah'.\n * @param {string} text - The input text containing death year references.\n * @returns {string} - The modified text with death years removed.\n */\nexport const removeDeathYear = (text: string) => {\n return text.replace(/\\[(d)\\.\\s*\\d{1,4}[hH]\\]\\s*|\\((d)\\.\\s*\\d{1,4}[hH]\\)\\s*/g, '');\n};\n\n/**\n * Removes numeric digits and dashes from the text.\n * Example: 'ABC 123-Xyz' becomes 'ABC Xyz'.\n * @param {string} text - The input text containing digits and dashes.\n * @returns {string} - The modified text with numbers and dashes removed.\n */\nexport const removeNumbersAndDashes = (text: string) => {\n return text.replace(/[\\d-]/g, '');\n};\n\n/**\n * Removes single digit references like (1), «2», [3] from the text.\n * Example: 'Ref (1), Ref «2», Ref [3]' becomes 'Ref , Ref , Ref '.\n * @param {string} text - The input text containing single digit references.\n * @returns {string} - The modified text with single digit references removed.\n */\nexport const removeSingleDigitReferences = (text: string) => {\n return text.replace(/\\(\\d{1}\\)|\\[\\d{1}\\]|«\\d»/g, '');\n};\n\n/**\n * Removes URLs from the text.\n * Example: 'Visit https://example.com' becomes 'Visit '.\n * @param {string} text - The input text containing URLs.\n * @returns {string} - The modified text with URLs removed.\n */\nexport const removeUrls = (text: string) => {\n return text.replace(\n /https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g,\n '',\n );\n};\n\n/**\n * Truncates a string to a specified length, adding an ellipsis if truncated.\n *\n * @param val - The string to truncate\n * @param n - Maximum length of the string (default: 150)\n * @returns The truncated string with ellipsis if needed, otherwise the original string\n *\n * @example\n * ```javascript\n * truncate('The quick brown fox jumps over the lazy dog', 20);\n * // Output: 'The quick brown fox…'\n *\n * truncate('Short text', 50);\n * // Output: 'Short text'\n * ```\n */\nexport const truncate = (val: string, n = 150): string => (val.length > n ? `${val.substring(0, n - 1)}…` : val);\n\n/**\n * Truncates a string from the middle, preserving both the beginning and end portions.\n *\n * @param text - The string to truncate\n * @param maxLength - Maximum length of the resulting string (default: 50)\n * @param endLength - Number of characters to preserve at the end (default: 1/3 of maxLength, minimum 3)\n * @returns The truncated string with ellipsis in the middle if needed, otherwise the original string\n *\n * @example\n * ```javascript\n * truncateMiddle('The quick brown fox jumps right over the lazy dog', 20);\n * // Output: 'The quick bro…zy dog'\n *\n * truncateMiddle('The quick brown fox jumps right over the lazy dog', 25, 8);\n * // Output: 'The quick brown …lazy dog'\n *\n * truncateMiddle('Short text', 50);\n * // Output: 'Short text'\n * ```\n */\nexport const truncateMiddle = (text: string, maxLength: number = 50, endLength?: number) => {\n if (text.length <= maxLength) {\n return text;\n }\n\n // Default end length is roughly 1/3 of max length, minimum 3 characters\n const defaultEndLength = Math.max(3, Math.floor(maxLength / 3));\n const actualEndLength = endLength ?? defaultEndLength;\n\n // Reserve space for the ellipsis character (1 char)\n const availableLength = maxLength - 1;\n\n // Calculate start length (remaining space after end portion)\n const startLength = availableLength - actualEndLength;\n\n // Ensure we have at least some characters at the start\n if (startLength < 1) {\n // If we can't fit both start and end, just truncate normally\n return `${text.substring(0, maxLength - 1)}…`;\n }\n\n const startPortion = text.substring(0, startLength);\n const endPortion = text.substring(text.length - actualEndLength);\n\n return `${startPortion}…${endPortion}`;\n};\n\n/**\n * Unescapes backslash-escaped spaces and trims whitespace from both ends.\n * Commonly used to clean file paths that have been escaped when pasted into terminals.\n *\n * @param input - The string to unescape and clean\n * @returns The cleaned string with escaped spaces converted to regular spaces and trimmed\n *\n * @example\n * ```javascript\n * unescapeSpaces('My\\\\ Folder\\\\ Name');\n * // Output: 'My Folder Name'\n *\n * unescapeSpaces(' /path/to/My\\\\ Document.txt ');\n * // Output: '/path/to/My Document.txt'\n *\n * unescapeSpaces('regular text');\n * // Output: 'regular text'\n * ```\n */\nexport const unescapeSpaces = (input: string) => input.replace(/\\\\ /g, ' ').trim();\n","import { normalizeSpaces } from './formatting';\n\n/**\n * Replaces common Arabic prefixes (like 'Al-', 'Ar-', 'Ash-', etc.) with 'al-' in the text.\n * Handles different variations of prefixes such as Ash- and Al- but not when the second word\n * does not start with 'S'.\n * Example: 'Ash-Shafiee' becomes 'al-Shafiee'.\n *\n * @param {string} text - The input text containing Arabic prefixes.\n * @returns {string} - The modified text with standardized 'al-' prefixes.\n */\nexport const normalizeArabicPrefixesToAl = (text: string) => {\n return text\n .replace(/(\\b|\\W)(Al |Al-|Ar-|As-|Adh-|Ad-|Ats-|Ath |Ath-|Az |Az-|az-|adh-|as-|ar-)/g, '$1al-')\n .replace(/(\\b|\\W)(Ash-S|ash-S)/g, '$1al-S')\n .replace(/al- (.+?)\\b/g, 'al-$1');\n};\n\n/**\n * Removes double occurrences of Arabic apostrophes such as ʿʿ or ʾʾ in the text.\n * Example: 'ʿulamāʾʾ' becomes 'ʿulamāʾ'.\n *\n * @param {string} text - The input text containing double apostrophes.\n * @returns {string} - The modified text with condensed apostrophes.\n */\nexport const normalizeDoubleApostrophes = (text: string) => {\n return text.replace(/ʿʿ/g, 'ʿ').replace(/ʾʾ/g, 'ʾ');\n};\n\n/**\n * Replaces common salutations such as \"sallahu alayhi wasallam\" with \"ﷺ\" in the text.\n * It also handles variations of the salutation phrase, including 'peace and blessings be upon him'.\n * Example: 'Then Muḥammad (sallahu alayhi wasallam)' becomes 'Then Muḥammad ﷺ'.\n *\n * @param {string} text - The input text containing salutations.\n * @returns {string} - The modified text with salutations replaced.\n */\nexport const replaceSalutationsWithSymbol = (text: string) => {\n return text\n .replace(\n /\\(peace be upon him\\)|(Messenger of (Allah|Allāh)|Messenger|Prophet|Mu[hḥ]ammad) *\\((s[^)]*m|peace[^)]*him|May[^)]*him|may[^)]*him)\\)*/gi,\n '$1 ﷺ',\n )\n .replace(/,\\s*ﷺ\\s*,/g, ' ﷺ');\n};\n\n/**\n * Normalizes the text by removing diacritics, apostrophes, and dashes.\n * Example: 'Al-Jadwal' becomes 'AlJadwal'.\n *\n * @param {string} input - The input text to normalize.\n * @returns {string} - The normalized text.\n */\nexport const normalize = (input: string) => {\n return input\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/`|ʾ|ʿ|-/g, '');\n};\n\n/**\n * Replaces various apostrophe characters (‛, ’, ‘) with the standard apostrophe (').\n * Example: '‛ulama’ al-su‘' becomes ''ulama' al-su''.\n *\n * @param {string} text - The input text containing different apostrophe characters.\n * @returns {string} - The modified text with normalized apostrophes.\n */\nexport const normalizeApostrophes = (text: string) => {\n return text.replace(/‛|’|‘/g, \"'\");\n};\n\n/**\n * Strips common Arabic prefixes like 'al-', 'bi-', 'fī', 'wa-', etc. from the beginning of words.\n * Example: 'al-Bukhari' becomes 'Bukhari'.\n *\n * @param {string} text - The input text containing Arabic prefixes.\n * @returns {string} - The modified text with prefixes stripped.\n */\nexport const removeArabicPrefixes = (text: string) => {\n return normalizeSpaces(text.replace(/(\\bal-|\\bli-|\\bbi-|\\bfī|\\bwa[-\\s]+|\\bl-|\\bliʿl|\\Bʿalá|\\Bʿan|\\bb\\.)/gi, ''));\n};\n\n/**\n * Simplifies English transliterations by removing diacritics, apostrophes, and common prefixes.\n * Example: 'Al-Jadwal' becomes 'Jadwal', and 'āḍġḥīṣṭū' becomes 'adghistu'.\n *\n * @param {string} text - The input text to simplify.\n * @returns {string} - The simplified text.\n */\nexport const normalizeTransliteratedEnglish = (text: string) => normalize(removeArabicPrefixes(text));\n\n/**\n * Extracts the initials from the input string, typically used for names or titles.\n * Example: 'Nayl al-Awtar' becomes 'NA'.\n *\n * @param {string} text - The input text to extract initials from.\n * @returns {string} - The extracted initials.\n */\nexport const extractInitials = (fullName: string) => {\n const initials = normalizeTransliteratedEnglish(fullName)\n .trim()\n .split(/[ -]/)\n .slice(0, 2)\n .map((word) => {\n return word.charAt(0).toUpperCase();\n })\n .join('');\n return initials;\n};\n"],"names":[],"version":3,"file":"main.js.map","sourceRoot":"../"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bitaboom",
3
3
  "description": "Use string utils library to format Arabic and English translations.",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "author": "Ragaeeb Haq",
6
6
  "license": "MIT",
7
7
  "private": false,