farsit 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amir Salehi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,85 @@
1
- # Temporary Holding Version
1
+ # farsit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Accurate Persian → Finglish transliteration. No AI, no dictionary, zero deps. Slugs included.**
4
+
5
+ > موتور دقیق تبدیل متن فارسی به فینگلیش (حروف لاتین)؛ بدون هوش مصنوعی، بدون فرهنگ لغت و بدون وابستگی. اسلاگ URL هم دارد. کاملاً آفلاین و الگوریتمی؛ خروجی هرگز `x` ندارد (خ=kh، ش=sh، چ=ch، ژ=zh، ق/غ=gh).
6
+
7
+ `farsit` reads Persian the way people pronounce it, filling in the short vowels Persian script leaves out, and writes it in everyday Finglish. Runs offline in the browser or Node: ESM + CJS, fully typed, ~147 KB gzip including the model.
8
+
9
+ ```ts
10
+ import { transliterate, slugify, explain } from 'farsit';
11
+
12
+ transliterate('استقامت در اصفهان'); // "esteghamat dar esfahan"
13
+ slugify('آموزش برنامه‌نویسی ۱۴۰۳'); // "amuzesh-barnamenevisi-1403"
14
+ transliterate('پارچه های زیبا'); // "parche haye ziba" (phrase ezafe)
15
+ transliterate('نسبتا'); // "nesbatan" (implicit tanvin)
16
+ explain('استقامت'); // per-letter trace of every decision
17
+ ```
18
+
19
+ ## Use cases
20
+
21
+ - **URL slugs** for Persian titles (`slugify`)
22
+ - **Usernames and email addresses** from Persian names
23
+ - **Latin filenames** for uploads and exports
24
+ - **Latin-only form fields and tickets** (banking, travel, legacy systems)
25
+ - **Search matching** for users who type in Finglish
26
+ - **Pronunciation hints** for learners and TTS (`explain` shows every decision)
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ npm install farsit
32
+ ```
33
+
34
+ ## API
35
+
36
+ ### `transliterate(text, options?) → string`
37
+ | option | default | |
38
+ |---|---|---|
39
+ | `ezafe` | `true` | Add the ezafe vowel to a word ending in the glide ی (‌های، درختای، خانه‌ی) when another content word follows in the same phrase: `پارچه‌های زیبا` → `parchehaye ziba`. It is skipped at the end of a phrase, before punctuation, conjunctions, prepositions or the copula, and before verb-shaped words. |
40
+ | `longU` | `'u'` | `'oo'` spells long /u/ as `oo` (`noor`). |
41
+ | `layers` | all on | `{ diacritics, morphology, wazn }`: switch individual layers off. |
42
+ | `beam` | `8` | Viterbi beam width. |
43
+
44
+ ### `slugify(text, options?) → string`
45
+ Takes all the options above, plus `separator` (`'-'`), `lowercase` (`true`), `maxLength` (cuts at a word boundary) and `keepDigits` (`true`; Persian and Arabic digits become ASCII).
46
+
47
+ ### `explain(text, options?) → Explanation`
48
+ Returns the normalised input, the output, and for each token its segments, the wazn match, tanvin and ezafe flags, and the per-letter labels with the constraints that produced them.
49
+
50
+ Also exported: `normalize` (Arabic → Persian letters, digits, ZWNJ cleanup) and `WAZNS`.
51
+
52
+ ## How it works
53
+
54
+ 1. **Normalisation**: unify Arabic/Persian letters, digits and ZWNJ.
55
+ 2. **Diacritics**: any harakat present become hard constraints.
56
+ 3. **Morphology**: an affix table learned from the training data splits ZWNJ compounds (‌ها، می‌، ‌ترین …).
57
+ 4. **Wazn**: Arabic morphological templates (تفعیل، مفعول، افتعال …). Each pattern ships only if it helped on the dev split, with its own score margin and a confidence gate.
58
+ 5. **Tanvin**: a structural rule for a word ending in bare ا (نسبتا nesbatan, صراحتا sarahatan).
59
+ 6. **Model**: a compact graphone 4-gram trie LM plus a letter-context model, decoded with a Viterbi beam.
60
+ 7. **Phrase ezafe**, then rendering to Finglish.
61
+
62
+ The only fixed pronunciations are 30 closed-class function words (`src/function-words.ts`: و، از، به، که …). There are no lists of names, places or content words. The model is trained on the HomoRich G2P corpus (CC0-1.0).
63
+
64
+ ## Results
65
+
66
+ Measured on a held-out test split of 4,367 words whose stems never appear in training:
67
+
68
+ | | |
69
+ |---|---|
70
+ | exact match (cleaned refs) | **67.6 %** · 72.5 % frequency-weighted |
71
+ | exact match (raw HomoRich refs) | 59.2 % · 65.3 % weighted |
72
+ | hand-written slug cases | 99 / 110 |
73
+ | speed (Node, Apple Silicon) | ~20 µs per unique word (~49k words/s); ~110–125k words/s on running text |
74
+ | load | import ~2 ms, first call ~16–17 ms |
75
+ | size | 147 KB gzip / 129 KB brotli (whole library + model) |
76
+
77
+ See [bench/RESULTS.md](bench/RESULTS.md) for the full numbers, the ablations and a head-to-head against other npm packages.
78
+
79
+ ## Development
80
+
81
+ `npm test` · `npm run build` · `npm run size` (150 KB gzip budget) · `npm run eval` · `npm run bench` · `npm run train` · `npm run demo` (http://localhost:5180) · `npx tsx tools/regress.ts` (diffs every output against `bench/baseline.json`)
82
+
83
+ ## License
84
+
85
+ MIT