Hîsyêô Abugida

Newest candidate for Koqatha's official writing system.

by MadcapJake

HTML

<label>
  <input id="quoteTypeSquare" type="radio" name="quoteType" checked/> 「 and 」
</label>
<label>
  <input id="quoteTypeButton" type="radio" name="quoteType"/>  ◖ and ◗
</label>
<label>
  <input id="commaToggle" type="checkbox" checked/> , = 、
</label>
<br /><br />
<div class="inWrapper">
  <label>Latin:</label>
  <textarea id="latinIn" cols="80" rows="3" spellcheck="false">
    zowo hônyo cûtî bûlo fîkî ulyô socok xe kôs zoston mût boxô dîzel yê zowo legêfû onô.
  </textarea>
  <button id="copyHisyeo" type="button">Copy 👇</button>
</div>
<div class="hidden" id="hisyeoOutText"></div>
<div id="hisyeoOut"></div>

CSS

@import url('https://fonts.cdnfonts.com/css/charis-sil');
@import url('https://fonts.cdnfonts.com/css/doulos-sil');
@import url('https://fonts.cdnfonts.com/css/gentium-plus');
@import url('https://fonts.cdnfonts.com/css/noto-sans');

* {
  /* font-family: 'Charis SIL', sans-serif; */
  /* font-family: 'Gentium Plus', sans-serif; */
  font-family: "Noto Sans", sans-serif;
  /* font-family: "Arial", sans-serif; */
}

.inWrapper {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

#hisyeoOut, #latinOut {
  margin-top: 5px;
  padding: 3px;
  border: 2px solid black;
  min-width: 400px;
  min-height: 20px;
  border-radius: 5px;
  font-size: 2em;
  background-color: white;
}


.hidden {
  display: none;
}

label {
  padding-right: 20px;
}

button {
  margin: 3px;
  color: black;
}

button.flash {
  animation: flash 1s linear forwards;
}

@keyframes flash {
 0% { color: red; }
 100% { color: black; } 
}

JavaScript

const lCons =  ["'", "ꞌ", 'h', 'k', 'g', 't', 'c', 's', 'x', 'd', 'z', 'b', 'f', 'm', 'n', 'w', 'l', 'y'],
		  kCons =  ['ɽ', 'ɽ', 'ɂ', 'ɔ', 'ꜿ', 'c', 'ꞇ', 'ɐ', 'ɋ', 'ʌ', 'ⱴ', 'ʋ', 'ɤ', 'ƶ', 'ƨ', 'ʒ', 'ʓ', 'ɀ']; // oϷʑʌxɕƨɂɞɤʁⱶ
const lVowels = ['o', 'ô', 'u', 'û', 'i', 'î', 'e', 'ê'];
const kVowels = ['',  'ı', 'ʃ', 'ʄ', 'ȷ', 'ɟ', 'ɿ', 'ʇ']; // 'ɿjɉɩᵼ'; //ꜣꞌᶫ      ıȷjʝſɿɾrɍɩᵼ℩℩
const lDiacritics = ['t',/* ◌̑ */'k',/* ◌͒ */ 's',/* ◌̀ */'c',/* ◌̄ */'n',/* ◌̉ */'l',/* ◌̉ */],
	    kDiacritics = ['\u0306',  '\u0311',   '\u0301',  '\u0304',  '\u0303',  '\u034a',];

quoteTypeSquare.oninput = quoteTypeButton.oninput = commaToggle.oninput = () => latinIn.oninput()

index = (loc, val) => loc.indexOf(val.toLowerCase())

latinIn.oninput = function (e) {
    let quotation = quoteTypeSquare.checked ? ['\uFF62', '\uFF63'] : ['\u25D6', '\u25D7']
    hisyeoOutText.innerText = latinIn.value
        // Pre-process quotation marks, replacing with [ and ] as placeholder quotation marks
        .split('"')
        .reduce((acc, v, i) => acc + (i % 2 ? '[' : ']') + v)
        // Pre-process proper nouns, adding { and } as placeholder transliteration marks
        .replace(/\b[A-ZÔÊÎÛ][A-ZÔÊÎÛa-zôêîûꞌ']*(?: [A-ZÔÊÎÛ][A-ZÔÊÎÛa-zôêîûꞌ']*)*/g, '{$&}')
        // Replace abugida characters
        .replace(
            /([ꞌhkgtcsxdzbfmnlwy])?([oôuûiîeê])((?:[kntscl])(?![oôuûiîeê]))?|([ꞌhkgtcsxdzbfmnlwy])(?![oôuûiîeê])/gi, // RegEx: cons?+vowel+n? | const
            (p0, p1, p2, p3, p4) => {
            		// console.log(p0);
                return p4 // If no vowel found
                    ? kCons[index(lCons, p4)] // Null consonant
                    : kCons[(p1 ? index(lCons, p1) : 0)]  + // Leading consonant
                      (p3 ? kDiacritics[index(lDiacritics, p3)] : '') +
                      (kVowels[index(lVowels, p2)] || '')
            }
                      
        )
        // Replace punctuation
        .replace(/,/g,...