Pronunciation nasal improvement (#1834)

* Organize

* Add utility to get diacritic information about a character

* Show mora without diacritic

* Add a hidden handakuten for copy-paste purposes
This commit is contained in:
toasted-nutbread 2021-07-17 12:20:11 -04:00 committed by GitHub
parent 4a2b824371
commit a933cfdc07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 7 deletions

View File

@ -77,6 +77,12 @@
box-sizing: border-box;
z-index: 1;
}
.pitch-accent-character-nasal-diacritic {
position: absolute;
width: 0;
height: 0;
opacity: 0;
}
.pitch-accent-position::before {
content: ' [';

View File

@ -35,16 +35,14 @@ class PronunciationGenerator {
const n1 = document.createElement('span');
n1.className = 'pitch-accent-character';
const n2 = document.createElement('span');
n2.className = 'pitch-accent-character-inner';
n1.appendChild(n2);
n1.dataset.position = `${i}`;
n1.dataset.pitch = highPitch ? 'high' : 'low';
n1.dataset.pitchNext = highPitchNext ? 'high' : 'low';
const n2 = document.createElement('span');
n2.className = 'pitch-accent-character-inner';
n2.textContent = mora;
n1.appendChild(n2);
if (devoice) {
n1.dataset.devoice = 'true';
@ -54,7 +52,13 @@ class PronunciationGenerator {
}
if (nasal) {
n1.dataset.nasal = 'true';
const n3 = document.createElement('span');
n1.dataset.originalText = mora;
n2.textContent = this._getPlainMora(mora);
let n3 = document.createElement('span');
n3.className = 'pitch-accent-character-nasal-diacritic';
n3.textContent = '\u309a'; // Combining handakuten
n1.appendChild(n3);
n3 = document.createElement('span');
n3.className = 'pitch-accent-character-nasal-indicator';
n1.appendChild(n3);
}
@ -142,4 +146,11 @@ class PronunciationGenerator {
node.setAttribute('r', radius);
return node;
}
_getPlainMora(mora) {
const first = mora[0];
const info = this._japaneseUtil.getKanaDiacriticInfo(first);
if (info === null) { return mora; }
return `${info.character}${mora.substring(1)}`;
}
}

View File

@ -154,6 +154,21 @@ const JapaneseUtil = (() => {
return map;
})();
const DIACRITIC_MAPPING = (() => {
const kana = 'うゔ-かが-きぎ-くぐ-けげ-こご-さざ-しじ-すず-せぜ-そぞ-ただ-ちぢ-つづ-てで-とど-はばぱひびぴふぶぷへべぺほぼぽワヷ-ヰヸ-ウヴ-ヱヹ-ヲヺ-カガ-キギ-クグ-ケゲ-コゴ-サザ-シジ-スズ-セゼ-ソゾ-タダ-チヂ-ツヅ-テデ-トド-ハバパヒビピフブプヘベペホボポ';
const map = new Map();
for (let i = 0, ii = kana.length; i < ii; i += 3) {
const character = kana[i];
const dakuten = kana[i + 1];
const handakuten = kana[i + 2];
map.set(dakuten, {character, type: 'dakuten'});
if (handakuten !== '-') {
map.set(handakuten, {character, type: 'handakuten'});
}
}
return map;
})();
function isCodePointInRange(codePoint, [min, max]) {
return (codePoint >= min && codePoint <= max);
@ -417,6 +432,11 @@ const JapaneseUtil = (() => {
return this._wanakana !== null;
}
getKanaDiacriticInfo(character) {
const info = DIACRITIC_MAPPING.get(character);
return typeof info !== 'undefined' ? {character: info.character, type: info.type} : null;
}
// Furigana distribution
distributeFurigana(term, reading) {