ipa-hangul 1.2.3 → 1.3.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.
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +24 -4
- package/dist/index.mjs +24 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
interface IpaToHangulOptions {
|
|
14
14
|
markStress?: 'markdown' | 'html';
|
|
15
|
+
/**
|
|
16
|
+
* When true, trailing consonants move to next syllable if it starts with a vowel.
|
|
17
|
+
* This produces more natural Korean loan word pronunciation.
|
|
18
|
+
* e.g., "tɪti" → "티티" instead of "팉이"
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
preferOnset?: boolean;
|
|
15
22
|
}
|
|
16
23
|
/**
|
|
17
24
|
* Convert IPA notation to Korean Hangul pronunciation
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
interface IpaToHangulOptions {
|
|
14
14
|
markStress?: 'markdown' | 'html';
|
|
15
|
+
/**
|
|
16
|
+
* When true, trailing consonants move to next syllable if it starts with a vowel.
|
|
17
|
+
* This produces more natural Korean loan word pronunciation.
|
|
18
|
+
* e.g., "tɪti" → "티티" instead of "팉이"
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
preferOnset?: boolean;
|
|
15
22
|
}
|
|
16
23
|
/**
|
|
17
24
|
* Convert IPA notation to Korean Hangul pronunciation
|
package/dist/index.js
CHANGED
|
@@ -262,7 +262,7 @@ function preprocessIPA(ipa) {
|
|
|
262
262
|
function hasIPAVowel(text) {
|
|
263
263
|
return /[iɪeɛæɑɒɔʌəɜɝʊuoa]/.test(text);
|
|
264
264
|
}
|
|
265
|
-
function getTrailingConsonants(text) {
|
|
265
|
+
function getTrailingConsonants(text, preferOnset = false) {
|
|
266
266
|
let i = text.length;
|
|
267
267
|
while (i > 0) {
|
|
268
268
|
if (i >= 2) {
|
|
@@ -284,6 +284,25 @@ function getTrailingConsonants(text) {
|
|
|
284
284
|
if (!allTrailing) {
|
|
285
285
|
return { before: text, trailing: "" };
|
|
286
286
|
}
|
|
287
|
+
if (preferOnset) {
|
|
288
|
+
if (allTrailing.length >= 2) {
|
|
289
|
+
const lastTwo = allTrailing.substring(allTrailing.length - 2);
|
|
290
|
+
if (CONSONANT_TO_CHOSEONG[lastTwo] || CONSONANT_TO_JAMO[lastTwo]) {
|
|
291
|
+
return {
|
|
292
|
+
before: beforeConsonants + allTrailing.substring(0, allTrailing.length - 2),
|
|
293
|
+
trailing: lastTwo
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const lastOne = allTrailing[allTrailing.length - 1];
|
|
298
|
+
if (CONSONANT_TO_CHOSEONG[lastOne] || CONSONANT_TO_JAMO[lastOne]) {
|
|
299
|
+
return {
|
|
300
|
+
before: beforeConsonants + allTrailing.substring(0, allTrailing.length - 1),
|
|
301
|
+
trailing: lastOne
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
return { before: text, trailing: "" };
|
|
305
|
+
}
|
|
287
306
|
let keepUntil = 0;
|
|
288
307
|
if (allTrailing.length >= 2) {
|
|
289
308
|
const twoChar = allTrailing.substring(0, 2);
|
|
@@ -305,7 +324,7 @@ function getTrailingConsonants(text) {
|
|
|
305
324
|
function startsWithVowel(text) {
|
|
306
325
|
return matchVowel(text, 0) !== null;
|
|
307
326
|
}
|
|
308
|
-
function parseSyllables(text) {
|
|
327
|
+
function parseSyllables(text, preferOnset = true) {
|
|
309
328
|
const syllables = [];
|
|
310
329
|
const parts = text.split(".");
|
|
311
330
|
for (const part of parts) {
|
|
@@ -332,7 +351,7 @@ function parseSyllables(text) {
|
|
|
332
351
|
const curr = merged[i];
|
|
333
352
|
const next = merged[i + 1];
|
|
334
353
|
if (startsWithVowel(next.text)) {
|
|
335
|
-
const { before, trailing } = getTrailingConsonants(curr.text);
|
|
354
|
+
const { before, trailing } = getTrailingConsonants(curr.text, preferOnset);
|
|
336
355
|
if (trailing && before) {
|
|
337
356
|
curr.text = before;
|
|
338
357
|
next.text = trailing + next.text;
|
|
@@ -512,9 +531,10 @@ function applyStressMarker(hangul, stress, format) {
|
|
|
512
531
|
}
|
|
513
532
|
function ipaToHangul(ipa, options) {
|
|
514
533
|
if (!ipa) return "";
|
|
534
|
+
const preferOnset = options?.preferOnset !== false;
|
|
515
535
|
const cleaned = preprocessIPA(ipa);
|
|
516
536
|
if (!cleaned) return "";
|
|
517
|
-
const syllables = parseSyllables(cleaned);
|
|
537
|
+
const syllables = parseSyllables(cleaned, preferOnset);
|
|
518
538
|
const results = [];
|
|
519
539
|
for (const syllable of syllables) {
|
|
520
540
|
const segments = splitByLongVowel(syllable.text);
|
package/dist/index.mjs
CHANGED
|
@@ -238,7 +238,7 @@ function preprocessIPA(ipa) {
|
|
|
238
238
|
function hasIPAVowel(text) {
|
|
239
239
|
return /[iɪeɛæɑɒɔʌəɜɝʊuoa]/.test(text);
|
|
240
240
|
}
|
|
241
|
-
function getTrailingConsonants(text) {
|
|
241
|
+
function getTrailingConsonants(text, preferOnset = false) {
|
|
242
242
|
let i = text.length;
|
|
243
243
|
while (i > 0) {
|
|
244
244
|
if (i >= 2) {
|
|
@@ -260,6 +260,25 @@ function getTrailingConsonants(text) {
|
|
|
260
260
|
if (!allTrailing) {
|
|
261
261
|
return { before: text, trailing: "" };
|
|
262
262
|
}
|
|
263
|
+
if (preferOnset) {
|
|
264
|
+
if (allTrailing.length >= 2) {
|
|
265
|
+
const lastTwo = allTrailing.substring(allTrailing.length - 2);
|
|
266
|
+
if (CONSONANT_TO_CHOSEONG[lastTwo] || CONSONANT_TO_JAMO[lastTwo]) {
|
|
267
|
+
return {
|
|
268
|
+
before: beforeConsonants + allTrailing.substring(0, allTrailing.length - 2),
|
|
269
|
+
trailing: lastTwo
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const lastOne = allTrailing[allTrailing.length - 1];
|
|
274
|
+
if (CONSONANT_TO_CHOSEONG[lastOne] || CONSONANT_TO_JAMO[lastOne]) {
|
|
275
|
+
return {
|
|
276
|
+
before: beforeConsonants + allTrailing.substring(0, allTrailing.length - 1),
|
|
277
|
+
trailing: lastOne
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
return { before: text, trailing: "" };
|
|
281
|
+
}
|
|
263
282
|
let keepUntil = 0;
|
|
264
283
|
if (allTrailing.length >= 2) {
|
|
265
284
|
const twoChar = allTrailing.substring(0, 2);
|
|
@@ -281,7 +300,7 @@ function getTrailingConsonants(text) {
|
|
|
281
300
|
function startsWithVowel(text) {
|
|
282
301
|
return matchVowel(text, 0) !== null;
|
|
283
302
|
}
|
|
284
|
-
function parseSyllables(text) {
|
|
303
|
+
function parseSyllables(text, preferOnset = true) {
|
|
285
304
|
const syllables = [];
|
|
286
305
|
const parts = text.split(".");
|
|
287
306
|
for (const part of parts) {
|
|
@@ -308,7 +327,7 @@ function parseSyllables(text) {
|
|
|
308
327
|
const curr = merged[i];
|
|
309
328
|
const next = merged[i + 1];
|
|
310
329
|
if (startsWithVowel(next.text)) {
|
|
311
|
-
const { before, trailing } = getTrailingConsonants(curr.text);
|
|
330
|
+
const { before, trailing } = getTrailingConsonants(curr.text, preferOnset);
|
|
312
331
|
if (trailing && before) {
|
|
313
332
|
curr.text = before;
|
|
314
333
|
next.text = trailing + next.text;
|
|
@@ -488,9 +507,10 @@ function applyStressMarker(hangul, stress, format) {
|
|
|
488
507
|
}
|
|
489
508
|
function ipaToHangul(ipa, options) {
|
|
490
509
|
if (!ipa) return "";
|
|
510
|
+
const preferOnset = options?.preferOnset !== false;
|
|
491
511
|
const cleaned = preprocessIPA(ipa);
|
|
492
512
|
if (!cleaned) return "";
|
|
493
|
-
const syllables = parseSyllables(cleaned);
|
|
513
|
+
const syllables = parseSyllables(cleaned, preferOnset);
|
|
494
514
|
const results = [];
|
|
495
515
|
for (const syllable of syllables) {
|
|
496
516
|
const segments = splitByLongVowel(syllable.text);
|