prpm-dbp 0.18.1 → 0.20.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/SKILL.md +44 -154
- package/bin/cli.js +25 -0
- package/package.json +1 -1
- package/src/gate.js +210 -0
- package/src/semak.js +49 -0
- package/src/tukar.js +14 -5
package/SKILL.md
CHANGED
|
@@ -30,6 +30,50 @@ Semuanya kata lazim dalam bahan Pendidikan Islam. Setiap satu ada jawapan tegas
|
|
|
30
30
|
|
|
31
31
|
Alat untuk menangkap kesemuanya ada di tangan agen itu sepanjang masa. Ia tidak pernah dijalankan ke atas teks Rumi keluarannya sendiri. Kedua-dua pusingan ditemui kerana **pengguna bertanya**, bukan kerana proses menangkapnya.
|
|
32
32
|
|
|
33
|
+
`gate` menyemak **kedua-dua tulisan dalam panggilan yang sama**. Versi terdahulu menyemak Rumi sahaja, jadi dokumen Jawi penuh melepasinya tanpa satu aduan pun — tepat jenis dokumen yang alat ini paling diperlukan.
|
|
34
|
+
|
|
35
|
+
Empat perkara yang ditangkap dalam teks Jawi:
|
|
36
|
+
|
|
37
|
+
| Keadaan | Contoh | Keputusan |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| ruang tersasar di dalam perkataan | `ݢول وڠن` | **ralat**, cadang `ݢولوڠن` |
|
|
40
|
+
| ejaan tiada dalam DBP | `منجاوهكن` | **ralat**, cadang `منجاءوهکن` |
|
|
41
|
+
| homograf tulen | `سنة` | tidak dapat disahkan, dua bacaan |
|
|
42
|
+
| petikan Arab | `الشِّمال` | tidak dapat disahkan, §11.1 |
|
|
43
|
+
|
|
44
|
+
Ruang tersasar itu kes paling berbahaya. Separuh perkataan boleh **berjaya secara palsu**: `ݢول` benar-benar memetakan kepada dua perkataan DBP tulen, `gol` dan `gul`. Penukar yang memilih calon paling kerap akan mengeluarkan "gol" dengan yakin, dan separuh perkataan hilang tanpa sesiapa perasan. Sebab itu percantuman dicuba apabila **salah satu** jiran belum selesai, bukan kedua-duanya.
|
|
45
|
+
|
|
46
|
+
## Teks Arab dan al-Quran TIDAK PERNAH ditukar
|
|
47
|
+
|
|
48
|
+
Pedoman §11.1: petikan al-Quran, hadis, nama surah, nama tokoh dan nama tempat **kekal ejaan Arab asalnya**. Ia tidak ditransliterasi ke Rumi dan tidak pernah dicadangkan pembetulan ejaan Melayu.
|
|
49
|
+
|
|
50
|
+
Ini bukan teori. `الدين` (ad-Din) memetakan kepada dua entri dalam data, jadi penukar lama mengeluarkan `addin|al-din` untuk teks Arab tulen dan pembaca tidak nampak apa-apa salah.
|
|
51
|
+
|
|
52
|
+
Dua isyarat automatik, kedua-duanya diukur pada 66,323 ejaan Jawi DBP sebenar:
|
|
53
|
+
|
|
54
|
+
| Isyarat | Padanan palsu | Contoh dilindungi |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| tanda baris (harakat) | **0** | `إِنَّ ٱللَّهَ مَعَ ٱلصَّٰبِرِينَ` |
|
|
57
|
+
| `أ` atau `آ` di awal | 5 (0.008%) | `أصحاب` |
|
|
58
|
+
| `ال` di awal, tidak dikenali | — | `اليمين`, `المقربون`, `الفاتحة` |
|
|
59
|
+
|
|
60
|
+
Petikan al-Quran datang bertanda baris dalam amalan biasa, jadi ia dilindungi tanpa apa-apa persediaan.
|
|
61
|
+
|
|
62
|
+
**Istilah Arab telanjang** — yang tiada tanda baris dan padan sesuatu dalam kamus, seperti `الدين` — diisytihar sekali:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx prpm-dbp nama ad-din الدين --jenis arab
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Selepas itu ia tidak disentuh lagi, dalam `rumi` mahupun `gate`.
|
|
69
|
+
|
|
70
|
+
**Dua perkara yang sengaja TIDAK dibuat**, kedua-duanya diuji dan ditolak:
|
|
71
|
+
|
|
72
|
+
1. **Rentang Arab tidak merebak kepada jiran.** Kelihatan betul sehingga diuji: satu ejaan Melayu yang salah di sebelah petikan al-Quran tidak dapat dibezakan daripada satu perkataan Arab di sebelah petikan al-Quran, jadi `منجاوهكن` diserap dan kesilapan sebenar hilang. Mendiamkan ralat tulen lebih buruk daripada menandakan satu perkataan Arab yang jarang.
|
|
73
|
+
2. **Jaminan DBP tidak dituntut untuk mengatasi isyarat `ال`.** Ia membekukan 325 daripada 346 perkataan ber-`ال`, termasuk `alah`, `alaf` dan `alabaster`, yang alif-lamnya sebahagian perkataan dan bukan kata sandang. Ortografi sahaja tidak dapat membezakannya.
|
|
74
|
+
|
|
75
|
+
Nama khas Arab tanpa kata sandang `ال` (`أصحاب`, nama tokoh, nama tempat) tidak dapat disahkan kamus Melayu. Isytiharkannya melalui `npx prpm-dbp nama <rumi> <jawi> --jenis arab`; selepas itu ia berhenti menjadi ralat, tetapi tetap **bukan** lulus DBP.
|
|
76
|
+
|
|
33
77
|
`gate` keluar dengan kod 1 apabila ada ralat, jadi ia boleh dipasang sebagai hook atau langkah CI. Peraturan yang bergantung pada agen ingat sendiri akan gagal, dan gagal secara senyap.
|
|
34
78
|
|
|
35
79
|
## Kuatkuasa automatik
|
|
@@ -237,83 +281,6 @@ Ejaan yang disimpan begini ditandakan datang daripada pengguna, bukan daripada D
|
|
|
237
281
|
|
|
238
282
|
Bagi nama berasal Arab, ejaan Jawinya memang ejaan Arab asal, jadi ia nampak seperti dikekalkan. Bagi nama bukan Arab ia ditransliterasi penuh: `Kuala Lumpur` menjadi `کوالا لومڤور`.
|
|
239
283
|
|
|
240
|
-
## Sebelum menghantar apa-apa
|
|
241
|
-
|
|
242
|
-
Jalankan `npx prpm-dbp gate <fail> --luar-talian` ke atas **keseluruhan teks**. Bukan sebahagian. Bukan perkataan yang anda rasa berisiko.
|
|
243
|
-
|
|
244
|
-
Ejaan yang salah ialah tepat ejaan yang anda **tidak** syak. Kalau anda syak, anda sudah menyemaknya.
|
|
245
|
-
|
|
246
|
-
Ini termasuk ejaan yang anda tulis dalam **kod, ujian dan dokumentasi**, bukan hanya dalam teks untuk pengguna. Semasa membina pakej ini sendiri, satu nilai Jawi ditulis ke dalam ujian daripada ingatan tanpa disemak. Nilainya kebetulan betul. Kebetulan bukan proses.
|
|
247
|
-
|
|
248
|
-
**Apa yang berlaku apabila langkah ini dilangkau:**
|
|
249
|
-
|
|
250
|
-
Satu agen menggunakan skill ini sepanjang sesi penuh untuk menukar Jawi ke Rumi, kemudian menghantar 549 kad RPH Pendidikan Islam ke pangkalan data produksi dengan **273 ejaan yang salah**.
|
|
251
|
-
|
|
252
|
-
```
|
|
253
|
-
pusingan 1 sunnah x206, hadith x16, fardhu x2 -> masuk produksi
|
|
254
|
-
pusingan 2 tayammum, dhuha, qadha, redha, iddah x90 -> masuk produksi
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
Semuanya kata lazim dalam bahan Pendidikan Islam. Setiap satu ada jawapan tegas dalam PRPM: `sunnah` ialah rujukan silang ke `sunah`, `hadith` sepatutnya `hadis`, `fardhu` sepatutnya `fardu`, `tayammum` sepatutnya `tayamum`, `dhuha` sepatutnya `duha`, `qadha` sepatutnya `qada`.
|
|
258
|
-
|
|
259
|
-
Alat untuk menangkap kesemuanya ada di tangan agen itu sepanjang masa. Ia tidak pernah dijalankan ke atas teks Rumi keluarannya sendiri. Kedua-dua pusingan ditemui kerana **pengguna bertanya**, bukan kerana proses menangkapnya.
|
|
260
|
-
|
|
261
|
-
`gate` keluar dengan kod 1 apabila ada ralat, jadi ia boleh dipasang sebagai hook atau langkah CI. Peraturan yang bergantung pada agen ingat sendiri akan gagal, dan gagal secara senyap.
|
|
262
|
-
|
|
263
|
-
## Kuatkuasa automatik
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
npx prpm-dbp install --hook
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
Memasang hook PostToolUse yang menjalankan `gate --luar-talian` ke atas setiap fail `.md`, `.txt` atau `.json` yang ditulis atau disunting. Ia **melaporkan** ralat kepada agen tanpa menyekat tulisan: menyekat atas kamus yang tidak lengkap akan menghalang kerja yang sah, manakala melaporkan sudah memadai kerana agen membaca output hook.
|
|
270
|
-
|
|
271
|
-
Untuk menampal sendiri: `npx prpm-dbp hook-json`.
|
|
272
|
-
|
|
273
|
-
Panaskan cache **sekali** semasa pemasangan, bukan semasa gate berjalan:
|
|
274
|
-
|
|
275
|
-
```bash
|
|
276
|
-
npx prpm-dbp warm kosa-kata-projek.txt
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
Gate atas cache panas mengambil 0.19 saat bagi 406 perkataan. Itu cukup pantas untuk setiap penyuntingan. Gate yang perlahan akan dimatikan orang.
|
|
280
|
-
|
|
281
|
-
## Tiga keadaan gate, bukan dua
|
|
282
|
-
|
|
283
|
-
| Medan | Maksud | Kesan |
|
|
284
|
-
|---|---|---|
|
|
285
|
-
| `lulusDbp` | ada dalam PRPM, ejaan padan | — |
|
|
286
|
-
| `ralat` | ada dalam PRPM dengan ejaan lain, entri rujukan silang `®`, atau tiada dalam PRPM mahupun dataset | **exit 1** |
|
|
287
|
-
| `tidakDapatDisahkan` | tiada dalam cache, nama khas, akronim, atau tiada entri PRPM tetapi wujud dalam dataset | dilapor; exit 1 jika melebihi `--ambang` |
|
|
288
|
-
|
|
289
|
-
`tidakDapatDisahkan` **tidak pernah lulus senyap**. Gate yang lulus atas cache sejuk memberi jaminan palsu, dan itu lebih bahaya daripada tiada gate. Gunakan `--ambang 10` supaya cache sejuk menggagalkan gate.
|
|
290
|
-
|
|
291
|
-
PRPM tiada entri untuk kata tugas paling asas: `dan`, `di`, `ke`, `yang`, `atau`. Menandakannya sebagai ralat menjadikan gate mustahil dipakai. Pembezanya bersumber, bukan senarai putih: kata tugas itu **semua** wujud dalam dataset, manakala `hadith`, `fardhu`, `tayammum`, `dhuha`, `qadha`, `redha` dan `iddah` **tiada satu pun**.
|
|
292
|
-
|
|
293
|
-
## Prosedur wajib
|
|
294
|
-
|
|
295
|
-
Ikut ini setiap kali, jangan langkau langkah.
|
|
296
|
-
|
|
297
|
-
**Menulis Jawi daripada Rumi:**
|
|
298
|
-
|
|
299
|
-
1. `npx prpm-dbp jawi <fail> --luar-talian --homograf --json`
|
|
300
|
-
2. Baca `belumDisahkan` dan `namaKhas`. Jangan reka ejaan untuknya. Sahkan dengan `lookup`, atau tanya pengguna, atau tandakan dalam hasil akhir.
|
|
301
|
-
3. Baca `mencurigakan`. Setiap satu bermakna PRPM sendiri mungkin tersilap. Semak di pautan yang diberi sebelum menggunakannya.
|
|
302
|
-
4. Baca `homograf`. Beritahu pengguna perkataan mana yang akan taksa apabila dibaca.
|
|
303
|
-
5. Laporkan `semuanyaDbp`. Jika `false`, nyatakan bahagian mana bukan daripada sumber rasmi.
|
|
304
|
-
|
|
305
|
-
**Merumikan daripada Jawi:**
|
|
306
|
-
|
|
307
|
-
1. `npx prpm-dbp rumi <fail> --pilih --konteks --json`
|
|
308
|
-
2. Untuk **setiap** item dalam `kabur`: baca ayat yang mengandunginya, baca makna setiap calon, tentukan yang mana sesuai.
|
|
309
|
-
3. Jika `dipilih` salah bagi ayat itu, **gantikan** dalam hasil akhir. Kekerapan kalah kepada konteks.
|
|
310
|
-
4. Nyatakan kepada pengguna berapa banyak kekaburan wujud dan mana yang anda ubah.
|
|
311
|
-
5. `tidakDikenali` bermakna perkataan itu tiada dalam cache. Jalankan `warm` di luar talian, bukan tinggalkan bertanda.
|
|
312
|
-
|
|
313
|
-
**Berhenti dan tanya pengguna apabila:** ejaan `mencurigakan` mengubah makna, nama khas tiada rujukan bertulis, atau dua calon sama-sama munasabah dalam ayat itu.
|
|
314
|
-
|
|
315
|
-
Semua perintah menyokong `--json`, jadi langkah di atas boleh dibuat secara berulang tanpa menghurai teks.
|
|
316
|
-
|
|
317
284
|
## Peraturan Pedoman DBP
|
|
318
285
|
|
|
319
286
|
Satu fail sahaja dalam pakej ini **menjana** ejaan dan bukan mencarinya: `src/pedoman.js`. Ia dibenarkan kerana setiap peraturan di dalamnya datang daripada *Pedoman Umum Ejaan Jawi Bahasa Melayu* terbitan DBP, dan dirujuk pada seksyennya.
|
|
@@ -425,83 +392,6 @@ Dua puluh dua kes kabur yang tinggal itu sah: `قلقله` boleh dibaca `qalqala
|
|
|
425
392
|
|
|
426
393
|
**Sifar perkataan hilang atau rosak.**
|
|
427
394
|
|
|
428
|
-
## Sebelum menghantar apa-apa
|
|
429
|
-
|
|
430
|
-
Jalankan `npx prpm-dbp gate <fail> --luar-talian` ke atas **keseluruhan teks**. Bukan sebahagian. Bukan perkataan yang anda rasa berisiko.
|
|
431
|
-
|
|
432
|
-
Ejaan yang salah ialah tepat ejaan yang anda **tidak** syak. Kalau anda syak, anda sudah menyemaknya.
|
|
433
|
-
|
|
434
|
-
Ini termasuk ejaan yang anda tulis dalam **kod, ujian dan dokumentasi**, bukan hanya dalam teks untuk pengguna. Semasa membina pakej ini sendiri, satu nilai Jawi ditulis ke dalam ujian daripada ingatan tanpa disemak. Nilainya kebetulan betul. Kebetulan bukan proses.
|
|
435
|
-
|
|
436
|
-
**Apa yang berlaku apabila langkah ini dilangkau:**
|
|
437
|
-
|
|
438
|
-
Satu agen menggunakan skill ini sepanjang sesi penuh untuk menukar Jawi ke Rumi, kemudian menghantar 549 kad RPH Pendidikan Islam ke pangkalan data produksi dengan **273 ejaan yang salah**.
|
|
439
|
-
|
|
440
|
-
```
|
|
441
|
-
pusingan 1 sunnah x206, hadith x16, fardhu x2 -> masuk produksi
|
|
442
|
-
pusingan 2 tayammum, dhuha, qadha, redha, iddah x90 -> masuk produksi
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
Semuanya kata lazim dalam bahan Pendidikan Islam. Setiap satu ada jawapan tegas dalam PRPM: `sunnah` ialah rujukan silang ke `sunah`, `hadith` sepatutnya `hadis`, `fardhu` sepatutnya `fardu`, `tayammum` sepatutnya `tayamum`, `dhuha` sepatutnya `duha`, `qadha` sepatutnya `qada`.
|
|
446
|
-
|
|
447
|
-
Alat untuk menangkap kesemuanya ada di tangan agen itu sepanjang masa. Ia tidak pernah dijalankan ke atas teks Rumi keluarannya sendiri. Kedua-dua pusingan ditemui kerana **pengguna bertanya**, bukan kerana proses menangkapnya.
|
|
448
|
-
|
|
449
|
-
`gate` keluar dengan kod 1 apabila ada ralat, jadi ia boleh dipasang sebagai hook atau langkah CI. Peraturan yang bergantung pada agen ingat sendiri akan gagal, dan gagal secara senyap.
|
|
450
|
-
|
|
451
|
-
## Kuatkuasa automatik
|
|
452
|
-
|
|
453
|
-
```bash
|
|
454
|
-
npx prpm-dbp install --hook
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
Memasang hook PostToolUse yang menjalankan `gate --luar-talian` ke atas setiap fail `.md`, `.txt` atau `.json` yang ditulis atau disunting. Ia **melaporkan** ralat kepada agen tanpa menyekat tulisan: menyekat atas kamus yang tidak lengkap akan menghalang kerja yang sah, manakala melaporkan sudah memadai kerana agen membaca output hook.
|
|
458
|
-
|
|
459
|
-
Untuk menampal sendiri: `npx prpm-dbp hook-json`.
|
|
460
|
-
|
|
461
|
-
Panaskan cache **sekali** semasa pemasangan, bukan semasa gate berjalan:
|
|
462
|
-
|
|
463
|
-
```bash
|
|
464
|
-
npx prpm-dbp warm kosa-kata-projek.txt
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
Gate atas cache panas mengambil 0.19 saat bagi 406 perkataan. Itu cukup pantas untuk setiap penyuntingan. Gate yang perlahan akan dimatikan orang.
|
|
468
|
-
|
|
469
|
-
## Tiga keadaan gate, bukan dua
|
|
470
|
-
|
|
471
|
-
| Medan | Maksud | Kesan |
|
|
472
|
-
|---|---|---|
|
|
473
|
-
| `lulusDbp` | ada dalam PRPM, ejaan padan | — |
|
|
474
|
-
| `ralat` | ada dalam PRPM dengan ejaan lain, entri rujukan silang `®`, atau tiada dalam PRPM mahupun dataset | **exit 1** |
|
|
475
|
-
| `tidakDapatDisahkan` | tiada dalam cache, nama khas, akronim, atau tiada entri PRPM tetapi wujud dalam dataset | dilapor; exit 1 jika melebihi `--ambang` |
|
|
476
|
-
|
|
477
|
-
`tidakDapatDisahkan` **tidak pernah lulus senyap**. Gate yang lulus atas cache sejuk memberi jaminan palsu, dan itu lebih bahaya daripada tiada gate. Gunakan `--ambang 10` supaya cache sejuk menggagalkan gate.
|
|
478
|
-
|
|
479
|
-
PRPM tiada entri untuk kata tugas paling asas: `dan`, `di`, `ke`, `yang`, `atau`. Menandakannya sebagai ralat menjadikan gate mustahil dipakai. Pembezanya bersumber, bukan senarai putih: kata tugas itu **semua** wujud dalam dataset, manakala `hadith`, `fardhu`, `tayammum`, `dhuha`, `qadha`, `redha` dan `iddah` **tiada satu pun**.
|
|
480
|
-
|
|
481
|
-
## Prosedur wajib
|
|
482
|
-
|
|
483
|
-
Ikut ini setiap kali, jangan langkau langkah.
|
|
484
|
-
|
|
485
|
-
**Menulis Jawi daripada Rumi:**
|
|
486
|
-
|
|
487
|
-
1. `npx prpm-dbp jawi <fail> --luar-talian --homograf --json`
|
|
488
|
-
2. Baca `belumDisahkan` dan `namaKhas`. Jangan reka ejaan untuknya. Sahkan dengan `lookup`, atau tanya pengguna, atau tandakan dalam hasil akhir.
|
|
489
|
-
3. Baca `mencurigakan`. Setiap satu bermakna PRPM sendiri mungkin tersilap. Semak di pautan yang diberi sebelum menggunakannya.
|
|
490
|
-
4. Baca `homograf`. Beritahu pengguna perkataan mana yang akan taksa apabila dibaca.
|
|
491
|
-
5. Laporkan `semuanyaDbp`. Jika `false`, nyatakan bahagian mana bukan daripada sumber rasmi.
|
|
492
|
-
|
|
493
|
-
**Merumikan daripada Jawi:**
|
|
494
|
-
|
|
495
|
-
1. `npx prpm-dbp rumi <fail> --pilih --konteks --json`
|
|
496
|
-
2. Untuk **setiap** item dalam `kabur`: baca ayat yang mengandunginya, baca makna setiap calon, tentukan yang mana sesuai.
|
|
497
|
-
3. Jika `dipilih` salah bagi ayat itu, **gantikan** dalam hasil akhir. Kekerapan kalah kepada konteks.
|
|
498
|
-
4. Nyatakan kepada pengguna berapa banyak kekaburan wujud dan mana yang anda ubah.
|
|
499
|
-
5. `tidakDikenali` bermakna perkataan itu tiada dalam cache. Jalankan `warm` di luar talian, bukan tinggalkan bertanda.
|
|
500
|
-
|
|
501
|
-
**Berhenti dan tanya pengguna apabila:** ejaan `mencurigakan` mengubah makna, nama khas tiada rujukan bertulis, atau dua calon sama-sama munasabah dalam ayat itu.
|
|
502
|
-
|
|
503
|
-
Semua perintah menyokong `--json`, jadi langkah di atas boleh dibuat secara berulang tanpa menghurai teks.
|
|
504
|
-
|
|
505
395
|
## Peraturan yang sengaja TIDAK dilaksanakan
|
|
506
396
|
|
|
507
397
|
| Seksyen | Sebab |
|
package/bin/cli.js
CHANGED
|
@@ -7,6 +7,17 @@ import { banding, cariKamus } from '../src/kamus.js'
|
|
|
7
7
|
import { keJawi, keRumi, semakJawi } from '../src/tukar.js'
|
|
8
8
|
import { huraiTsv, muatDataset, simpanDataset } from '../src/dataset.js'
|
|
9
9
|
import { NAMA_PATH, muatNama, tambahNama } from '../src/nama.js'
|
|
10
|
+
|
|
11
|
+
// Istilah Arab yang pengguna sahkan sendiri. Petikan al-Quran datang
|
|
12
|
+
// bertanda baris dalam amalan biasa dan dikenali automatik; istilah
|
|
13
|
+
// telanjang seperti الدين diisytihar sekali di sini dan tidak pernah
|
|
14
|
+
// ditransliterasi lagi, dalam `rumi` mahupun `gate`.
|
|
15
|
+
const arabDiisytiharkan = async () =>
|
|
16
|
+
new Set(
|
|
17
|
+
Object.values(await muatNama())
|
|
18
|
+
.filter((n) => n?.jenis === 'arab' && n.jawi)
|
|
19
|
+
.map((n) => n.jawi),
|
|
20
|
+
)
|
|
10
21
|
import { gate, kodKeluar } from '../src/gate.js'
|
|
11
22
|
import {
|
|
12
23
|
CACHE_PATH,
|
|
@@ -252,6 +263,7 @@ async function main() {
|
|
|
252
263
|
pilihLazim: pilihan.pilih,
|
|
253
264
|
padanRangka: pilihan.rangka,
|
|
254
265
|
glosari: pilihan.glosari ? JSON.parse(await readFile(pilihan.glosari, 'utf8')) : null,
|
|
266
|
+
arabDiisytihar: await arabDiisytiharkan(),
|
|
255
267
|
})
|
|
256
268
|
if (pilihan.json) { keluar(h); break }
|
|
257
269
|
console.log(h.teks)
|
|
@@ -318,6 +330,19 @@ async function main() {
|
|
|
318
330
|
for (const fail of baki) {
|
|
319
331
|
const laporan = await gate(await readFile(fail, 'utf8'), cache, {
|
|
320
332
|
...opts,
|
|
333
|
+
// Dataset MESTI dimuatkan. Tanpanya peta songsang menyusut daripada
|
|
334
|
+
// 64k ejaan kepada saiz cache sahaja, dan kata tugas paling asas
|
|
335
|
+
// seperti دان dilaporkan sebagai ejaan Jawi yang salah.
|
|
336
|
+
dataset: await muatDataset(),
|
|
337
|
+
// Nama khas Arab (nama surah, tokoh, tempat) tidak boleh disahkan
|
|
338
|
+
// kamus Melayu. Yang sudah diisytihar melalui `nama` diambil kira
|
|
339
|
+
// supaya pengisytiharan itu benar-benar bermakna.
|
|
340
|
+
namaJawi: new Set(
|
|
341
|
+
Object.values(await muatNama())
|
|
342
|
+
.map((n) => n?.jawi)
|
|
343
|
+
.filter(Boolean),
|
|
344
|
+
),
|
|
345
|
+
arabDiisytihar: await arabDiisytiharkan(),
|
|
321
346
|
luarTalian: pilihan.luarTalian !== false,
|
|
322
347
|
abai,
|
|
323
348
|
})
|
package/package.json
CHANGED
package/src/gate.js
CHANGED
|
@@ -14,13 +14,216 @@
|
|
|
14
14
|
* TIGA keadaan, bukan dua. `tidakDapatDisahkan` TIDAK PERNAH lulus senyap:
|
|
15
15
|
* gate yang lulus atas cache sejuk memberi jaminan palsu, dan itu lebih
|
|
16
16
|
* bahaya daripada tiada gate.
|
|
17
|
+
*
|
|
18
|
+
* Versi pertama menyemak Rumi SAHAJA. Regexnya `[A-Za-zÀ-ÿ]` bermakna
|
|
19
|
+
* dokumen Jawi penuh melepasi hook tanpa satu aduan pun — tepat jenis
|
|
20
|
+
* dokumen yang skill ini paling diperlukan. Sebaris teks pelajaran dengan
|
|
21
|
+
* `ݢول وڠن` (golongan dengan ruang tersasar di tengahnya) dan `منجاوهكن`
|
|
22
|
+
* (menjauhkan tanpa hamzah) lulus sepenuhnya. Gate kini menyemak
|
|
23
|
+
* kedua-dua tulisan.
|
|
17
24
|
*/
|
|
18
25
|
|
|
19
26
|
import { lookup } from './prpm.js'
|
|
20
27
|
import { mungkinAkronim, mungkinNamaKhas } from './nama.js'
|
|
21
28
|
import { cariDataset } from './dataset.js'
|
|
29
|
+
import { normalisasiJawi } from './kamus.js'
|
|
30
|
+
import { jarakHuruf, petaSongsang } from './tukar.js'
|
|
31
|
+
import { pisahUlangJawi } from './pedoman.js'
|
|
32
|
+
import { isyaratArab, rangkaKonsonan } from './semak.js'
|
|
22
33
|
|
|
23
34
|
const TOKEN_RUMI = /([A-Za-zÀ-ÿ][A-Za-zÀ-ÿ'-]*)/g
|
|
35
|
+
const TOKEN_JAWI = /([-ۿݐ-ݿﭐ-﷿ﹰ-]+)/g
|
|
36
|
+
|
|
37
|
+
// Baris tanda vokal Arab. Jawi Melayu tidak menggunakannya; petikan al-Quran
|
|
38
|
+
// dan hadis dalam dokumen Melayu menggunakannya. Kehadirannya bermakna
|
|
39
|
+
// potongan itu bahasa Arab, yang Pedoman §11.1 kata kekalkan seadanya.
|
|
40
|
+
const HARAKAT = /[ً-ْٰٓ-ٕ]/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Semak token Jawi terhadap peta songsang DBP.
|
|
44
|
+
*
|
|
45
|
+
* Yang paling penting di sini ialah pengesanan RUANG TERSASAR. Sebuah
|
|
46
|
+
* perkataan yang terbelah dua boleh gagal dengan LANTANG pada satu separuh
|
|
47
|
+
* dan BERJAYA SECARA PALSU pada separuh yang lain: `ݢولوڠن` (golongan)
|
|
48
|
+
* yang terbelah menjadi `ݢول` + `وڠن` meninggalkan `ݢول`, yang benar-benar
|
|
49
|
+
* memetakan kepada dua perkataan DBP tulen, gol dan gul. Penukar yang
|
|
50
|
+
* memilih calon paling kerap akan mengeluarkan "gol" dengan penuh yakin,
|
|
51
|
+
* dan separuh perkataan hilang tanpa sesiapa perasan.
|
|
52
|
+
*
|
|
53
|
+
* Sebab itu percantuman dicuba apabila SALAH SATU jiran tidak dapat
|
|
54
|
+
* diselesaikan. Menuntut kedua-duanya gagal akan terlepas kes ini justeru
|
|
55
|
+
* kerana separuh pertama "berjaya".
|
|
56
|
+
*/
|
|
57
|
+
export function gateJawi(teks, cache, opts = {}) {
|
|
58
|
+
const { dataset = null, abai = new Set(), namaJawi = new Set(), arabDiisytihar = new Set() } = opts
|
|
59
|
+
const peta = petaSongsang(cache, dataset)
|
|
60
|
+
|
|
61
|
+
// Indeks rangka konsonan, dibina sekali. Ejaan yang tersalah biasanya
|
|
62
|
+
// berbeza hanya pada vokal atau hamzah — منجاوهكن lawan منجاءوهکن — jadi
|
|
63
|
+
// rangkanya kekal sama dan ejaan DBP yang betul boleh dinamakan terus.
|
|
64
|
+
// Melaporkan "tiada dalam DBP" sahaja menyerahkan kerja mencari kepada
|
|
65
|
+
// pembaca; melaporkan ejaan sebenar menutup jurang itu.
|
|
66
|
+
const rangka = new Map()
|
|
67
|
+
for (const [kunci, slot] of peta) {
|
|
68
|
+
if (!slot.layak.length) continue
|
|
69
|
+
const r = rangkaKonsonan(kunci)
|
|
70
|
+
if (!r) continue
|
|
71
|
+
if (!rangka.has(r)) rangka.set(r, [])
|
|
72
|
+
rangka.get(r).push({ jawi: kunci, rumi: slot.layak[0] })
|
|
73
|
+
}
|
|
74
|
+
const cadang = (t) => {
|
|
75
|
+
const senarai = rangka.get(rangkaKonsonan(t)) ?? []
|
|
76
|
+
if (!senarai.length) return null
|
|
77
|
+
const terbaik = senarai
|
|
78
|
+
.map((c) => ({ ...c, jarak: jarakHuruf(normalisasiJawi(t), c.jawi) }))
|
|
79
|
+
.sort((a, b) => a.jarak - b.jarak)[0]
|
|
80
|
+
// Jarak besar bermakna ia perkataan lain sepenuhnya yang kebetulan
|
|
81
|
+
// berkongsi rangka, bukan salah eja. Cadangan begitu mengelirukan.
|
|
82
|
+
return terbaik.jarak <= 3 ? terbaik : null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const lulusDbp = []
|
|
86
|
+
const ralat = []
|
|
87
|
+
const tidakDapatDisahkan = []
|
|
88
|
+
const dilihat = new Set()
|
|
89
|
+
|
|
90
|
+
const bahagian = teks.split(TOKEN_JAWI)
|
|
91
|
+
const token = []
|
|
92
|
+
for (const [i, cebis] of bahagian.entries()) {
|
|
93
|
+
if (i % 2 === 1) token.push({ teks: cebis, i })
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Pemisah antara dua token mesti ruang tulen sebelum percantuman dicuba.
|
|
97
|
+
// Tanda baca, petikan atau baris baru antara mereka bermakna ia memang
|
|
98
|
+
// dua perkataan berasingan, bukan satu yang terbelah.
|
|
99
|
+
const ruangSahaja = (a, b) => /^[ \t ]*$/.test(bahagian.slice(a + 1, b).join(''))
|
|
100
|
+
|
|
101
|
+
// §17.1: kata ulang penuh ialah kata dasar + angka dua Arab. `اوسها٢`
|
|
102
|
+
// ialah usaha-usaha, dan kata dasarnya yang ada dalam kamus, bukan bentuk
|
|
103
|
+
// berangka itu. Tanpa langkah ini setiap kata ulang dalam dokumen jadi
|
|
104
|
+
// ralat palsu.
|
|
105
|
+
const cari = (t) => {
|
|
106
|
+
const langsung = peta.get(normalisasiJawi(t))
|
|
107
|
+
if (langsung) return langsung
|
|
108
|
+
const dasar = pisahUlangJawi(t)
|
|
109
|
+
return dasar ? (peta.get(normalisasiJawi(dasar)) ?? null) : null
|
|
110
|
+
}
|
|
111
|
+
const selesai = (t) => {
|
|
112
|
+
const m = cari(t)
|
|
113
|
+
return m ? m.layak.length === 1 : false
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ── Kesan rentang Arab SEBELUM apa-apa dinilai ────────────────────────
|
|
117
|
+
//
|
|
118
|
+
// Pedoman §11.1: petikan al-Quran, hadis, nama surah, nama tokoh dan nama
|
|
119
|
+
// tempat KEKAL ejaan Arab asalnya. Ia tidak boleh disemak dengan kamus
|
|
120
|
+
// Melayu, dan lebih penting lagi ia tidak boleh DICADANGKAN pembetulan.
|
|
121
|
+
// Gate hanya melapor, tetapi agen yang membaca "guna اصحاب" akan menyunting
|
|
122
|
+
// ayat al-Quran. Mencadangkan pembetulan pada teks wahyu lebih teruk
|
|
123
|
+
// daripada tidak menyemaknya langsung.
|
|
124
|
+
//
|
|
125
|
+
// Diukur pada 66,323 ejaan Jawi DBP sebenar:
|
|
126
|
+
// harakat 0 padanan -> isyarat sempurna
|
|
127
|
+
// `أ` di awal 4 padanan -> 0.006%, dan keempat-empatnya larut sendiri
|
|
128
|
+
// `إ` di awal 7 padanan -> termasuk إسلام, jadi BUKAN isyarat
|
|
129
|
+
// `ال` di awal 360 padanan -> hanya berguna bersama syarat tidak larut
|
|
130
|
+
const benihArab = (t) => isyaratArab(t, (x) => Boolean(cari(x)), arabDiisytihar)
|
|
131
|
+
|
|
132
|
+
const arab = new Set()
|
|
133
|
+
for (const tok of token) if (benihArab(tok.teks)) arab.add(tok.i)
|
|
134
|
+
|
|
135
|
+
// Rentang Arab SENGAJA TIDAK merebak kepada jiran. Percubaan merebak
|
|
136
|
+
// melalui ruang kepada token yang tidak larut kelihatan betul sehingga
|
|
137
|
+
// diuji: satu ejaan Melayu yang salah di sebelah petikan al-Quran tidak
|
|
138
|
+
// dapat dibezakan daripada satu perkataan Arab di sebelah petikan
|
|
139
|
+
// al-Quran, jadi منجاوهكن diserap dan kesilapan sebenar hilang.
|
|
140
|
+
//
|
|
141
|
+
// Mendiamkan ralat tulen lebih buruk daripada menandakan satu perkataan
|
|
142
|
+
// Arab yang jarang. Setiap token mesti membawa isyaratnya sendiri.
|
|
143
|
+
// Petikan al-Quran datang bertanda baris dalam amalan biasa, jadi ia
|
|
144
|
+
// dilindungi; apa yang tidak, diisytihar melalui `nama` atau `--abai`.
|
|
145
|
+
|
|
146
|
+
for (const [n, tok] of token.entries()) {
|
|
147
|
+
const t = tok.teks
|
|
148
|
+
if (abai.has(t) || abai.has(normalisasiJawi(t))) continue
|
|
149
|
+
|
|
150
|
+
if (arab.has(tok.i)) {
|
|
151
|
+
// Bukan lulus DBP: kamus Melayu tidak mengesahkannya. Bukan ralat:
|
|
152
|
+
// ejaan Arab asal memang betul. Ia keadaan ketiga, dan TIADA cadangan
|
|
153
|
+
// pembetulan dikeluarkan untuknya.
|
|
154
|
+
if (!dilihat.has(t)) {
|
|
155
|
+
dilihat.add(t)
|
|
156
|
+
tidakDapatDisahkan.push({ kata: t, sebab: 'teks Arab, kekalkan seadanya (Pedoman §11.1)' })
|
|
157
|
+
}
|
|
158
|
+
continue
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const m = cari(t)
|
|
162
|
+
|
|
163
|
+
// Cuba cantum dengan jiran SEBELUM melaporkan apa-apa, kerana ruang
|
|
164
|
+
// tersasar mencemarkan kedua-dua separuh sekali gus.
|
|
165
|
+
const seterusnya = token[n + 1]
|
|
166
|
+
if (seterusnya && !arab.has(seterusnya.i) && ruangSahaja(tok.i, seterusnya.i)) {
|
|
167
|
+
const belumSelesai = !selesai(t) || !selesai(seterusnya.teks)
|
|
168
|
+
if (belumSelesai) {
|
|
169
|
+
const gabung = cari(t + seterusnya.teks)
|
|
170
|
+
if (gabung?.layak.length) {
|
|
171
|
+
const kunci = t + ' ' + seterusnya.teks
|
|
172
|
+
if (!dilihat.has(kunci)) {
|
|
173
|
+
dilihat.add(kunci)
|
|
174
|
+
ralat.push({
|
|
175
|
+
kata: kunci,
|
|
176
|
+
sebab: 'ruang tersasar di dalam perkataan',
|
|
177
|
+
sepatutnya: t + seterusnya.teks,
|
|
178
|
+
bacaan: gabung.layak[0],
|
|
179
|
+
})
|
|
180
|
+
}
|
|
181
|
+
dilihat.add(t)
|
|
182
|
+
dilihat.add(seterusnya.teks)
|
|
183
|
+
continue
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (dilihat.has(t)) continue
|
|
189
|
+
dilihat.add(t)
|
|
190
|
+
|
|
191
|
+
if (!m) {
|
|
192
|
+
// Nama khas yang SUDAH diisytihar pengguna bukan ralat. Ia tetap bukan
|
|
193
|
+
// lulus DBP — kamus Melayu tidak mengesahkannya — jadi ia keadaan
|
|
194
|
+
// ketiga, dan pembaca nampak apa yang tidak disemak.
|
|
195
|
+
if (namaJawi.has(t) || namaJawi.has(normalisasiJawi(t))) {
|
|
196
|
+
tidakDapatDisahkan.push({ kata: t, sebab: 'nama khas diisytihar pengguna' })
|
|
197
|
+
continue
|
|
198
|
+
}
|
|
199
|
+
const c = cadang(t)
|
|
200
|
+
ralat.push({
|
|
201
|
+
kata: t,
|
|
202
|
+
sebab: 'ejaan Jawi tiada dalam DBP mahupun dataset',
|
|
203
|
+
...(c ? { sepatutnya: c.jawi, bacaan: c.rumi } : {}),
|
|
204
|
+
})
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
if (m.layak.length === 1) {
|
|
208
|
+
lulusDbp.push(t)
|
|
209
|
+
continue
|
|
210
|
+
}
|
|
211
|
+
if (m.layak.length > 1) {
|
|
212
|
+
// Homograf tulen. Ejaannya SAH; hanya bacaannya perlu konteks. Ini
|
|
213
|
+
// bukan ralat, dan menandakannya begitu akan menggagalkan setiap
|
|
214
|
+
// dokumen yang mengandungi سنة.
|
|
215
|
+
tidakDapatDisahkan.push({ kata: t, sebab: `homograf, ${m.layak.length} bacaan DBP`, calon: m.layak })
|
|
216
|
+
continue
|
|
217
|
+
}
|
|
218
|
+
if (m.entah.length) {
|
|
219
|
+
tidakDapatDisahkan.push({ kata: t, sebab: 'hanya dalam dataset, bukan DBP', calon: m.entah })
|
|
220
|
+
continue
|
|
221
|
+
}
|
|
222
|
+
ralat.push({ kata: t, sebab: 'hanya padan bentuk rujukan silang DBP', calon: m.tolak })
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return { lulusDbp, ralat, tidakDapatDisahkan }
|
|
226
|
+
}
|
|
24
227
|
|
|
25
228
|
/**
|
|
26
229
|
* Semak teks Rumi. Setiap perkataan jatuh ke dalam SATU daripada tiga baldi.
|
|
@@ -114,6 +317,13 @@ export async function gate(teks, cache, opts = {}) {
|
|
|
114
317
|
lulusDbp.push(kata)
|
|
115
318
|
}
|
|
116
319
|
|
|
320
|
+
// Jawi disemak dalam panggilan yang SAMA. Kalau ia perintah berasingan,
|
|
321
|
+
// ia jadi langkah yang boleh dilupakan, dan itu punca kegagalan asal.
|
|
322
|
+
const j = gateJawi(teks, cache, opts)
|
|
323
|
+
lulusDbp.push(...j.lulusDbp)
|
|
324
|
+
ralat.push(...j.ralat.map((r) => ({ ...r, tulisan: 'jawi' })))
|
|
325
|
+
tidakDapatDisahkan.push(...j.tidakDapatDisahkan.map((r) => ({ ...r, tulisan: 'jawi' })))
|
|
326
|
+
|
|
117
327
|
const jumlah = lulusDbp.length + ralat.length + tidakDapatDisahkan.length
|
|
118
328
|
const peratusTidakSah = jumlah ? Math.round((tidakDapatDisahkan.length / jumlah) * 100) : 0
|
|
119
329
|
|
package/src/semak.js
CHANGED
|
@@ -152,3 +152,52 @@ export function rangkaKonsonan(jawi) {
|
|
|
152
152
|
if (keluar && HUJUNG_SETARA.has(keluar.slice(-1))) keluar = keluar.slice(0, -1) + 'ه'
|
|
153
153
|
return keluar
|
|
154
154
|
}
|
|
155
|
+
|
|
156
|
+
// ── Pengesan teks Arab ────────────────────────────────────────────────────
|
|
157
|
+
//
|
|
158
|
+
// Pedoman DBP §11.1: petikan al-Quran, hadis, nama surah, nama tokoh dan
|
|
159
|
+
// nama tempat KEKAL ejaan Arab asalnya. Ia tidak boleh ditransliterasi ke
|
|
160
|
+
// Rumi dan tidak boleh dicadangkan pembetulan ejaan Melayu.
|
|
161
|
+
//
|
|
162
|
+
// Ini bukan sekadar teori. `الدين` (ad-Din) memetakan kepada dua entri Jawi
|
|
163
|
+
// dalam data DBP, jadi tanpa pemeriksaan ini penukar mengeluarkan
|
|
164
|
+
// "addin|al-din" untuk teks Arab dan pembaca tidak nampak apa-apa salah.
|
|
165
|
+
//
|
|
166
|
+
// Diukur pada 66,323 ejaan Jawi DBP sebenar:
|
|
167
|
+
// harakat 0 padanan -> isyarat sempurna
|
|
168
|
+
// `أ` `آ` awal 5 padanan -> 0.008%
|
|
169
|
+
// `ال` awal 360 padanan -> berguna HANYA bersama syarat tidak larut
|
|
170
|
+
// `إ` awal 7 padanan -> termasuk إسلام, jadi BUKAN isyarat
|
|
171
|
+
const HARAKAT = /[ً-ْٰٓ-ٕ]/
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {string} token satu perkataan Jawi/Arab
|
|
175
|
+
* @param {(t: string) => boolean} larut adakah token ini dikenali sebagai
|
|
176
|
+
* kata Melayu langsung
|
|
177
|
+
* @param {Set<string>} diisytihar istilah Arab yang pengguna sahkan sendiri
|
|
178
|
+
*
|
|
179
|
+
* Menuntut jaminan DBP lapisan 1 untuk mengatasi isyarat `ال` telah diuji
|
|
180
|
+
* dan DITOLAK: ia membekukan 325 daripada 346 perkataan ber-`ال`, termasuk
|
|
181
|
+
* alah, alaf dan alabaster, yang alif-lamnya sebahagian perkataan dan bukan
|
|
182
|
+
* kata sandang. Ortografi sahaja tidak dapat membezakannya.
|
|
183
|
+
*
|
|
184
|
+
* Yang tinggal ialah dua isyarat yang benar-benar bersih, ditambah
|
|
185
|
+
* pengisytiharan pengguna. Petikan al-Quran datang bertanda baris dalam
|
|
186
|
+
* amalan biasa; istilah Arab telanjang seperti `الدين` diisytihar sekali
|
|
187
|
+
* melalui simpanan `nama --jenis arab` dan tidak pernah disentuh lagi.
|
|
188
|
+
*
|
|
189
|
+
* Isyarat sengaja per-token dan TIDAK merebak kepada jiran. Percubaan
|
|
190
|
+
* merebak melalui ruang kelihatan betul sehingga diuji: satu ejaan Melayu
|
|
191
|
+
* yang salah di sebelah petikan al-Quran tidak dapat dibezakan daripada satu
|
|
192
|
+
* perkataan Arab di sebelah petikan al-Quran, jadi ralat tulen diserap dan
|
|
193
|
+
* hilang. Mendiamkan kesilapan sebenar lebih buruk daripada menandakan satu
|
|
194
|
+
* perkataan Arab yang jarang.
|
|
195
|
+
*/
|
|
196
|
+
export function isyaratArab(token, larut = () => false, diisytihar = new Set()) {
|
|
197
|
+
if (HARAKAT.test(token)) return 'harakat'
|
|
198
|
+
if (diisytihar.has(token)) return 'diisytihar pengguna'
|
|
199
|
+
if (larut(token)) return null
|
|
200
|
+
if (/^[أآ]/.test(token)) return 'hamzah awal'
|
|
201
|
+
if (/^ال/.test(token)) return 'kata sandang'
|
|
202
|
+
return null
|
|
203
|
+
}
|
package/src/tukar.js
CHANGED
|
@@ -12,7 +12,7 @@ import { lookup } from './prpm.js'
|
|
|
12
12
|
import { normalisasiJawi } from './kamus.js'
|
|
13
13
|
import { cariDataset, muatDataset } from './dataset.js'
|
|
14
14
|
import { cariNama, mungkinAkronim, mungkinNamaKhas } from './nama.js'
|
|
15
|
-
import { rangkaKonsonan, semakHurufAkhir } from './semak.js'
|
|
15
|
+
import { isyaratArab, rangkaKonsonan, semakHurufAkhir } from './semak.js'
|
|
16
16
|
import {
|
|
17
17
|
imbuhAkhiranAn,
|
|
18
18
|
imbuhAkhiranKan,
|
|
@@ -170,7 +170,7 @@ export async function cariDasar(kata, cache, opts = {}) {
|
|
|
170
170
|
* dan ia mengalahkan سورة (surah) yang sebenarnya betul. Susunan huruf itulah
|
|
171
171
|
* maklumat yang membezakannya.
|
|
172
172
|
*/
|
|
173
|
-
function jarakHuruf(a, b) {
|
|
173
|
+
export function jarakHuruf(a, b) {
|
|
174
174
|
const m = a.length
|
|
175
175
|
const n = b.length
|
|
176
176
|
if (!m) return n
|
|
@@ -491,6 +491,7 @@ export function keRumi(
|
|
|
491
491
|
pilihLazim = false,
|
|
492
492
|
padanRangka = false,
|
|
493
493
|
glosari = null,
|
|
494
|
+
arabDiisytihar = new Set(),
|
|
494
495
|
} = {},
|
|
495
496
|
) {
|
|
496
497
|
const peta = petaSongsang(cache, dataset)
|
|
@@ -521,9 +522,17 @@ export function keRumi(
|
|
|
521
522
|
}
|
|
522
523
|
}
|
|
523
524
|
|
|
524
|
-
// Teks Arab
|
|
525
|
-
//
|
|
526
|
-
|
|
525
|
+
// Teks Arab dibiarkan seadanya. Cuba menukarnya akan merosakkan petikan
|
|
526
|
+
// al-Quran dan hadis dalam dokumen Melayu.
|
|
527
|
+
//
|
|
528
|
+
// Tanda baris sahaja TIDAK memadai. Frasa seperti أصحاب اليمين datang
|
|
529
|
+
// tanpa baris, dan lebih buruk lagi `الدين` memetakan kepada dua entri
|
|
530
|
+
// Jawi dalam data DBP — jadi penukar mengeluarkan "addin|al-din" untuk
|
|
531
|
+
// teks Arab tulen dan pembaca tidak nampak apa-apa salah. Perkataan
|
|
532
|
+
// yang benar-benar larut dalam DBP tidak terjejas: isyarat kata sandang
|
|
533
|
+
// hanya terpakai apabila perkataan itu bukan kata Melayu.
|
|
534
|
+
const tandaArab = isyaratArab(bahagian[i], (t) => peta.has(normalisasiJawi(t)), arabDiisytihar)
|
|
535
|
+
if (tandaArab) {
|
|
527
536
|
arab.push(bahagian[i])
|
|
528
537
|
keluar.push(bahagian[i])
|
|
529
538
|
continue
|