UNPKG

@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.

145 lines (144 loc) 6.09 kB
import { insertGlottalStop } from "./insert-glottal-stop.js"; /** * Represents strings that have alternatives when preceded by W or Y, such as * most of the vowel forms in column 3 of the standard vowel table. */ export class WithWYAlternative { defaultValue; valueAfterW; valueAfterY; static add(first, second) { if (typeof first == "string") { if (typeof second == "string") { return first + second; } return first + second.withPreviousText(first); } return first.add(second); } /** * Coerces a string or `WithWYAlternative` as a `WithWYAlternative`. * * @param text The string or `WithWYAlternative` to create an object from. * @returns A `WithWYAlternative` containing the input data. */ static of(text) { if (text instanceof WithWYAlternative) { return text; } return new WithWYAlternative(text, text, text); } /** * Constructs a `WithWYAlternative`. * * @param defaultValue The default value. * @param valueAfterW The value when preceded by W. * @param valueAfterY The value when preceded by Y. * @returns The constructed, frozen `WithWYAlternative`. */ constructor(defaultValue, valueAfterW, valueAfterY) { this.defaultValue = defaultValue; this.valueAfterW = valueAfterW; this.valueAfterY = valueAfterY; Object.freeze(this); } /** * Gets the appropriate field (defaultValue, precededByW, or precededByY) * based on the contents of text preceding this `WithWYAlternative`. * * @param text The text preceding this `WithWYAlternative`. * @returns The value of the appropriate field. */ withPreviousText(text) { if (text.endsWith("w")) { return this.valueAfterW; } if (text.endsWith("y")) { return this.valueAfterY; } return this.defaultValue; } /** * Adds this `WithWYAlternative` to a string or another `WithWYAlternative`. * * @param other A string or `WithWYAlternative` to add this to. * @returns A `WithWYAlternative` containing the appropriate outputs. */ add(other) { other = WithWYAlternative.of(other); return new WithWYAlternative(this.defaultValue + other.withPreviousText(this.defaultValue), this.valueAfterW + other.withPreviousText(this.valueAfterW), this.valueAfterY + other.withPreviousText(this.valueAfterY)); } /** * Stringifies this WithWYAlternative. * * @returns A stringified representation of this WithWYAlternative. */ toString() { if (this.defaultValue != this.valueAfterW && this.defaultValue != this.valueAfterY) { return `(${this.defaultValue}/${this.valueAfterW}/${this.valueAfterY})`; } if (this.defaultValue != this.valueAfterW) { return `(${this.defaultValue}/${this.valueAfterW})`; } if (this.defaultValue != this.valueAfterY) { return `(${this.defaultValue}/${this.valueAfterY})`; } return this.defaultValue; } /** * Inserts glottal stops into this `WithWYAlternative`. * * @param isAtEndOfWord Whether this `WithWYAlternative` is at the end of a * word. * @returns A `WithWYAlternative` containing the contents of this one, but * with a glottal stop in each alternative. */ insertGlottalStop(isAtEndOfWord) { return new WithWYAlternative(insertGlottalStop(this.defaultValue, isAtEndOfWord), insertGlottalStop(this.valueAfterW, isAtEndOfWord), insertGlottalStop(this.valueAfterY, isAtEndOfWord)); } } /** A `WithWYAlternative` instance containing the empty string. */ export const EMPTY = /* @__PURE__ */ new WithWYAlternative("", "", ""); /** A `WithWyAlternative` instance containing `ia/uä`. */ export const IA_UÄ = /* @__PURE__ */ new WithWYAlternative("ia", "ia", "uä"); /** A `WithWyAlternative` instance containing `ie/uë`. */ export const IE_UË = /* @__PURE__ */ new WithWYAlternative("ie", "ie", "uë"); /** A `WithWyAlternative` instance containing `io/üä`. */ export const IO_ÜÄ = /* @__PURE__ */ new WithWYAlternative("io", "io", "üä"); /** A `WithWyAlternative` instance containing `iö/üë`. */ export const IÖ_ÜË = /* @__PURE__ */ new WithWYAlternative("iö", "iö", "üë"); /** A `WithWyAlternative` instance containing `uö/öë`. */ export const UÖ_ÖË = /* @__PURE__ */ new WithWYAlternative("uö", "öë", "uö"); /** A `WithWyAlternative` instance containing `uo/öä`. */ export const UO_ÖÄ = /* @__PURE__ */ new WithWYAlternative("uo", "öä", "uo"); /** A `WithWyAlternative` instance containing `ue/ië`. */ export const UE_IË = /* @__PURE__ */ new WithWYAlternative("ue", "ië", "ue"); /** A `WithWyAlternative` instance containing `ua/iä`. */ export const UA_IÄ = /* @__PURE__ */ new WithWYAlternative("ua", "iä", "ua"); /** * Joins several strings and vowel forms into a `WithWYAlternative`. Passing the * proper `isAtEndOfWord` value to `VowelForm`s is taken care of automatically. * * This is intended to be used to create a full word, as it will not preserve * forms which can alternate if they are at the beginning of the word. * * @param texts The strings and `WithWYAlternative`s to create an object from. * @returns A `WithWYAlternative` containing all input data, joined properly. */ export function join(...texts) { return texts .flat() .filter((x) => x != null) .filter((x) => x != "") .reduce((a, b, i, list) => { if (b instanceof WithWYAlternative || typeof b == "string") { return WithWYAlternative.add(a, b); } const isEnd = list.slice(i + 1).every( // Only need to check `defaultValue` since we're after a // `VowelForm`, which will never end in -w or -y (x) => x instanceof WithWYAlternative && x.defaultValue == ""); return a + b.toString(isEnd); }, ""); }