hebrew-transliteration 2.7.0 → 2.8.0
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/cjs/rules.js +132 -130
- package/dist/cjs/rules.js.map +3 -3
- package/dist/cjs/schema.js +23 -9
- package/dist/cjs/schema.js.map +3 -3
- package/dist/cjs/schemas/jss.js +1 -1
- package/dist/cjs/schemas/jss.js.map +1 -1
- package/dist/cjs/schemas/sblAcademicSpirantization.js +1 -1
- package/dist/cjs/schemas/sblAcademicSpirantization.js.map +1 -1
- package/dist/cjs/schemas/tiberian.js +9 -4
- package/dist/cjs/schemas/tiberian.js.map +2 -2
- package/dist/esm/rules.js +182 -180
- package/dist/esm/rules.js.map +1 -1
- package/dist/esm/schema.js +31 -17
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/schemas/jss.js +1 -1
- package/dist/esm/schemas/sblAcademicSpirantization.js +1 -1
- package/dist/esm/schemas/tiberian.js +17 -6
- package/dist/esm/schemas/tiberian.js.map +1 -1
- package/dist/types/rules.d.ts +0 -18
- package/dist/types/schema.d.ts +42 -22
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/schemas/tiberian.ts"],
|
|
4
|
-
"sourcesContent": ["import { Schema } from \"../schema\";\n\nexport const tiberian: Schema = {\n VOCAL_SHEVA: \"a\",\n HATAF_SEGOL: \"\u025B\",\n HATAF_PATAH: \"a\",\n HATAF_QAMATS: \"\u0254\",\n HIRIQ: \"i\",\n TSERE: \"e\",\n SEGOL: \"\u025B\",\n PATAH: \"a\",\n QAMATS: \"\u0254\",\n HOLAM: \"o\",\n HOLAM_HASER: \"o\",\n QUBUTS: \"u\",\n DAGESH: \"\",\n DAGESH_CHAZAQ: true,\n MAQAF: \"-\",\n PASEQ: \"\",\n SOF_PASUQ: \"\",\n QAMATS_QATAN: \"\u0254\",\n FURTIVE_PATAH: \"a\",\n HIRIQ_YOD: \"i\u02D0\",\n TSERE_YOD: \"e\u02D0\",\n SEGOL_YOD: \"\u025B\u02D0\",\n SHUREQ: \"u\u02D0\",\n HOLAM_VAV: \"o\u02D0\",\n QAMATS_HE: \"\u0254\u02D0\",\n SEGOL_HE: \"\u025B\u02D0\",\n TSERE_HE: \"e\u02D0\",\n MS_SUFX: \"\u0254w\",\n ALEF: \"\u0294\",\n BET: \"v\",\n BET_DAGESH: \"b\",\n GIMEL: \"\u0281\",\n GIMEL_DAGESH: \"g\",\n DALET: \"\u00F0\",\n DALET_DAGESH: \"d\",\n HE: \"h\",\n VAV: \"v\",\n ZAYIN: \"z\",\n HET: \"\u0127\",\n TET: \"t\u02C1\",\n YOD: \"j\",\n FINAL_KAF: \"\u03C7\",\n KAF: \"\u03C7\",\n KAF_DAGESH: \"k\u02B0\",\n LAMED: \"l\",\n FINAL_MEM: \"m\",\n MEM: \"m\",\n FINAL_NUN: \"n\",\n NUN: \"n\",\n SAMEKH: \"s\",\n AYIN: \"\u0295\",\n FINAL_PE: \"f\",\n PE: \"f\",\n PE_DAGESH: \"p\u02B0\",\n FINAL_TSADI: \"s\u02C1\",\n TSADI: \"s\u02C1\",\n QOF: \"q\u031F\",\n RESH: \"\u0280\u031F\",\n SHIN: \"\u0283\",\n SIN: \"s\",\n TAV: \"\u03B8\",\n TAV_DAGESH: \"t\u02B0\",\n DIVINE_NAME: \"\u0294a\u00F0o\u02D0\u02C8n\u0254\u02D0\u0254j\",\n DIVINE_NAME_ELOHIM: \"\u0294\u025Blo\u02D0\u02C8hi\u02D0im\",\n STRESS_MARKER: { location: \"before-syllable\", mark: \"\u02C8\" },\n ADDITIONAL_FEATURES: [\n {\n FEATURE: \"cluster\",\n HEBREW: \"\\u{05D9}\\u{05BC}\",\n TRANSLITERATION: (cluster, hebrew) => {\n return cluster.text.replace(hebrew, \"\u025F\u025F\");\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05EA\u05BC(?!\\u{05B0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // if there is a dagesh, but it is the beginning of the word\n // we can return the text, as the character w/ the dagesh will not be doubled\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n // if there is a dagesh, it may be that it is a dagesh qal (i.e. lene)\n // if it is a dagesh lene, then like the beginning of the word,\n // the character w/ the dagesh will not be doubled\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05EA\")) {\n return cluster.text;\n }\n\n // because the *_DAGESH value is a digraph, we need to replace the first character\n // or it will be doubled in rules.ts as \"t\u02B0t\u02B0\"\n const noAspiration = schema[\"TAV_DAGESH\"]?.replace(\"\u02B0\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05EA\u05BC\", `${noAspiration + schema[\"TAV_DAGESH\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05E4(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA(?!\\u{05b0})/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05E4\")) {\n return cluster.text;\n }\n\n const noAspiration = schema[\"PE_DAGESH\"]?.replace(\"\u02B0\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05E4\u05BC\", `${noAspiration + schema[\"PE_DAGESH\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05D8\u05BC(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA(?!\\u{05b0})/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05D8\")) {\n return cluster.text;\n }\n\n const noPharyngealization = schema[\"TET\"]?.replace(\"\u02C1\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05D8\", `${noPharyngealization + schema[\"TET\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05E6\u05BC(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA(?!\\u{05b0})/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05E6\")) {\n return cluster.text;\n }\n\n const noPharyngealization = schema[\"TSADI\"]?.replace(\"\u02C1\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05E6\", `${noPharyngealization + schema[\"TSADI\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /(\u05DB\u05BC|\u05DA\u05BC)(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA\u05BC[\\u{05B4}-\\u{05BB}]/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05DB\") && !prevCoda?.includes(\"\u05DA\")) {\n return cluster.text;\n }\n\n const noAspiration = schema[\"KAF_DAGESH\"]?.replace(\"\u02B0\", \"\") ?? \"\";\n return cluster.text.replace(/\u05DB\u05BC|\u05DA\u05BC/u, `${noAspiration + schema[\"KAF_DAGESH\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: \"\\u{05D0}(?![\\u{05B1}-\\u{05BB}\\u{05C7}])\",\n TRANSLITERATION: (cluster) => {\n const next = cluster.next?.value;\n if (next && next.isShureq) {\n return cluster.text;\n }\n\n return \"\";\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: \"\\u{05D0}\\u{05BC}\",\n TRANSLITERATION: (cluster) => {\n // remove the dagesh\n return cluster.text.replace(\"\\u{05BC}\", \"\");\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /\u05E8/u,\n TRANSLITERATION: (syllable) => {\n // see TPT 229 for a summary if the pharyngealized resh\n const alveolars = /[\u05D3\u05D6\u05E6\u05EA\u05D8\u05E1\u05DC\u05E0]|\u05E9\u05C2/;\n\n // find cluster containing resh\n const cluster = syllable.clusters.filter((c) => c.text.includes(\"\u05E8\"))[0];\n const prevCluster = cluster.prev?.value;\n const currentSyllable = cluster?.syllable;\n const [onset, _, coda] = currentSyllable ? currentSyllable.structure(true) : [\"\", \"\", \"\"];\n\n if (prevCluster && alveolars.test(prevCluster.text)) {\n if (onset.includes(\"\u05E8\") && !prevCluster.hasVowel) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n\n if (coda.includes(\"\u05E8\") && prevCluster.hasVowel) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n }\n\n const nextCluster = cluster.next?.value;\n const lamedAndNun = /[\u05DC\u05E0\u05DF]/;\n if (nextCluster && lamedAndNun.test(nextCluster.text)) {\n if (onset.includes(\"\u05E8\") && !cluster.hasVowel) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n\n if (coda.includes(\"\u05E8\") && cluster.hasSheva) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n }\n\n // default\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: \"\u05D7\\u{05B7}\\u{05C3}?$\",\n PASS_THROUGH: true,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // furtive patach before het preceded by vav or yod\n const prevText = syllable.prev?.value?.text || \"\";\n // see Khan 497-98 for examples involving length and the meteg\n // make sure to adjust other rules\n if (syllable.isFinal && prevText) {\n if (/[\u05D9\u05D5]/.test(prevText)) {\n const glide = /\u05D5/.test(prevText) ? \"w\" : \"j\";\n return glide + schema[\"PATAH\"] + schema[\"HET\"];\n }\n return schema[\"PATAH\"] + schema[\"HET\"];\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: \"\u05E2\\u{05B7}\\u{05C3}?$\",\n PASS_THROUGH: true,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // furtive patach before ayin preceded by vav or yod\n const prevText = syllable.prev?.value?.text;\n\n if (syllable.isFinal && prevText) {\n if (/[\u05D9\u05D5]/.test(prevText)) {\n const glide = /\u05D5/.test(prevText) ? \"w\" : \"j\";\n return glide + schema[\"PATAH\"] + schema[\"AYIN\"];\n }\n return schema[\"PATAH\"] + schema[\"AYIN\"];\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: \"\u05D4\\u{05BC}\\u{05B7}\\u{05C3}?$\",\n PASS_THROUGH: true,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // furtive patach before he preceded by vav or yod\n const prevText = syllable.prev?.value?.text;\n\n if (syllable.isFinal && prevText) {\n if (/[\u05D9\u05D5]/.test(prevText)) {\n const glide = /\u05D5/.test(prevText) ? \"w\" : \"j\";\n return glide + schema[\"PATAH\"] + schema[\"HE\"];\n }\n return schema[\"PATAH\"] + schema[\"HE\"];\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /\u05D5\u05BC(?![\\u{05B4}-\\u{05BB}])/u,\n TRANSLITERATION: (syllable, _, schema) => {\n // finds a vav with a dagesh not followed by a vowel character\n // if the syllable is the first syllable, replace with wu\u02D0\n // syllable.clusters[0].isShureq is not totally necessary, but it's a good check\n if (!syllable.prev && syllable.clusters[0].isShureq) {\n const text = syllable.text;\n const hasMeteg = syllable.clusters.map((c) => c.hasMeteg).includes(true); // also called gaya marking half long vowel length (\u00A71.2.8.2.2)\n const secondaryAccent = hasMeteg ? \"\u02CC\" : \"\";\n const halfLengthMarker = hasMeteg ? \"\u02D1\" : \"\";\n return text.replace(\"\u05D5\u05BC\", `${secondaryAccent}wu${halfLengthMarker}`);\n }\n\n if (syllable.isAccented && syllable.isClosed) {\n const noLength = schema[\"SHUREQ\"].replace(\"\u02D0\", \"\");\n return syllable.text.replace(\"\u05D5\u05BC\", schema[\"SHUREQ\"] + noLength);\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /[\\u{05B4}-\\u{05BB}\\u{05C7}]/u,\n TRANSLITERATION: (syllable, _, schema) => {\n // this features matches any syllable that has a full vowel character (i.e. not sheva)\n const vowelName = syllable.vowelNames[0];\n const vowel = syllable.vowels[0];\n\n if (!vowel || !vowelName) {\n return syllable.text;\n }\n\n if (vowelName === \"SHEVA\") {\n throw new Error(`Syllable ${syllable.text} has a sheva as vowel, should not have matched`);\n }\n\n // half vowels do not have length; exit early\n const hasHalfVowel = syllable.clusters.map((c) => c.hasHalfVowel).includes(true);\n if (hasHalfVowel) {\n throw new Error(`Syllable ${syllable.text} has a hataf as vowel, should not have matched`);\n }\n\n const [onset, _nuclues, coda] = syllable.structure(true);\n /**\n * Determines the realization of a patach\n *\n * @param vowelChar the hebrew vowel character\n * @returns the back unrounded patach realization of the vowel or the original vowel if not patach\n */\n function determinePatachRealization(vowelChar: string) {\n // see comment for explanation: https://github.com/charlesLoder/hebrew-transliteration/issues/45#issuecomment-1712186201\n // exit early if not patach\n if (vowelName !== \"PATAH\" && vowelName !== \"HATAF_PATAH\") {\n return vowelChar;\n }\n\n // by this point, the resh has already been pharyngealized\n // but only for the current syllable\n const pharyngealized = /r\u02C1|\u05D8|\u05E6|\u05E5/;\n if (pharyngealized.test(onset) || pharyngealized.test(coda)) {\n return \"\u0251\";\n }\n\n // the resh of the next syllable has not been transliterated yet\n // check if the next syllable has a resh in the onset\n // and if the current syllable's coda is an alveolar\n const nextSyllable = syllable.next?.value;\n const nextOnset = nextSyllable?.onset;\n const alveolars = /[\u05D3\u05D6\u05E6\u05EA\u05D8\u05E1\u05DC\u05E0]|\u05E9\u05C2/;\n if (nextOnset === \"\u05E8\" && alveolars.test(coda)) {\n return \"\u0251\";\n }\n\n return vowelChar;\n }\n\n const noMaterText = syllable.clusters\n .filter((c) => !c.isMater)\n .map((c) => c.text)\n .join(\"\")\n // a holem followed by a he without a mappiq is not a mater\n // but b/c the he is not pronounced, we need to remove the final he\n .replace(/(\\u{05B9}.{1})\\u{05D4}(?!\\u{05BC})/u, \"$1\");\n\n const hasMaters = syllable.clusters.map((c) => c.isMater).includes(true);\n const lengthMarker = \"\u02D0\";\n const halfLengthMarker = \"\u02D1\";\n\n // See TPT \u00A71.2.10 concering meteg/gaya\n const hasMeteg = syllable.clusters.map((c) => c.hasMeteg).includes(true);\n if (hasMeteg) {\n const hasLongVowel = syllable.clusters.map((c) => c.hasLongVowel).includes(true);\n // when a meteg is present, the syllable implicitly has secondary stress\n // and the vowel is extended if it is not already long\n const firstConsonant = noMaterText[0];\n return noMaterText\n .replace(firstConsonant, `\u02CC${firstConsonant}`)\n .replace(vowel, `${determinePatachRealization(vowel)}${hasLongVowel ? lengthMarker : halfLengthMarker}`);\n }\n\n const isClosed = syllable.isClosed;\n const isAccented = syllable.isAccented;\n\n // TPT \u00A71.2.4, p288\n // When long vowels with the main stress occur in closed syllables,\n // there is evidence that an epenthetic with the same quality as that of the long vowel\n // occurred before the final consonant in its phonetic realization\"\n if (isAccented && isClosed) {\n const syllableSeparator = schema[\"SYLLABLE_SEPARATOR\"] || \"\";\n const vowelRealization = determinePatachRealization(vowel);\n return noMaterText.replace(\n vowel,\n `${vowelRealization + lengthMarker + syllableSeparator + vowelRealization}`\n );\n }\n\n // https://github.com/charlesLoder/hebrew-transliteration/issues/45#issuecomment-1747967050\n const longerVowels = [\"HOLAM\", \"TSERE\", \"QAMATS\"];\n if (!isAccented && isClosed && !syllable.isFinal && longerVowels.includes(vowelName)) {\n const syllableSeparator = schema[\"SYLLABLE_SEPARATOR\"] || \"\";\n const vowelRealization = determinePatachRealization(vowel);\n return noMaterText.replace(\n vowel,\n `${vowelRealization + lengthMarker + syllableSeparator + vowelRealization}`\n );\n }\n\n // TPT \u00A71.2.2.1 p268\n // Vowels represented by basic vowel signs are long when they are either\n // (i) in a stressed syllable or (ii) in an unstressed open syllable.\n if (isAccented || (!isAccented && !isClosed)) {\n return noMaterText.replace(vowel, `${determinePatachRealization(vowel) + lengthMarker}`);\n }\n\n if (!hasMaters && !isClosed && !isAccented) {\n return noMaterText.replace(vowel, `${determinePatachRealization(vowel)}`);\n }\n\n return syllable.text.replace(vowel, `${determinePatachRealization(vowel)}`);\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /[\\u{05B1}-\\u{05B3}]/u,\n TRANSLITERATION: (syllable) => {\n // this features matches any syllable that has a hataf vowel character\n const vowelName = syllable.vowelNames[0];\n const vowel = syllable.vowels[0];\n\n if (!vowel || !vowelName) {\n return syllable.text;\n }\n\n if (vowelName === \"SHEVA\") {\n throw new Error(`Syllable ${syllable.text} has a sheva as vowel, should not have matched`);\n }\n\n const hasNonHalfVowels = syllable.clusters.map((c) => c.hasShortVowel || c.hasLongVowel).includes(true);\n if (hasNonHalfVowels) {\n throw new Error(`Syllable ${syllable.text} does not have a hataf vowel, should not have matched`);\n }\n\n const [onset, _nuclues, coda] = syllable.structure(true);\n /**\n * Determines the realization of a patach\n *\n * @param vowelChar the hebrew vowel character\n * @returns the back unrounded patach realization of the vowel or the original vowel if not patach\n */\n function determinePatachRealization(vowelChar: string) {\n // exit early if not hataf patach\n if (vowelName !== \"HATAF_PATAH\") {\n return vowelChar;\n }\n\n // by this point, the resh has already been pharyngealized in the transliteration\n // but only for the current syllable\n const pharyngealized = /r\u02C1|\u05D8|\u05E6|\u05E5/;\n if (pharyngealized.test(onset) || pharyngealized.test(coda)) {\n return \"\u0251\";\n }\n\n // the resh of the next syllable has not been transliterated yet\n // check if the next syllable has a resh in the onset\n // and if the current syllable's coda is an alveolar\n const nextSyllable = syllable.next?.value;\n const nextOnset = nextSyllable?.onset;\n const alveolars = /[\u05D3\u05D6\u05E6\u05EA\u05D8\u05E1\u05DC\u05E0]|\u05E9\u05C2/;\n if (nextOnset === \"\u05E8\" && alveolars.test(coda)) {\n return \"\u0251\";\n }\n\n // check for the \"environment of pharyngealized consonants\"\n // https://www.tiberianhebrew.com/patah\n if (nextOnset && /[\u05E6\u05E5\u05D8]/.test(nextOnset)) {\n return \"\u0251\";\n }\n\n return vowelChar;\n }\n\n return syllable.text.replace(vowel, `${determinePatachRealization(vowel)}`);\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /(?<!.*([\\u{05B4}-\\u{05BB}\\u{05C7}]|\\u{05D5}\\u{05BC}).*)\\u{05B0}/u,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // matches any syllable that contains a sheva that is not preceded by a full vowel character [\\u{05B4}-\\u{05BB}\\u{05C7}]\n // or shureq \\u{5D5}\\u{5BC}\n const nextSyllable = syllable.next?.value;\n if (!nextSyllable) return syllable.text;\n\n const nextSylFirstCluster = nextSyllable.clusters[0].text;\n if (!nextSylFirstCluster) return syllable.text;\n\n const [onset, _, coda] = syllable.structure(true);\n\n function isBackUnrounded() {\n // see comment for explanation: https://github.com/charlesLoder/hebrew-transliteration/issues/45#issuecomment-1712186201\n // by this point, the resh has already been pharyngealized in the transliteration\n const pharyngealized = /r\u02C1|\u05D8|\u05E6|\u05E5/;\n if (pharyngealized.test(onset) || pharyngealized.test(coda)) {\n return true;\n }\n\n const nextSyllable = syllable.next?.value;\n if (!nextSyllable) {\n return false;\n }\n\n const nextOnset = nextSyllable.onset;\n if (pharyngealized.test(nextOnset)) {\n return true;\n }\n\n return false;\n }\n\n function transliterateShevaAsVowel(vowel: string) {\n const hasMeteg = syllable.clusters.map((c) => c.hasMeteg).includes(true);\n const secondaryAccent = hasMeteg ? \"\u02CC\" : \"\";\n const halfLengthMarker = hasMeteg ? \"\u02D1\" : \"\";\n const newVowel = vowel.replace(\"\u02D0\", \"\") + halfLengthMarker;\n\n return secondaryAccent + syllable.text.replace(/\\u{05B0}/u, newVowel);\n }\n\n const isGuttural = /[\u05D0\u05D4\u05D7\u05E2]/.test(nextSylFirstCluster);\n if (!isGuttural) {\n return transliterateShevaAsVowel(isBackUnrounded() ? \"\u0251\" : schema[\"PATAH\"]);\n }\n\n const nextVowel = nextSyllable.vowelNames[0];\n if (!nextVowel) {\n throw new Error(\n `Syllable ${syllable.text} has a sheva as a vowel, but the next syllable ${nextSylFirstCluster} does not have a vowel`\n );\n }\n\n if (nextVowel === \"SHEVA\") {\n throw new Error(\n `Syllable ${syllable.text} has a sheva as a vowel, but the next syllable ${nextSylFirstCluster} also has a sheva as a vowel`\n );\n }\n\n return transliterateShevaAsVowel(schema[nextVowel]);\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /\\u{5B4}\u05DD/u,\n TRANSLITERATION: (syl, heb) => {\n // a hiriq preceding a final mem only occurs in Jerusalem\n return syl.text.replace(heb, \"jim\");\n }\n },\n {\n FEATURE: \"word\",\n HEBREW: /(\u05D5\u05B0)?\u05D9\u05B4\u05E9\u05C2\u05BC\u05B8\u05E9\u05DB\u05B8\u05E8/,\n PASS_THROUGH: true,\n TRANSLITERATION: (word, heb) => {\n // matches the name Issachar\n const taamim = /[\\u{0590}-\\u{05AF}\\u{05BD}\\u{05BF}]/gu;\n const text = word.text.replace(taamim, \"\");\n const match = text.match(heb);\n const vav = match && match[1] ? match[1] : \"\";\n const issachar = \"jiss\u0254\u02D0\u02C8\u03C7\u0254\u02D0\u0254\u0280\u031F\";\n return `${vav}${issachar}`;\n }\n }\n ],\n allowNoNiqqud: false,\n article: false,\n holemHaser: \"remove\",\n ketivQeres: [\n {\n input: \"\u05D4\u05B4\u05D5\u05D0\",\n output: \"\u05D4\u05B4\u05D9\u05D0\",\n captureTaamim: true,\n ignoreTaamim: true\n }\n ],\n longVowels: false,\n qametsQatan: true,\n shevaAfterMeteg: false,\n shevaWithMeteg: true,\n sqnmlvy: false,\n strict: true,\n wawShureq: false\n};\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { Schema } from \"../schema\";\n\nexport const tiberian: Schema = {\n VOCAL_SHEVA: \"a\",\n HATAF_SEGOL: \"\u025B\",\n HATAF_PATAH: \"a\",\n HATAF_QAMATS: \"\u0254\",\n HIRIQ: \"i\",\n TSERE: \"e\",\n SEGOL: \"\u025B\",\n PATAH: \"a\",\n QAMATS: \"\u0254\",\n HOLAM: \"o\",\n HOLAM_HASER: \"o\",\n QUBUTS: \"u\",\n DAGESH: \"\",\n DAGESH_CHAZAQ: true,\n MAQAF: \"-\",\n PASEQ: \"\",\n SOF_PASUQ: \"\",\n QAMATS_QATAN: \"\u0254\",\n FURTIVE_PATAH: \"a\",\n HIRIQ_YOD: \"i\u02D0\",\n TSERE_YOD: \"e\u02D0\",\n SEGOL_YOD: \"\u025B\u02D0\",\n SHUREQ: \"u\u02D0\",\n HOLAM_VAV: \"o\u02D0\",\n QAMATS_HE: \"\u0254\u02D0\",\n SEGOL_HE: \"\u025B\u02D0\",\n TSERE_HE: \"e\u02D0\",\n MS_SUFX: \"\u0254w\",\n ALEF: \"\u0294\",\n BET: \"v\",\n BET_DAGESH: \"b\",\n GIMEL: \"\u0281\",\n GIMEL_DAGESH: \"g\",\n DALET: \"\u00F0\",\n DALET_DAGESH: \"d\",\n HE: \"h\",\n VAV: \"v\",\n ZAYIN: \"z\",\n HET: \"\u0127\",\n TET: \"t\u02C1\",\n YOD: \"j\",\n FINAL_KAF: \"\u03C7\",\n KAF: \"\u03C7\",\n KAF_DAGESH: \"k\u02B0\",\n LAMED: \"l\",\n FINAL_MEM: \"m\",\n MEM: \"m\",\n FINAL_NUN: \"n\",\n NUN: \"n\",\n SAMEKH: \"s\",\n AYIN: \"\u0295\",\n FINAL_PE: \"f\",\n PE: \"f\",\n PE_DAGESH: \"p\u02B0\",\n FINAL_TSADI: \"s\u02C1\",\n TSADI: \"s\u02C1\",\n QOF: \"q\u031F\",\n RESH: \"\u0280\u031F\",\n SHIN: \"\u0283\",\n SIN: \"s\",\n TAV: \"\u03B8\",\n TAV_DAGESH: \"t\u02B0\",\n DIVINE_NAME: \"\u0294a\u00F0o\u02D0\u02C8n\u0254\u02D0\u0254j\",\n DIVINE_NAME_ELOHIM: \"\u0294\u025Blo\u02D0\u02C8hi\u02D0im\",\n STRESS_MARKER: { location: \"before-syllable\", mark: \"\u02C8\" },\n ADDITIONAL_FEATURES: [\n {\n FEATURE: \"cluster\",\n HEBREW: \"\\u{05D9}\\u{05BC}\",\n TRANSLITERATION: (cluster, hebrew) => {\n return cluster.text.replace(hebrew, \"\u025F\u025F\");\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05EA\u05BC(?!\\u{05B0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // if there is a dagesh, but it is the beginning of the word\n // we can return the text, as the character w/ the dagesh will not be doubled\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n // if there is a dagesh, it may be that it is a dagesh qal (i.e. lene)\n // if it is a dagesh lene, then like the beginning of the word,\n // the character w/ the dagesh will not be doubled\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05EA\")) {\n return cluster.text;\n }\n\n // because the *_DAGESH value is a digraph, we need to replace the first character\n // or it will be doubled in rules.ts as \"t\u02B0t\u02B0\"\n const noAspiration = schema[\"TAV_DAGESH\"]?.replace(\"\u02B0\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05EA\u05BC\", `${noAspiration + schema[\"TAV_DAGESH\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05E4(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA(?!\\u{05b0})/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05E4\")) {\n return cluster.text;\n }\n\n const noAspiration = schema[\"PE_DAGESH\"]?.replace(\"\u02B0\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05E4\u05BC\", `${noAspiration + schema[\"PE_DAGESH\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05D8\u05BC(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA(?!\\u{05b0})/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05D8\")) {\n return cluster.text;\n }\n\n const noPharyngealization = schema[\"TET\"]?.replace(\"\u02C1\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05D8\", `${noPharyngealization + schema[\"TET\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /\u05E6\u05BC(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA(?!\\u{05b0})/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05E6\")) {\n return cluster.text;\n }\n\n const noPharyngealization = schema[\"TSADI\"]?.replace(\"\u02C1\", \"\") ?? \"\";\n return cluster.text.replace(\"\u05E6\", `${noPharyngealization + schema[\"TSADI\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: /(\u05DB\u05BC|\u05DA\u05BC)(?!\\u{05b0})/u,\n TRANSLITERATION: (cluster, _, schema) => {\n // /\u05EA\u05BC[\\u{05B4}-\\u{05BB}]/u rule for explanation\n if (!cluster.prev || cluster.prev.value?.isNotHebrew) {\n return cluster.text;\n }\n\n const prevCoda = cluster.syllable?.prev?.value?.codaWithGemination;\n if (!prevCoda?.includes(\"\u05DB\") && !prevCoda?.includes(\"\u05DA\")) {\n return cluster.text;\n }\n\n const noAspiration = schema[\"KAF_DAGESH\"]?.replace(\"\u02B0\", \"\") ?? \"\";\n return cluster.text.replace(/\u05DB\u05BC|\u05DA\u05BC/u, `${noAspiration + schema[\"KAF_DAGESH\"]}`);\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: \"\\u{05D0}(?![\\u{05B1}-\\u{05BB}\\u{05C7}])\",\n TRANSLITERATION: (cluster) => {\n const next = cluster.next?.value;\n if (next && next.isShureq) {\n return cluster.text;\n }\n\n return \"\";\n }\n },\n {\n FEATURE: \"cluster\",\n HEBREW: \"\\u{05D0}\\u{05BC}\",\n TRANSLITERATION: (cluster) => {\n // remove the dagesh\n return cluster.text.replace(\"\\u{05BC}\", \"\");\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /\u05E8/u,\n TRANSLITERATION: (syllable) => {\n // see TPT 229 for a summary if the pharyngealized resh\n const alveolars = /[\u05D3\u05D6\u05E6\u05EA\u05D8\u05E1\u05DC\u05E0]|\u05E9\u05C2/;\n\n // find cluster containing resh\n const cluster = syllable.clusters.filter((c) => c.text.includes(\"\u05E8\"))[0];\n const prevCluster = cluster.prev?.value;\n const currentSyllable = cluster?.syllable;\n const [onset, _, coda] = currentSyllable ? currentSyllable.structure(true) : [\"\", \"\", \"\"];\n\n if (prevCluster && alveolars.test(prevCluster.text)) {\n if (onset.includes(\"\u05E8\") && !prevCluster.hasVowel) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n\n if (coda.includes(\"\u05E8\") && prevCluster.hasVowel) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n }\n\n const nextCluster = cluster.next?.value;\n const lamedAndNun = /[\u05DC\u05E0\u05DF]/;\n if (nextCluster && lamedAndNun.test(nextCluster.text)) {\n if (onset.includes(\"\u05E8\") && !cluster.hasVowel) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n\n if (coda.includes(\"\u05E8\") && cluster.hasSheva) {\n return syllable.text.replace(\"\u05E8\", \"r\u02C1\");\n }\n }\n\n // default\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: \"\u05D7\\u{05B7}\\u{05C3}?$\",\n PASS_THROUGH: true,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // furtive patach before het preceded by vav or yod\n const prevText = syllable.prev?.value?.text || \"\";\n // see Khan 497-98 for examples involving length and the meteg\n // make sure to adjust other rules\n if (syllable.isFinal && prevText) {\n if (/[\u05D9\u05D5]/.test(prevText)) {\n const glide = /\u05D5/.test(prevText) ? \"w\" : \"j\";\n return glide + schema[\"PATAH\"] + schema[\"HET\"];\n }\n return schema[\"PATAH\"] + schema[\"HET\"];\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: \"\u05E2\\u{05B7}\\u{05C3}?$\",\n PASS_THROUGH: true,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // furtive patach before ayin preceded by vav or yod\n const prevText = syllable.prev?.value?.text;\n\n if (syllable.isFinal && prevText) {\n if (/[\u05D9\u05D5]/.test(prevText)) {\n const glide = /\u05D5/.test(prevText) ? \"w\" : \"j\";\n return glide + schema[\"PATAH\"] + schema[\"AYIN\"];\n }\n return schema[\"PATAH\"] + schema[\"AYIN\"];\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: \"\u05D4\\u{05BC}\\u{05B7}\\u{05C3}?$\",\n PASS_THROUGH: true,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // furtive patach before he preceded by vav or yod\n const prevText = syllable.prev?.value?.text;\n\n if (syllable.isFinal && prevText) {\n if (/[\u05D9\u05D5]/.test(prevText)) {\n const glide = /\u05D5/.test(prevText) ? \"w\" : \"j\";\n return glide + schema[\"PATAH\"] + schema[\"HE\"];\n }\n return schema[\"PATAH\"] + schema[\"HE\"];\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /\u05D5\u05BC(?![\\u{05B4}-\\u{05BB}])/u,\n TRANSLITERATION: (syllable, _, schema) => {\n // finds a vav with a dagesh not followed by a vowel character\n // if the syllable is the first syllable, replace with wu\u02D0\n // syllable.clusters[0].isShureq is not totally necessary, but it's a good check\n if (!syllable.prev && syllable.clusters[0].isShureq) {\n const text = syllable.text;\n const hasMeteg = syllable.clusters.map((c) => c.hasMeteg).includes(true); // also called gaya marking half long vowel length (\u00A71.2.8.2.2)\n const secondaryAccent = hasMeteg ? \"\u02CC\" : \"\";\n const halfLengthMarker = hasMeteg ? \"\u02D1\" : \"\";\n return text.replace(\"\u05D5\u05BC\", `${secondaryAccent}wu${halfLengthMarker}`);\n }\n\n if (syllable.isAccented && syllable.isClosed) {\n const noLength = schema[\"SHUREQ\"].replace(\"\u02D0\", \"\");\n return syllable.text.replace(\"\u05D5\u05BC\", schema[\"SHUREQ\"] + noLength);\n }\n\n return syllable.text;\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /[\\u{05B4}-\\u{05BB}\\u{05C7}]/u,\n TRANSLITERATION: (syllable, _, schema) => {\n // this features matches any syllable that has a full vowel character (i.e. not sheva)\n const vowelName = syllable.vowelNames[0];\n const vowel = syllable.vowels[0];\n\n if (!vowel || !vowelName) {\n return syllable.text;\n }\n\n if (vowelName === \"SHEVA\") {\n throw new Error(`Syllable ${syllable.text} has a sheva as vowel, should not have matched`);\n }\n\n // half vowels do not have length; exit early\n const hasHalfVowel = syllable.clusters.map((c) => c.hasHalfVowel).includes(true);\n if (hasHalfVowel) {\n throw new Error(`Syllable ${syllable.text} has a hataf as vowel, should not have matched`);\n }\n\n const [onset, _nuclues, coda] = syllable.structure(true);\n /**\n * Determines the realization of a patach\n *\n * @param vowelChar the hebrew vowel character\n * @returns the back unrounded patach realization of the vowel or the original vowel if not patach\n */\n function determinePatachRealization(vowelChar: string) {\n // see comment for explanation: https://github.com/charlesLoder/hebrew-transliteration/issues/45#issuecomment-1712186201\n // exit early if not patach\n if (vowelName !== \"PATAH\" && vowelName !== \"HATAF_PATAH\") {\n return vowelChar;\n }\n\n // by this point, the resh has already been pharyngealized\n // but only for the current syllable\n const pharyngealized = /r\u02C1|\u05D8|\u05E6|\u05E5/;\n if (pharyngealized.test(onset) || pharyngealized.test(coda)) {\n return \"\u0251\";\n }\n\n // the resh of the next syllable has not been transliterated yet\n // check if the next syllable has a resh in the onset\n // and if the current syllable's coda is an alveolar\n const nextSyllable = syllable.next?.value;\n const nextOnset = nextSyllable?.onset;\n const alveolars = /[\u05D3\u05D6\u05E6\u05EA\u05D8\u05E1\u05DC\u05E0]|\u05E9\u05C2/;\n if (nextOnset === \"\u05E8\" && alveolars.test(coda)) {\n return \"\u0251\";\n }\n\n return vowelChar;\n }\n\n const noMaterText = syllable.clusters\n .filter((c) => !c.isMater)\n .map((c) => c.text)\n .join(\"\")\n // a holam, tsere, or segol followed by a he without a mappiq is not a mater\n // but b/c the he is not pronounced, we need to remove the final he\n .replace(/([\\u{05B5}\\u{05B6}\\u{05B9}].{1})\\u{05D4}(?!\\u{05BC})/u, \"$1\");\n\n const hasMaters = syllable.clusters.map((c) => c.isMater).includes(true);\n const lengthMarker = \"\u02D0\";\n const halfLengthMarker = \"\u02D1\";\n\n // See TPT \u00A71.2.10 concering meteg/gaya\n const hasMeteg = syllable.clusters.map((c) => c.hasMeteg).includes(true);\n if (hasMeteg) {\n const hasLongVowel = syllable.clusters.map((c) => c.hasLongVowel).includes(true);\n // when a meteg is present, the syllable implicitly has secondary stress\n // and the vowel is extended if it is not already long\n const firstConsonant = noMaterText[0];\n return noMaterText\n .replace(firstConsonant, `\u02CC${firstConsonant}`)\n .replace(vowel, `${determinePatachRealization(vowel)}${hasLongVowel ? lengthMarker : halfLengthMarker}`);\n }\n\n const isClosed = syllable.isClosed;\n const isAccented = syllable.isAccented;\n\n // TPT \u00A71.2.4, p288\n // When long vowels with the main stress occur in closed syllables,\n // there is evidence that an epenthetic with the same quality as that of the long vowel\n // occurred before the final consonant in its phonetic realization\"\n if (isAccented && isClosed) {\n const syllableSeparator = schema[\"SYLLABLE_SEPARATOR\"] || \"\";\n const vowelRealization = determinePatachRealization(vowel);\n return noMaterText.replace(\n vowel,\n `${vowelRealization + lengthMarker + syllableSeparator + vowelRealization}`\n );\n }\n\n // https://github.com/charlesLoder/hebrew-transliteration/issues/45#issuecomment-1747967050\n const longerVowels = [\"HOLAM\", \"TSERE\", \"QAMATS\"];\n if (!isAccented && isClosed && !syllable.isFinal && longerVowels.includes(vowelName)) {\n const syllableSeparator = schema[\"SYLLABLE_SEPARATOR\"] || \"\";\n const vowelRealization = determinePatachRealization(vowel);\n return noMaterText.replace(\n vowel,\n `${vowelRealization + lengthMarker + syllableSeparator + vowelRealization}`\n );\n }\n\n // TPT \u00A71.2.2.1 p268\n // Vowels represented by basic vowel signs are long when they are either\n // (i) in a stressed syllable or (ii) in an unstressed open syllable.\n if (isAccented || (!isAccented && !isClosed)) {\n return noMaterText.replace(vowel, `${determinePatachRealization(vowel) + lengthMarker}`);\n }\n\n if (!hasMaters && !isClosed && !isAccented) {\n return noMaterText.replace(vowel, `${determinePatachRealization(vowel)}`);\n }\n\n return syllable.text.replace(vowel, `${determinePatachRealization(vowel)}`);\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /[\\u{05B1}-\\u{05B3}]/u,\n TRANSLITERATION: (syllable) => {\n // this features matches any syllable that has a hataf vowel character\n const vowelName = syllable.vowelNames[0];\n const vowel = syllable.vowels[0];\n\n if (!vowel || !vowelName) {\n return syllable.text;\n }\n\n if (vowelName === \"SHEVA\") {\n throw new Error(`Syllable ${syllable.text} has a sheva as vowel, should not have matched`);\n }\n\n const hasNonHalfVowels = syllable.clusters.map((c) => c.hasShortVowel || c.hasLongVowel).includes(true);\n if (hasNonHalfVowels) {\n throw new Error(`Syllable ${syllable.text} does not have a hataf vowel, should not have matched`);\n }\n\n const [onset, _nuclues, coda] = syllable.structure(true);\n /**\n * Determines the realization of a patach\n *\n * @param vowelChar the hebrew vowel character\n * @returns the back unrounded patach realization of the vowel or the original vowel if not patach\n */\n function determinePatachRealization(vowelChar: string) {\n // exit early if not hataf patach\n if (vowelName !== \"HATAF_PATAH\") {\n return vowelChar;\n }\n\n // by this point, the resh has already been pharyngealized in the transliteration\n // but only for the current syllable\n const pharyngealized = /r\u02C1|\u05D8|\u05E6|\u05E5/;\n if (pharyngealized.test(onset) || pharyngealized.test(coda)) {\n return \"\u0251\";\n }\n\n // the resh of the next syllable has not been transliterated yet\n // check if the next syllable has a resh in the onset\n // and if the current syllable's coda is an alveolar\n const nextSyllable = syllable.next?.value;\n const nextOnset = nextSyllable?.onset;\n const alveolars = /[\u05D3\u05D6\u05E6\u05EA\u05D8\u05E1\u05DC\u05E0]|\u05E9\u05C2/;\n if (nextOnset === \"\u05E8\" && alveolars.test(coda)) {\n return \"\u0251\";\n }\n\n // check for the \"environment of pharyngealized consonants\"\n // https://www.tiberianhebrew.com/patah\n if (nextOnset && /[\u05E6\u05E5\u05D8]/.test(nextOnset)) {\n return \"\u0251\";\n }\n\n return vowelChar;\n }\n\n return syllable.text.replace(vowel, `${determinePatachRealization(vowel)}`);\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /(?<!.*([\\u{05B4}-\\u{05BB}\\u{05C7}]|\\u{05D5}\\u{05BC}).*)\\u{05B0}/u,\n TRANSLITERATION: (syllable, _hebrew, schema) => {\n // matches any syllable that contains a sheva that is not preceded by a full vowel character [\\u{05B4}-\\u{05BB}\\u{05C7}]\n // or shureq \\u{5D5}\\u{5BC}\n const nextSyllable = syllable.next?.value;\n if (!nextSyllable) return syllable.text;\n\n const nextSylFirstCluster = nextSyllable.clusters[0].text;\n if (!nextSylFirstCluster) return syllable.text;\n\n const [onset, _, coda] = syllable.structure(true);\n\n function isBackUnrounded() {\n // see comment for explanation: https://github.com/charlesLoder/hebrew-transliteration/issues/45#issuecomment-1712186201\n // by this point, the resh has already been pharyngealized in the transliteration\n const pharyngealized = /r\u02C1|\u05D8|\u05E6|\u05E5/;\n if (pharyngealized.test(onset) || pharyngealized.test(coda)) {\n return true;\n }\n\n const nextSyllable = syllable.next?.value;\n if (!nextSyllable) {\n return false;\n }\n\n const nextOnset = nextSyllable.onset;\n if (pharyngealized.test(nextOnset)) {\n return true;\n }\n\n return false;\n }\n\n function transliterateShevaAsVowel(vowel: string) {\n const hasMeteg = syllable.clusters.map((c) => c.hasMeteg).includes(true);\n const secondaryAccent = hasMeteg ? \"\u02CC\" : \"\";\n const halfLengthMarker = hasMeteg ? \"\u02D1\" : \"\";\n const newVowel = vowel.replace(\"\u02D0\", \"\") + halfLengthMarker;\n\n return secondaryAccent + syllable.text.replace(/\\u{05B0}/u, newVowel);\n }\n\n const isGuttural = /[\u05D0\u05D4\u05D7\u05E2]/.test(nextSylFirstCluster);\n if (!isGuttural) {\n return transliterateShevaAsVowel(isBackUnrounded() ? \"\u0251\" : schema[\"PATAH\"]);\n }\n\n const nextVowel = nextSyllable.vowelNames[0];\n if (!nextVowel) {\n throw new Error(\n `Syllable ${syllable.text} has a sheva as a vowel, but the next syllable ${nextSylFirstCluster} does not have a vowel`\n );\n }\n\n if (nextVowel === \"SHEVA\") {\n throw new Error(\n `Syllable ${syllable.text} has a sheva as a vowel, but the next syllable ${nextSylFirstCluster} also has a sheva as a vowel`\n );\n }\n\n return transliterateShevaAsVowel(schema[nextVowel]);\n }\n },\n {\n FEATURE: \"syllable\",\n HEBREW: /^\\u{5B4}\\u{5DD}/u,\n TRANSLITERATION: (syl, heb, schema) => {\n // This rule attempts to find instances of Jerusalem spelled without a yod\n\n // this is just a sanity check that the previous syllable\n // should be a lamed with a qamats or a patah\n const prev = syl.prev?.value;\n if (\n prev &&\n !prev.isClosed &&\n !prev.hasVowelName(\"QAMATS\") &&\n !prev.hasVowelName(\"PATAH\") &&\n prev.onset !== \"\u05DC\"\n ) {\n return syl.text;\n }\n\n // update this syllable to match the later spelling of Jerusalem\n return syl.text.replace(heb, `${schema[\"YOD\"]}${schema[\"HIRIQ\"]}${schema[\"FINAL_MEM\"]}`);\n }\n },\n {\n FEATURE: \"word\",\n HEBREW: /(\u05D5\u05B0)?\u05D9\u05B4\u05E9\u05C2\u05BC\u05B8\u05E9\u05DB\u05B8\u05E8/,\n PASS_THROUGH: true,\n TRANSLITERATION: (word, heb) => {\n // matches the name Issachar\n const taamim = /[\\u{0590}-\\u{05AF}\\u{05BD}\\u{05BF}]/gu;\n const text = word.text.replace(taamim, \"\");\n const match = text.match(heb);\n const vav = match && match[1] ? match[1] : \"\";\n const issachar = \"jiss\u0254\u02D0\u02C8\u03C7\u0254\u02D0\u0254\u0280\u031F\";\n return `${vav}${issachar}`;\n }\n }\n ],\n allowNoNiqqud: false,\n article: false,\n holemHaser: \"remove\",\n ketivQeres: [\n {\n input: \"\u05D4\u05B4\u05D5\u05D0\",\n output: \"\u05D4\u05B4\u05D9\u05D0\",\n captureTaamim: true,\n ignoreTaamim: true\n }\n ],\n longVowels: false,\n qametsQatan: true,\n shevaAfterMeteg: false,\n shevaWithMeteg: true,\n sqnmlvy: false,\n strict: true,\n wawShureq: false\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["_a", "nextSyllable"]
|
|
7
7
|
}
|
package/dist/esm/rules.js
CHANGED
|
@@ -1,49 +1,63 @@
|
|
|
1
1
|
import { Cluster } from "havarotjs/cluster";
|
|
2
2
|
import { Syllable } from "havarotjs/syllable";
|
|
3
|
+
import { clusterSplitGroup, hebChars } from "havarotjs/utils/regularExpressions";
|
|
3
4
|
import { Word } from "havarotjs/word";
|
|
4
|
-
import { hebChars, clusterSplitGroup } from "havarotjs/utils/regularExpressions";
|
|
5
5
|
import { transliterateMap as map } from "./hebCharsTrans.js";
|
|
6
6
|
const taamim = /[\u{0590}-\u{05AF}\u{05BD}\u{05BF}]/gu;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
const copySyllable = (newText, old) => {
|
|
8
|
+
const newClusters = newText.split(clusterSplitGroup).map((clusterString) => new Cluster(clusterString, true));
|
|
9
|
+
const oldClusters = old.clusters;
|
|
10
|
+
// set prev and next based on old syllable
|
|
11
|
+
if (newClusters.length === oldClusters.length) {
|
|
12
|
+
newClusters.forEach((c, i) => ((c.prev = oldClusters[i]?.prev ?? null), (c.next = oldClusters[i]?.next ?? null)));
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
for (let i = 0; i < newClusters.length; i++) {
|
|
16
|
+
const c = newClusters[i];
|
|
17
|
+
if (oldClusters[i]?.text[0] === c?.text[0]) {
|
|
18
|
+
c.prev = oldClusters[i]?.prev ?? null;
|
|
19
|
+
c.next = oldClusters[i]?.next ?? null;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
c.prev = oldClusters[i]?.prev ?? null;
|
|
23
|
+
c.next = oldClusters[i + 1]?.next ?? null;
|
|
24
|
+
i++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const newSyl = new Syllable(newClusters, {
|
|
29
|
+
isClosed: old.isClosed,
|
|
30
|
+
isAccented: old.isAccented,
|
|
31
|
+
isFinal: old.isFinal
|
|
32
|
+
});
|
|
33
|
+
newClusters.forEach((c) => (c.syllable = newSyl));
|
|
34
|
+
newSyl.prev = old.prev;
|
|
35
|
+
newSyl.next = old.next;
|
|
36
|
+
newSyl.word = old.word;
|
|
37
|
+
return newSyl;
|
|
38
|
+
};
|
|
39
|
+
const getDageshChazaqVal = (input, dagesh, isChazaq) => {
|
|
40
|
+
if (!isChazaq) {
|
|
41
|
+
return input;
|
|
42
|
+
}
|
|
43
|
+
if (typeof dagesh === "boolean") {
|
|
44
|
+
return input.repeat(2);
|
|
45
|
+
}
|
|
46
|
+
return input + dagesh;
|
|
17
47
|
};
|
|
18
48
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @param input the string to be modified
|
|
22
|
-
* @param regex the regex to be used as the search value
|
|
23
|
-
* @param replaceValue the string to replace the regex
|
|
24
|
-
* @returns
|
|
25
|
-
*/
|
|
26
|
-
const replaceWithRegex = (input, regex, replaceValue) => input.replace(regex, replaceValue);
|
|
27
|
-
/**
|
|
28
|
-
* replaces part of a string and transliterates the remaining characters according to the schema
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```ts
|
|
32
|
-
* // replaces בָ as VA, but only when matching the regex sequence
|
|
33
|
-
* const betAndQamats = /\u{05D1}\u{05B8}/u
|
|
34
|
-
* replaceAndTransliterate("דָּבָר", betAndQamats, "VA", schema);
|
|
35
|
-
* // dāVAr
|
|
36
|
-
* ```
|
|
49
|
+
* Formats the Divine Name with any Latin chars
|
|
37
50
|
*
|
|
38
|
-
* @param
|
|
39
|
-
* @param
|
|
40
|
-
* @
|
|
41
|
-
* @param schema the Schema
|
|
42
|
-
* @returns
|
|
51
|
+
* @param str word text
|
|
52
|
+
* @param schema
|
|
53
|
+
* @returns the Divine Name with any pre or proceding Latin chars
|
|
43
54
|
*/
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
55
|
+
const getDivineName = (str, schema) => {
|
|
56
|
+
const begn = str[0];
|
|
57
|
+
const end = str[str.length - 1];
|
|
58
|
+
// if DN is pointed with a hiriq, then it is read as 'elohim
|
|
59
|
+
const divineName = schema.DIVINE_NAME_ELOHIM && /\u{05B4}/u.test(str) ? schema.DIVINE_NAME_ELOHIM : schema.DIVINE_NAME;
|
|
60
|
+
return `${hebChars.test(begn) ? "" : begn}${divineName}${hebChars.test(end) ? "" : end}`;
|
|
47
61
|
};
|
|
48
62
|
const isDageshChazaq = (cluster, schema) => {
|
|
49
63
|
// if there is no dagesh chazaq in the schema, then return false
|
|
@@ -73,78 +87,6 @@ const isDageshChazaq = (cluster, schema) => {
|
|
|
73
87
|
}
|
|
74
88
|
return prevCoda === cluster.syllable?.onset;
|
|
75
89
|
};
|
|
76
|
-
const getDageshChazaqVal = (input, dagesh, isChazaq) => {
|
|
77
|
-
if (!isChazaq) {
|
|
78
|
-
return input;
|
|
79
|
-
}
|
|
80
|
-
if (typeof dagesh === "boolean") {
|
|
81
|
-
return input.repeat(2);
|
|
82
|
-
}
|
|
83
|
-
return input + dagesh;
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* formats the Divine Name with any Latin chars
|
|
87
|
-
*
|
|
88
|
-
* @param str word text
|
|
89
|
-
* @param schema
|
|
90
|
-
* @returns the Divine Name with any pre or proceding Latin chars
|
|
91
|
-
*/
|
|
92
|
-
const getDivineName = (str, schema) => {
|
|
93
|
-
const begn = str[0];
|
|
94
|
-
const end = str[str.length - 1];
|
|
95
|
-
// if DN is pointed with a hiriq, then it is read as 'elohim
|
|
96
|
-
const divineName = schema.DIVINE_NAME_ELOHIM && /\u{05B4}/u.test(str) ? schema.DIVINE_NAME_ELOHIM : schema.DIVINE_NAME;
|
|
97
|
-
return `${hebChars.test(begn) ? "" : begn}${divineName}${hebChars.test(end) ? "" : end}`;
|
|
98
|
-
};
|
|
99
|
-
const materFeatures = (syl, schema) => {
|
|
100
|
-
const mater = syl.clusters.filter((c) => c.isMater)[0];
|
|
101
|
-
const prev = mater.prev instanceof Cluster ? mater.prev : null;
|
|
102
|
-
const materText = mater.text;
|
|
103
|
-
const prevText = (prev?.text || "").replace(taamim, "");
|
|
104
|
-
// string comprised of all non-mater clusters in a syl with a mater
|
|
105
|
-
let noMaterText = syl.clusters
|
|
106
|
-
.filter((c) => !c.isMater)
|
|
107
|
-
.map((c) => consonantFeatures(c.text.replace(taamim, ""), syl, c, schema))
|
|
108
|
-
.join("");
|
|
109
|
-
// workaround for maqaf
|
|
110
|
-
const hasMaqaf = mater.text.includes("־");
|
|
111
|
-
noMaterText = hasMaqaf ? noMaterText.concat("־") : noMaterText;
|
|
112
|
-
if (/י/.test(materText)) {
|
|
113
|
-
// hiriq
|
|
114
|
-
if (/\u{05B4}/u.test(prevText)) {
|
|
115
|
-
return replaceWithRegex(noMaterText, /\u{05B4}/u, schema.HIRIQ_YOD);
|
|
116
|
-
}
|
|
117
|
-
// tsere
|
|
118
|
-
if (/\u{05B5}/u.test(prevText)) {
|
|
119
|
-
return replaceWithRegex(noMaterText, /\u{05B5}/u, schema.TSERE_YOD);
|
|
120
|
-
}
|
|
121
|
-
// segol
|
|
122
|
-
if (/\u{05B6}/u.test(prevText)) {
|
|
123
|
-
return replaceWithRegex(noMaterText, /\u{05B6}/u, schema.SEGOL_YOD);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (/ו/u.test(materText)) {
|
|
127
|
-
// holam
|
|
128
|
-
if (/\u{05B9}/u.test(prevText)) {
|
|
129
|
-
return replaceWithRegex(noMaterText, /\u{05B9}/u, schema.HOLAM_VAV);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (/ה/.test(materText)) {
|
|
133
|
-
// qamets
|
|
134
|
-
if (/\u{05B8}/u.test(prevText)) {
|
|
135
|
-
return replaceWithRegex(noMaterText, /\u{05B8}/u, schema.QAMATS_HE);
|
|
136
|
-
}
|
|
137
|
-
// seghol
|
|
138
|
-
if (/\u{05B6}/u.test(prevText)) {
|
|
139
|
-
return replaceWithRegex(noMaterText, /\u{05B6}/u, schema.SEGOL_HE);
|
|
140
|
-
}
|
|
141
|
-
// tsere
|
|
142
|
-
if (/\u{05B5}/u.test(prevText)) {
|
|
143
|
-
return replaceWithRegex(noMaterText, /\u{05B5}/u, schema.TSERE_HE);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return materText;
|
|
147
|
-
};
|
|
148
90
|
const joinSyllableChars = (syl, sylChars, schema) => {
|
|
149
91
|
const isInConstruct = syl.word?.isInConstruct;
|
|
150
92
|
if (isInConstruct) {
|
|
@@ -204,7 +146,9 @@ const joinSyllableChars = (syl, sylChars, schema) => {
|
|
|
204
146
|
schema.SEGOL_YOD,
|
|
205
147
|
schema.HOLAM_VAV,
|
|
206
148
|
schema.SHUREQ
|
|
207
|
-
]
|
|
149
|
+
]
|
|
150
|
+
.filter((v) => typeof v === "string")
|
|
151
|
+
.sort((a, b) => b.length - a.length);
|
|
208
152
|
const vowelRgx = new RegExp(`${vowels.join("|")}`);
|
|
209
153
|
const str = sylChars.map(mapChars(schema)).join("");
|
|
210
154
|
const match = str.match(vowelRgx);
|
|
@@ -216,30 +160,114 @@ const joinSyllableChars = (syl, sylChars, schema) => {
|
|
|
216
160
|
}
|
|
217
161
|
return sylChars.map(mapChars(schema)).join("");
|
|
218
162
|
};
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Maps Hebrew characters to schema
|
|
165
|
+
*
|
|
166
|
+
* @param input - text to be transliterated
|
|
167
|
+
* @param schema - a {@link Schema} for transliterating the input
|
|
168
|
+
* @returns transliteration of characters
|
|
169
|
+
*
|
|
170
|
+
*/
|
|
171
|
+
const mapChars = (schema) => (input) => {
|
|
172
|
+
return [...input].map((char) => (char in map ? schema[map[char]] : char)).join("");
|
|
173
|
+
};
|
|
174
|
+
const materFeatures = (syl, schema) => {
|
|
175
|
+
const mater = syl.clusters.filter((c) => c.isMater)[0];
|
|
176
|
+
const prev = mater.prev instanceof Cluster ? mater.prev : null;
|
|
177
|
+
const materText = mater.text;
|
|
178
|
+
const prevText = (prev?.text || "").replace(taamim, "");
|
|
179
|
+
// string comprised of all non-mater clusters in a syl with a mater
|
|
180
|
+
let noMaterText = syl.clusters
|
|
181
|
+
.filter((c) => !c.isMater)
|
|
182
|
+
.map((c) => cluterRules(c, schema))
|
|
183
|
+
.join("");
|
|
184
|
+
// workaround for maqaf
|
|
185
|
+
const hasMaqaf = mater.text.includes("־");
|
|
186
|
+
noMaterText = hasMaqaf ? noMaterText.concat("־") : noMaterText;
|
|
187
|
+
if (/י/.test(materText)) {
|
|
188
|
+
// hiriq
|
|
189
|
+
if (/\u{05B4}/u.test(prevText)) {
|
|
190
|
+
return replaceWithRegex(noMaterText, /\u{05B4}/u, schema.HIRIQ_YOD);
|
|
191
|
+
}
|
|
192
|
+
// tsere
|
|
193
|
+
if (/\u{05B5}/u.test(prevText)) {
|
|
194
|
+
return replaceWithRegex(noMaterText, /\u{05B5}/u, schema.TSERE_YOD);
|
|
195
|
+
}
|
|
196
|
+
// segol
|
|
197
|
+
if (/\u{05B6}/u.test(prevText)) {
|
|
198
|
+
return replaceWithRegex(noMaterText, /\u{05B6}/u, schema.SEGOL_YOD);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (/ו/u.test(materText)) {
|
|
202
|
+
// holam
|
|
203
|
+
if (/\u{05B9}/u.test(prevText)) {
|
|
204
|
+
return replaceWithRegex(noMaterText, /\u{05B9}/u, schema.HOLAM_VAV);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (/ה/.test(materText)) {
|
|
208
|
+
// qamets
|
|
209
|
+
if (/\u{05B8}/u.test(prevText)) {
|
|
210
|
+
return replaceWithRegex(noMaterText, /\u{05B8}/u, schema.QAMATS_HE);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return materText;
|
|
214
|
+
};
|
|
215
|
+
const removeTaamim = (input) => input.replace(taamim, "");
|
|
216
|
+
/**
|
|
217
|
+
* Replaces part of a string and transliterates the remaining characters according to the schema
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* // replaces בָ as VA, but only when matching the regex sequence
|
|
222
|
+
* const betAndQamats = /\u{05D1}\u{05B8}/u
|
|
223
|
+
* replaceAndTransliterate("דָּבָר", betAndQamats, "VA", schema);
|
|
224
|
+
* // dāVAr
|
|
225
|
+
* ```
|
|
226
|
+
*
|
|
227
|
+
* @param input the text to be transliterated
|
|
228
|
+
* @param regex the regex used as the search value
|
|
229
|
+
* @param replaceValue the string to replace the regex
|
|
230
|
+
* @param schema the Schema
|
|
231
|
+
*/
|
|
232
|
+
const replaceAndTransliterate = (input, regex, replaceValue, schema) => {
|
|
233
|
+
const sylSeq = replaceWithRegex(input, regex, replaceValue);
|
|
234
|
+
return [...sylSeq].map(mapChars(schema)).join("");
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Wrapper around `String.replace()` to constrain to a RegExp
|
|
238
|
+
*
|
|
239
|
+
* @param input the string to be modified
|
|
240
|
+
* @param regex the regex to be used as the search value
|
|
241
|
+
* @param replaceValue the string to replace the regex
|
|
242
|
+
*/
|
|
243
|
+
const replaceWithRegex = (input, regex, replaceValue) => input.replace(regex, replaceValue);
|
|
244
|
+
// MAIN RULES
|
|
245
|
+
const cluterRules = (cluster, schema) => {
|
|
246
|
+
let clusterText = removeTaamim(cluster.text);
|
|
247
|
+
const clusterFeatures = schema.ADDITIONAL_FEATURES?.filter((seq) => seq.FEATURE === "cluster");
|
|
248
|
+
if (clusterFeatures) {
|
|
249
|
+
for (const feature of clusterFeatures) {
|
|
250
|
+
const heb = new RegExp(feature.HEBREW, "u");
|
|
251
|
+
if (feature.FEATURE === "cluster" && heb.test(clusterText)) {
|
|
252
|
+
const transliteration = feature.TRANSLITERATION;
|
|
253
|
+
const passThrough = feature.PASS_THROUGH ?? true;
|
|
227
254
|
if (typeof transliteration === "string") {
|
|
228
255
|
return replaceAndTransliterate(clusterText, heb, transliteration, schema);
|
|
229
256
|
}
|
|
230
257
|
if (!passThrough) {
|
|
231
|
-
return transliteration(cluster,
|
|
258
|
+
return transliteration(cluster, feature.HEBREW, schema);
|
|
232
259
|
}
|
|
233
|
-
clusterText = transliteration(cluster,
|
|
260
|
+
clusterText = transliteration(cluster, feature.HEBREW, schema);
|
|
234
261
|
}
|
|
235
262
|
}
|
|
236
263
|
}
|
|
237
|
-
|
|
264
|
+
const syl = cluster.syllable;
|
|
265
|
+
clusterText = cluster.hasSheva && syl?.isClosed ? clusterText.replace(/\u{05B0}/u, "") : clusterText;
|
|
238
266
|
// mappiq he
|
|
239
267
|
if (/ה\u{05BC}$/mu.test(clusterText)) {
|
|
240
268
|
return replaceWithRegex(clusterText, /ה\u{05BC}/u, schema.HE);
|
|
241
269
|
}
|
|
242
|
-
if (syl
|
|
270
|
+
if (syl?.isFinal && !syl?.isClosed) {
|
|
243
271
|
const furtiveChet = /\u{05D7}\u{05B7}$/mu;
|
|
244
272
|
if (furtiveChet.test(clusterText)) {
|
|
245
273
|
return replaceWithRegex(clusterText, furtiveChet, "\u{05B7}\u{05D7}");
|
|
@@ -292,62 +320,28 @@ const consonantFeatures = (clusterText, syl, cluster, schema) => {
|
|
|
292
320
|
}
|
|
293
321
|
return clusterText;
|
|
294
322
|
};
|
|
295
|
-
const copySyllable = (newText, old) => {
|
|
296
|
-
const newClusters = newText.split(clusterSplitGroup).map((clusterString) => new Cluster(clusterString, true));
|
|
297
|
-
const oldClusters = old.clusters;
|
|
298
|
-
// set prev and next based on old syllable
|
|
299
|
-
if (newClusters.length === oldClusters.length) {
|
|
300
|
-
newClusters.forEach((c, i) => ((c.prev = oldClusters[i]?.prev ?? null), (c.next = oldClusters[i]?.next ?? null)));
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
for (let i = 0; i < newClusters.length; i++) {
|
|
304
|
-
const c = newClusters[i];
|
|
305
|
-
if (oldClusters[i]?.text[0] === c?.text[0]) {
|
|
306
|
-
c.prev = oldClusters[i]?.prev ?? null;
|
|
307
|
-
c.next = oldClusters[i]?.next ?? null;
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
c.prev = oldClusters[i]?.prev ?? null;
|
|
311
|
-
c.next = oldClusters[i + 1]?.next ?? null;
|
|
312
|
-
i++;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
const newSyl = new Syllable(newClusters, {
|
|
317
|
-
isClosed: old.isClosed,
|
|
318
|
-
isAccented: old.isAccented,
|
|
319
|
-
isFinal: old.isFinal
|
|
320
|
-
});
|
|
321
|
-
newClusters.forEach((c) => (c.syllable = newSyl));
|
|
322
|
-
newSyl.prev = old.prev;
|
|
323
|
-
newSyl.next = old.next;
|
|
324
|
-
newSyl.word = old.word;
|
|
325
|
-
return newSyl;
|
|
326
|
-
};
|
|
327
323
|
export const sylRules = (syl, schema) => {
|
|
328
324
|
const sylTxt = syl.text.replace(taamim, "");
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
for (const
|
|
332
|
-
const heb = new RegExp(
|
|
333
|
-
if (
|
|
334
|
-
const transliteration =
|
|
335
|
-
const passThrough =
|
|
336
|
-
// if transliteration is a string, then replace
|
|
325
|
+
const syllableFeatures = schema.ADDITIONAL_FEATURES?.filter((seq) => seq.FEATURE === "syllable");
|
|
326
|
+
if (syllableFeatures) {
|
|
327
|
+
for (const feature of syllableFeatures) {
|
|
328
|
+
const heb = new RegExp(feature.HEBREW, "u");
|
|
329
|
+
if (feature.FEATURE === "syllable" && heb.test(sylTxt)) {
|
|
330
|
+
const transliteration = feature.TRANSLITERATION;
|
|
331
|
+
const passThrough = feature.PASS_THROUGH ?? true;
|
|
337
332
|
if (typeof transliteration === "string") {
|
|
338
333
|
return replaceAndTransliterate(sylTxt, heb, transliteration, schema);
|
|
339
334
|
}
|
|
340
|
-
// if transliteration is a function and passThrough is false, then transliterate and exit
|
|
341
335
|
if (!passThrough) {
|
|
342
|
-
return transliteration(syl,
|
|
336
|
+
return transliteration(syl, feature.HEBREW, schema);
|
|
343
337
|
}
|
|
344
|
-
const newText = transliteration(syl,
|
|
338
|
+
const newText = transliteration(syl, feature.HEBREW, schema);
|
|
345
339
|
// if the transliteration just returns the syllable.text, then no need to copy the syllable
|
|
346
340
|
if (newText !== sylTxt) {
|
|
347
341
|
syl = copySyllable(newText, syl);
|
|
348
342
|
}
|
|
349
343
|
}
|
|
350
|
-
}
|
|
344
|
+
}
|
|
351
345
|
}
|
|
352
346
|
// syllable is 3ms sufx
|
|
353
347
|
const mSSuffix = /\u{05B8}\u{05D9}\u{05D5}/u;
|
|
@@ -361,11 +355,19 @@ export const sylRules = (syl, schema) => {
|
|
|
361
355
|
const materSyl = materFeatures(syl, schema);
|
|
362
356
|
return joinSyllableChars(syl, [...materSyl], schema);
|
|
363
357
|
}
|
|
358
|
+
if (schema.SEGOL_HE && /\u{05B6}\u{05D4}/u.test(sylTxt)) {
|
|
359
|
+
const returnTxt = syl.clusters.map((cluster) => cluterRules(cluster, schema));
|
|
360
|
+
const joined = joinSyllableChars(syl, returnTxt, schema).replace(taamim, "");
|
|
361
|
+
return joined.replace(schema["SEGOL"] + schema["HE"], schema.SEGOL_HE);
|
|
362
|
+
}
|
|
363
|
+
// tsere
|
|
364
|
+
if (schema.TSERE_HE && /\u{05B5}\u{05D4}/u.test(sylTxt)) {
|
|
365
|
+
const returnTxt = syl.clusters.map((cluster) => cluterRules(cluster, schema));
|
|
366
|
+
const joined = joinSyllableChars(syl, returnTxt, schema).replace(taamim, "");
|
|
367
|
+
return joined.replace(schema["TSERE"] + schema["HE"], schema.TSERE_HE);
|
|
368
|
+
}
|
|
364
369
|
// regular syllables
|
|
365
|
-
const returnTxt = syl.clusters.map((cluster) =>
|
|
366
|
-
const clusterText = cluster.text.replace(taamim, "");
|
|
367
|
-
return consonantFeatures(clusterText, syl, cluster, schema);
|
|
368
|
-
});
|
|
370
|
+
const returnTxt = syl.clusters.map((cluster) => cluterRules(cluster, schema));
|
|
369
371
|
// there may be taamim still in the text, so remove them
|
|
370
372
|
return joinSyllableChars(syl, returnTxt, schema).replace(taamim, "");
|
|
371
373
|
};
|
|
@@ -379,21 +381,21 @@ export const wordRules = (word, schema) => {
|
|
|
379
381
|
if (word.isNotHebrew) {
|
|
380
382
|
return word.text;
|
|
381
383
|
}
|
|
382
|
-
const
|
|
383
|
-
if (
|
|
384
|
-
const
|
|
385
|
-
for (const
|
|
386
|
-
const heb = new RegExp(
|
|
387
|
-
if (
|
|
388
|
-
const transliteration =
|
|
389
|
-
const passThrough =
|
|
384
|
+
const wordFeatures = schema.ADDITIONAL_FEATURES?.filter((seq) => seq.FEATURE === "word");
|
|
385
|
+
if (wordFeatures) {
|
|
386
|
+
const text = word.text.replace(taamim, "");
|
|
387
|
+
for (const feature of wordFeatures) {
|
|
388
|
+
const heb = new RegExp(feature.HEBREW, "u");
|
|
389
|
+
if (heb.test(text)) {
|
|
390
|
+
const transliteration = feature.TRANSLITERATION;
|
|
391
|
+
const passThrough = feature.PASS_THROUGH ?? true;
|
|
390
392
|
if (typeof transliteration === "string") {
|
|
391
393
|
return replaceAndTransliterate(text, heb, transliteration, schema);
|
|
392
394
|
}
|
|
393
395
|
if (!passThrough) {
|
|
394
|
-
return transliteration(word,
|
|
396
|
+
return transliteration(word, feature.HEBREW, schema);
|
|
395
397
|
}
|
|
396
|
-
return new Word(transliteration(word,
|
|
398
|
+
return new Word(transliteration(word, feature.HEBREW, schema), schema);
|
|
397
399
|
}
|
|
398
400
|
}
|
|
399
401
|
return word;
|