5
Format Konten Teks
Materi tajwid di repository ini disimpan sebagai teks biasa, dan tata letaknya ditentukan oleh konvensi penulisan di dalam teks itu sendiri. Dua modul membaca konvensi tersebut: lessonLayout memecah satu materi menjadi Section yang berisi Part, sedangkan meetingPlan memecah satu pertemuan kelas menjadi langkah materi, drills, mushaf, dan task (src/lib/lesson-layout.ts:1-41, src/lib/meeting-plan.ts:1-112). Tidak ada schema per materi; yang harus dipatuhi penulis hanyalah bentuk baris dan pemisah blok.
graph TD
TEKS["content teks biasa"] --> BLOK["blok dipisah baris kosong"]
BLOK --> LL["lessonLayout"]
BLOK --> MP["meetingPlan"]
LL --> SEC["Section + Part"]
MP --> LANGKAH["MeetingStep"]
MP --> NOL["null"]
style TEKS fill:#f59e0b,color:#000
style BLOK fill:#f59e0b,color:#000
style LL fill:#2d7d46,color:#fff
style MP fill:#2d7d46,color:#fff
style SEC fill:#8b5cf6,color:#fff
style LANGKAH fill:#8b5cf6,color:#fff
style NOL fill:#dc2626,color:#fff
%% fig: Satu teks, dua parser
%% desc: Konten teks biasa dipotong menjadi blok, lalu diurai lessonLayout menjadi Section berisi Part atau oleh meetingPlan menjadi MeetingStep, dengan null untuk materi biasa.Blok dan baris
Konten dipotong pada satu baris kosong. Teks dipecah dengan \n\s*\n, tiap blok di-trim, dan blok kosong dibuang (src/lib/lesson-layout.ts:136-1393, src/lib/meeting-plan.ts:35-384). Di dalam satu blok, baris juga di-trim dan baris kosong diabaikan (src/lib/lesson-layout.ts:162-1655, src/lib/meeting-plan.ts:526).
Blok yang seluruh isinya aksara Arab langsung menjadi satu Part bertipe arabic dan tidak diurai per baris (src/lib/lesson-layout.ts:156-1607). Part yang mungkin muncul adalah union paragraph, lead, subheading, list, steps, numbered, symbols, examples, verse, fact, note, dan arabic, sementara butir di dalamnya memakai Item dengan number, term, text, examples, exampleText, dan points (src/lib/lesson-layout.ts:33-458, src/lib/lesson-layout.ts:299).
Bentuk baris dan Part yang dihasilkan
Urutan percabangan di dalam loop baris menentukan bentuk akhirnya: bullet, langkah lingkaran, contoh, penomoran angka, lalu catatan, fakta, simbol, lead, dan sisanya paragraf (src/lib/lesson-layout.ts:186-28410).
| Bentuk baris | Pengenal | Hasil |
|---|---|---|
• … | BULLET | list berisi Item, atau fact bila isinya label fakta |
① … sampai ⑳ … | STEP | steps, dengan forbidden dari lead sebelumnya |
1. … | NUMBERED | numbered; • sesudahnya menjadi points milik item terakhir |
Contoh: … atau Contoh (nun sukun · tanwin): | EXAMPLE | examples, atau lead plus nama columns |
Hukum: …, Panjangnya 4 atau 5 harakat. | FACT | fact dengan label dari factLabels |
Penting: …, Catatan: …, Cara membacanya: … | NOTE | note dengan NoteTone dari noteTone |
Qaf (ق): pangkal lidah terangkat. | TERM | term pada Item, atau symbols bila dibuka tanda Arab |
baris berakhir : | — | lead, sekaligus menyetel forbidden bila memuat kata larangan |
| baris lain | — | paragraph |
Setiap cabang dijaga tes. • menjadi list berisi term dan examples (tests/lesson-layout.test.ts:44-6011), Contoh (…): menamai kolom tabel contoh (tests/lesson-layout.test.ts:62-6812), forbidden menyala setelah lead yang melarang (tests/lesson-layout.test.ts:70-81), dan catatan, fakta, simbol, ayat, serta blok Arab dikenali berurutan (tests/lesson-layout.test.ts:83-97). Butir • di bawah item bernomor menempel sebagai points (tests/lesson-layout.test.ts:99-105).
Label fakta dipetakan ke bentuk pendek oleh factLabels, misalnya Hukumnya dan Hukum menjadi Hukum, Panjangnya menjadi Panjang (src/lib/lesson-layout.ts:59-6616). Label catatan dipetakan ke NoteTone oleh noteTone: Penting dan Ingat menjadi important, Catatan menjadi note, Cara membaca… menjadi howto, sisanya tip (src/lib/lesson-layout.ts:68-7317). TERM hanya menerima bagian sebelum : sepanjang 1–48 karakter (src/lib/lesson-layout.ts:5718), dan bagian itu tidak boleh berakhir tanda baca agar jadi term (src/lib/lesson-layout.ts:113-11419).
Sesudah semua baris dibaca, list yang seluruh itemnya aksara Arab murni diubah menjadi examples, dan list yang semua itemnya terbaca verseParts dipecah menjadi verse (src/lib/lesson-layout.ts:288-29520). Bagian tanpa parts, title, maupun group dibuang (src/lib/lesson-layout.ts:29721).
Judul, subjudul, dan grup
heading menolak baris yang dibuka bullet atau langkah, baris lebih dari 80 karakter, dan baris tanpa huruf Latin (src/lib/lesson-layout.ts:7922). Bentuk Hukum 1: … membaca nomor dan judul (src/lib/lesson-layout.ts:81-8223), A. … menjadi subheading (src/lib/lesson-layout.ts:85-86), sedangkan baris yang berakhir tanda baca atau memuat : bukan judul (src/lib/lesson-layout.ts:88). Sisanya dibaca sebagai 1. Judul atau judul polos (src/lib/lesson-layout.ts:90-91).
⚠️ Judul yang salah tulis tidak menimbulkan error: baris berakhiran titik atau memuat
:diam-diam menjadiparagraphbiasa (src/lib/lesson-layout.ts:8825). Baris lebih dari 80 karakter juga kehilangan status judul (src/lib/lesson-layout.ts:7922).
Bagian pertama selalu pengantar (src/lib/lesson-layout.ts:145-14627). id bagian di-slug dari judulnya: NFKD, diakritik dibuang, non-alfanumerik menjadi -, maksimum 48 karakter, duplikat diberi akhiran -2 dan seterusnya, dengan cadangan bagian (src/lib/lesson-layout.ts:119-13328). Paragraf pertama blok berupa ① Waqaf Idhthirari, karena terpaksa yang diikuti penjelasan membuka bagian bernomor 1 dan memakai sisa baris sebagai isi (src/lib/lesson-layout.ts:167-17529, tests/lesson-layout.test.ts:30-4230).
Blok yang hanya berisi judul dan diikuti blok berjudul lain menjadi group, bukan bagian baru (src/lib/lesson-layout.ts:176-18031). Tes pertama memeriksa pemisahan bagian, group, dan Rujukan: sekaligus (tests/lesson-layout.test.ts:7-2832).
Langkah pertemuan
meetingPlan memindai blok dengan STEP_HEADING (Materi, Latihan ayat), MUSHAF, dan TASK (src/lib/meeting-plan.ts:26-2933). Isi tiap langkah diurai oleh lessonLayout lewat pembungkus partsOf (src/lib/meeting-plan.ts:3134).
stateDiagram-v2
[*] --> Materi
Materi --> Materi: blok tanpa penanda langkah
Materi --> Drills: STEP_HEADING Latihan ayat
Materi --> Mushaf: baris MUSHAF
Materi --> Tugas: blok TASK
Materi --> Lain: blok lain berjudul
Drills --> Mushaf: baris MUSHAF
Mushaf --> Tugas: blok TASK
Tugas --> [*]
classDef jalur fill:#2d7d46,color:#fff
classDef turunan fill:#8b5cf6,color:#fff
classDef lainnya fill:#f59e0b,color:#000
class Materi,Tugas jalur
class Drills,Mushaf turunan
class Lain lainnya
%% fig: Perpindahan antar langkah pertemuan
%% desc: Setiap blok menambah isi Materi atau membuka langkah baru; urutan materi, drills, mushaf, tugas adalah bentuk yang dipakai tes.| Blok pembuka | Pengenal | MeetingStep |
|---|---|---|
Materi | STEP_HEADING | materi berisi Section hasil lessonLayout |
Latihan ayat | STEP_HEADING + DRILL | drills berisi Drill dengan surah, ayah, words, note |
Praktik mushaf: 603–604 | MUSHAF | mushaf dengan from, to, dan parts |
Tugas mandiri: … | TASK | task berisi satu text |
| blok lain | lessonLayout | other per Section, memakai title atau group |
Materi menampung blok berikutnya sampai penanda langkah baru muncul (src/lib/meeting-plan.ts:62-6535, tests/meeting-plan.test.ts:46-6336). Baris latihan berbentuk 1:2 | kata | catatan dibaca DRILL; baris yang tidak cocok masuk ke intro (src/lib/meeting-plan.ts:82-92, tests/meeting-plan.test.ts:65-69). MUSHAF menerima tanda pisah – atau -, dan nomor tunggal berarti satu halaman (src/lib/meeting-plan.ts:75-80, tests/meeting-plan.test.ts:35-44). Tugas mandiri: mengambil seluruh sisa blok sebagai teks tugas (src/lib/meeting-plan.ts:69-73, tests/meeting-plan.test.ts:21-33). Blok di luar materi seperti Bentuk ujian tetap disimpan sebagai langkah bertajuk (src/lib/meeting-plan.ts:94-96).
⚠️
meetingPlanmengembalikannullbila tidak ada satu pun langkahdrills,mushaf, atautask(src/lib/meeting-plan.ts:10044). Materi tajwid biasa seperti itu bukan pertemuan, sehingga tidak punya langkah yang bisa ditampilkan (tests/meeting-plan.test.ts:71-7345).
mushafRange membentang from sampai to, meetingPages mengumpulkan seluruh halaman, dan meetingDrills mengumpulkan seluruh ayat latihan (src/lib/meeting-plan.ts:104-11446). Daftar itu dipakai ulang oleh skrip data Qur'an, yang memakai pola baris yang sama untuk Praktik mushaf: dan 1:2 | … (scripts/build-quran-data.mjs:101-10747); rinciannya ada di Data Qur'an dan Mushaf. Seluruh 26 pertemuan yang di-seed wajib lolos pemeriksaan ini (tests/meeting-plan.test.ts:90-9948).
Aksara Arab, contoh, dan ayat
isArabicOnly menandai teks yang hanya berisi aksara Arab tanpa kata Latin, dan itulah syarat banyak cabang di atas (src/lib/lesson-layout.ts:6-1049). exampleGroups memakai · sebagai pemisah kelompok atau kolom dan ، sebagai pemisah kata di dalam kelompok (src/lib/lesson-layout.ts:13-1950). verseParts memisahkan kutipan dari rujukannya, misalnya … (Al-Baqarah: 2) menjadi arabic dan reference, dan mengembalikan null untuk teks Latin (src/lib/lesson-layout.ts:22-2751). Kedua helper ini diuji langsung (tests/lesson-layout.test.ts:109-11752).
Di sisi tampilan, arabicRuns memotong teks menjadi potongan bertanda arabic agar rentetan aksara Arab bisa disetel dengan typeface Arab tanpa memotong kalimat Latin di sekitarnya (src/lib/lesson-layout.ts:301-30853, tests/lesson-layout.test.ts:119-12554). Cara komponen memakainya dijelaskan di Komponen UI Pelajaran.
Rujukan dan batas angka
Blok terakhir yang dibuka Rujukan: diambil sebagai source dan dikeluarkan dari daftar blok, pada kedua parser (src/lib/lesson-layout.ts:14255, src/lib/meeting-plan.ts:4156). Nilainya diverifikasi tes sebagai layout.source dan plan.source (tests/lesson-layout.test.ts:7-2832, tests/meeting-plan.test.ts:21-3342).
| Batas | Nilai | Rujukan |
|---|---|---|
| panjang baris maksimum agar jadi judul | 80 karakter | src/lib/lesson-layout.ts:7922 |
panjang term sebelum : | 1–48 karakter | src/lib/lesson-layout.ts:5718 |
panjang id bagian | 48 karakter | src/lib/lesson-layout.ts:119-13328 |
panjang baris latihan surah dan ayah | 1–3 digit | src/lib/meeting-plan.ts:26-2933 |
kecepatan readingMinutes | 180 kata per menit, minimal 1 menit | src/lib/lesson-layout.ts:311-31357 |
readingMinutes membulatkan jumlah kata dibagi 180 dan tidak pernah menghasilkan nol (src/lib/lesson-layout.ts:311-31357, tests/lesson-layout.test.ts:127-13058).