urdu-text-utils 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4
4
+
5
+ - Add Urdu stop words module (`URDU_STOP_WORDS`, `isStopWord`, `filterStopWords`, `removeStopWords`) with a curated set of 130+ canonical functional words.
6
+ - Enhance sentence segmentation in `splitSentences` and `countSentences` with abbreviation & honorific protection (e.g. `ڈاکٹر.`, `پروفیسر.`, `صاحب.`), numeric decimal protection, and optional `preserveTerminators` option.
7
+
3
8
  ## 0.1.3
4
9
 
5
10
  - Significantly expand transliteration dictionary coverage across pronouns & oblique forms (`مجھے`, `ہمیں`, `انہیں`, `اسے`, `جسے`), everyday verbs and inflections, calendar & weekdays, numbers & ordinals, food, household objects, health, geography, and common Pakistani names.
package/README.md CHANGED
@@ -76,14 +76,30 @@ hasUrduSpecificLetters("لڑکی"); // true — ڑ does not exist in Arabic
76
76
  hasUrduSpecificLetters("كتاب مدرسة"); // false
77
77
  ```
78
78
 
79
- ## Word and sentence counting
79
+ ## Word and sentence tokenization
80
80
 
81
81
  ```ts
82
82
  countWords("پاکستان ایک خوبصورت ملک ہے"); // 5
83
83
  countWords("آپ کیسے ہیں؟"); // 3 — attached punctuation is not a word
84
84
  countSentences("یہ پہلا جملہ ہے۔ یہ دوسرا ہے۔"); // 2
85
85
  splitWords(text); // string[]
86
- splitSentences(text); // string[]
86
+ splitSentences(text); // string[] — protects abbreviations like ڈاکٹر. and decimals
87
+ splitSentences(text, { preserveTerminators: true }); // preserves ending punctuation
88
+ ```
89
+
90
+ ## Stop words
91
+
92
+ ```ts
93
+ import { isStopWord, filterStopWords, removeStopWords, URDU_STOP_WORDS } from "urdu-text-utils";
94
+
95
+ isStopWord("اور"); // true
96
+ isStopWord("کتاب"); // false
97
+
98
+ filterStopWords(["یہ", "ایک", "بہترین", "کتاب", "ہے"]);
99
+ // ["بہترین", "کتاب"]
100
+
101
+ removeStopWords("پاکستان ایک خوبصورت ملک ہے");
102
+ // "پاکستان خوبصورت ملک"
87
103
  ```
88
104
 
89
105
  ## Urdu numbers
package/dist/index.cjs CHANGED
@@ -300,12 +300,51 @@ function splitWords(input) {
300
300
  if (!input) return [];
301
301
  return input.split(WORD_SPLIT_RE).map((w) => w.trim()).filter((w) => w.length > 0);
302
302
  }
303
- function countSentences(input) {
304
- return splitSentences(input).length;
303
+ var ABBREVIATIONS = [
304
+ "\u0688\u0627\u06A9\u0679\u0631",
305
+ "\u067E\u0631\u0648\u0641\u06CC\u0633\u0631",
306
+ "\u0627\u0646\u062C\u06CC\u0646\u0626\u0631",
307
+ "\u0627\u06CC\u0688\u0648\u0648\u06A9\u06CC\u0679",
308
+ "\u062C\u0646\u0627\u0628",
309
+ "\u0635\u0627\u062D\u0628",
310
+ "\u0635\u0627\u062D\u0628\u06C1",
311
+ "\u0645\u062D\u062A\u0631\u0645",
312
+ "\u0645\u062D\u062A\u0631\u0645\u06C1",
313
+ "\u0645\u0648\u0644\u0627\u0646\u0627",
314
+ "\u0645\u0641\u062A\u06CC",
315
+ "\u0639\u0644\u0627\u0645\u06C1",
316
+ "\u0628\u06CC\u06AF\u0645",
317
+ "\u0648\u063A\u06CC\u0631\u06C1",
318
+ "\u0631\u062D\u0645\u062A\u06C1",
319
+ "\u0631\u0636\u06CC",
320
+ "\u062A\u0639\u0627\u0644\u06CC",
321
+ "\u062A\u0639\u0627\u0644\u06CC\u0670",
322
+ "\u0639\u0644\u06CC\u06C1",
323
+ "\u0627\u0644\u0633\u0644\u0627\u0645",
324
+ "\u0635\u0644\u06CC",
325
+ "\u0648\u0633\u0644\u0645"
326
+ ];
327
+ var ABBREV_PATTERN = new RegExp(`(?:${ABBREVIATIONS.join("|")})[.\u06D4]`, "gu");
328
+ function countSentences(input, options) {
329
+ return splitSentences(input, options).length;
305
330
  }
306
- function splitSentences(input) {
331
+ function splitSentences(input, options = {}) {
307
332
  if (!input) return [];
308
- return input.split(SENTENCE_SPLIT_RE).map((s) => s.trim()).filter((s) => s.length > 0);
333
+ const { preserveTerminators = false } = options;
334
+ const PROTECTED_DOT = "\uE000";
335
+ const PROTECTED_URDU_FULL_STOP = "\uE001";
336
+ let sanitized = input.replace(/(\d)\.(\d)/gu, `$1${PROTECTED_DOT}$2`).replace(ABBREV_PATTERN, (match) => {
337
+ return match.replace(/\./g, PROTECTED_DOT).replace(/۔/g, PROTECTED_URDU_FULL_STOP);
338
+ });
339
+ if (preserveTerminators) {
340
+ const matches = sanitized.match(/[^۔؟?!.…]+[۔؟?!.…]+|[^۔؟?!.…]+$/gu) ?? [];
341
+ return matches.map(
342
+ (s) => s.replace(new RegExp(PROTECTED_DOT, "gu"), ".").replace(new RegExp(PROTECTED_URDU_FULL_STOP, "gu"), "\u06D4").trim()
343
+ ).filter((s) => s.length > 0);
344
+ }
345
+ return sanitized.split(SENTENCE_SPLIT_RE).map(
346
+ (s) => s.replace(new RegExp(PROTECTED_DOT, "gu"), ".").replace(new RegExp(PROTECTED_URDU_FULL_STOP, "gu"), "\u06D4").trim()
347
+ ).filter((s) => s.length > 0);
309
348
  }
310
349
  function analyzeUrdu(input) {
311
350
  const text = input ?? "";
@@ -328,6 +367,264 @@ function analyzeUrdu(input) {
328
367
  };
329
368
  }
330
369
 
370
+ // src/stopwords.ts
371
+ var URDU_STOP_WORDS = /* @__PURE__ */ new Set([
372
+ // Tense auxiliaries & copulas
373
+ "\u06C1\u06D2",
374
+ "\u06C1\u06CC\u06BA",
375
+ "\u06C1\u0648\u06BA",
376
+ "\u06C1\u0648",
377
+ "\u062A\u06BE\u0627",
378
+ "\u062A\u06BE\u06CC",
379
+ "\u062A\u06BE\u06D2",
380
+ "\u062A\u06BE\u06CC\u06BA",
381
+ "\u06C1\u0648\u06AF\u0627",
382
+ "\u06C1\u0648\u06AF\u06CC",
383
+ "\u06C1\u0648\u0646\u06AF\u06D2",
384
+ "\u06C1\u0648\u06BA\u06AF\u06D2",
385
+ "\u06C1\u0648\u0646\u0627",
386
+ "\u06C1\u0648\u0646\u06D2",
387
+ "\u06C1\u0648\u0627",
388
+ "\u06C1\u0648\u0626\u06CC",
389
+ "\u06C1\u0648\u0626\u06D2",
390
+ // Postpositions, relations & prepositions
391
+ "\u06A9\u0627",
392
+ "\u06A9\u06CC",
393
+ "\u06A9\u06D2",
394
+ "\u06A9\u0648",
395
+ "\u0646\u06D2",
396
+ "\u0633\u06D2",
397
+ "\u067E\u0631",
398
+ "\u062A\u06A9",
399
+ "\u0645\u06CC\u06BA",
400
+ "\u0644\u06CC\u06D2",
401
+ "\u0633\u0627\u062A\u06BE",
402
+ "\u0628\u063A\u06CC\u0631",
403
+ "\u0637\u0631\u062D",
404
+ "\u0637\u0631\u0641",
405
+ "\u0628\u0627\u0631\u06D2",
406
+ "\u0628\u0639\u062F",
407
+ "\u067E\u06C1\u0644\u06D2",
408
+ "\u062F\u0648\u0631\u0627\u0646",
409
+ "\u062F\u0631\u0645\u06CC\u0627\u0646",
410
+ "\u0639\u0644\u0627\u0648\u06C1",
411
+ "\u0633\u0648\u0627\u0626\u06D2",
412
+ "\u0633\u0648\u0627",
413
+ "\u0645\u0637\u0627\u0628\u0642",
414
+ "\u0628\u0627\u0639\u062B",
415
+ "\u0630\u0631\u06CC\u0639\u06D2",
416
+ "\u062A\u062D\u062A",
417
+ "\u0627\u0648\u067E\u0631",
418
+ "\u0646\u06CC\u0686\u06D2",
419
+ "\u0622\u06AF\u06D2",
420
+ "\u067E\u06CC\u0686\u06BE\u06D2",
421
+ "\u0627\u0646\u062F\u0631",
422
+ "\u0628\u0627\u06C1\u0631",
423
+ "\u067E\u0627\u0633",
424
+ "\u0642\u0631\u06CC\u0628",
425
+ "\u0646\u0632\u062F\u06CC\u06A9",
426
+ // Conjunctions & discourse markers
427
+ "\u0627\u0648\u0631",
428
+ "\u06CC\u0627",
429
+ "\u0627\u06AF\u0631",
430
+ "\u0644\u06CC\u06A9\u0646",
431
+ "\u0645\u06AF\u0631",
432
+ "\u062A\u0648",
433
+ "\u0628\u06BE\u06CC",
434
+ "\u06C1\u06CC",
435
+ "\u0646\u06C1",
436
+ "\u0646\u06C1\u06CC\u06BA",
437
+ "\u0645\u062A",
438
+ "\u0646\u0627",
439
+ "\u0628\u0644\u06A9\u06C1",
440
+ "\u062D\u0627\u0644\u0627\u0646\u06A9\u06C1",
441
+ "\u0686\u0648\u0646\u06A9\u06C1",
442
+ "\u06A9\u06CC\u0648\u0646\u06A9\u06C1",
443
+ "\u062A\u0627\u06A9\u06C1",
444
+ "\u0648\u0631\u0646\u06C1",
445
+ "\u0627\u0644\u0628\u062A\u06C1",
446
+ "\u0645\u062B\u0644\u0627\u064B",
447
+ "\u06CC\u0639\u0646\u06CC",
448
+ "\u062E\u0635\u0648\u0635\u0627\u064B",
449
+ "\u0639\u0645\u0648\u0645\u0627\u064B",
450
+ "\u0686\u0646\u0627\u0646\u0686\u06C1",
451
+ "\u062E\u0648\u0627\u06C1",
452
+ "\u0686\u0627\u06C1\u06D2",
453
+ "\u06AF\u0648\u06CC\u0627",
454
+ "\u062A\u0627\u06C1\u0645",
455
+ "\u0646\u06CC\u0632",
456
+ "\u062D\u062A\u06CC",
457
+ "\u0648\u063A\u06CC\u0631\u06C1",
458
+ "\u0635\u0631\u0641",
459
+ "\u0645\u062D\u0636",
460
+ "\u0641\u0642\u0637",
461
+ // Pronouns, determiners & question words
462
+ "\u06C1\u0645",
463
+ "\u062A\u0645",
464
+ "\u0622\u067E",
465
+ "\u0648\u06C1",
466
+ "\u06CC\u06C1",
467
+ "\u0645\u06CC\u0631\u0627",
468
+ "\u0645\u06CC\u0631\u06CC",
469
+ "\u0645\u06CC\u0631\u06D2",
470
+ "\u06C1\u0645\u0627\u0631\u0627",
471
+ "\u06C1\u0645\u0627\u0631\u06CC",
472
+ "\u06C1\u0645\u0627\u0631\u06D2",
473
+ "\u062A\u0645\u06C1\u0627\u0631\u0627",
474
+ "\u062A\u0645\u06C1\u0627\u0631\u06CC",
475
+ "\u062A\u0645\u06C1\u0627\u0631\u06D2",
476
+ "\u0622\u067E\u06A9\u0627",
477
+ "\u0622\u067E\u06A9\u06CC",
478
+ "\u0622\u067E\u06A9\u06D2",
479
+ "\u0627\u0633",
480
+ "\u0627\u0633\u06A9\u0627",
481
+ "\u0627\u0633\u06A9\u06CC",
482
+ "\u0627\u0633\u06A9\u06D2",
483
+ "\u0627\u0633\u06D2",
484
+ "\u0627\u0646",
485
+ "\u0627\u0646\u06A9\u0627",
486
+ "\u0627\u0646\u06A9\u06CC",
487
+ "\u0627\u0646\u06A9\u06D2",
488
+ "\u0627\u0646\u06C1\u06CC\u06BA",
489
+ "\u0645\u062C\u06BE\u06D2",
490
+ "\u06C1\u0645\u06CC\u06BA",
491
+ "\u062A\u0645\u06C1\u06CC\u06BA",
492
+ "\u062C\u0633",
493
+ "\u062C\u0633\u06A9\u0627",
494
+ "\u062C\u0633\u06A9\u06CC",
495
+ "\u062C\u0633\u06A9\u06D2",
496
+ "\u062C\u0633\u06D2",
497
+ "\u062C\u0646",
498
+ "\u062C\u0646\u06A9\u0627",
499
+ "\u062C\u0646\u06A9\u06CC",
500
+ "\u062C\u0646\u06A9\u06D2",
501
+ "\u062C\u0646\u06C1\u0648\u06BA",
502
+ "\u0627\u0646\u06C1\u0648\u06BA",
503
+ "\u06A9\u0633",
504
+ "\u06A9\u0633\u06A9\u0627",
505
+ "\u06A9\u0633\u06A9\u06CC",
506
+ "\u06A9\u0633\u06A9\u06D2",
507
+ "\u06A9\u0633\u06D2",
508
+ "\u06A9\u0633\u06A9\u0648",
509
+ "\u06A9\u0648\u0646",
510
+ "\u06A9\u06CC\u0627",
511
+ "\u06A9\u06C1\u0627\u06BA",
512
+ "\u06A9\u062F\u06BE\u0631",
513
+ "\u0627\u062F\u06BE\u0631",
514
+ "\u062C\u062F\u06BE\u0631",
515
+ "\u06A9\u0628",
516
+ "\u06A9\u06CC\u0648\u06BA",
517
+ "\u06A9\u06CC\u0633\u06D2",
518
+ "\u06A9\u06CC\u0633\u0627",
519
+ "\u06A9\u06CC\u0633\u06CC",
520
+ "\u06A9\u062A\u0646\u0627",
521
+ "\u06A9\u062A\u0646\u06CC",
522
+ "\u06A9\u062A\u0646\u06D2",
523
+ "\u062C\u0648",
524
+ "\u0633\u0628",
525
+ "\u0633\u0628\u06BE\u06CC",
526
+ "\u06A9\u0648\u0626\u06CC",
527
+ "\u06A9\u0686\u06BE",
528
+ "\u06C1\u0631",
529
+ "\u0627\u06CC\u06A9",
530
+ "\u0627\u067E\u0646\u0627",
531
+ "\u0627\u067E\u0646\u06CC",
532
+ "\u0627\u067E\u0646\u06D2",
533
+ "\u062E\u0648\u062F",
534
+ // Common light/auxiliary verb forms
535
+ "\u06A9\u0631\u0646\u0627",
536
+ "\u06A9\u0631\u062A\u0627",
537
+ "\u06A9\u0631\u062A\u06CC",
538
+ "\u06A9\u0631\u062A\u06D2",
539
+ "\u06A9\u0631\u06CC\u06BA",
540
+ "\u06A9\u0631\u0648",
541
+ "\u06A9\u0631",
542
+ "\u06A9\u0631\u0646\u06D2",
543
+ "\u06A9\u06CC\u06D2",
544
+ "\u062C\u0627\u0646\u0627",
545
+ "\u062C\u0627\u062A\u0627",
546
+ "\u062C\u0627\u062A\u06CC",
547
+ "\u062C\u0627\u062A\u06D2",
548
+ "\u062C\u0627\u0626\u06D2",
549
+ "\u062C\u0627\u0626\u06CC\u06BA",
550
+ "\u062C\u0627\u0624",
551
+ "\u062C\u0627",
552
+ "\u062C\u0627\u0646\u06D2",
553
+ "\u06AF\u06CC\u0627",
554
+ "\u06AF\u0626\u06CC",
555
+ "\u06AF\u0626\u06D2",
556
+ "\u0622\u0646\u0627",
557
+ "\u0622\u062A\u0627",
558
+ "\u0622\u062A\u06CC",
559
+ "\u0622\u062A\u06D2",
560
+ "\u0622\u0626\u06D2",
561
+ "\u0622\u0626\u06CC\u06BA",
562
+ "\u0622\u06CC\u0627",
563
+ "\u0622\u0626\u06CC",
564
+ "\u0622\u0646\u06D2",
565
+ "\u0622\u0624",
566
+ "\u0622",
567
+ "\u062F\u06CC\u0646\u0627",
568
+ "\u062F\u06CC\u062A\u0627",
569
+ "\u062F\u06CC\u062A\u06CC",
570
+ "\u062F\u06CC\u062A\u06D2",
571
+ "\u062F\u06CC\u0627",
572
+ "\u062F\u06CC\u06D2",
573
+ "\u062F\u06D2",
574
+ "\u062F\u0648",
575
+ "\u062F\u06CC\u06BA",
576
+ "\u062F\u06CC\u0646\u06D2",
577
+ "\u0644\u06CC\u0646\u0627",
578
+ "\u0644\u06CC\u062A\u0627",
579
+ "\u0644\u06CC\u062A\u06CC",
580
+ "\u0644\u06CC\u062A\u06D2",
581
+ "\u0644\u06CC\u0627",
582
+ "\u0644\u06D2",
583
+ "\u0644\u0648",
584
+ "\u0644\u06CC\u06BA",
585
+ "\u0644\u06CC\u0646\u06D2",
586
+ "\u0631\u06C1\u0646\u0627",
587
+ "\u0631\u06C1\u0627",
588
+ "\u0631\u06C1\u06CC",
589
+ "\u0631\u06C1\u06D2",
590
+ "\u0631\u06C1\u062A\u0627",
591
+ "\u0631\u06C1\u062A\u06CC",
592
+ "\u0631\u06C1\u062A\u06D2",
593
+ "\u0631\u06C1\u0646\u06D2",
594
+ "\u0633\u06A9\u0646\u0627",
595
+ "\u0633\u06A9\u062A\u0627",
596
+ "\u0633\u06A9\u062A\u06CC",
597
+ "\u0633\u06A9\u062A\u06D2",
598
+ "\u0648\u0627\u0644\u0627",
599
+ "\u0648\u0627\u0644\u06CC",
600
+ "\u0648\u0627\u0644\u06D2"
601
+ ]);
602
+ function toStopWordSet(custom) {
603
+ if (!custom) return URDU_STOP_WORDS;
604
+ if (custom instanceof Set) return custom;
605
+ return new Set(custom.map((w) => normalizeUrdu(w.trim())));
606
+ }
607
+ function isStopWord(word, customStopWords) {
608
+ if (!word) return false;
609
+ const normalized = normalizeUrdu(word.trim());
610
+ const stopSet = toStopWordSet(customStopWords);
611
+ return stopSet.has(normalized);
612
+ }
613
+ function filterStopWords(words, customStopWords) {
614
+ if (!words || words.length === 0) return [];
615
+ const stopSet = toStopWordSet(customStopWords);
616
+ return words.filter((w) => {
617
+ const normalized = normalizeUrdu(w.trim());
618
+ return normalized.length > 0 && !stopSet.has(normalized);
619
+ });
620
+ }
621
+ function removeStopWords(text, customStopWords) {
622
+ if (!text) return "";
623
+ const words = splitWords(text);
624
+ const filtered = filterStopWords(words, customStopWords);
625
+ return filtered.join(" ");
626
+ }
627
+
331
628
  // src/collate.ts
332
629
  var ALPHABET = [
333
630
  "\u0627",
@@ -2999,20 +3296,24 @@ function urduSlug(input, options = {}) {
2999
3296
  return slug;
3000
3297
  }
3001
3298
 
3299
+ exports.URDU_STOP_WORDS = URDU_STOP_WORDS;
3002
3300
  exports.analyzeUrdu = analyzeUrdu;
3003
3301
  exports.compareUrdu = compareUrdu;
3004
3302
  exports.convertNumbers = convertNumbers;
3005
3303
  exports.countSentences = countSentences;
3006
3304
  exports.countWords = countWords;
3007
3305
  exports.editDistance = editDistance;
3306
+ exports.filterStopWords = filterStopWords;
3008
3307
  exports.foldUrdu = foldUrdu;
3009
3308
  exports.hasUrduSpecificLetters = hasUrduSpecificLetters;
3010
3309
  exports.highlightUrdu = highlightUrdu;
3310
+ exports.isStopWord = isStopWord;
3011
3311
  exports.isUrdu = isUrdu;
3012
3312
  exports.normalizeUrdu = normalizeUrdu;
3013
3313
  exports.numberToUrduWords = numberToUrduWords;
3014
3314
  exports.parseUrduNumber = parseUrduNumber;
3015
3315
  exports.removeDiacritics = removeDiacritics;
3316
+ exports.removeStopWords = removeStopWords;
3016
3317
  exports.romanToUrdu = romanToUrdu;
3017
3318
  exports.romanize = romanize;
3018
3319
  exports.searchUrdu = searchUrdu;