@zsnout/ithkuil
Version:
A set of tools which can generate and parse romanized Ithkuil text and which can generate Ithkuil script from text and JSON data.
147 lines (146 loc) • 3.96 kB
JavaScript
import { deepFreezeAndNullPrototype } from "../generate/index.js";
export const STRESSED_TO_UNSTRESSED_VOWEL_MAP =
/* @__PURE__ */ deepFreezeAndNullPrototype({
á: "a",
é: "e",
í: "i",
ó: "o",
ú: "u",
â: "ä",
ê: "ë",
ô: "ö",
û: "ü",
});
// Taken from https://github.com/ngoriyasjil/IthkuilGloss/blob/181241b89c962d83b999a669c298366b07df53b9/src/ithkuil/iv/gloss/Constants.kt#L27C4-L27C4
const LETTER_SUBSTITUTIONS = /* @__PURE__ */ deepFreezeAndNullPrototype({
"": "",
// The previous line is keyed with the Unicode Byte Order Mark
"’": "'",
ʼ: "'",
"‘": "'",
á: "á",
ä: "ä",
â: "â",
é: "é",
ë: "ë",
ê: "ê",
ì: "i",
ı: "i",
ì: "i",
í: "í",
ó: "ó",
ö: "ö",
ô: "ô",
ù: "u",
ù: "u",
ú: "ú",
ü: "ü",
û: "û",
č: "č",
ç: "ç",
ṭ: "ţ",
ŧ: "ţ",
ț: "ţ",
ţ: "ţ",
ṭ: "ţ",
ḍ: "ḑ",
đ: "ḑ",
ḍ: "ḑ",
ḑ: "ḑ",
ł: "ļ",
ḷ: "ļ",
ḷ: "ļ",
ļ: "ļ",
š: "š",
ž: "ž",
ż: "ż",
ẓ: "ż",
ẓ: "ż",
ṇ: "ň",
ň: "ň",
ņ: "ň",
ṇ: "ň",
ṛ: "ř",
ř: "ř",
ŗ: "ř",
r͕: "ř",
ŗ: "ř",
ṛ: "ř",
});
const LETTER_SUBSTITUTION_REGEX =
// The first element of this character class is the Unicode Byte Order Mark
/[’ʼ‘ìıùṭŧțḍđłḷẓṇṛŗ]|á|ä|â|é|ë|ê|ì|í|ó|ö|ô|ù|ú|ü|û|č|ç|ţ|ṭ|ḍ|ḑ|ḷ|ļ|š|ž|ż|ẓ|ň|ņ|ṇ|ř|ŗ|r͕|ṛ/gu;
/**
* Transforms a word by normalizing spelling and parsing and removing stress
* markings.
*
* @param word The word to be transformed.
* @returns An object containing information about the transformed word.
*/
export function transformWord(word) {
const original = word;
word = word
.toLowerCase()
.replace(LETTER_SUBSTITUTION_REGEX, (x) => LETTER_SUBSTITUTIONS[x]);
if (word.startsWith("'")) {
word = word.slice(1);
}
const syllables = word.match(/[aáeéëêoóuú][ií]|[aáeéëêiíoó][uú]|[aeiouäëöüáéíóúâêôû]/g);
let stress;
if (syllables == null) {
stress = "zerosyllabic";
}
else if (syllables.length == 1) {
stress = "monosyllabic";
}
else {
const stressed = syllables.map((syllable) => /[áéíóúâêôû]/.test(syllable));
const index = stressed.findIndex((x) => x);
const lastIndex = stressed.findLastIndex((x) => x);
if (index != lastIndex) {
throw new Error("Two syllables are marked as stressed.");
}
if (index == -1) {
stress = "penultimate";
}
else {
const value = stressed.length - index;
if (value == 1) {
stress = "ultimate";
}
else if (value == 2) {
stress = "penultimate";
}
else if (value == 3) {
stress = "antepenultimate";
}
else {
throw new Error("Invalid stress in '" + word + "'.");
}
}
}
return Object.freeze({
original,
word: word.replace(/[áéíóúâêôû]/g, (x) => STRESSED_TO_UNSTRESSED_VOWEL_MAP[x]),
stress,
});
}
/**
* Transforms a word by normalizing spelling. Does not remove stress markings.
*
* @param word The word to be transformed.
* @returns An object containing information about the transformed word.
*/
export function transformWordButLeaveStressMarkings(word) {
const original = word;
word = word
.toLowerCase()
.replace(LETTER_SUBSTITUTION_REGEX, (x) => LETTER_SUBSTITUTIONS[x]);
if (word.startsWith("'")) {
word = word.slice(1);
}
return Object.freeze({
original,
word,
});
}