ghunna

Tajweed rules, derived.

A derivation engine for classical tajweed. Vocalized Uthmani text in, rule annotations out: every span carries its trigger letters, a derivation in English and Arabic, and a citation to the line of the source poem it comes from.

41 rules 2 classical sources, cited to the line 99.80% corpus agreement with independent datasets 108 divergence sites, each one examined and documented 110 tests 0 runtime dependencies

What a call returns

import { annotateVerse } from "ghunna";

const { text, annotations } = annotateVerse(2, 255);

// each annotation:
// {
//   rule: "iqlab",
//   name: { arabic: "الإقلاب", transliteration: "iqlāb", english: "conversion to mīm" },
//   range: [17, 22],            // codepoint range into text
//   derivation: "nūn sākinah/tanwīn followed by ب → the nūn is converted to a concealed mīm with ghunnah",
//   citation: { text: "tuhfah", lines: [13] },   // line 13 of Tuḥfat al-Aṭfāl
//   waqfDependent: false,
//   confidence: "certain",
// }

The scope is riwāyat Ḥafṣ ʿan ʿĀṣim by ṭarīq al-Shāṭibiyyah. The library is pure TypeScript, runs identically in the browser and in Node, and ships as ESM and CJS.

Derived, not looked up

Existing digital tajweed resources are, without exception we are aware of, encodings of an already-annotated muṣḥaf: a fixed table of colored spans transcribed from a printed page. This library takes the opposite approach. It implements the rules as stated in the two canonical teaching poems, Tuḥfat al-Aṭfāl and al-Muqaddimah al-Jazariyyah, and derives every annotation from the letters and diacritics of the text alone.

The distinction has a precise technical form. The Uthmani encoding carries pronunciation hints printed in the muṣḥaf: the small mīm at iqlāb sites, the maddah sign over long madds. The engine never reads them. They are reserved for verification, where the derived output is compared against what the muṣḥaf tradition prints. A derivation engine can be checked against the printed tradition; a transcription of the printed tradition cannot be checked against anything.

Three consequences follow. First, every annotation can explain itself: the output carries the derivation and the citation, not just a color class. Second, recitation context becomes a parameter rather than a baked-in assumption; see the waqf model. Third, rule families that the digital datasets never carried at all, such as the tafkhīm and tarqīq family, can be derived like any other; see the rule catalog.

Verified against the printed tradition

The engine's output over all 6,236 verses is compared against two independent datasets and, at every disputed site, against page photographs of the printed Dar al-Maarifah tajweed muṣḥaf itself. Agreement over the mapped categories is 99.80% in continuation mode and 99.82% in stop mode. The 108 sites of disagreement are not averaged away: each one is classified, researched against the published tajweed literature, and documented in the residue. In every group the evidence favors the rules as written over the datasets, and 90 of the 108 reduce to a single identifiable defect in the reference dataset's madd classifier.

Method and results in full.

Install

npm install ghunna
// full package (bundled Qur'an text):
import { annotateVerse, getVerseText } from "ghunna";

// corpus-free core: bring your own Tanzil-Uthmani-encoded text
import { annotate, tokenize, RULE_META } from "ghunna/core";

Getting started →