quran-madina-html 2.1.0 → 2.1.1
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 +40 -370
- package/dist/quran-madina-html.min.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,319 +1,39 @@
|
|
|
1
|
-
# Quran Madina Html
|
|
1
|
+
# Quran Madina Html
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/quran-madina-html)
|
|
4
|
+
[](https://www.npmjs.com/package/@tarekeldeeb/quran-madina-react)
|
|
5
|
+
[](https://pub.dev/packages/quran_madina_flutter)
|
|
6
|
+
[](https://tarekeldeeb.github.io/quran-madina-html/docs/)
|
|
7
|
+
[](LICENSE.md)
|
|
8
|
+
[](https://github.com/tarekeldeeb/quran-madina-html/actions/workflows/npm-grunt.yml)
|
|
9
|
+
[](https://github.com/tarekeldeeb/quran-madina-html/actions/workflows/py_test.yml)
|
|
10
|
+
[](https://github.com/tarekeldeeb/quran-madina-html/actions/workflows/flutter.yml)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
Quran pages that look like the printed Madina Mushaf, as real text: selectable, searchable and
|
|
13
|
+
copyable, with no images. Lines are justified the way the print fills them, by stretching the
|
|
14
|
+
letters themselves. One tag renders a page, a verse range or a few words, with highlighted
|
|
15
|
+
words and emphasised letters, in the 1441H, 1405H or IndoPak print.
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
<quran-madina-html
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
**[See it live →](https://tarekeldeeb.github.io/quran-madina-html/demo/index.html)** (view the page source too —
|
|
20
|
-
GitHub strips `<script>` tags from this README, so the tag can't render *here*, but it's just as simple as
|
|
21
|
-
the snippet above once it's on your own page.)
|
|
22
|
-
|
|
23
|
-
## Why
|
|
24
|
-
|
|
25
|
-
* **Pixel-faithful to the printed Madina Mushaf** — same line breaks, same justification, same page layout.
|
|
26
|
-
* **Pure HTML/CSS, no images** — text stays selectable, searchable, and copy-pasteable; pages load fast.
|
|
27
|
-
* **One HTML tag** — no build step, no framework required.
|
|
28
|
-
* **Three layouts** — the 1441H and 1405H Madina prints and the 15-line IndoPak, at any font size.
|
|
29
|
-
* **Word-level addressing** — render any word range, even across ayas, pages, and suras.
|
|
30
|
-
|
|
31
|
-
## New in 2.1: emphasise letters
|
|
32
|
-
|
|
33
|
-
`letters` marks single letters inside words, in a colour of your choice, optionally blinking —
|
|
34
|
-
on plain text and inside `highlight`/`error` words. See [Emphasising letters](#emphasising-letters).
|
|
35
|
-
|
|
36
|
-
```html
|
|
37
|
-
<quran-madina-html sura="1" aya="2-4" highlight="1" error="4"
|
|
38
|
-
letters="1:3, 4:3+5 lapis blink, 6:4 emerald"></quran-madina-html>
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Also new: a [Flutter wrapper](#flutter-wrapper) for Android, iOS, macOS and the web, which
|
|
42
|
-
can work offline.
|
|
43
|
-
|
|
44
|
-
## New in 2.0: lines justified like the print
|
|
45
|
-
|
|
46
|
-
Version 2 stretches the **letters themselves** (kashida strokes and wider letter forms, the way a
|
|
47
|
-
calligrapher fills a line) instead of inserting tatweel characters or squashing whole lines. It
|
|
48
|
-
uses the [DigitalKhatt](https://github.com/DigitalKhatt/digitalkhatt.org) fonts by Amine Anane
|
|
49
|
-
(OFL), with HarfBuzz deciding every stretch at build time; the browser only needs the font and
|
|
50
|
-
one `font-feature-settings` per word. The text is still real, selectable text.
|
|
51
|
-
|
|
52
|
-
Three layouts, picked with `data-layout` on the script tag:
|
|
53
|
-
|
|
54
|
-
<table>
|
|
55
|
-
<tr>
|
|
56
|
-
<td align="center"><img src="demo/img/v2-p50-1441H.png" width="220" alt="page 50, 1441H"><br/><code>1441H</code> (default)<br/>New Madina Mushaf</td>
|
|
57
|
-
<td align="center"><img src="demo/img/v2-p50-1405H.png" width="220" alt="page 50, 1405H"><br/><code>1405H</code><br/>Old Madina Mushaf</td>
|
|
58
|
-
<td align="center"><img src="demo/img/v2-p50-IndoPak.png" width="220" alt="page 50, IndoPak"><br/><code>IndoPak</code><br/>15-line IndoPak</td>
|
|
59
|
-
</tr>
|
|
60
|
-
</table>
|
|
61
|
-
|
|
62
|
-
```html
|
|
63
|
-
<script src="https://unpkg.com/quran-madina-html" data-layout="1441H" data-font-size="22"></script>
|
|
64
|
-
<quran-madina-html page="50"></quran-madina-html>
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
| | `1441H` | `1405H` | `IndoPak` |
|
|
68
|
-
|---|---|---|---|
|
|
69
|
-
| Font | DigitalKhatt New Madina | DigitalKhatt Old Madina | DigitalKhatt IndoPak |
|
|
70
|
-
| Text | [Tanzil](https://tanzil.net) Uthmani; pause marks of the 1441H print | Tanzil Uthmani | DigitalKhatt's IndoPak text (IndoPak spelling) |
|
|
71
|
-
| Line breaks | the 1441H print (King Fahd Complex page data) | the 1405H print | DigitalKhatt's IndoPak layout |
|
|
72
|
-
| Pages | 604 | 604 | 610 |
|
|
73
|
-
|
|
74
|
-
* Everything else works the same in every layout: `page`, `sura`/`aya`, `words`, `highlight`,
|
|
75
|
-
`error`, `headless`, `notitle`, copy and translate. `sura`/`aya` always use the Kufan
|
|
76
|
-
numbering, so the same attributes show the same verse in every layout.
|
|
77
|
-
* Any font size: the v2 databases are in em, so `data-font-size` just scales the page.
|
|
78
|
-
* Spacing follows the print: words keep the print's ink-to-ink gaps, loose lines stretch
|
|
79
|
-
letters, dense lines narrow their words (never the aya numbers). See
|
|
80
|
-
[`docs/v2`](docs/v2/design-decisions.md) for how it was measured against the print.
|
|
81
|
-
* **Upgrading from 1.x** is a drop-in replacement: existing tags render with 2.0 unchanged.
|
|
82
|
-
Pick a layout with `data-layout`; 1.x's font options no longer apply (pin
|
|
83
|
-
`quran-madina-html@1` to keep the 1.x renderer). The 1.x documentation is in
|
|
84
|
-
[README_v1.md](README_v1.md).
|
|
85
|
-
|
|
86
|
-
## Next to the print
|
|
87
|
-
|
|
88
|
-
Page 106 of the printed (1405H) Madina Mushaf, and the same page rendered with
|
|
89
|
-
`data-layout="1405H"` — same lines, same words on each line, as live text:
|
|
90
|
-
|
|
91
|
-
<table>
|
|
92
|
-
<tr>
|
|
93
|
-
<td align="center"><img src="demo/img/p106-image.JPG" width="260" alt="Scanned Madina Mushaf page 106"><br/>Printed Madina Mushaf</td>
|
|
94
|
-
<td align="center"><img src="demo/img/p106-1405H.png" width="260" alt="quran-madina-html rendering of page 106"><br/><code><quran-madina-html page="106" headless="true"></code></td>
|
|
95
|
-
</tr>
|
|
96
|
-
</table>
|
|
97
|
-
|
|
98
|
-
## Features
|
|
99
|
-
|
|
100
|
-
### Verse ranges — framed or frameless
|
|
101
|
-
|
|
102
|
-
`sura`/`aya` renders just the ayat you ask for, laid out exactly as they sit on the Madina page.
|
|
103
|
-
By default you get a header (sura name + copy/translate icons); add `headless="true"` to strip
|
|
104
|
-
that chrome and keep only the Quran text:
|
|
105
|
-
|
|
106
|
-
<table>
|
|
107
|
-
<tr>
|
|
108
|
-
<td align="center">
|
|
109
|
-
|
|
110
|
-
```html
|
|
111
|
-
<quran-madina-html sura="5" aya="1-2">
|
|
112
|
-
</quran-madina-html>
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
<img src="demo/img/verse-default.png" width="300" alt="Verse range with the default header">
|
|
116
|
-
</td>
|
|
117
|
-
<td align="center">
|
|
118
|
-
|
|
119
|
-
```html
|
|
120
|
-
<quran-madina-html sura="5" aya="1-2"
|
|
121
|
-
headless="true">
|
|
122
|
-
</quran-madina-html>
|
|
123
|
-
```
|
|
17
|
+
<p align="center">
|
|
18
|
+
<img src="https://raw.githubusercontent.com/tarekeldeeb/quran-madina-html/main/docs/assets/img/showcase.gif" width="720" alt="quran-madina-html rendering a page, a verse, highlighted words, blinking letters, a selection across suras, and three prints">
|
|
19
|
+
</p>
|
|
124
20
|
|
|
125
|
-
<
|
|
126
|
-
</
|
|
127
|
-
</
|
|
128
|
-
</
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://tarekeldeeb.github.io/quran-madina-html/docs/"><b>Documentation</b></a> ·
|
|
23
|
+
<a href="https://tarekeldeeb.github.io/quran-madina-html/demo/index.html"><b>Live demo</b></a>
|
|
24
|
+
</p>
|
|
129
25
|
|
|
130
|
-
|
|
26
|
+
## Getting started
|
|
131
27
|
|
|
132
|
-
|
|
133
|
-
text *in place*, so the original Madina line justification is preserved instead of being
|
|
134
|
-
reflowed. Counting continues past the end of the given aya, so a selection can cross aya, page,
|
|
135
|
-
and even sura boundaries:
|
|
136
|
-
|
|
137
|
-
<table>
|
|
138
|
-
<tr>
|
|
139
|
-
<td align="center">
|
|
28
|
+
### HTML
|
|
140
29
|
|
|
141
30
|
```html
|
|
142
|
-
<quran-madina-html
|
|
143
|
-
words="1:2">
|
|
144
|
-
</quran-madina-html>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
first two words of Al-Fatiha; the rest of the
|
|
148
|
-
line stays in place, hidden (the blank before
|
|
149
|
-
the closing quote)
|
|
150
|
-
<br/><br/>
|
|
151
|
-
<img src="demo/img/words-inline.png" width="216" alt="words attribute, inline selection">
|
|
152
|
-
</td>
|
|
153
|
-
<td align="center">
|
|
154
|
-
|
|
155
|
-
```html
|
|
156
|
-
<quran-madina-html sura="1" aya="7"
|
|
157
|
-
words="1-14">
|
|
158
|
-
</quran-madina-html>
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
words 1-14 counted from Al-Fatiha's last aya
|
|
162
|
-
spill into Surat Al-Baqara — its basmala
|
|
163
|
-
counts as words 10-13
|
|
164
|
-
<br/><br/>
|
|
165
|
-
<img src="demo/img/words-multiline.png" width="300" alt="words attribute, spanning Al-Fatiha into Al-Baqara">
|
|
166
|
-
</td>
|
|
167
|
-
</tr>
|
|
168
|
-
</table>
|
|
169
|
-
|
|
170
|
-
### Highlighting words
|
|
171
|
-
|
|
172
|
-
`highlight` (soft yellow) and `error` (soft red) mark a word range — same 1-based, inclusive
|
|
173
|
-
format as `words` — on top of whatever is being shown. Unlike `words`, they work with or without
|
|
174
|
-
a `words` selection, and even on a full `page` render:
|
|
175
|
-
|
|
176
|
-
```html
|
|
177
|
-
<quran-madina-html sura="1" aya="1" highlight="2-3"></quran-madina-html>
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
<img src="demo/img/highlight.png" width="216" alt="highlight attribute marking words 2-3 of Al-Fatiha's first aya">
|
|
181
|
-
|
|
182
|
-
### Emphasising letters
|
|
183
|
-
|
|
184
|
-
`letters` marks single letters inside words, for teaching a letter or pointing at a mistake:
|
|
185
|
-
comma-separated groups of `word:letters colour blink`. Word numbers count like `highlight`/`error`;
|
|
186
|
-
letters are `3`, `3-5` or `3+5`; the colour is optional — `crimson` (default), `emerald`, `lapis`,
|
|
187
|
-
`gold`, `violet` or any CSS colour; `blink` is optional too (no animation by default). The letter
|
|
188
|
-
gets a soft halo of its own colour that sits behind the surrounding ink; with `blink` the halo
|
|
189
|
-
pulses gently while the letter keeps its colour in every frame (still in print and with reduced
|
|
190
|
-
motion). It works inside `highlight`/`error` words and gets a lighter shade on dark pages.
|
|
191
|
-
Nothing changes size or position.
|
|
192
|
-
|
|
193
|
-
```html
|
|
194
|
-
<quran-madina-html sura="1" aya="2-4" highlight="1" error="4"
|
|
195
|
-
letters="1:3, 4:3+5 lapis blink, 6:4 emerald"></quran-madina-html>
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
<img src="demo/img/letters.png" width="300" alt="letters attribute marking letters inside highlighted, error and plain words">
|
|
199
|
-
|
|
200
|
-
Lam-alef (لا) is a single glyph, so marking either of its letters colours both.
|
|
201
|
-
|
|
202
|
-
## Getting Started
|
|
203
|
-
|
|
204
|
-
### Installation
|
|
205
|
-
|
|
206
|
-
Install via **npm**:
|
|
31
|
+
<script src="https://unpkg.com/quran-madina-html@2"></script>
|
|
207
32
|
|
|
208
|
-
|
|
209
|
-
npm install quran-madina-html
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
Or include directly via **CDN script tag** in your HTML `<head>`:
|
|
213
|
-
|
|
214
|
-
```html
|
|
215
|
-
<script type="text/javascript" src="https://unpkg.com/quran-madina-html"></script>
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
* ``data-layout``: ``1441H`` (default), ``1405H``, ``IndoPak`` — see *New in 2.0* above
|
|
219
|
-
* ``data-font-size`` defaults to 16 (px); any size works
|
|
220
|
-
|
|
221
|
-
Then in your body, just add the tag.
|
|
222
|
-
|
|
223
|
-
```html
|
|
224
|
-
<quran-madina-html sura="2" aya="8-10"></quran-madina-html>
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
If the selected aya(s) fit on a single line, the default is to generate an inline ``<span>`` element, otherwise a ``<div>`` is generated.
|
|
228
|
-
|
|
229
|
-
You can also restrict the output to a specific word sequence with the ``words`` attribute (1-based, inclusive; ``start-end``, ``start:end`` or a single ``index``). Word indices are counted starting from the given ``sura``/``aya`` and may run past it, so the rendered selection can span multiple ayas — and even cross page and sura boundaries. The **basmala counts as 4 real, individually selectable words** — matching the flat Tanzil word indexing most consumers count against (At-Tawba has none; Al-Fatiha's basmala is its real aya 1). This holds both when the selection crosses into a new sura and when it is **anchored at a sura's aya 1** (word 1 is then بسم and word 5 the aya's first word), while the **sura title** stays uncounted decoration, shown for context only. Display follows the printed Mushaf: when **all 4** basmala words fall inside the selection (or on a full ``page`` render) they show as the traditional **﷽ ligature**; a partial selection (1–3 of the 4) renders the individual words. Either way the basmala occupies 4 word indices. The non-selected words are kept in place so the original Madina line layout is preserved — only the chosen words are shown. Aya-number markers are not counted.
|
|
230
|
-
|
|
231
|
-
> **Changed in 0.9.0:** the basmala used to be a *never counted* decoration; a cross-sura ``words``
|
|
232
|
-
> index now lands 4 words later than in 0.8.x.
|
|
233
|
-
>
|
|
234
|
-
> **Changed in 0.9.3:** a ``words`` walk anchored at a sura's aya 1 now counts that sura's own
|
|
235
|
-
> basmala too (0.9.0–0.9.2 only counted *crossed-into* basmalas, so aya-1-anchored word indices
|
|
236
|
-
> landed 4 words early relative to the Tanzil flat indexing).
|
|
237
|
-
>
|
|
238
|
-
> **Changed in 0.9.5:** a ``words`` walk that runs past the end of An-Nas now **wraps around to
|
|
239
|
-
> Al-Fatiha** and keeps counting (previously it stopped, silently truncating the selection);
|
|
240
|
-
> Al-Fatiha's title stays uncounted decoration, and its basmala — being its real aya 1 —
|
|
241
|
-
> renders as normal aya words.
|
|
242
|
-
|
|
243
|
-
```html
|
|
244
|
-
<quran-madina-html sura="1" aya="1" words="1:2"></quran-madina-html> <!-- first two words only -->
|
|
245
|
-
<quran-madina-html sura="1" aya="1" words="3-10"></quran-madina-html> <!-- words 3..10, spanning ayas 1-3 -->
|
|
246
|
-
<quran-madina-html sura="1" aya="7" words="1-14"></quran-madina-html> <!-- spans Al-Fatiha into Al-Baqara:
|
|
247
|
-
9 words + 4 basmala words + الٓمٓ -->
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
The ``words`` attribute is ignored when rendering a full ``page``.
|
|
251
|
-
|
|
252
|
-
To embed a selection inside your own chrome (e.g. a quiz that already labels the sura/aya), the ``notitle`` attribute hides the crossed-into sura's **name text** while keeping its decorated title line (the ornamental frame stays, empty) — and the basmala, being real counted words, still renders:
|
|
253
|
-
|
|
254
|
-
```html
|
|
255
|
-
<quran-madina-html sura="1" aya="7" words="1-14" notitle="true"></quran-madina-html>
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
#### Highlighting and marking words
|
|
259
|
-
|
|
260
|
-
Two more range attributes lay a visual mark over a sub-range of whatever is being shown —
|
|
261
|
-
``highlight`` (soft yellow) and ``error`` (soft red) — using the same 1-based, inclusive range
|
|
262
|
-
format as ``words`` (``start-end``, ``start:end``, or a single index). Unlike ``words``, they
|
|
263
|
-
work in **every** render mode: alongside a ``words`` selection, on a plain ``sura``/``aya`` verse
|
|
264
|
-
(counted from that aya's first word), and even on a full ``page`` render (counted from the
|
|
265
|
-
page's first aya — a page never starts mid-aya, so this is always well-defined). A range must
|
|
266
|
-
fall entirely within whatever is actually displayed (the ``words`` selection if one is set,
|
|
267
|
-
otherwise the whole verse/page); an out-of-range or malformed value is ignored with a console
|
|
268
|
-
warning rather than breaking the render. When ``highlight`` and ``error`` overlap on the same
|
|
269
|
-
word, ``error`` wins.
|
|
270
|
-
|
|
271
|
-
```html
|
|
272
|
-
<quran-madina-html sura="1" aya="7" words="1-14" highlight="10-13" error="1-2"></quran-madina-html>
|
|
273
|
-
<quran-madina-html sura="2" aya="255" highlight="5-8"></quran-madina-html> <!-- no words needed -->
|
|
274
|
-
<quran-madina-html page="2" error="1-4"></quran-madina-html> <!-- counted from the page's first aya -->
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Colors come from the ``--qmh-highlight``/``--qmh-error`` CSS custom properties on
|
|
278
|
-
``quran-madina-html`` (defaults: soft yellow/soft red) — override them, or the
|
|
279
|
-
``.quran-madina-html-word-highlight``/``.quran-madina-html-word-error`` classes directly, from
|
|
280
|
-
your own stylesheet.
|
|
281
|
-
|
|
282
|
-
Another option exists to render a complete quran page:
|
|
283
|
-
|
|
284
|
-
```html
|
|
285
|
-
<quran-madina-html page="106"></quran-madina-html>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
By default a multiline render gets a header (sura name + copy/translate icons); clicking any aya (inline or multiline) opens a small copy/translate popup scoped to it. Set ``headless="true"`` to drop the header and render only the Quran text:
|
|
289
|
-
|
|
290
|
-
```html
|
|
291
|
-
<quran-madina-html sura="2" aya="8-10" headless="true"></quran-madina-html> <!-- no header -->
|
|
33
|
+
<quran-madina-html sura="2" aya="255"></quran-madina-html>
|
|
292
34
|
```
|
|
293
35
|
|
|
294
|
-
###
|
|
295
|
-
|
|
296
|
-
| Attribute | Type | Default | Description |
|
|
297
|
-
|---|---|---|---|
|
|
298
|
-
| `sura` | `number \| string` | - | Sura number (1–114). Required when using `aya`. |
|
|
299
|
-
| `aya` | `number \| string` | - | Single aya or verse range (e.g., `255`, `"8-10"`). |
|
|
300
|
-
| `page` | `number \| string` | - | Full Mushaf page number (1–604; IndoPak 1–610). Mutually exclusive with `sura`/`aya`. |
|
|
301
|
-
| `words` | `string` | - | 1-based word index or range (e.g., `"1:2"`, `"3-10"`, or single index `"5"`). |
|
|
302
|
-
| `highlight` | `string` | - | 1-based word range to mark soft yellow (same format as `words`). Works with or without `words`, and with `page` too. |
|
|
303
|
-
| `error` | `string` | - | 1-based word range to mark soft red (same format as `words`). Wins over `highlight` on overlap. |
|
|
304
|
-
| `letters` | `string` | - | Letters to emphasise inside words: `"1:3 crimson, 4:3-5 emerald blink"` (word:letters, optional colour — crimson by default — and optional `blink`). Works with `highlight`/`error`, `words` and `page`. |
|
|
305
|
-
| `headless` | `boolean \| string` | `false` | Set to `"true"` to remove top sura header chrome and copy/translate icons. |
|
|
306
|
-
| `notitle` | `boolean \| string` | `false` | Set to `"true"` to hide sura name text while retaining title frame decoration. |
|
|
307
|
-
| `data-layout` | `string` | `"1441H"` | Layout: `1441H`, `1405H`, `IndoPak`. |
|
|
308
|
-
| `data-font-size` | `number \| string` | `16` | Font size in px; any size. |
|
|
309
|
-
| `data-cdn` | `string` | unpkg | Base URL for the CSS and databases (self-hosting, offline apps). |
|
|
310
|
-
|
|
311
|
-
## React wrapper
|
|
312
|
-
|
|
313
|
-
For React apps (web, or mobile via a Capacitor WebView), use
|
|
314
|
-
[`@tarekeldeeb/quran-madina-react`](https://www.npmjs.com/package/@tarekeldeeb/quran-madina-react),
|
|
315
|
-
a thin component wrapping the `<quran-madina-html>` tag — lives in this repo's [`react/`](react)
|
|
316
|
-
folder and is released in lockstep with this package.
|
|
36
|
+
### React
|
|
317
37
|
|
|
318
38
|
```bash
|
|
319
39
|
npm install @tarekeldeeb/quran-madina-react react
|
|
@@ -322,86 +42,36 @@ npm install @tarekeldeeb/quran-madina-react react
|
|
|
322
42
|
```jsx
|
|
323
43
|
import QuranMadinaHtml from "@tarekeldeeb/quran-madina-react";
|
|
324
44
|
|
|
325
|
-
<QuranMadinaHtml
|
|
45
|
+
<QuranMadinaHtml sura={2} aya="255" />
|
|
326
46
|
```
|
|
327
47
|
|
|
328
|
-
|
|
329
|
-
(iOS/Android) packaging guide.
|
|
330
|
-
|
|
331
|
-
## Flutter wrapper
|
|
332
|
-
|
|
333
|
-
For Flutter apps, use `quran_madina_flutter`, a widget with the same options as the React
|
|
334
|
-
component. It lives in this repo's [`flutter/`](flutter) folder and is released in step with
|
|
335
|
-
this package.
|
|
336
|
-
|
|
337
|
-
- **Android, iOS, macOS:** the text renders in the platform's own WebView (WKWebView on Apple
|
|
338
|
-
devices), the same engine as a Capacitor app.
|
|
339
|
-
- **Web:** no WebView; the `<quran-madina-html>` tag goes straight into the page.
|
|
340
|
-
- **Offline:** `dart run quran_madina_flutter:bundle` copies the library, databases and fonts
|
|
341
|
-
into the app's assets. `bundled: true` then loads them from there instead of unpkg.
|
|
48
|
+
### Flutter
|
|
342
49
|
|
|
343
50
|
```yaml
|
|
344
51
|
dependencies:
|
|
345
|
-
quran_madina_flutter:
|
|
346
|
-
git:
|
|
347
|
-
url: https://github.com/tarekeldeeb/quran-madina-html
|
|
348
|
-
path: flutter
|
|
52
|
+
quran_madina_flutter: ^2.1.0
|
|
349
53
|
```
|
|
350
54
|
|
|
351
55
|
```dart
|
|
352
56
|
import 'package:quran_madina_flutter/quran_madina_flutter.dart';
|
|
353
57
|
|
|
354
|
-
QuranMadinaFlutter(sura:
|
|
355
|
-
QuranMadinaFlutter(page: 106, bundled: true) // offline
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
See [`flutter/README.md`](flutter/README.md) for the full option reference and the one-time
|
|
359
|
-
platform settings for offline use. The example app's web build runs live at
|
|
360
|
-
<https://tarekeldeeb.github.io/quran-madina-html/flutter/>.
|
|
361
|
-
|
|
362
|
-
## Dev Setup
|
|
363
|
-
|
|
364
|
-
The project is published on npm ``npm install quran-madina-html``, with sources, assets and distributables.
|
|
365
|
-
Alternatively, you can fork this repo, then clone it.
|
|
366
|
-
|
|
367
|
-
```bash
|
|
368
|
-
apt install python3-distutils nodejs npm chromium-driver
|
|
369
|
-
npm install // install components and scripts
|
|
370
|
-
npm run release // build the dist with dependencies
|
|
371
|
-
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
(`npm run build-db` still rebuilds the 1.x databases in `assets/db/`; the runtime no longer reads them.)
|
|
375
|
-
|
|
376
|
-
The databases (`assets/db/v2`) are built from the Tanzil text and a checkout of
|
|
377
|
-
[digitalkhatt.org](https://github.com/DigitalKhatt/digitalkhatt.org) (fonts and layouts):
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
python src/db/v2/build_v2.py --layout 1441H --tanzil quran-uthmani.txt --dk-src ../digitalkhatt.org/ClientApp/src
|
|
381
|
-
python src/db/v2/build_v2.py --layout 1405H --tanzil quran-uthmani.txt --dk-src ../digitalkhatt.org/ClientApp/src
|
|
382
|
-
python src/db/v2/build_v2.py --layout IndoPak --dk-src ../digitalkhatt.org/ClientApp/src
|
|
383
|
-
for db in Madina-1441H Madina-1405H IndoPak-15; do python src/db/shard_db.py assets/db/v2/$db.json assets/db/v2; done
|
|
384
|
-
python src/db/v2/check_v2_db.py assets/db/v2/Madina-1441H.json
|
|
58
|
+
QuranMadinaFlutter(sura: 2, aya: '255')
|
|
385
59
|
```
|
|
386
60
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
The README screenshots in `demo/img` are taken from the current build by
|
|
390
|
-
`python scripts/readme_screenshots.py` (with `npm run start` running).
|
|
61
|
+
Everything else (pages, word selection, highlighting, letters, layouts, styling, offline use,
|
|
62
|
+
and every option) is in the [documentation](https://tarekeldeeb.github.io/quran-madina-html/docs/).
|
|
391
63
|
|
|
392
64
|
## Credits
|
|
393
65
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
by Amine Anane, sponsored by Tarteel (fonts OFL 1.1, code MIT). The fonts in `assets/db/v2`
|
|
397
|
-
modified copies
|
|
398
|
-
|
|
399
|
-
[`quran-qcf4`](https://www.npmjs.com/package/quran-qcf4) package (
|
|
66
|
+
- Quran text: [Tanzil Project](https://tanzil.net) (Uthmani 1.1).
|
|
67
|
+
- Fonts and the 1405H and IndoPak layouts: [DigitalKhatt](https://github.com/DigitalKhatt/digitalkhatt.org)
|
|
68
|
+
by Amine Anane, sponsored by Tarteel (fonts OFL 1.1, code MIT). The fonts in `assets/db/v2`
|
|
69
|
+
are modified copies, with stretch features added, under the same license and renamed `QMH ...`.
|
|
70
|
+
- 1441H line breaks: King Fahd Glorious Quran Printing Complex page data, as published in the
|
|
71
|
+
[`quran-qcf4`](https://www.npmjs.com/package/quran-qcf4) package (MIT); only the line
|
|
400
72
|
boundaries are used.
|
|
401
73
|
|
|
402
|
-
##
|
|
403
|
-
|
|
404
|
-
<https://tarekeldeeb.github.io/quran-madina-html/demo/index.html>
|
|
405
|
-
|
|
406
|
-
Don't forget to see the page source!
|
|
74
|
+
## License
|
|
407
75
|
|
|
76
|
+
Code and assets are licensed under the ["Waqf" General Public License 2.0](https://github.com/ojuba-org/waqf/tree/master/2.0).
|
|
77
|
+
See [LICENSE.md](LICENSE.md).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! quran-madina-html
|
|
1
|
+
/*! quran-madina-html 18-10-2026 */
|
|
2
2
|
!function(){var z="quran-madina-html",n=/localhost/.test(document.location.hostname)?"../":`https://www.unpkg.com/${z}/`,P={content:"Loading .."},g=/[\u0621-\u064A\u0671-\u06D3]/,N="﷽";function j(t,e){return 1===e&&0!==t}var l={};function m(e){try{for(var t=sessionStorage.length-1;0<=t;t--){var r=sessionStorage.key(t);r&&0===r.indexOf("quran-madina-html:"+e)&&sessionStorage.removeItem(r)}}catch(t){}Object.keys(l).forEach(function(t){0===t.indexOf(e)&&delete l[t]})}var o={};function a(s,t,e,r){var i,n=!r&&function(t){if(l[t])return l[t];try{var e=sessionStorage.getItem("quran-madina-html:"+t);if(e)return l[t]=JSON.parse(e)}catch(t){}return null}(s);n?t&&setTimeout(function(){t(n)},0):o[s]?o[s].push({success:t,error:e}):(o[s]=[{success:t,error:e}],(i=new XMLHttpRequest).onreadystatechange=function(){if(i.readyState===XMLHttpRequest.DONE){var t=o[s];if(delete o[s],200===i.status){var e=JSON.parse(i.responseText),r=s,n=e,a=i.responseText;l[r]=n;try{sessionStorage.setItem("quran-madina-html:"+r,a)}catch(t){}t.forEach(function(t){t.success&&t.success(e)})}else t.forEach(function(t){t.error&&t.error(i)})}},i.open("GET",s,!0),i.send())}function T(t){console.log(z+"> "+t)}function H(t){return null!=t&&(""===(t=String(t).trim().toLowerCase())||"true"===t||"1"===t||"yes"===t)}function M(t){var e=(e=(e=getComputedStyle(t).color)&&e.match(/[\d.]+/g))?.2126*r(+e[0])+.7152*r(+e[1])+.0722*r(+e[2]):1;function r(t){return(t/=255)<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)}t.setAttribute("data-qmh-text-scheme",.5<e?"dark":"light")}function B(t){return Array(2).fill(t.split("-")[0]-1)}function O(t){return 2==t.split("-").length?t.split("-").map(t=>parseInt(t)+1):Array(2).fill(parseInt(t.split("-")[0])+1)}function D(t){return null==t||2!=(t=1==(t=t.split(/[-:]/).map(t=>parseInt(t,10))).length?[t[0],t[0]]:t).length||isNaN(t[0])||isNaN(t[1])||t[0]<1||t[1]<t[0]?null:t}function F(t,e,r){return null==e?null:e[0]<r[0]||e[1]>r[1]?(T(`${t} range ${e[0]}-${e[1]} outside displayed words ${r[0]}-${r[1]}, ignoring`),null):e}function V(t,e){if(null!=t&&"auto"!==t){if("no"===t)return!0;T("yes"===t?'inline="yes" is not implemented yet; falling back to "auto"':"Bad inline parameter: "+t)}return e}function u(t){return g.test(t)}function R(t,e){return(0===t?2:1)<=e}function X(t){var e=0;return t.t.split(/\s+/).forEach(function(t){u(t)&&(e+=1)}),e}function W(t){var e=0;return t.r.forEach(function(t){e+=X(t)}),e}function Y(t){for(var e=t.p,r=null,n=0;n<t.r.length;n++)null!==r&&t.r[n].l<r&&(e+=1),r=t.r[n].l;return e}function Z(t,e,r){for(var n=P.suras[t].ayas,a=0,s=e;s<=r;s++)R(t,s)&&(a+=W(n[s]));return a}function tt(t,e,r,n,a){for(var s=0,i=t;i<=r;i++)for(var l=P.suras[i].ayas,o=i===r?n:l.length-1,u=i===t?e:0;u<=o;u++){var c=l[u];void 0!==c&&c.p===a&&R(i,u)&&(s+=W(c))}return s}function et(t,e="class",n=null,a="transparent"){var s="tag"===e.toLowerCase()?document.getElementsByTagName(t):document.getElementsByClassName(t);Array.from(s).forEach(function(r){r.onmouseover=function(){var t,e=n||(t=r,getComputedStyle(t).getPropertyValue("--qmh-hover").trim())||`rgba(${(getComputedStyle(t).color.match(/[\d.]+/g)||[128,128,128]).slice(0,3).join(",")},0.12)`;Array.from(s).forEach(function(t){t.style.backgroundColor=e})},r.onmouseout=function(){Array.from(s).forEach(function(t){t.style.backgroundColor=a})}})}function rt(t,e){var r=(t,e)=>String(t).padStart(e,"0"),r=[z+"-part",`${z}-${r(t,3)}-`+r(e,3)];return(-1==e||1==t&&0==e)&&r.push("quran-madina-html-sura-start"),r}function y(){var t=document.createElement("div");return t.innerHTML='<svg viewBox="0 0 24 24" class="quran-madina-html-icon" width="20px"><path d="M16.02 20.96H3.78c-.41 0-.75-.34-.75-.75V7.74c0-.41.34-.75.75-.75h7.87c.21 0 .39.08.53.22l4.37 4.37c.14.14.22.32.22.53v8.11c0 .4-.34.74-.75.74ZM4.53 19.47h10.75v-6.61h-3.62c-.41 0-.75-.34-.75-.75V8.48H4.53v10.99Z"></path><path d="m20.74 7.63-4.37-4.37c-.14-.14-.36-.2-.53-.22H8.01c-.41 0-.75.34-.75.75V5.5h1.49v-.97h6.34v3.62c0 .41.34.75.75.75h3.62v8.19h-1.2v1.49h1.95c.41 0 .75-.34.75-.75V8.16c0-.21-.08-.4-.22-.53Z"></path></svg>'.trim(),t.firstChild}function v(){var t=document.createElement("div");return t.innerHTML='<svg class="quran-madina-html-icon" viewBox="0 0 820 615" style="height:20px"><path d="M70 1.9C37.6 8.8 12.6 33.4 3.4 67.5c-1.8 6.6-1.9 11.9-1.9 98v91l2.3 8c5.1 17.8 17 36.4 29.9 46.7 10.8 8.6 25.4 15.4 38.1 17.8 3.1.6 15.2 1 26.8 1 17.7 0 21.3.2 21.7 1.4.4.9.6 17.1.7 36.1 0 32.4.2 34.9 2 38.5 6.4 12.5 21.4 17.4 33.3 10.8 2.3-1.3 7.5-6.4 12.1-11.9l63-74.1c.6-.4 16.3-.8 34.9-.8H300l-.2-18.3-.3-18.2-42.8.1-43.1.5c-.2.2-12.7 15.1-27.9 33.1-15.1 18-27.8 32.4-28.1 32.1-.3-.4-.6-15.3-.6-33.2v-32.6l-38.8-.1c-42.1-.2-43.9-.4-54.3-6-6.5-3.6-16.9-14.6-20.2-21.5-5.8-11.9-5.7-10-5.7-100.7 0-92-.2-89.4 6.3-101.7 3.9-7.3 13.5-17.1 20.3-20.7C76 36.7 66.1 37 244.5 37L412 38.1c18 4.1 33.5 20.5 37.5 39.6 2.2 10.2 2.1 164.6 0 174.8-3.9 18.3-16.4 32.7-33.5 38.5-3.2 1.1-7.8 2-10 2-3.1 0-4 .4-4 1.7 0 1-.2 8.8-.3 17.3-.2 8.5-.2 16.2 0 17 .9 3.3 21.7-.5 34.1-6 13.7-6.3 27.5-17.9 36.2-30.5 5-7.2 10.8-20.4 13.2-30.1l2.3-8.9V165 76.5l-2.3-9c-8.1-31.4-30.5-54.9-61.7-64.8l-7-2.2-169-.2C87.7.1 78 .2 70 1.9zm277.294 102.559q19.5-.5 28.25 24.5 2.5 7.25-3.75 19.75-5.75 11.75-9.75 16-19.5 21.5-67 25.25-27.75 2.25-50.25-2.25-5.25 38.25-16.5 50-26 26.75-66 29.5-27.75 2-42.5-11-20.25-17.75-16.5-48.5 3-23.75 14.25-42.5 2.75-4.5 4.75-7.5 2-3 3-4.25 2.25-2.75 4.75-1.25 2.75 1.5 0 6.25-12.75 24.5-10 45 4 30.5 44.5 30.5 30.25 0 53.25-15.5 12.5-8.25 14.75-14.25-2.25-20.75-13.75-35.75-3.5-4.25-1.75-8l9.5-23.5q3-7.5 8.25 1.25l8.75 14.75q7.75 4.25 28.25 5 16.75-19.25 39.25-36.25 22.5-16.75 36.25-17.25zm11.5 40.5q-12.5-9.5-31.75-5.75-19 3.75-41.25 19.5 50.75.5 73-13.75zm-71.5-89.75q1.5-2 4.25-1.25 5 1.75 9.5 4.5 4.75 2.75 8.75 6.25 2 2 .75 4.5l-12 19q-1.75 2.5-4.5.5-2.5-2-18-11.25-2.75-1.75-1-4.25zm278.784 232.623c-4.7.4-4.7.4-6.7 6.1-1.2 3.1-9.3 25.9-18 50.7l-36.6 102.7-3.5 9.8h17.9 17.8l5.7-17 5.7-17h31.7 31.8l5.6 17.2 5.6 17.3 17.9-.3 18-.3-6-17.2-15-43.2-13.3-38.5-14.1-41-9.9-28.7c-.3-.6-30.2-1.1-34.6-.6zm35.7 106c-.2.2-10 .2-21.9.1l-21.5-.3 9.8-29.5 11-32.5c1.2-2.9 1.8-1.4 12.1 29.4l10.5 32.8zm148.8 139.609c32.4-6.9 57.4-31.5 66.6-65.6 1.8-6.6 1.9-11.9 1.9-98v-91l-2.3-8c-5.1-17.8-17-36.4-29.9-46.7-10.8-8.6-25.4-15.4-38.1-17.8-3.1-.6-15.2-1-26.8-1-17.7 0-21.3-.2-21.7-1.4-.4-.9-.6-17.1-.7-36.1 0-32.4-.2-34.9-2-38.5-6.4-12.5-21.4-17.4-33.3-10.8-2.3 1.3-7.5 6.4-12.1 11.9l-63 74.1c-.6.4-16.3.8-34.9.8h-33.7l.2 18.3.3 18.2 42.8-.1 43.1-.5c.2-.2 12.7-15.1 27.9-33.1 15.1-18 27.8-32.4 28.1-32.1.3.4.6 15.3.6 33.2v32.6l38.8.1c42.1.2 43.9.4 54.3 6 6.5 3.6 16.9 14.6 20.2 21.5 5.8 11.9 5.7 10 5.7 100.7 0 92 .2 89.4-6.3 101.7-3.9 7.3-13.5 17.1-20.3 20.7-11.4 6.1-1.5 5.8-179.9 5.8-108.2 0-164.5-.4-167.5-1.1-18-4.1-33.5-20.5-37.5-39.6-2.2-10.2-2.1-164.6 0-174.8 3.9-18.3 16.4-32.7 33.5-38.5 3.2-1.1 7.8-2 10-2 3.1 0 4-.4 4-1.7 0-1 .2-8.8.3-17.3.2-8.5.2-16.2 0-17-.9-3.3-21.7.5-34.1 6-13.7 6.3-27.5 17.9-36.2 30.5-5 7.2-10.8 20.4-13.2 30.1l-2.3 8.9v88.5 88.5l2.3 9c8.1 31.4 30.5 54.9 61.7 64.8l7 2.2 169 .2 177.5-1.6z"/></svg>'.trim(),t.firstChild}function nt(t){var e=document.createElement("quran-madina-html-header"),t=(e.innerHTML=t,y()),r=(t.addEventListener("click",I),v());return r.addEventListener("click",$),e.appendChild(t),e.appendChild(r),e}var h=null;function J(){h&&(h.popup.classList.remove(z+"-open"),document.removeEventListener("click",h.outsideClick),document.removeEventListener("keydown",h.onEscape),h=null)}function w(e,t,r,n,a){J();function s(t){u.contains(t.target)||J()}function i(t){"Escape"===t.key&&J()}l=e,(o=document.querySelector(`body > ${z}-aya-popup`))||((o=document.createElement(z+"-aya-popup")).appendChild(y()),o.appendChild(v()),document.body.appendChild(o)),["--qmh-header","--qmh-background"].forEach(function(t){o.style.setProperty(t,getComputedStyle(l).getPropertyValue(t))});var l,o,u=o,c=u.children[0],d=u.children[1];c.onclick=function(t){t.stopPropagation();t="“"+(t=e,t=Array.from(t.getElementsByClassName(r)).map(function(t){return t.textContent}).join(" ").replace(/\s+/g," ").trim(),G()?b(t):t)+"”\n\n"+P.suras[n-1].name;navigator.clipboard.writeText(t),alert("⎘ تم نسخ:\n\n"+t),J()},d.onclick=function(t){t.stopPropagation(),window.open(`https://quran.com/${n}/`+a,"_blank"),J()},c=u,d=(d=t).getBoundingClientRect(),c.style.left=Math.max(4,d.left)+"px",c.style.top=(0<d.top-34-6?d.top-34-6:d.bottom+6)+"px",u.classList.add(z+"-open");document.addEventListener("click",s),document.addEventListener("keydown",i),h={popup:u,outsideClick:s,onEscape:i}}function at(r,n,a,s){s<1||Array.from(r.getElementsByClassName(n)).forEach(function(e){e.style.cursor="pointer",e.onclick=function(t){t.stopPropagation(),w(r,e,n,a,s)}})}function st(t,e,r){t.style="display:block;",t.style.setProperty("font-family",P.font_family,""),t.style.setProperty("font-size",P.font_size+"px",""),"me_quran"===P.font_family&&t.style.setProperty("line-height",2*P.font_size+"px",""),G()&&t.style.setProperty("line-height","1.8",""),t.style.width=P.line_width+10+"px",r||t.style.setProperty("box-shadow","inset "+(e%2==1?"":"-")+"8px 0 7px -7px #333","")}function G(){return 2===P.version}function it(t,e,r){e=P.lines[e-1][r-1];t._qmh={row:e,words:0},e.z&&(t.style.setProperty("font-size",e.z+"em",""),t.style.setProperty("line-height",String(1.8/e.z),"")),t.style.setProperty("width",e.w/(e.z||1)+"em",""),t.style.setProperty("margin","0 auto",""),t.style.setProperty("white-space","nowrap",""),"text"!==e.k&&t.style.setProperty("text-align","center",""),e.x&&t.style.setProperty("transform",`scaleX(${e.x})`,"")}function U(a,t,s,i){t._qmh||(t._qmh={row:null,words:0});var l=t._qmh,o=null!==l.row&&"text"===l.row.k;s.t.split(" ").forEach(function(t,e){var r,n;""!==t&&(0<l.words&&(o?((n=document.createElement("span")).className=z+"-space",n.textContent=" ",r=l.row.s[l.words-1],n.style.cssText=0<=r?`display:inline-block;width:${r}em`:`display:inline-block;width:0;margin-left:${r}em`,a.appendChild(n)):a.appendChild(document.createTextNode(" "))),l.words=l.words+1,(r=document.createElement("span")).textContent=t,r.classList.add(z+"-word"),o&&s.f&&s.f[e]&&(r.style.fontFeatureSettings=s.f[e].split(",").map(function(t){t=t.split("=");return`"q${t[0].slice(2)}${Number(t[1]||1).toString(36)}"`}).join(", ")),o&&l.row.c&&t.indexOf("")<0&&(r.style.display="inline-block",r.style.transform=`scaleX(${l.row.c})`,0==(n=l.words-1)?r.style.transformOrigin="right":n===l.row.s.length&&(r.style.transformOrigin="left")),i&&i(r,t),a.appendChild(r))})}function b(t){return t.replace(/ا͏ٔ͏/g,"أ").replace(/إ͏/g,"إ").replace(/و͏ٔ͏/g,"ؤ").replace(/ي͏ٔ͏/g,"ئ").replace(/͏/g,"").replace(/ࣰ/g,"ً").replace(/ࣱ/g,"ٌ").replace(/ࣲ/g,"ٍ")}function lt(t,e){G()||(0<=e?t.style.setProperty("transform",`scaleX(${e*(P.stretch_scale||1)})`,""):t.style.setProperty("text-align","center",""))}function E(t,e,r,n){n&&e>=n[0]&&e<=n[1]?t.classList.add(z+"-word-error"):r&&e>=r[0]&&e<=r[1]&&t.classList.add(z+"-word-highlight")}function ot(r,t,n,a,s,i,e,l){return G()&&e&&l?U(r,l,e,function(t,e){u(e)&&(a+=1,t.setAttribute("data-qmh-w",a)),n&&(a<n[0]||a>n[1])&&t.classList.add(z+"-word-hidden"),E(t,a,s,i)}):t.split(/(\s+)/).forEach(function(t){var e;""!==t&&(/^\s+$/.test(t)?r.appendChild(document.createTextNode(t)):((e=document.createElement("span")).textContent=t,e.classList.add(z+"-word"),u(t)&&(a+=1,e.setAttribute("data-qmh-w",a)),n&&(a<n[0]||a>n[1])&&e.classList.add(z+"-word-hidden"),E(e,a,s,i),r.appendChild(e)))}),a}var C={crimson:"#a3263a",emerald:"#0f6b4f",lapis:"#1f4fb0",gold:"#8a5a00",violet:"#5b2aa8"};function x(t){var n;return null!=t&&(n=[],String(t).split(",").forEach(function(t){var a,e,r,t=t.trim().match(/^(\d+)\s*:\s*([\d+\-\s]*\d)\s*(\S.*)?$/);t&&(a=[],t[2].replace(/\s+/g,"").split("+").forEach(function(t){t=t.match(/^(\d+)(?:-(\d+))?$/);if(t)for(var e=parseInt(t[1],10),r=t[2]?parseInt(t[2],10):e,n=e;n<=r&&n-e<50;n++)1<=n&&a.push(n)}),a.length)&&(e=!1,(r=t[3]?t[3].trim().split(/\s+/):[]).length&&"blink"===r[r.length-1].toLowerCase()&&(e=!0,r.pop()),(r=r.length?r.join(" "):null)&&C[r.toLowerCase()]&&(r=C[r.toLowerCase()]),n.push({word:parseInt(t[1],10),letters:a,color:r,blink:e}))}),n.length)?n:null}var q=/[\u0300-\u036F\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E8\u06EA-\u06ED\u08D3-\u08FF\u200C\u200D\u0640]/;function A(t){var e=document.createElement("span");return e.className=z+"-ink",e.textContent=t,e}function _(e,r){var n=e.textContent,a=function(t){for(var e=[],r=0;r<t.length;r++){var n=t[r];q.test(n)||e.push(r)}return e.push(t.length),e}(n),s=[],i=0,l=!1;return Object.keys(r).map(Number).filter(function(t){return t<a.length}).sort(function(t,e){return t-e}).forEach(function(t){a[t-1]>i&&s.push(A(n.slice(i,a[t-1])));var e=document.createElement("span");e.className=z+"-letter",r[t].color&&e.style.setProperty("--qmh-letter",r[t].color),r[t].blink&&e.classList.add(z+"-letter-blink"),e.textContent=n.slice(a[t-1],a[t]),s.push(e),i=a[t],l=!0}),l&&(i<n.length&&s.push(A(n.slice(i))),e.textContent="",s.forEach(function(t){e.appendChild(t)}),e.classList.add(z+"-word-lettered"),1)}function k(t,e,r){var n,a,s;t.classList.remove(z+"-lettered"),e&&(M(t),n={},a={},t.querySelectorAll(`.${z}-word[data-qmh-w]`).forEach(function(t){n[t.getAttribute("data-qmh-w")]=t}),e.forEach(function(e){var r=a[e.word]=a[e.word]||{};e.letters.forEach(function(t){r[t]={color:e.color,blink:e.blink}})}),s=[],Object.keys(a).forEach(function(t){var e=n[parseInt(t,10)+(r||0)];e&&_(e,a[t])||s.push(t)}),s.length&&T("letters: no such word/letter for word(s) "+s.join(", ")),t.classList.add(z+"-lettered"))}function ut(e,r,t,n,a){function s(t){return!t||e+1>=t[0]&&e+r<=t[1]}function i(t){return t&&!s(t)&&e+r>=t[0]&&e+1<=t[1]}return G()||!s(t)||i(n)||i(a)?{ligature:!1}:(t=null,a&&s(a)?t="error":n&&s(n)&&(t="highlight"),{ligature:!0,cls:t})}function L(t,e){for(var r=0;r<t.r.length;r++)if(t.r[r].l===e)return t.r[r];return null}function S(t,e,r){var n,t=P.suras[t].ayas;return e<=0||void 0===(n=t[e-1])||n.p!==t[e].p||null===L(n,r)}function K(t,e,r,n,a){for(var s=P.suras[t].ayas,i=[],l=n+a;0<=l&&l<s.length&&void 0!==s[l]&&s[l].p==e;l+=a){var o=L(s[l],r);if(null===o)break;if(a<0){if(i.unshift(o),S(t,l,r))break}else i.push(o)}return i}function Q(t,e){for(var r=0;r<e.length;r++){var n=document.createElement("div");n.style.cssText="display:inline;visibility:hidden",G()?U(n,t,e[r]):n.textContent=e[r].t,t.appendChild(n)}}function I(){var t=this.parentElement.parentElement,e=t.querySelector("quran-madina-html-header"),r=(e=e?e.textContent.replace(/\s+/g," ").trim():null!=(e=t.getAttribute("sura"))?P.suras[e-1].name:"",(r=(t=(t=t).cloneNode(!0)).querySelector("quran-madina-html-header"))&&r.parentNode.removeChild(r),Array.from(t.querySelectorAll(`.${z}-word-hidden`)).forEach(function(t){t.parentNode.removeChild(t)}),Array.from(t.querySelectorAll("div,span")).forEach(function(t){/visibility:\s*hidden/.test(t.getAttribute("style")||"")&&t.parentNode.removeChild(t)}),t),t=r.querySelectorAll("quran-madina-html-line"),t=t.length?Array.from(t).map(function(t){return t.textContent.replace(/\s+/g," ").trim()}).filter(function(t){return""!==t}).join(" "):r.textContent.replace(/\s+/g," ").trim(),r="“"+(t=G()?b(t):t)+"”\n\n"+e;navigator.clipboard.writeText(r),alert("⎘ تم نسخ:\n\n"+r)}function $(){var t=this.parentElement.parentElement;let e;e=null!=t.getAttribute("sura")&&null!=t.getAttribute("aya")?`https://quran.com/${t.getAttribute("sura")}/`+t.getAttribute("aya"):"https://quran.com/page/"+t.getAttribute("page"),window.open(e,"_blank")}function ct(l,t,e,o,r,n,a,u,c,d){(c||d)&&M(l);var t=function(t,e,r){for(var n=[],a=null,s=0,i=P.suras.length,l=2===e&&0<t?1:e,o=0;o<i;o++){for(var u=(t+o)%i,c=P.suras[u].ayas,d=!1,h=0===o?l:0;h<c.length;h++){var p=R(u,h),f=c[h];if(void 0===f)break;for(var g=0;g<f.r.length;g++){var m,y=f.r[g];""!==y.t&&(m=f.p+":"+y.l,a&&a.key===m||(a={key:m,stretch:y.s,parts:[]},n.push(a)),a.parts.push({sura:u,ayaIdx:h,part:y,countable:p}))}if(p&&(s+=W(f))>=r[1]){d=!0;break}}if(d)break}for(var v=0,w=(n.forEach(function(t){t.parts.forEach(function(t){t.countable&&(v+=X(t.part))}),t.lastWord=v}),0);w<n.length-1&&n[w].lastWord<r[0];)w+=1;for(var b=w;b<n.length-1&&n[b].lastWord<r[1];)b+=1;return{groups:n.slice(w,b+1),counterStart:0<w?n[w-1].lastWord:0}}(t,e,o),s=t.groups,h=V(a,1<s.length),p=t.counterStart;J(),l.innerHTML="",l.removeAttribute("style"),l.classList.toggle(z+"-inline",!h&&!n),h&&(e=parseInt(s[0].key.split(":")[0],10),st(l,e,r),r||l.appendChild(nt(P.suras[s[0].parts[0].sura].name))),s.forEach(function(t,e){var r,i=document.createElement("quran-madina-html-line");h?(i.style.setProperty("display","block",""),G()&&(r=t.key.split(":"),it(i,parseInt(r[0],10),parseInt(r[1],10))),lt(i,t.stretch),S((r=t.parts[0]).sura,r.ayaIdx,r.part.l)||Q(i,K(r.sura,P.suras[r.sura].ayas[r.ayaIdx].p,r.part.l,r.ayaIdx,-1))):(i.style.setProperty("font-family",P.font_family,""),i.style.setProperty("font-size",P.font_size+"px","")),l.appendChild(i),t.parts.forEach(function(t){var e,r,n,a=document.createElement("div"),s=rt(t.sura+1,t.ayaIdx-1);DOMTokenList.prototype.add.apply(a.classList,s),t.countable?(n=0<(e=j(t.sura,t.ayaIdx)?X(t.part):0)?ut(p,e,o,c,d):{ligature:!1}).ligature?((r=document.createElement("span")).classList.add(z+"-word",z+"-basmala"),n.cls&&r.classList.add(z+"-word-"+n.cls),r.textContent=N,a.appendChild(r),p+=e):p=ot(a,t.part.t,o,p,c,d,t.part,i):u&&(0===t.ayaIdx||0===t.sura&&1===t.ayaIdx)?((n=document.createElement("span")).textContent=t.part.t,n.style.visibility="hidden",a.appendChild(n)):a.textContent=t.part.t,a.style.cssText="display:inline",i.appendChild(a),et(s.slice(-1)[0]),at(l,s.slice(-1)[0],t.sura+1,t.ayaIdx-1)}),h&&e===s.length-1&&(r=t.parts[t.parts.length-1],Q(i,K(r.sura,P.suras[r.sura].ayas[r.ayaIdx].p,r.part.l,r.ayaIdx,1)))})}var dt,t,c,e=16,r=[6,100],s=document.currentScript||document.querySelector(`script[src*="${z}"]`),ht=s.getAttribute("data-name")||"Madina05",pt=(s.getAttribute("data-font")||"me_quran").replaceAll(" ","_"),i=parseFloat(s.getAttribute("data-font-size"))||e,d=((i<r[0]||r[1]<i)&&(T(`font-size ${i} outside ${r[0]}..${r[1]}, using `+e),i=e),s.getAttribute("data-layout")||"1441H"),r=(["data-font","data-name"].forEach(function(t){s.hasAttribute(t)&&console.warn(z+`> ${t} is ignored since 2.0: every tag uses the v2 fonts `+'(choose a layout with data-layout="1441H" | "1405H" | "IndoPak")')}),{"1441H":"Madina-1441H","1405H":"Madina-1405H",indopak:"IndoPak-15"}),e=(void 0===r[d]&&(d=void 0!==r[String(d).toLowerCase()]?String(d).toLowerCase():(console.warn(z+`> unknown data-layout "${d}", using 1441H`),"1441H")),s.getAttribute("data-cdn")),e=(e&&(n=e.replace(/\/?$/,"/")),T(`layout: ${d} size: `+i),n+"dist/"+z+".min.css?v=1.1");function ft(t){c=n+`assets/db/${ht+`-${pt}-${i=t}px`}/`}document.getElementById(z)||(dt=document.getElementsByTagName("head")[0],(t=document.createElement("link")).id=z,t.rel="stylesheet",t.type="text/css",t.href=e,t.media="all",dt.appendChild(t)),ft(i);var gt,p={};function f(t,e){if(!P.juz)return-1;for(var r=Math.max(e,2),n=0,a=P.juz,s=0;s<a.length&&(a[s][0]<t||a[s][0]===t&&a[s][1]<=r);s++)n=s;return n}function mt(t,i){if(P.juz){for(var l,e=[],r=0;r<t.length;r++){var n=t[r];0<=n&&n<P.juz.length&&!p[n]&&e.indexOf(n)<0&&e.push(n)}0===e.length?i():(l=e.length,e.forEach(function(s){var t;a(c+"juz-"+((t=s+1)<10?"0":"")+t+".json",function(t){for(var e=t,r=0;r<e.d.length;r++){var n=e.d[r];P.suras[n[0]].ayas[n[1]]={p:n[2],r:n[3]}}if(e.L&&P.lines)for(var a in e.L)Object.prototype.hasOwnProperty.call(e.L,a)&&(P.lines[a-1]=e.L[a]);p[s]=!0,0==--l&&i()},function(t){console.error(z+"> failed to load juz "+(s+1),t),p[s]=!0,0==--l&&i()})}))}else i()}function yt(t){if(!P.juz)return[];var e,r=[];if(null!=t.getAttribute("sura")&&null!=t.getAttribute("aya")){var n,a=B(t.getAttribute("sura"))[0],s=O(t.getAttribute("aya"));if(null!=t.getAttribute("words"))return[n=f(a,s[0]),(n+1)%P.juz.length];for(e=f(a,s[0]);e<=f(a,s[1]);e++)r.push(e)}else{if(null==t.getAttribute("page"))return[];var i=P.pages[parseInt(t.getAttribute("page"),10)-1];if(!i)return[];for(e=f(i[0],i[1]);e<=f(i[2],i[3]);e++)r.push(e)}return r}function vt(){const t=new FontFace(P.font_family,"url("+encodeURI(null==(e=P.font_url)||/^(https?:)?\/\//.test(e)?e:n+String(e).replace(/^\//,""))+")");var e;t.load().then(()=>{document.fonts.add(t)});class r extends HTMLElement{static get observedAttributes(){return["page","page_param","aya","sura","words","highlight","error","headless","quotes","inline","notitle","letters"]}constructor(){super(),this._data={}}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}get page(){return this.getAttribute("page")}set page(t){this._data.page=t}get page_param(){return this.getAttribute("page_param")}set page_param(t){this._data.page_param=t}get aya(){return this.getAttribute("aya")}set aya(t){this._data.aya=t}get sura(){return this.getAttribute("sura")}set sura(t){this._data.sura=t}get words(){return this.getAttribute("words")}set words(t){this._data.words=t}get highlight(){return this.getAttribute("highlight")}set highlight(t){this._data.highlight=t}get error(){return this.getAttribute("error")}set error(t){this._data.error=t}get letters(){return this.getAttribute("letters")}set letters(t){this._data.letters=t}get headless(){return this.getAttribute("headless")}set headless(t){this._data.headless=t}get quotes(){return this.getAttribute("quotes")}set quotes(t){this._data.quotes=t}get inline(){return this.getAttribute("inline")}set inline(t){this._data.inline=t}get notitle(){return this.getAttribute("notitle")}set notitle(t){this._data.notitle=t}render(e=this){var r;this._data.rendering||mt(yt(r=this),function(){if(!r._data.rendering){r._data.rendering=!0;try{e._qmhLetterShift=0;var t=x(r.letters);null!=r.letters&&null==t&&T("Bad letters parameter: "+r.letters),e._qmhLetters=t,r.doRender(e),k(e,t,e._qmhLetterShift)}finally{r._data.rendering=!1}}})}doRender(e){var r,n,a,s,t=null,i=null!=this.highlight?D(this.highlight):null,l=(null!=this.highlight&&null==i&&T("Bad highlight parameter: "+this.highlight),null!=this.error?D(this.error):null),o=(null!=this.error&&null==l&&T("Bad error parameter: "+this.error),this.page),u=H(this.headless),c=H(this.notitle),d=null!=this.quotes&&!H(this.quotes),h=this.inline,p=null!=this.sura&&null!=this.aya;if(p)y=g=B(this.sura)[0],a=!1,[m,v]=O(this.aya),null!=this.page&&T("Ignoring page parameter!"),o=P.suras[g].ayas[m].p;else{if(null==this.page)return console.error(z+"> Bad arguments: Not rendering!"),1;if(P.pages)var f=P.pages[o-1],g=f[0],m=f[1],y=f[2],v=f[3];else{for(v=m=y=g=0;P.suras[g].ayas.slice(-1)[0].p<o;)g+=1;for(y=g;y<114&&P.suras[y].ayas[0].p<=o;)y+=1;for(y-=1;P.suras[g].ayas[m].p<o;)m+=1;for(v=P.suras[y].ayas.length-1;P.suras[y].ayas[v].p>o;)v-=1}a=!0,null!=this.inline&&T("Ignoring inline parameter with page!")}if(null!=this.words)if(p){if(null!=(t=D(this.words)))return v!==m&&T("Ignoring aya range end with words parameter!"),500<t[1]-t[0]+1&&(T("words selection capped at 500 words"),t[1]=t[0]+499),void ct(e,g,m,t,u,d,h,c,i=F("highlight",i,t),l=F("error",l,t));T("Bad words parameter: "+this.words)}else T("Ignoring words parameter with page!");if(p&&Y(P.suras[y].ayas[v])!=o)s=2===m&&0<g?W(P.suras[g].ayas[1]):0,f=Z(g,m,v),c=function(t){return null==t?null:[t[0]+s,t[1]+s]},e._qmhLetterShift=s,i=c(F("highlight",i,[1,f])),l=c(F("error",l,[1,f])),ct(e,g,m,[s+1,s+f],u,d,h,!1,i,l);else{var t=p?Z(g,m,v):tt(g,m,y,v,parseInt(o,10)),i=F("highlight",i,[1,t]),l=F("error",l,[1,t]),w=null!=i||null!=l||null!=e._qmhLetters,b=(w&&M(e),J(),e.innerHTML="",e.removeAttribute("style"),a=V(h,a=(r=P.suras[g].ayas[m].r[0].l)!=(n=P.suras[y].ayas[v].r.slice(-1)[0].l)?!0:a),e.classList.toggle(z+"-inline",!a&&!d),a&&(st(e,o,u),u||e.appendChild(nt(P.suras[g].name))),m),E=g,C=0;for(let t=r;t<=n;t++){const $=t;var x=document.createElement("quran-madina-html-line"),q=(e.appendChild(x),a?(x.style.setProperty("display","block",""),G()&&it(x,parseInt(o,10),t)):(x.style.setProperty("font-family",P.font_family,""),x.style.setProperty("font-size",P.font_size+"px","")),a&&p&&t===r&&Q(x,K(g,o,r,m,-1)),g==y?v:P.suras[E].ayas.length-1);for(let t=b;t<=Math.min(b+5,q);t++){var A,_,k,L,S,I=P.suras[E].ayas[t];void 0!==I&&I.p==o&&(I=I.r.filter(t=>t.l==$)).length&&(a&<(x,I[0].s),A=document.createElement("div"),_=rt(E+1,t-1),DOMTokenList.prototype.add.apply(A.classList,_),w&&R(E,t)?(S=0<(k=j(E,t)?X(I[0]):0)?ut(C,k,null,i,l):{ligature:!1}).ligature?((L=document.createElement("span")).classList.add(z+"-word",z+"-basmala"),S.cls&&L.classList.add(z+"-word-"+S.cls),L.textContent=N,A.appendChild(L),C+=k):C=ot(A,I[0].t,null,C,i,l,I[0],x):G()&&R(E,t)?U(A,x,I[0]):A.textContent=!G()&&j(E,t)&&""!==I[0].t?N:I[0].t,A.style.cssText="display:inline",x.appendChild(A),et(_.slice(-1)[0]),at(e,_.slice(-1)[0],E+1,t-1),b=t,S=E<113?P.suras[E+1].ayas[0]:void 0,q<=b)&&void 0!==S&&S.p==o&&S.r[0].l==$+1&&(E+=1,b=0)}a&&p&&t===n&&Q(x,K(y,o,n,v,1))}}}}customElements.define(z,r)}function wt(){P.font_size=i,P.line_width_em=P.line_width,P.line_width=P.line_width*i,vt()}a((c=n+`assets/db/v2/${gt=r[d]||"Madina-"+d}/`)+"manifest.json",function(e){if(e.content_hash){var t="quran-madina-html:hash:"+c,r=null;try{r=sessionStorage.getItem(t)}catch(t){}null!==r&&r!==e.content_hash&&m(c);try{sessionStorage.setItem(t,e.content_hash)}catch(t){}}P={},Object.keys(e).forEach(function(t){"suras"!==t&&"n_pages"!==t&&(P[t]=e[t])}),P.suras=e.suras.map(function(t){return{name:t[0],ayas:new Array(t[1])}}),P.lines=new Array(e.n_pages),wt()},function(){c=null,a(n+`assets/db/v2/${gt}.json`,function(t){P=t,wt()},function(t){console.error(z+"> no v2 DB for layout "+d,t)})},!0)}();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quran-madina-html",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"grunt": "^1.6.2",
|
|
6
6
|
"grunt-contrib-clean": "^2.0.1",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"madina"
|
|
40
40
|
],
|
|
41
41
|
"author": "Tarek Eldeeb",
|
|
42
|
-
"license": "
|
|
42
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
43
43
|
"bugs": {
|
|
44
44
|
"url": "https://github.com/tarekeldeeb/quran-madina-html/issues"
|
|
45
45
|
},
|