prpm-dbp 0.16.0 → 0.17.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 +100 -0
- package/bin/cli.js +14 -0
- package/package.json +1 -1
- package/src/prpm.js +34 -1
- package/src/semak.js +50 -0
- package/src/tukar.js +48 -2
package/SKILL.md
CHANGED
|
@@ -9,6 +9,30 @@ Sumber kebenaran tunggal untuk ejaan BM dan Jawi ialah PRPM DBP, bukan ingatan m
|
|
|
9
9
|
|
|
10
10
|
Model boleh hasilkan Jawi yang nampak betul tetapi salah, dan pembaca tidak dapat kesan. Skill ini tukar tekaan jadi semakan.
|
|
11
11
|
|
|
12
|
+
## Prosedur wajib
|
|
13
|
+
|
|
14
|
+
Ikut ini setiap kali, jangan langkau langkah.
|
|
15
|
+
|
|
16
|
+
**Menulis Jawi daripada Rumi:**
|
|
17
|
+
|
|
18
|
+
1. `npx prpm-dbp jawi <fail> --luar-talian --homograf --json`
|
|
19
|
+
2. Baca `belumDisahkan` dan `namaKhas`. Jangan reka ejaan untuknya. Sahkan dengan `lookup`, atau tanya pengguna, atau tandakan dalam hasil akhir.
|
|
20
|
+
3. Baca `mencurigakan`. Setiap satu bermakna PRPM sendiri mungkin tersilap. Semak di pautan yang diberi sebelum menggunakannya.
|
|
21
|
+
4. Baca `homograf`. Beritahu pengguna perkataan mana yang akan taksa apabila dibaca.
|
|
22
|
+
5. Laporkan `semuanyaDbp`. Jika `false`, nyatakan bahagian mana bukan daripada sumber rasmi.
|
|
23
|
+
|
|
24
|
+
**Merumikan daripada Jawi:**
|
|
25
|
+
|
|
26
|
+
1. `npx prpm-dbp rumi <fail> --pilih --konteks --json`
|
|
27
|
+
2. Untuk **setiap** item dalam `kabur`: baca ayat yang mengandunginya, baca makna setiap calon, tentukan yang mana sesuai.
|
|
28
|
+
3. Jika `dipilih` salah bagi ayat itu, **gantikan** dalam hasil akhir. Kekerapan kalah kepada konteks.
|
|
29
|
+
4. Nyatakan kepada pengguna berapa banyak kekaburan wujud dan mana yang anda ubah.
|
|
30
|
+
5. `tidakDikenali` bermakna perkataan itu tiada dalam cache. Jalankan `warm` di luar talian, bukan tinggalkan bertanda.
|
|
31
|
+
|
|
32
|
+
**Berhenti dan tanya pengguna apabila:** ejaan `mencurigakan` mengubah makna, nama khas tiada rujukan bertulis, atau dua calon sama-sama munasabah dalam ayat itu.
|
|
33
|
+
|
|
34
|
+
Semua perintah menyokong `--json`, jadi langkah di atas boleh dibuat secara berulang tanpa menghurai teks.
|
|
35
|
+
|
|
12
36
|
## Peraturan
|
|
13
37
|
|
|
14
38
|
0. **Semak ejaan ikut DBP, bukan ikut ingatan.** Ini peraturan pertama kerana ia yang paling kerap dilanggar. Perkataan yang anda "tahu" ejaannya masih perlu disemak. Contoh sebenar daripada penggunaan: `sunah` ialah `سنة` tetapi `sunat` ialah `سونت`; `bena` langsung tiada ejaan Jawi dalam PRPM walaupun ia perkataan yang sah; `salat` hanyalah rujukan silang kepada `solat`. Tiada satu pun daripada perbezaan ini boleh diteka daripada bentuk Rumi. Jalankan `lookup` atau `jawi`, jangan tulis daripada ingatan.
|
|
@@ -160,6 +184,30 @@ Ejaan yang disimpan begini ditandakan datang daripada pengguna, bukan daripada D
|
|
|
160
184
|
|
|
161
185
|
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 `کوالا لومڤور`.
|
|
162
186
|
|
|
187
|
+
## Prosedur wajib
|
|
188
|
+
|
|
189
|
+
Ikut ini setiap kali, jangan langkau langkah.
|
|
190
|
+
|
|
191
|
+
**Menulis Jawi daripada Rumi:**
|
|
192
|
+
|
|
193
|
+
1. `npx prpm-dbp jawi <fail> --luar-talian --homograf --json`
|
|
194
|
+
2. Baca `belumDisahkan` dan `namaKhas`. Jangan reka ejaan untuknya. Sahkan dengan `lookup`, atau tanya pengguna, atau tandakan dalam hasil akhir.
|
|
195
|
+
3. Baca `mencurigakan`. Setiap satu bermakna PRPM sendiri mungkin tersilap. Semak di pautan yang diberi sebelum menggunakannya.
|
|
196
|
+
4. Baca `homograf`. Beritahu pengguna perkataan mana yang akan taksa apabila dibaca.
|
|
197
|
+
5. Laporkan `semuanyaDbp`. Jika `false`, nyatakan bahagian mana bukan daripada sumber rasmi.
|
|
198
|
+
|
|
199
|
+
**Merumikan daripada Jawi:**
|
|
200
|
+
|
|
201
|
+
1. `npx prpm-dbp rumi <fail> --pilih --konteks --json`
|
|
202
|
+
2. Untuk **setiap** item dalam `kabur`: baca ayat yang mengandunginya, baca makna setiap calon, tentukan yang mana sesuai.
|
|
203
|
+
3. Jika `dipilih` salah bagi ayat itu, **gantikan** dalam hasil akhir. Kekerapan kalah kepada konteks.
|
|
204
|
+
4. Nyatakan kepada pengguna berapa banyak kekaburan wujud dan mana yang anda ubah.
|
|
205
|
+
5. `tidakDikenali` bermakna perkataan itu tiada dalam cache. Jalankan `warm` di luar talian, bukan tinggalkan bertanda.
|
|
206
|
+
|
|
207
|
+
**Berhenti dan tanya pengguna apabila:** ejaan `mencurigakan` mengubah makna, nama khas tiada rujukan bertulis, atau dua calon sama-sama munasabah dalam ayat itu.
|
|
208
|
+
|
|
209
|
+
Semua perintah menyokong `--json`, jadi langkah di atas boleh dibuat secara berulang tanpa menghurai teks.
|
|
210
|
+
|
|
163
211
|
## Peraturan Pedoman DBP
|
|
164
212
|
|
|
165
213
|
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.
|
|
@@ -271,6 +319,30 @@ Dua puluh dua kes kabur yang tinggal itu sah: `قلقله` boleh dibaca `qalqala
|
|
|
271
319
|
|
|
272
320
|
**Sifar perkataan hilang atau rosak.**
|
|
273
321
|
|
|
322
|
+
## Prosedur wajib
|
|
323
|
+
|
|
324
|
+
Ikut ini setiap kali, jangan langkau langkah.
|
|
325
|
+
|
|
326
|
+
**Menulis Jawi daripada Rumi:**
|
|
327
|
+
|
|
328
|
+
1. `npx prpm-dbp jawi <fail> --luar-talian --homograf --json`
|
|
329
|
+
2. Baca `belumDisahkan` dan `namaKhas`. Jangan reka ejaan untuknya. Sahkan dengan `lookup`, atau tanya pengguna, atau tandakan dalam hasil akhir.
|
|
330
|
+
3. Baca `mencurigakan`. Setiap satu bermakna PRPM sendiri mungkin tersilap. Semak di pautan yang diberi sebelum menggunakannya.
|
|
331
|
+
4. Baca `homograf`. Beritahu pengguna perkataan mana yang akan taksa apabila dibaca.
|
|
332
|
+
5. Laporkan `semuanyaDbp`. Jika `false`, nyatakan bahagian mana bukan daripada sumber rasmi.
|
|
333
|
+
|
|
334
|
+
**Merumikan daripada Jawi:**
|
|
335
|
+
|
|
336
|
+
1. `npx prpm-dbp rumi <fail> --pilih --konteks --json`
|
|
337
|
+
2. Untuk **setiap** item dalam `kabur`: baca ayat yang mengandunginya, baca makna setiap calon, tentukan yang mana sesuai.
|
|
338
|
+
3. Jika `dipilih` salah bagi ayat itu, **gantikan** dalam hasil akhir. Kekerapan kalah kepada konteks.
|
|
339
|
+
4. Nyatakan kepada pengguna berapa banyak kekaburan wujud dan mana yang anda ubah.
|
|
340
|
+
5. `tidakDikenali` bermakna perkataan itu tiada dalam cache. Jalankan `warm` di luar talian, bukan tinggalkan bertanda.
|
|
341
|
+
|
|
342
|
+
**Berhenti dan tanya pengguna apabila:** ejaan `mencurigakan` mengubah makna, nama khas tiada rujukan bertulis, atau dua calon sama-sama munasabah dalam ayat itu.
|
|
343
|
+
|
|
344
|
+
Semua perintah menyokong `--json`, jadi langkah di atas boleh dibuat secara berulang tanpa menghurai teks.
|
|
345
|
+
|
|
274
346
|
## Peraturan yang sengaja TIDAK dilaksanakan
|
|
275
347
|
|
|
276
348
|
| Seksyen | Sebab |
|
|
@@ -357,6 +429,34 @@ Empat kelas berasingan, kerana menggabungkannya menenggelamkan yang penting:
|
|
|
357
429
|
|
|
358
430
|
Penambahan huruf vokal **tidak** dikira ejaan lama. Kalau kehadiran `ي` diabaikan, `بينا` (bina) dan `بنا` (bena) akan kelihatan sama, sedangkan itu dua perkataan berlainan.
|
|
359
431
|
|
|
432
|
+
## Ejaan bukan piawai DBP
|
|
433
|
+
|
|
434
|
+
Dokumen kurikulum Malaysia kerap menggunakan ortografi Jawi yang berbeza daripada piawai DBP. Pasangan yang disahkan daripada DSKP Pendidikan Islam KPM sebenar:
|
|
435
|
+
|
|
436
|
+
| Rumi | DBP | DSKP | Beza |
|
|
437
|
+
|---|---|---|---|
|
|
438
|
+
| surah | `سورة` | `سوره` | ta marbutah jadi ha |
|
|
439
|
+
| iktibar | `اعتبار` | `اعتبر` | alif digugurkan |
|
|
440
|
+
| bersifat | `برصيفت` | `برصفة` | ya digugurkan, ta marbutah |
|
|
441
|
+
| dalil | `دليل` | `داليل` | alif ditambah |
|
|
442
|
+
| syirik | `شيريک` | `شرك` | ya digugurkan, kaf Arab |
|
|
443
|
+
|
|
444
|
+
Kesemuanya berbeza hanya pada huruf vokal dan bentuk huruf, bukan pada rangka konsonan. `--rangka` memadan rangka itu:
|
|
445
|
+
|
|
446
|
+
```
|
|
447
|
+
$ npx prpm-dbp rumi dskp.txt --luar-talian --rangka
|
|
448
|
+
ejaan bukan piawai DBP (209):
|
|
449
|
+
اعتبر -> iktibar [DBP eja: اعتبار]
|
|
450
|
+
سوره -> surah [DBP eja: سورة]
|
|
451
|
+
کتب -> kitab|katib|kutub (rangka sama, PILIH ikut konteks)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Diukur pada 168 baris DSKP sebenar: token yang langsung tidak dikenali turun daripada 100 kepada 47.
|
|
455
|
+
|
|
456
|
+
**Ini lapisan terakhir dan ia LOSSY.** 29% rangka dikongsi lebih daripada satu perkataan, purata 4.1 calon. Ia hanya digunakan selepas padanan tepat gagal, hasilnya sentiasa berlabel `ejaanBukanPiawai` berserta ejaan DBP untuk perbandingan, dan ia **tidak pernah memilih sendiri** apabila calon berbilang.
|
|
457
|
+
|
|
458
|
+
Kegunaannya bukan menjadikan alat lebih longgar. Ia membezakan **"ini surah, cuma dieja lain"** daripada **"saya tidak kenal benda ini"** — dua keadaan yang dahulu keluar sama sebagai `«...»`.
|
|
459
|
+
|
|
360
460
|
## Rantai kepercayaan
|
|
361
461
|
|
|
362
462
|
Setiap ejaan Jawi yang dikeluarkan membawa asal-usulnya. Jangan runtuhkan lapisan ini.
|
package/bin/cli.js
CHANGED
|
@@ -38,6 +38,7 @@ Pilihan: --refresh --had <n> --delay <ms> --json --cepat
|
|
|
38
38
|
--luar-talian jangan sentuh rangkaian langsung (wajib untuk laluan permintaan app)
|
|
39
39
|
--homograf tandakan perkataan yang ejaan Jawinya dikongsi perkataan lain
|
|
40
40
|
--konteks papar ayat dan makna setiap calon bagi kekaburan (rumi)
|
|
41
|
+
--rangka padan ejaan bukan piawai melalui rangka konsonan (berlabel)
|
|
41
42
|
--pilih pilih calon paling lazim supaya teks boleh terus dibaca;
|
|
42
43
|
setiap pilihan disenaraikan untuk disemak ikut konteks
|
|
43
44
|
|
|
@@ -58,6 +59,7 @@ function huraiArgs(argv) {
|
|
|
58
59
|
else if (a === '--homograf') pilihan.homograf = true
|
|
59
60
|
else if (a === '--konteks') pilihan.konteks = true
|
|
60
61
|
else if (a === '--pilih') pilihan.pilih = true
|
|
62
|
+
else if (a === '--rangka') pilihan.rangka = true
|
|
61
63
|
else if (a === '--jenis') pilihan.jenis = argv[++i]
|
|
62
64
|
else if (a === '--had') pilihan.had = Number(argv[++i])
|
|
63
65
|
else if (a === '--delay') pilihan.delay = Number(argv[++i])
|
|
@@ -226,6 +228,7 @@ async function main() {
|
|
|
226
228
|
const h = keRumi(teks, cache, {
|
|
227
229
|
dataset: await muatDataset(),
|
|
228
230
|
pilihLazim: pilihan.pilih,
|
|
231
|
+
padanRangka: pilihan.rangka,
|
|
229
232
|
})
|
|
230
233
|
if (pilihan.json) { keluar(h); break }
|
|
231
234
|
console.log(h.teks)
|
|
@@ -255,6 +258,17 @@ async function main() {
|
|
|
255
258
|
}
|
|
256
259
|
}
|
|
257
260
|
}
|
|
261
|
+
if (h.ejaanBukanPiawai?.length) {
|
|
262
|
+
const tunggal = h.ejaanBukanPiawai.filter((x) => x.calon.length === 1)
|
|
263
|
+
const banyak = h.ejaanBukanPiawai.filter((x) => x.calon.length > 1)
|
|
264
|
+
console.error(`\nejaan bukan piawai DBP (${h.ejaanBukanPiawai.length}):`)
|
|
265
|
+
for (const x of tunggal.slice(0, 20)) {
|
|
266
|
+
console.error(` ${x.jawi} -> ${x.calon[0].rumi} [DBP eja: ${x.calon[0].jawiDbp}]`)
|
|
267
|
+
}
|
|
268
|
+
for (const x of banyak.slice(0, 10)) {
|
|
269
|
+
console.error(` ${x.jawi} -> ${x.calon.map((c) => c.rumi).join('|')} (rangka sama, PILIH ikut konteks)`)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
258
272
|
if (h.arab.length) console.error(`teks Arab dibiarkan (${h.arab.length}): ${h.arab.join(' ')}`)
|
|
259
273
|
for (const k of h.kabur) {
|
|
260
274
|
console.error(
|
package/package.json
CHANGED
package/src/prpm.js
CHANGED
|
@@ -127,10 +127,43 @@ export async function loadCache() {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Simpan cache dengan MENGGABUNGKAN keadaan di cakera terlebih dahulu.
|
|
132
|
+
*
|
|
133
|
+
* Menulis ganti secara membuta memusnahkan kerja proses lain. Dua sesi yang
|
|
134
|
+
* berjalan serentak akan memuat keadaan yang sama, masing-masing menambah
|
|
135
|
+
* perkataannya, dan yang menyimpan kemudian memadam tambahan yang awal.
|
|
136
|
+
* Ia diperhatikan secara langsung: entri yang baru dipanaskan hilang selepas
|
|
137
|
+
* sesi lain menyimpan.
|
|
138
|
+
*
|
|
139
|
+
* Rekod di cakera menang bagi kunci yang sama, kerana ia mungkin lebih baharu.
|
|
140
|
+
* Rekod benih (`ringkas`) tidak pernah menewaskan rekod penuh.
|
|
141
|
+
*/
|
|
130
142
|
export async function saveCache(cache) {
|
|
131
143
|
await mkdir(dirname(CACHE_PATH), { recursive: true })
|
|
144
|
+
|
|
145
|
+
let diCakera = {}
|
|
146
|
+
try {
|
|
147
|
+
diCakera = JSON.parse(await readFile(CACHE_PATH, 'utf8'))
|
|
148
|
+
} catch {
|
|
149
|
+
diCakera = {}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const gabung = { ...cache }
|
|
153
|
+
for (const [kata, rec] of Object.entries(diCakera)) {
|
|
154
|
+
const sedia = gabung[kata]
|
|
155
|
+
// Rekod penuh mengatasi rekod ringkas; selain itu cakera menang.
|
|
156
|
+
if (sedia && !sedia.ringkas && rec.ringkas) continue
|
|
157
|
+
gabung[kata] = rec
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Rekod benih tidak ditulis ke cache pengguna: ia sudah ada dalam pakej.
|
|
161
|
+
for (const [kata, rec] of Object.entries(gabung)) {
|
|
162
|
+
if (rec?.benih) delete gabung[kata]
|
|
163
|
+
}
|
|
164
|
+
|
|
132
165
|
const tmp = `${CACHE_PATH}.tmp`
|
|
133
|
-
await writeFile(tmp, JSON.stringify(
|
|
166
|
+
await writeFile(tmp, JSON.stringify(gabung, null, 1), 'utf8')
|
|
134
167
|
await rename(tmp, CACHE_PATH)
|
|
135
168
|
}
|
|
136
169
|
|
package/src/semak.js
CHANGED
|
@@ -102,3 +102,53 @@ export function ejaanLamaSahaja(a, b) {
|
|
|
102
102
|
if (!a || !b || a === b) return false
|
|
103
103
|
return samakanLama(a) === samakanLama(b)
|
|
104
104
|
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Rangka konsonan: buang huruf vokal pilihan dan samakan varian bentuk.
|
|
108
|
+
*
|
|
109
|
+
* Dokumen kurikulum Malaysia kerap menggunakan ejaan Jawi yang berbeza
|
|
110
|
+
* daripada piawai DBP. Corak yang disahkan pada pasangan sebenar DSKP:
|
|
111
|
+
*
|
|
112
|
+
* surah DBP سورة DSKP سوره ta marbutah jadi ha
|
|
113
|
+
* iktibar DBP اعتبار DSKP اعتبر alif digugurkan
|
|
114
|
+
* bersifat DBP برصيفت DSKP برصفة ya digugurkan, ta marbutah
|
|
115
|
+
* dalil DBP دليل DSKP داليل alif ditambah
|
|
116
|
+
* syirik DBP شيريک DSKP شرك ya digugurkan, kaf Arab
|
|
117
|
+
*
|
|
118
|
+
* Kesemuanya berbeza hanya pada huruf vokal dan bentuk huruf, bukan pada
|
|
119
|
+
* rangka konsonan. Membuang vokal menjadikan kedua-dua ejaan sepadan.
|
|
120
|
+
*
|
|
121
|
+
* INI LOSSY dan MESTI kekal di bawah lapisan 1 dan 2. Banyak perkataan
|
|
122
|
+
* berkongsi rangka yang sama, jadi padanan begini adalah inferens, bukan
|
|
123
|
+
* rekod DBP, dan hasilnya mesti berlabel.
|
|
124
|
+
*/
|
|
125
|
+
const VOKAL_PILIHAN = /[اويى]/g
|
|
126
|
+
|
|
127
|
+
const SAMA_BENTUK = new Map([
|
|
128
|
+
['ة', 'ه'],
|
|
129
|
+
['ك', 'ک'],
|
|
130
|
+
['ڬ', 'ݢ'],
|
|
131
|
+
['ف', 'ڤ'],
|
|
132
|
+
['ج', 'چ'],
|
|
133
|
+
['أ', 'ا'],
|
|
134
|
+
['إ', 'ا'],
|
|
135
|
+
['ء', ''],
|
|
136
|
+
])
|
|
137
|
+
|
|
138
|
+
// Pedoman §6.4: ta marbutah melambangkan [t] ATAU [h] sebagai kelainan
|
|
139
|
+
// sebutan pada kata serapan Arab (akibat/akibah, hidayat/hidayah). Ketiga-tiga
|
|
140
|
+
// huruf itu boleh bertukar di HUJUNG kata sahaja. Di tengah kata ia huruf
|
|
141
|
+
// berlainan dan tidak boleh dilipat.
|
|
142
|
+
const HUJUNG_SETARA = new Set(['ة', 'ه', 'ت'])
|
|
143
|
+
|
|
144
|
+
export function rangkaKonsonan(jawi) {
|
|
145
|
+
if (!jawi) return ''
|
|
146
|
+
let keluar = ''
|
|
147
|
+
for (const huruf of String(jawi).normalize('NFC')) {
|
|
148
|
+
const ganti = SAMA_BENTUK.has(huruf) ? SAMA_BENTUK.get(huruf) : huruf
|
|
149
|
+
keluar += ganti
|
|
150
|
+
}
|
|
151
|
+
keluar = keluar.replace(VOKAL_PILIHAN, '').replace(/\s+/g, '')
|
|
152
|
+
if (keluar && HUJUNG_SETARA.has(keluar.slice(-1))) keluar = keluar.slice(0, -1) + 'ه'
|
|
153
|
+
return keluar
|
|
154
|
+
}
|
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 { semakHurufAkhir } from './semak.js'
|
|
15
|
+
import { rangkaKonsonan, semakHurufAkhir } from './semak.js'
|
|
16
16
|
import {
|
|
17
17
|
imbuhAkhiranAn,
|
|
18
18
|
imbuhAkhiranKan,
|
|
@@ -162,6 +162,33 @@ export async function cariDasar(kata, cache, opts = {}) {
|
|
|
162
162
|
* bilangan perkataan terpanjang supaya pembacaan songsang boleh memadan
|
|
163
163
|
* jujukan, bukan token tunggal sahaja.
|
|
164
164
|
*/
|
|
165
|
+
/**
|
|
166
|
+
* Indeks rangka konsonan, untuk memadan ejaan bukan piawai.
|
|
167
|
+
*
|
|
168
|
+
* Dokumen kurikulum Malaysia kerap menggunakan ortografi yang berbeza
|
|
169
|
+
* daripada DBP: vokal digugur atau ditambah, ta marbutah bertukar ha, bentuk
|
|
170
|
+
* Arab menggantikan bentuk Jawi Melayu. Indeks ini memadan rangka konsonan
|
|
171
|
+
* supaya `سوره` masih dikenali sebagai `surah`.
|
|
172
|
+
*
|
|
173
|
+
* LOSSY: 29% rangka dikongsi lebih daripada satu perkataan, purata 4.1 calon.
|
|
174
|
+
* Kerana itu ia hanya digunakan selepas padanan tepat gagal, hasilnya sentiasa
|
|
175
|
+
* berlabel, dan ia TIDAK PERNAH memilih sendiri apabila calon berbilang.
|
|
176
|
+
*/
|
|
177
|
+
export function petaRangka(cache, dataset = null) {
|
|
178
|
+
const peta = new Map()
|
|
179
|
+
const tambah = (jawi, rumi) => {
|
|
180
|
+
const kunci = rangkaKonsonan(jawi)
|
|
181
|
+
if (!kunci) return
|
|
182
|
+
if (!peta.has(kunci)) peta.set(kunci, new Map())
|
|
183
|
+
if (!peta.get(kunci).has(rumi)) peta.get(kunci).set(rumi, jawi)
|
|
184
|
+
}
|
|
185
|
+
for (const rec of Object.values(cache)) if (rec?.jawi) tambah(rec.jawi, rec.kata)
|
|
186
|
+
for (const [rumi, ejaan] of Object.entries(dataset?.peta ?? {})) {
|
|
187
|
+
for (const j of ejaan) tambah(j, rumi)
|
|
188
|
+
}
|
|
189
|
+
return peta
|
|
190
|
+
}
|
|
191
|
+
|
|
165
192
|
export function petaSongsang(cache, dataset = null) {
|
|
166
193
|
const peta = new Map()
|
|
167
194
|
let maxKata = 1
|
|
@@ -428,13 +455,15 @@ export async function keJawi(teks, cache, opts = {}) {
|
|
|
428
455
|
export function keRumi(
|
|
429
456
|
teksJawi,
|
|
430
457
|
cache,
|
|
431
|
-
{ penanda = ['«', '»'], dataset = null, pilihLazim = false } = {},
|
|
458
|
+
{ penanda = ['«', '»'], dataset = null, pilihLazim = false, padanRangka = false } = {},
|
|
432
459
|
) {
|
|
433
460
|
const peta = petaSongsang(cache, dataset)
|
|
434
461
|
const tidakDikenali = []
|
|
435
462
|
const kabur = []
|
|
436
463
|
const arab = []
|
|
437
464
|
const sendiDipisah = []
|
|
465
|
+
const bukanPiawai = []
|
|
466
|
+
const rangka = padanRangka ? petaRangka(cache, dataset) : null
|
|
438
467
|
const bahagian = teksJawi.split(PECAH_JAWI)
|
|
439
468
|
const keluar = []
|
|
440
469
|
|
|
@@ -491,6 +520,22 @@ export function keRumi(
|
|
|
491
520
|
}
|
|
492
521
|
if (dipisah) { keluar.push(dipisah); sendiDipisah.push(bahagian[i]); continue }
|
|
493
522
|
|
|
523
|
+
// Lapisan terakhir: ejaan bukan piawai. Berlabel, di bawah lapisan
|
|
524
|
+
// 1 dan 2, dan tidak pernah memilih sendiri apabila calon berbilang.
|
|
525
|
+
if (rangka) {
|
|
526
|
+
const padananRangka = rangka.get(rangkaKonsonan(bahagian[i]))
|
|
527
|
+
if (padananRangka?.size) {
|
|
528
|
+
const senarai = [...padananRangka.entries()].map(([rumi, jawiDbp]) => ({ rumi, jawiDbp }))
|
|
529
|
+
bukanPiawai.push({ jawi: bahagian[i], calon: senarai })
|
|
530
|
+
if (senarai.length === 1) {
|
|
531
|
+
keluar.push(senarai[0].rumi)
|
|
532
|
+
continue
|
|
533
|
+
}
|
|
534
|
+
keluar.push(penanda[0] + senarai.map((x) => x.rumi).join('|') + penanda[1])
|
|
535
|
+
continue
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
494
539
|
tidakDikenali.push(bahagian[i])
|
|
495
540
|
keluar.push(penanda[0] + bahagian[i] + penanda[1])
|
|
496
541
|
continue
|
|
@@ -521,6 +566,7 @@ export function keRumi(
|
|
|
521
566
|
kabur,
|
|
522
567
|
arab: [...new Set(arab)],
|
|
523
568
|
sendiDipisah,
|
|
569
|
+
ejaanBukanPiawai: bukanPiawai,
|
|
524
570
|
saizPeta: peta.size,
|
|
525
571
|
lengkap: tidakDikenali.length === 0,
|
|
526
572
|
}
|