prpm-dbp 0.10.0 → 0.10.1

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.
Files changed (3) hide show
  1. package/SKILL.md +7 -3
  2. package/package.json +1 -1
  3. package/src/tukar.js +38 -10
package/SKILL.md CHANGED
@@ -69,6 +69,10 @@ Contoh kedua: `dipelajari` ialah terbitan sah daripada `ajar`. Alat ini **tidak*
69
69
 
70
70
  **Bila `rumi` jumpa kekaburan**, satu ejaan Jawi memetakan kepada beberapa perkataan Rumi. Semua calon dipaparkan dipisah `|`. Pilih ikut konteks ayat, jangan ambil yang pertama secara membuta.
71
71
 
72
+ Sebahagian kekaburan itu palsu dan diselesaikan sendiri. DBP menandakan bentuk varian dengan **rujukan silang**: definisi `kalkalah` ialah `®qalqalah.`, bukan definisi sebenar. Varian begitu dinyahutamakan, jadi `قلقله` dibaca `qalqalah` terus.
73
+
74
+ Isyaratnya mestilah tanda `®` itu, **bukan** kehadiran ejaan Jawi. `pada` tiada ejaan Jawi dalam PRPM manakala `pad` (pinjaman Inggeris) ada. Mengutamakan "yang ada Jawi" akan menukar setiap `pada` menjadi `pad`.
75
+
72
76
  Jawi Melayu menulis vokal dengan alif, wau dan ya, tidak seperti Arab. Kerana itu kekaburan jarang berlaku, tetapi ia tetap wujud.
73
77
 
74
78
  `rumi` bekerja dari cache sahaja dan tidak menyentuh rangkaian. Perkataan yang belum pernah disemak dalam arah Rumi ke Jawi tidak akan dikenali. Jalankan `warm` atau `audit` dahulu pada kosa kata yang berkaitan.
@@ -215,12 +219,12 @@ Diuji terhadap 406 perkataan pelajaran Pendidikan Islam Tingkatan 4 sebenar, dit
215
219
 
216
220
  ```
217
221
  token asal 336 -> token pusing balik 336
218
- padan tepat 309 (92%)
219
- padan antara calon 27 (8%)
222
+ padan tepat 314 (93%)
223
+ padan antara calon 22 (7%)
220
224
  TIDAK padan 0 (0%)
221
225
  ```
222
226
 
223
- Dua puluh tujuh kes kabur itu sah: `قلقله` boleh dibaca `qalqalah` atau `kalkalah`, dua ejaan Rumi yang sama-sama betul bagi istilah Arab yang sama. Alat melaporkan kedua-duanya dan tidak memilih.
227
+ Dua puluh dua kes kabur yang tinggal itu sah: `قلقله` boleh dibaca `qalqalah` atau `kalkalah`, dua ejaan Rumi yang sama-sama betul bagi istilah Arab yang sama. Alat melaporkan kedua-duanya dan tidak memilih.
224
228
 
225
229
  **Sifar perkataan hilang atau rosak.**
226
230
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm-dbp",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Semak ejaan Bahasa Melayu dan Jawi terhadap PRPM Dewan Bahasa dan Pustaka. CLI dan skill untuk AI agent.",
5
5
  "keywords": [
6
6
  "bahasa-melayu",
package/src/tukar.js CHANGED
@@ -159,13 +159,28 @@ export function petaSongsang(cache, dataset = null) {
159
159
  const peta = new Map()
160
160
  let maxKata = 1
161
161
 
162
- const tambah = (jawi, rumi) => {
162
+ // DBP menandakan bentuk varian dengan rujukan silang: definisi `kalkalah`
163
+ // ialah "®qalqalah.", bukan definisi sebenar. Varian begitu dinyahutamakan
164
+ // supaya قلقله dibaca qalqalah dan bukan dilaporkan kabur.
165
+ //
166
+ // Isyaratnya mestilah tanda ® itu, BUKAN kehadiran ejaan Jawi. `pada`
167
+ // tiada Jawi dalam PRPM manakala `pad` (pinjaman Inggeris) ada, jadi
168
+ // mengutamakan "yang ada Jawi" akan menukar setiap `pada` menjadi `pad`.
169
+ const rujukanSilang = new Set()
170
+ for (const [kata, rec] of Object.entries(cache)) {
171
+ const def = rec?.entri?.[0]?.definisi ?? ''
172
+ if (/^®/.test(def.trim())) rujukanSilang.add(kata)
173
+ }
174
+
175
+ const tambah = (jawi, rumi, sumber) => {
163
176
  const kunci = normalisasiJawi(jawi)
164
177
  if (!kunci) return
165
178
  const bilangan = kunci.split(/\s+/).length
166
179
  if (bilangan > maxKata) maxKata = bilangan
167
- if (!peta.has(kunci)) peta.set(kunci, [])
168
- if (!peta.get(kunci).includes(rumi)) peta.get(kunci).push(rumi)
180
+ if (!peta.has(kunci)) peta.set(kunci, { utama: [], rujukan: [] })
181
+ const jenis = rujukanSilang.has(rumi) ? 'rujukan' : 'utama'
182
+ const slot = peta.get(kunci)[jenis]
183
+ if (!slot.includes(rumi)) slot.push(rumi)
169
184
  }
170
185
 
171
186
  for (const rec of Object.values(cache)) {
@@ -179,6 +194,19 @@ export function petaSongsang(cache, dataset = null) {
179
194
  return peta
180
195
  }
181
196
 
197
+ /**
198
+ * Pilih calon songsang. Bentuk yang DBP sendiri tandakan sebagai rujukan
199
+ * silang (®) hanya digunakan apabila tiada bentuk utama. Selain itu semua
200
+ * calon dilayan sama rata, dan kekaburan sebenar dilaporkan sepenuhnya.
201
+ */
202
+ export function pilihCalon(masuk) {
203
+ if (!masuk) return null
204
+ if (Array.isArray(masuk)) return { calon: masuk, sumber: 'campur' }
205
+ if (masuk.utama.length) return { calon: masuk.utama, sumber: 'utama' }
206
+ if (masuk.rujukan.length) return { calon: masuk.rujukan, sumber: 'rujukan' }
207
+ return null
208
+ }
209
+
182
210
  /**
183
211
  * Rumi -> Jawi. Pemisah, tanda baca dan baris baru dikekalkan.
184
212
  * Perkataan yang tidak disahkan dibalut penanda, tidak pernah direka.
@@ -360,17 +388,17 @@ export function keRumi(teksJawi, cache, { penanda = ['«', '»'], dataset = null
360
388
  }
361
389
  if (!bolehGabung) continue
362
390
  const frasa = bahagian.slice(i, akhir + 1).join(' ').replace(/\s+/g, ' ')
363
- const jumpa = peta.get(normalisasiJawi(frasa))
364
- if (jumpa) { padanan = jumpa; hujung = akhir; break }
391
+ const jumpa = pilihCalon(peta.get(normalisasiJawi(frasa)))
392
+ if (jumpa) { padanan = jumpa.calon; hujung = akhir; break }
365
393
  }
366
394
 
367
395
  if (!padanan) {
368
396
  // Pedoman DBP §17.1 songsang: kata dasar + ٢ menjadi kata berulang.
369
397
  const dasarUlang = pisahUlangJawi(bahagian[i])
370
398
  if (dasarUlang) {
371
- const jumpaUlang = peta.get(normalisasiJawi(dasarUlang))
372
- if (jumpaUlang?.length === 1) {
373
- keluar.push(jumpaUlang[0] + '-' + jumpaUlang[0])
399
+ const jumpaUlang = pilihCalon(peta.get(normalisasiJawi(dasarUlang)))
400
+ if (jumpaUlang?.calon.length === 1) {
401
+ keluar.push(jumpaUlang.calon[0] + '-' + jumpaUlang.calon[0])
374
402
  continue
375
403
  }
376
404
  }
@@ -379,8 +407,8 @@ export function keRumi(teksJawi, cache, { penanda = ['«', '»'], dataset = null
379
407
  // dalam kamus, jadi cuba pisahkan kata sendi di hadapan.
380
408
  let dipisah = null
381
409
  for (const calon of pisahSendi(bahagian[i])) {
382
- const jumpa = peta.get(normalisasiJawi(calon.baki))
383
- if (jumpa?.length === 1) { dipisah = calon.sendi + ' ' + jumpa[0]; break }
410
+ const jumpa = pilihCalon(peta.get(normalisasiJawi(calon.baki)))
411
+ if (jumpa?.calon.length === 1) { dipisah = calon.sendi + ' ' + jumpa.calon[0]; break }
384
412
  }
385
413
  if (dipisah) { keluar.push(dipisah); sendiDipisah.push(bahagian[i]); continue }
386
414