6
Data Qur'an dan Mushaf
src/data/quran.json bukan salinan Al-Qur'an lengkap. Berkas itu hanya memuat ayat yang dipakai kelas Lanjutan: ayat yang dilatih dan seluruh ayat pada halaman mushaf yang dipraktikkan, ditambah data surah untuk ayat-ayat tersebut. src/data/quran.json:1-81
Batas yang sama ditulis di komentar src/lib/quran.ts: berkas JSON menyimpan ayat latihan dan halaman mushaf, sedangkan scripts/build-quran-data.mjs membangunnya ulang dari teks Kemenag. src/lib/quran.ts:3-42
Isi berkas data
| Kunci | Isi | Rujukan |
|---|---|---|
surahs | satu objek per surah terpakai dengan nameArabic, nameLatin, ayahCount, dan location | src/data/quran.json:2-83 |
ayahs | larik ayat; tiap ayat memuat id, surahNumber, number, juz, page, dan arabic | src/data/quran.json:334-3424 |
Larik ayahs hanya berisi ayat yang lolos penyaringan, jadi id tidak berurutan tanpa celah: Al-Fātiḥah hanya menyisakan id 1, 2, 4, dan 6. src/data/quran.json:335-3625
src/lib/quran.ts mengimpor berkas JSON itu di tingkat modul, mengambil quran.surahs sebagai peta surah, lalu menempelkan data surah ke setiap ayat sehingga PageAyah selalu membawa nameArabic dan nameLatin. src/lib/quran.ts:1-126
Alur npm run quran:build
Perintah itu hanya alias satu baris ke skrip Node. package.json:197
npm run quran:build -- alquran/surah.csv
Skrip berhenti lebih dulu bila path CSV tidak diberikan; pesannya menyebut contoh pemakaian dan proses keluar dengan kode 1. scripts/build-quran-data.mjs:10-178
sequenceDiagram
participant CLI as npm run quran:build
participant Script as build-quran-data.mjs
participant CSV as surah.csv
participant Materi as tajwid-pertemuan.ts
participant Out as quran.json
CLI->>Script: node scripts/build-quran-data.mjs + path CSV
Script->>CSV: readFileSync(csvPath)
Script->>Script: parseCsv(teks)
Script->>Script: surahs Map + ayahs dengan juz, page, arabic
Script->>Script: validasi 114 surah dan 6236 ayat
alt data tidak valid
Script-->>CLI: process.exit(1) Data tidak valid
end
Script->>Materi: baca baris Praktik mushaf dan baris latihan ayat
Script->>Script: filter ayat halaman dan ayat latihan
alt latihan ayat tanpa teks
Script-->>CLI: process.exit(1) Ayat latihan tidak ditemukan
end
Script->>Out: writeFileSync({ surahs, ayahs })
Script-->>CLI: console.log jumlah ayat tersimpan
style Script fill:#f59e0b,color:#000
style CSV fill:#336791,color:#fff
style Out fill:#336791,color:#fff
style Materi fill:#8b5cf6,color:#fff
%% fig: Siklus npm run quran:build
%% desc: Skrip mengurai surah.csv, memvalidasi jumlah surah dan ayat, menyaring ayat yang dipakai materi Lanjutan, lalu menulis src/data/quran.json.surah.csv dibaca dengan parser RFC 4180 buatan sendiri (parseCsv) karena field berisi kutip bisa memuat koma, kutip ganda, dan baris baru; BOM di awal berkas dibuang sebelum header diurai. scripts/build-quran-data.mjs:19-589 scripts/build-quran-data.mjs:60-6310
Setiap record dipetakan menjadi satu entri peta surahs (nama Arab, nama Latin, jumlah ayat, lokasi) dan satu elemen ayahs dengan id, surahNumber, number, juz, page, serta arabic. scripts/build-quran-data.mjs:65-8511
README mencatat urutan pengambilan dataset dari Kaggle sebelum build: unduh alquran.zip, ekstrak, lalu jalankan npm run quran:build -- alquran/surah.csv. README.md:30-4112
Ayat yang disaring masuk berkas
Skrip membaca src/data/tajwid-pertemuan.ts sebagai teks, bukan mengimpornya. Dua pola regex mengambil nomor halaman dari baris Praktik mushaf: dan pasangan surah:ayat dari baris latihan ayat. scripts/build-quran-data.mjs:101-10713
Format kedua baris itu dijelaskan di header berkas materi: satu baris per ayat berbentuk surah:ayat | kata yang diperhatikan | catatan, dan nomor halaman mengikuti mushaf Madinah 15 baris (604 halaman; Juz 30 = halaman 582–604). src/data/tajwid-pertemuan.ts:5-814
Ayat yang dipertahankan adalah ayat yang page-nya ada di himpunan pages atau pasangan surah:ayat-nya ada di himpunan drills. Sesudah itu setiap drill diperiksa ulang agar tidak ada latihan tanpa teks. scripts/build-quran-data.mjs:109-11415
Validasi sebelum menulis
Tiga pemeriksaan menahan penulisan berkas: jumlah surah harus 114, jumlah ayat harus 6236, dan setiap ayat harus punya id, number, juz, page berupa integer serta arabic yang tidak kosong. scripts/build-quran-data.mjs:87-9516
| Kondisi | Pesan yang dicetak | Rujukan |
|---|---|---|
| path CSV tidak diberikan | Sertakan path ke surah.csv, misalnya: npm run quran:build -- ./alquran/surah.csv | scripts/build-quran-data.mjs:14-1717 |
| jumlah surah bukan 114 | jumlah surah ${surahs.size}, seharusnya 114 | scripts/build-quran-data.mjs:88-8918 |
| jumlah ayat bukan 6236 | jumlah ayat ${ayahs.length}, seharusnya 6236 | scripts/build-quran-data.mjs:9019 |
| field ayat tidak lengkap | ayat ${ayah.surahNumber}:${number} tidak lengkap | scripts/build-quran-data.mjs:91-9520 |
| ada temuan | Data tidak valid: diikuti maksimal 20 temuan pertama, lalu process.exit(1) | scripts/build-quran-data.mjs:96-9921 |
| latihan ayat tanpa teks | Ayat latihan tidak ditemukan: ... | scripts/build-quran-data.mjs:110-11422 |
Setelah semua pemeriksaan lolos, skrip menimpa seluruh berkas dengan writeFileSync dan JSON.stringify indentasi satu spasi, lalu mencetak jumlah ayat, halaman mushaf, dan drill yang tersimpan. scripts/build-quran-data.mjs:116-11923
⚠️ Skrip menimpa
src/data/quran.jsonsepenuhnya. Setiap suntingan manual pada berkas JSON itu hilang pada build berikutnya; ubah barisPraktik mushafatau latihan ayat di materi Lanjutan, lalu jalankan ulang perintah build. src/data/tajwid-pertemuan.ts:7-824
Membaca data saat render
graph LR
JSON["src/data/quran.json"] --> Q["src/lib/quran.ts"]
Q --> R["route /lanjutan/:slug"]
Q --> VIEW["MushafPageView"]
M["src/lib/mushaf.ts"] --> VIEW
M --> TEXT["QuranText"]
T["tests/quran.test.ts"] --> Q
T --> M
style JSON fill:#336791,color:#fff
style Q fill:#8b5cf6,color:#fff
style M fill:#8b5cf6,color:#fff
style R fill:#2d7d46,color:#fff
style VIEW fill:#2d7d46,color:#fff
style TEXT fill:#2d7d46,color:#fff
style T fill:#f59e0b,color:#000
%% fig: Pembaca data Qur'an dan helper mushaf
%% desc: quran.ts membaca quran.json dan menyuapi route Lanjutan serta MushafPageView, mushaf.ts menyuapi teks ayat dan halaman cetak, dan tests menguji keduanya.Dua fungsi di src/lib/quran.ts menjadi pintu masuk data ayat:
| Fungsi | Rujukan | Perilaku |
|---|---|---|
listPagesAyahs(pages) | src/lib/quran.ts:14-1925 | memfilter ayat yang page-nya termasuk himpunan pages; urutan mushaf terjaga karena ayahs sudah terurut |
listAyahsByRef(refs) | src/lib/quran.ts:21-2426 | memfilter pasangan { surah, ayah }; pasangan yang tidak ada di data dilewati |
Halaman pelajaran Lanjutan memanggil keduanya dari rencana pertemuan: meetingDrills(plan) menjadi argumen listAyahsByRef, dan meetingPages(plan) menjadi argumen listPagesAyahs. src/app/lanjutan/[slug]/page.tsx:44-4727
Kedua pengambil nomor itu hanya meratakan langkah rencana: meetingPages mengambil semua langkah berjenis mushaf lewat mushafRange, sedangkan meetingDrills mengambil semua step.drills. src/lib/meeting-plan.ts:106-11428
Rincian penyajian ayat dan halamannya ada di Komponen UI Pelajaran.
Menyiapkan teks mushaf
src/lib/mushaf.ts tidak membaca berkas data mana pun; isinya helper penyiapan teks yang dipakai komponen.
| Fungsi | Rujukan | Perilaku |
|---|---|---|
toArabicDigits(value) | src/lib/mushaf.ts:3-829 | mengganti setiap digit Latin dengan digit Arab-Indic |
pauseSegments(text) | src/lib/mushaf.ts:12-3430 | memecah teks ayat di sekitar tanda waqaf |
groupBySurah(ayahs) | src/lib/mushaf.ts:36-4631 | mengelompokkan ayat berurutan yang berasal dari surah sama |
showsBismillah(surahNumber) | src/lib/mushaf.ts:48-5032 | false hanya untuk surah 1 dan 9 |
pauseSegments memisahkan tanda waqaf U+06D6–U+06DC dan U+08D6 karena di dalam teks tanda itu berupa combining mark yang tidak bisa dikecilkan terpisah dari hurufnya; setiap segmen menyimpan lead, word, dan pause. src/lib/mushaf.ts:12-1833
Satu pengecualian penting: mim iqlab U+06E2 juga muncul setelah spasi, tetapi milik tanwin sebelumnya, jadi spasi di depannya dibuang agar mim menempel pada kata yang benar. src/lib/mushaf.ts:19-2034
Tanda waqaf hasil pemecahan digambar oleh QuranText sebagai elemen kecil di atas celah setelah katanya, sehingga lebar celah tidak berubah. src/components/quran-text.tsx:8-2435
MushafPageView memakai tiga helper: groupBySurah untuk memisahkan pembuka tiap surah src/components/mushaf/mushaf-page-view.tsx:59-6136, showsBismillah untuk menahan basmalah pada surah 1 dan 9 src/components/mushaf/mushaf-page-view.tsx:3437, dan toArabicDigits untuk nomor halaman src/components/mushaf/mushaf-page-view.tsx:79-8338.
Pengujian
tests/quran.test.ts menjaga dua sisi sekaligus: isi berkas data dan perilaku helper.
listPagesAyahs([603, 604])dimulai dari surah 109 ayat 1 di halaman 603 dan berakhir di surah 114 ayat 6 di halaman 604;idkeluar dalam urutan naik. tests/quran.test.ts:8-1339listAyahsByRefmelewati pasangan yang tidak ada di data, misalnya surah 9 ayat 999. tests/quran.test.ts:16-2340- Setiap pertemuan Tajwid harus menemukan seluruh ayat latihannya dan minimal satu ayat pada setiap halaman mushaf yang dipraktikkan. tests/quran.test.ts:25-3341
- Basmalah tidak diminta untuk surah 1 dan 9. tests/quran.test.ts:36-4042
- Digit Arab-Indic serta pemecahan tanda waqaf, termasuk penempelan mim iqlab. tests/quran.test.ts:42-6343
groupBySurahmemecah deret 112, 112, 113 menjadi dua kelompok. tests/quran.test.ts:65-7144
Langkah verifikasi menyeluruh ada di Pengujian dan Deploy.