@quran.ws/tajwid-rules 0.1.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,35 @@
1
+ Tajweed Rule Corpus (`@quran.ws/tajwid-rules`)
2
+ Copyright (c) 2026 Quranpedia
3
+
4
+ This work is licensed under the Creative Commons Attribution 4.0 International
5
+ License (CC BY 4.0).
6
+
7
+ You are free to:
8
+
9
+ - Share — copy and redistribute the material in any medium or format
10
+ - Adapt — remix, transform, and build upon the material for any purpose,
11
+ even commercially
12
+
13
+ Under the following terms:
14
+
15
+ - Attribution — You must give appropriate credit, provide a link to the
16
+ license, and indicate if changes were made.
17
+
18
+ Full license text: https://creativecommons.org/licenses/by/4.0/legalcode
19
+
20
+ ---
21
+
22
+ ATTRIBUTION
23
+
24
+ When redistributing this corpus or a derivative of it, credit:
25
+
26
+ Tajweed Rule Corpus, Quranpedia — https://github.com/quranpedia/tajweed-engine
27
+
28
+ ---
29
+
30
+ A NOTE ON MODIFICATION
31
+
32
+ CC BY 4.0 permits modification. Please note that the rules in this corpus
33
+ encode positions attributed to named scholars. If you modify a rule's matching
34
+ behaviour, change its `source` attribution as well, so that a position is not
35
+ misattributed to a scholar who did not hold it.
package/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # @quran.ws/tajwid-rules
2
+
3
+ The tajweed rule corpus: **7 topics → 27 categories → 58 ahkam → 182 rules**, for the riwayah of **Hafs ʿan ʿĀsim**.
4
+
5
+ This package is data only. It has no dependencies and no code. The engine that
6
+ runs it lives in [`@quran.ws/tajwid`](../core).
7
+
8
+ ```bash
9
+ npm install @quran.ws/tajwid-rules
10
+ ```
11
+
12
+ ```js
13
+ import corpus from '@quran.ws/tajwid-rules'
14
+
15
+ corpus.riwayah // 'hafs-an-asim'
16
+ corpus.rules.filter((rule) => rule.status === 'stable').length // 164
17
+ ```
18
+
19
+ ## Shape
20
+
21
+ ```
22
+ topics → categories → hukums → rules
23
+ التفخيم والترقيق مراتب التفخيم مرتبة التفخيم الأولى [ خَ صَ ضَ غَ طَ قَ ظَ] + ا
24
+ ```
25
+
26
+ A **rule** is one matchable pattern. A **hukum** is the ruling those patterns
27
+ demonstrate. Rules are what an engine runs; ahkam are what a reader is taught.
28
+ For example, the hukum `madd-muttasil` (المد الواجب المتصل) is one ruling, but it
29
+ takes three rules to match it — one each for madd by alef, waw and yaa.
30
+
31
+ Every id is a stable slug (`madd-muttasil.2`), namespaced under its hukum.
32
+ These slugs are the only identifiers in the corpus, and they are the contract:
33
+ join on them, store them, and expect them not to change.
34
+
35
+ ## The CASE notation
36
+
37
+ Documented in full in [docs/case-notation.md](../../docs/case-notation.md).
38
+ `case` is a compact Arabic notation, designed so that someone qualified in
39
+ tajweed but not in programming can write and check a rule:
40
+
41
+ | Notation | Meaning |
42
+ |---|---|
43
+ | `[ا ب ت]` | any one of these — space separates alternatives |
44
+ | `+` | followed by |
45
+ | `ــــ` | a wildcard — any single character |
46
+ | `نهاية الكلمة` | end of a word — a position, not a character |
47
+ | `بداية الكلمة` | start of a word |
48
+ | `الألف الخنجرية` | ٰ (U+0670), named because it is hard to type |
49
+ | `واو صغيرة` / `ياء صغيرة` | ۥ (U+06E5) / ۦ (U+06E6) |
50
+
51
+ So `نْ + [ذ ث ك ج ش س د ز ف ت]` reads as "a sakin noon, followed by any one of
52
+ these letters" — one of the إخفاء rules.
53
+
54
+ `scope` says what may sit between two groups: `within-word` allows no space at
55
+ all, `across-words` requires a separator, `either` allows one. Diacritics and
56
+ Quranic annotation marks are always allowed between groups, in every scope.
57
+
58
+ ## Status, and why disabled rules ship anyway
59
+
60
+ 164 rules are `stable`. 18 are `disabled` — published, but not matched by
61
+ default.
62
+
63
+ They are kept rather than deleted because a silently missing rule looks exactly
64
+ like a rule that was never written. Each disabled rule records a `gap` naming
65
+ what the CASE notation cannot yet say:
66
+
67
+ | Gap | Rules | What is missing |
68
+ |---|---|---|
69
+ | `ambiguous-wildcard` | 6 | A group mixing `ــ` with a multi-part sequence compiles as alternatives, because space separates alternatives |
70
+ | `unsupported-optional-group` | 3 | `[همزة وصل أو بدون]` — an optional part |
71
+ | `unsupported-exception` | 2 | `باستثناء كلمة فرق` — excluding one case from a group |
72
+ | `unsupported-negation` | 2 | `وليس بعده ألف` — a rule defined by what does *not* follow |
73
+ | `needs-rule-composition` | 2 | "any letter ruled tafkheem" — depends on other rules' results |
74
+ | `not-a-pattern` | 2 | Prose naming specific words at specific places |
75
+ | `unsupported-token` | 1 | Hamzat wasl as a named group |
76
+
77
+ Together, this table is the to-do list for the next version of the notation,
78
+ not a list of bugs.
79
+
80
+ ## Scholarly disagreement is modelled, not resolved
81
+
82
+ Where authorities differ, each position is its own hukum, tagged with a
83
+ `school`. The clearest case is the ranks of tafkheem: Ibn al-Jazarī counts
84
+ five, Ibn al-Ṭaḥḥān al-Andalusī counts three. Both are in the corpus. An app
85
+ that needs a single answer must pick a school; an app that teaches tajweed may
86
+ want to show that the disagreement exists.
87
+
88
+ ## Corrections
89
+
90
+ A rule that was changed from its source carries a `corrections` entry recording
91
+ the previous value and the evidence, and is flagged `needsReview: true` until a
92
+ qualified reviewer signs it off. The rule still matches in the meantime — the
93
+ flag exists so the change stays visible instead of being buried in a diff.
94
+
95
+ Four rules currently carry corrections, and eight more were newly written
96
+ rather than migrated. All twelve are flagged `needsReview`. See
97
+ [CONTRIBUTING.md](../../CONTRIBUTING.md) for what changing a rule requires.
98
+
99
+ ## Reading the text as printed
100
+
101
+ A rule may set `matchAgainst: "original"`, meaning its pattern is written
102
+ against the mushaf as printed rather than against the engine's normalised form.
103
+ Only two rules do. المد اللازم الحرفي is identified by a maddah sitting over a
104
+ consonant, which happens nowhere except the disjoined letters — and
105
+ normalisation removes that mark on purpose, exactly so that no ordinary rule
106
+ sees it.
107
+
108
+ ## Licence
109
+
110
+ CC BY 4.0 — see [LICENSE](./LICENSE). The code in this repository is MIT; the
111
+ corpus is not.
112
+
113
+ No Quranic text is distributed in this package.
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@quran.ws/tajwid-rules",
3
+ "version": "0.1.0",
4
+ "description": "A scholar-authored corpus of tajweed rules for the riwayah of Hafs 'an 'Asim, as versioned JSON.",
5
+ "license": "CC-BY-4.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "type": "module",
10
+ "main": "./rules.json",
11
+ "exports": {
12
+ ".": "./rules.json",
13
+ "./schema": "./schema/rules.schema.json"
14
+ },
15
+ "files": [
16
+ "rules.json",
17
+ "schema/",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/quran-ws/quran-tajweed.git",
24
+ "directory": "packages/rules"
25
+ },
26
+ "keywords": [
27
+ "quran",
28
+ "tajweed",
29
+ "arabic",
30
+ "hafs",
31
+ "uthmani"
32
+ ]
33
+ }