prpm-dbp 0.5.1 → 0.6.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 CHANGED
@@ -148,7 +148,16 @@ Pakej tidak perlu memilih antara dua ini. DBP sudah memilih, dan pilihan itu ter
148
148
 
149
149
  **§10 — enam belas perkataan dikecualikan daripada aturan pola:** `ada`, `apa`, `beta`, `bin`, `binti`, `dari`, `daripada`, `ini`, `itu`, `jika`, `kepada`, `kita`, `lima`, `maka`, `pada`, `demikian`. Ejaannya mesti datang daripada kamus dan tidak boleh dibetulkan oleh mana-mana peraturan pola.
150
150
 
151
- **§17.1 — kata ulang penuh menggunakan angka dua Arab `٢`**, bukan sempang: `rama-rama` menjadi `رام٢`. Sempang digunakan hanya apabila bahagian yang diulang berubah bentuk (§17.2).
151
+ **§17.1 — kata ulang penuh menggunakan angka dua Arab `٢`**, bukan sempang dan bukan kata dasar ditulis dua kali.
152
+
153
+ ```
154
+ Cikgu-cikgu -> چيقݢو٢
155
+ murid-murid -> موريد٢
156
+ ```
157
+
158
+ Kata dasar dicari dalam kamus seperti biasa, jadi ejaannya tetap datang daripada sumber. Hanya penambahan `٢` itu dijana oleh peraturan. Peraturan ini simetri: `چيقݢو٢` dibaca semula sebagai `cikgu-cikgu`.
159
+
160
+ §17.2 mengecualikan kata ulang yang **berubah bentuk** (berimbuhan atau berentak) seperti `bermaaf-maafan`. Di situ sempang kekal dan peraturan `٢` tidak terpakai, jadi padanan menuntut kedua-dua bahagian benar-benar serupa.
152
161
 
153
162
  ## Rantai kepercayaan
154
163
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm-dbp",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
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/pedoman.js CHANGED
@@ -110,3 +110,30 @@ export const ANGKA_DUA = '\u0662'
110
110
  * pendakwaan). Kerana itu ia tidak boleh dilipat semasa perbandingan.
111
111
  */
112
112
  export const NOTA_MAQSURAH = 'Pedoman DBP §11.6'
113
+
114
+ /**
115
+ * §17.1 — Kata ulang PENUH ditulis sebagai kata dasar diikuti angka dua
116
+ * Arab. Kata dasar tidak ditulis dua kali.
117
+ *
118
+ * kanak-kanak -> کانق٢ murid-murid -> موريد٢
119
+ *
120
+ * §17.2 — Ini TIDAK terpakai apabila bahagian yang diulang berubah bentuk
121
+ * (kata ulang berimbuhan atau berentak). Di situ sempang digunakan. Kerana
122
+ * itu padanan di bawah menuntut kedua-dua bahagian benar-benar serupa.
123
+ */
124
+ export function pisahKataUlang(kata) {
125
+ const m = /^(.+)-\1$/i.exec(String(kata))
126
+ return m ? m[1] : null
127
+ }
128
+
129
+ export function binaKataUlang(jawiDasar) {
130
+ if (!jawiDasar) return null
131
+ return { jawi: jawiDasar + ANGKA_DUA, rujukan: 'Pedoman DBP §17.1' }
132
+ }
133
+
134
+ /** Songsangan §17.1: kata dasar + ٢ menjadi kata dasar berulang penuh. */
135
+ export function pisahUlangJawi(jawi) {
136
+ if (!jawi.endsWith(ANGKA_DUA)) return null
137
+ const dasar = jawi.slice(0, -ANGKA_DUA.length)
138
+ return dasar ? dasar : null
139
+ }
package/src/tukar.js CHANGED
@@ -12,7 +12,14 @@ import { lookup } from './prpm.js'
12
12
  import { normalisasiJawi } from './kamus.js'
13
13
  import { cariDataset, muatDataset } from './dataset.js'
14
14
  import { cariNama, mungkinNamaKhas } from './nama.js'
15
- import { bolehCantumSendi, cantumSendi, pisahSendi } from './pedoman.js'
15
+ import {
16
+ binaKataUlang,
17
+ bolehCantumSendi,
18
+ cantumSendi,
19
+ pisahKataUlang,
20
+ pisahSendi,
21
+ pisahUlangJawi,
22
+ } from './pedoman.js'
16
23
 
17
24
  // Baris tanda vokal Arab (fathah, kasrah, dammah, sukun, syaddah, tanwin,
18
25
  // alef superscript). Jawi Melayu TIDAK menggunakannya; teks al-Quran dan
@@ -134,6 +141,7 @@ export async function keJawi(teks, cache, opts = {}) {
134
141
  const adaEntriTanpaJawi = []
135
142
  const dariNama = []
136
143
  const namaKhas = []
144
+ const kataUlang = []
137
145
  const bahagian = teks.split(PECAH_RUMI)
138
146
  const keluar = []
139
147
 
@@ -159,6 +167,21 @@ export async function keJawi(teks, cache, opts = {}) {
159
167
  }
160
168
  }
161
169
 
170
+ // Pedoman DBP §17.1: kata ulang penuh ialah kata dasar + angka dua Arab.
171
+ // Kata dasar dicari seperti biasa, jadi ejaannya tetap datang daripada
172
+ // kamus; hanya penambahan ٢ itu yang dijana oleh peraturan.
173
+ const dasarUlang = pisahKataUlang(cebis)
174
+ if (dasarUlang) {
175
+ const recDasar = await lookup(dasarUlang.toLowerCase(), cache, opts)
176
+ const jawiDasar = recDasar?.jawi ?? (gunaDataset ? (await cariDataset(dasarUlang.toLowerCase()))?.jawi : null)
177
+ const ulang = binaKataUlang(jawiDasar)
178
+ if (ulang) {
179
+ kataUlang.push({ kata: cebis, dasar: dasarUlang, jawi: ulang.jawi, rujukan: ulang.rujukan })
180
+ keluar.push(ulang.jawi)
181
+ continue
182
+ }
183
+ }
184
+
162
185
  // Nama khas yang pengguna sudah sahkan sendiri.
163
186
  const nm = await cariNama(cebis)
164
187
  if (nm?.jawi) {
@@ -210,6 +233,7 @@ export async function keJawi(teks, cache, opts = {}) {
210
233
  disahkanDbp: dbp.length,
211
234
  dariDataset,
212
235
  dariNama,
236
+ kataUlang,
213
237
  namaKhas: [...new Set(namaKhas)],
214
238
  adaEntriTanpaJawi: [...new Set(adaEntriTanpaJawi)],
215
239
  belumDisahkan: [...new Set(belumDisahkan)],
@@ -270,6 +294,16 @@ export function keRumi(teksJawi, cache, { penanda = ['«', '»'], dataset = null
270
294
  }
271
295
 
272
296
  if (!padanan) {
297
+ // Pedoman DBP §17.1 songsang: kata dasar + ٢ menjadi kata berulang.
298
+ const dasarUlang = pisahUlangJawi(bahagian[i])
299
+ if (dasarUlang) {
300
+ const jumpaUlang = peta.get(normalisasiJawi(dasarUlang))
301
+ if (jumpaUlang?.length === 1) {
302
+ keluar.push(jumpaUlang[0] + '-' + jumpaUlang[0])
303
+ continue
304
+ }
305
+ }
306
+
273
307
  // Pedoman DBP §14.1 songsang: bentuk bercantum seperti دمکة tiada
274
308
  // dalam kamus, jadi cuba pisahkan kata sendi di hadapan.
275
309
  let dipisah = null