npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

quran-madina-html

v1.0.1

Published

A Madina Quran HTML Renderer without images.

Readme

Quran Madina Html (no-images)

npm version License: ISC CodeQL pylint py_test npm-grunt Socket Badge

A Quran renderer for the browser that looks like the printed Madina Mushaf — without a single image. Every glyph is real, selectable, copy-pasteable text laid out with pure HTML/CSS, wrapped in one custom element:

<quran-madina-html sura="2" aya="255"></quran-madina-html>

See it live → (view the page source too — GitHub strips <script> tags from this README, so the tag can't render here, but it's just as simple as the snippet above once it's on your own page.)

Why

  • Pixel-faithful to the printed Madina Mushaf — same line breaks, same justification, same page layout.
  • Pure HTML/CSS, no images — text stays selectable, searchable, and copy-pasteable; pages load fast.
  • One HTML tag — no build step, no framework required.
  • Any font — Hafs, Uthman, Amiri Quran (plain or tajweed-colored), or your own.
  • Word-level addressing — render any word range, even across ayas, pages, and suras.

See it in action

Page 106, rendered by the library next to a scan of the actual printed page:

One engine, any font

The same JSON-driven layout engine re-flows for whichever font you point it at — data-font="Hafs" (default), Uthman, Amiri Quran, Amiri Quran Colored (tajweed rules color-coded), or the bundled me_quran.

Verse ranges — framed or frameless

sura/aya renders just the ayat you ask for, laid out exactly as they sit on the Madina page. By default you get a header (sura name + copy/translate icons); add headless="true" to strip that chrome and keep only the Quran text:

<quran-madina-html sura="5" aya="1-2">
</quran-madina-html>
<quran-madina-html sura="5" aya="1-2"
  headless="true">
</quran-madina-html>

Word-level selection

The words attribute picks out a word range — 1-based, inclusive — and hides the rest of the text in place, so the original Madina line justification is preserved instead of being reflowed. Counting continues past the end of the given aya, so a selection can cross aya, page, and even sura boundaries:

<quran-madina-html sura="1" aya="1"
  words="1:2">
</quran-madina-html>

first two words of Al-Fatiha; the dashed outline marks the hidden remainder of the line

<quran-madina-html sura="1" aya="7"
  words="1-14">
</quran-madina-html>

words 1-14 counted from Al-Fatiha's last aya spill into Surat Al-Baqara — its basmala counts as words 10-13

Highlighting words

highlight (soft yellow) and error (soft red) mark a word range — same 1-based, inclusive format as words — on top of whatever is being shown. Unlike words, they work with or without a words selection, and even on a full page render:

<quran-madina-html sura="1" aya="1" highlight="2-3"></quran-madina-html>

Getting Started

Installation

Install via npm:

npm install quran-madina-html

Or include directly via CDN script tag in your HTML <head>:

<script type="text/javascript" src="https://unpkg.com/quran-madina-html"></script>
  • Supported data-name parameters are: Madina05 (default), others are under development (Shemerly, Qaloon, Newer Madina)
  • Supported data-font parameters are: Hafs (default), Uthman, Amiri Quran, Amiri Quran Colored
  • Other options include: data-font-size which defaults to 16 (px). Any size from 6 to 100 works: 16 and 24 have pre-built databases, and every other size is fitted at load time by linear interpolation between those two anchors (page/line width interpolated, letter stretching re-scaled accordingly)

Then in your body, just add the tag.

<quran-madina-html sura="2" aya="8-10"></quran-madina-html>

If the selected aya(s) fit on a single line, the default is to generate an inline <span> element, otherwise a <div> is generated.

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.

Changed in 0.9.0: the basmala used to be a never counted decoration; a cross-sura words index now lands 4 words later than in 0.8.x.

Changed in 0.9.3: a words walk anchored at a sura's aya 1 now counts that sura's own basmala too (0.9.0–0.9.2 only counted crossed-into basmalas, so aya-1-anchored word indices landed 4 words early relative to the Tanzil flat indexing).

Changed in 0.9.5: a words walk that runs past the end of An-Nas now wraps around to Al-Fatiha and keeps counting (previously it stopped, silently truncating the selection); Al-Fatiha's title stays uncounted decoration, and its basmala — being its real aya 1 — renders as normal aya words.

<quran-madina-html sura="1" aya="1" words="1:2"></quran-madina-html>  <!-- first two words only -->
<quran-madina-html sura="1" aya="1" words="3-10"></quran-madina-html> <!-- words 3..10, spanning ayas 1-3 -->
<quran-madina-html sura="1" aya="7" words="1-14"></quran-madina-html> <!-- spans Al-Fatiha into Al-Baqara:
                                                                           9 words + 4 basmala words + الٓمٓ -->

The words attribute is ignored when rendering a full page.

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:

<quran-madina-html sura="1" aya="7" words="1-14" notitle="true"></quran-madina-html>

Highlighting and marking words

Two more range attributes lay a visual mark over a sub-range of whatever is being shown — highlight (soft yellow) and error (soft red) — using the same 1-based, inclusive range format as words (start-end, start:end, or a single index). Unlike words, they work in every render mode: alongside a words selection, on a plain sura/aya verse (counted from that aya's first word), and even on a full page render (counted from the page's first aya — a page never starts mid-aya, so this is always well-defined). A range must fall entirely within whatever is actually displayed (the words selection if one is set, otherwise the whole verse/page); an out-of-range or malformed value is ignored with a console warning rather than breaking the render. When highlight and error overlap on the same word, error wins.

<quran-madina-html sura="1" aya="7" words="1-14" highlight="10-13" error="1-2"></quran-madina-html>
<quran-madina-html sura="2" aya="255" highlight="5-8"></quran-madina-html> <!-- no words needed -->
<quran-madina-html page="2" error="1-4"></quran-madina-html> <!-- counted from the page's first aya -->

Colors come from the --qmh-highlight/--qmh-error CSS custom properties on quran-madina-html (defaults: soft yellow/soft red) — override them, or the .quran-madina-html-word-highlight/.quran-madina-html-word-error classes directly, from your own stylesheet.

Another option exists to render a complete quran page:

<quran-madina-html page="106"></quran-madina-html>

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:

<quran-madina-html sura="2" aya="8-10" headless="true"></quran-madina-html> <!-- no header -->

Attributes Reference

| Attribute | Type | Default | Description | |---|---|---|---| | sura | number \| string | - | Sura number (1–114). Required when using aya. | | aya | number \| string | - | Single aya or verse range (e.g., 255, "8-10"). | | page | number \| string | - | Full Mushaf page number (1–604). Mutually exclusive with sura/aya. | | words | string | - | 1-based word index or range (e.g., "1:2", "3-10", or single index "5"). | | highlight | string | - | 1-based word range to mark soft yellow (same format as words). Works with or without words, and with page too. | | error | string | - | 1-based word range to mark soft red (same format as words). Wins over highlight on overlap. | | headless | boolean \| string | false | Set to "true" to remove top sura header chrome and copy/translate icons. | | notitle | boolean \| string | false | Set to "true" to hide sura name text while retaining title frame decoration. | | data-font | string | "Hafs" | Font family: Hafs, Uthman, Amiri Quran, Amiri Quran Colored, me_quran. | | data-name | string | "Madina05" | Layout database dataset name. | | data-font-size | number \| string | 16 | Font size in px (6–100; interpolated between 16 and 24). |

React wrapper

For React apps (web, or mobile via a Capacitor WebView), use @tarekeldeeb/quran-madina-react, a thin component wrapping the <quran-madina-html> tag — lives in this repo's react/ folder and is released in lockstep with this package.

npm install @tarekeldeeb/quran-madina-react react
import QuranMadinaHtml from "@tarekeldeeb/quran-madina-react";

<QuranMadinaHtml page={106} font="Hafs" />

See react/README.md for the full prop reference and the Capacitor (iOS/Android) packaging guide.

Dev Setup

The project is published on npm npm install quran-madina-html, with sources, assets and distributables. Alternatively, you can fork this repo, then clone it.

apt install python3-distutils nodejs npm chromium-driver
npm install // install components and scripts
npm run build-db // build all json Db files
npm run release // build the dist with dependencies

Demo

https://tarekeldeeb.github.io/quran-madina-html/demo/index.html

Don't forget to see the page source!