Z30905

{
    "Z1K1": "Z2",
    "Z2K1": {
        "Z1K1": "Z6",
        "Z6K1": "Z30905"
    },
    "Z2K2": {
        "Z1K1": "Z14",
        "Z14K1": "Z30901",
        "Z14K3": {
            "Z1K1": "Z16",
            "Z16K1": "Z600",
            "Z16K2": "// https://github.com/jan-Ne/jan-ne.github.io/blob/5794de47f995f06772b0cf7014a5351b1e66a810/tp/tokiponize.js\n/* Copyright 2025 jan Ne (jan-ne.github.io)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst IPA = {\n\tNASALIZED: \"\\u0303\",\t\t// ◌̃ \n\tSYLLABIC: \"\\u0329\",\t\t\t// ◌̩ \n\tSYLLABIC_ALT: \"\\u030D\",\t\t// ◌̍ \n\tNONSYLLABIC: \"\\u032f\",\t\t// ◌̯\n\tRHOTIC: \"\\u02DE\",\t\t\t// ◌˞\n\t\n\tTONE_NUMS: \"\\u00B2\\u00B3\\u00B9\\u2070\\u2074-\\u2079\",\n\tVOWELS: \"aeiouyæøœɐɑɒɔɘəɚɛɜɝɞɤɨɪɯɵɶʉʊʌʏ\",\n\t//All IPA characters used\n\tFULL: \"\\u0061-\\u007A\\u00B2\\u00B3\\u00B9\\u00E6\\u00E7\\u00F0\\u00F8\\u0127\\u014B\\u0153\\u01C0-\\u01C3\\u0250-\\u0268\\u026A-\\u0276\\u0278-\\u027B\\u027D\\u027E\\u0280-\\u0284\\u0288-\\u0292\\u0294\\u0295\\u0298\\u0299\\u029B-\\u029D\\u029F\\u02A1\\u02A2\\u02B0-\\u036F\\u03B2\\u03B8\\u03C7\\u1D91\\u2070\\u2074-\\u2079\\u2C71\"\n};\n\nconst BLOCK = {\n\tSPACING_MODIFIER: \"\\u02B0-\\u02C7\\u02C9-\\u02CB\\u02CD-\\u02FF\",\t//unicode block excluding palatalized and rhotic modifiers\n\tCOMBINING_DIACRITICAL: \"\\u0300-\\u0302\\u0304-\\u030C\\u030E-\\u0328\\u032A-\\u032E\\u0330-\\u036F\"\t//unicode block excluding nasalized, nonsyllabic, and syllabic diacritics\n};\n\nconst rules = [\n\t{\n\t\tcategory: \"Warnings\",\n\t\tregex: [\n\t\t\t{ name: \"Unexpected unicode characters removed\", pattern: `[^${IPA.FULL}'.#\\\\s]`, replacement: \"\", type: \"warning\" },\n\t\t\t{ name: \"No vowels or marked syllabics detected\", pattern: `^[^${IPA.VOWELS}${IPA.SYLLABIC}${IPA.SYLLABIC_ALT}]*$`, flag: \"\", type: \"warning\" },\n\t\t\t{ name: \"No syllable boundaries detected\", pattern: `^(?=[^.]*$)(?=.*[${IPA.VOWELS}][^${IPA.VOWELS}${IPA.NONSYLLABIC}]+[${IPA.VOWELS}]).*$`, flag: \"\", type: \"warning\" },\n\t\t\t{ name: \"Orphaned non-syllabic consonant\", pattern: `(?\u003C=[.#\\\\s])(?![^\\\\s.#]*[${IPA.VOWELS}\\u0329\\u030D])([^${IPA.VOWELS}\\u0329\\u030D\\\\s.#]+)`, type: \"warning\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Deletions\",\n\t\tregex: [\n\t\t\t{ name: \"Remove IPA diacritics and modifiers\", pattern: `[${BLOCK.SPACING_MODIFIER}${BLOCK.COMBINING_DIACRITICAL}${IPA.TONE_NUMS}]`, replacement: \"\" },\n\t\t\t{ name: \"Laryngeals\", pattern: \"[ʡʔħʕhɦʜʢ]\", replacement: \"\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Feature-dependent changes\",\n\t\tregex: [\n\t\t\t{ name: \"Insert [i] after final palatals\", pattern: `\\\\.?([^${IPA.VOWELS}]ʲ|[ʃʒʂʐɕʑcɟǂ])(?=[#\\\\s])`, replacement: \".$1i\" },\n\t\t\t{ name: \"Remove palatalized modifier\", pattern: \"ʲ\", replacement: \"\" },\n\t\t\t{ name: \"Reduce clusters before fortition\", pattern: \"(?\u003C=[pbɓʘtʈɖǀǃɗᶑkgɡcɟqɢʡɠʛǂmɱnɳɲŋɴ])[fʙɸβðxɣχʁʀʜʢ](?![.#\\\\s])\", replacement: \"\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Vowels\",\n\t\tregex: [\n\t\t\t{ name: \"High front vowels\", pattern: \"[yɨɪʏ]\", replacement: \"i\" },\n\t\t\t{ name: \"High back vowels\", pattern: \"[ʉɯʊ]\", replacement: \"u\" },\n\t\t\t{ name: \"Mid front vowels\", pattern: \"[øɘɛœɜ]\", replacement: \"e\" },\n\t\t\t{ name: \"Mid back vowels\", pattern: \"[ɵɤɔɞʌɒ]\", replacement: \"o\" },\n\t\t\t{ name: \"Low vowels\", pattern: \"[æɶɐɑ]\", replacement: \"a\" },\n\t\t\t{ name: \"ɝ\", pattern: \"ɝ\", replacement: \"ew\" },\n\t\t\t{ name: \"ɚ\", pattern: \"ɚ\", replacement: \"əw\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Consonants\",\n\t\tregex: [\n\t\t\t{ name: \"Labial nasals\", pattern: \"ɱ\", replacement: \"m\" },\n\t\t\t{ name: \"Non-labial nasals\", pattern: \"[ɳɲŋɴ]\", replacement: \"n\" },\n\t\t\t{ name: \"Nasalized vowels\", pattern: `${IPA.NASALIZED}`, replacement: \"n\" },\n\t\t\t{ name: \"Coda nasals\", pattern: \"m(?=[\\\\.ˈ'#\\\\s])\", replacement: \"n\" },\n\t\t\t{ name: \"Labials\", pattern: \"[bfʙɸβʘɓ]\", replacement: \"p\" },\n\t\t\t{ name: \"Coronal stridents\", pattern: \"(ts|dz|tʃ|dʒ|ʈʂ|ɖʐ|tɕ|dʑ|tɬ|dɮ)|[zʃʒɕʑʂʐθɬɮɧ]\", replacement: \"s\" },\n\t\t\t{ name: \"Coronal non-stridents\", pattern: \"[dðʈɖǀǃɗᶑ]\", replacement: \"t\" },\n\t\t\t{ name: \"Dorsals\", pattern: \"[gɡcɟqɢxɣχʁʀʡʜʢɠʛǂ]\", replacement: \"k\" },\n\t\t\t{ name: \"Liquids\", pattern: \"[rɾɽɺɫɭʎʟǁ]\", replacement: \"l\" },\n\t\t\t{ name: \"Palatal approximants and fricatives\", pattern: \"[çʝɥʄ]\", replacement: \"j\" },\n\t\t\t{ name: \"Non-palatal approximants\", pattern: `[vⱱɹɻʋɰʍ${IPA.RHOTIC}]`, replacement: \"w\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Syllabic Consonants\",\n\t\tregex: [\n\t\t\t{ name: \"Reduce geminate syllabic consonants\", pattern: `([^aeiou])\\\\1(?=${IPA.SYLLABIC})`, replacement: \"$1\" },\n\t\t\t{ name: \"Insert schwa before syllabic nasal\", pattern: `[mn]${IPA.SYLLABIC}`, replacement: \"ən\" },\n\t\t\t{ name: \"Initial syllabic consonant\", pattern: `(?\u003C=[#\\\\s])([^aeiou])${IPA.SYLLABIC}`, replacement: \"$1ə\" },\n\t\t\t{ name: \"Initial syllabic consonant\", pattern: `(?\u003C=[#\\\\s])([^aeiou])${IPA.SYLLABIC_ALT}`, replacement: \"$1ə\" },\n\t\t\t{ name: \"Syllabic consonant\", pattern: `([^aeiou])${IPA.SYLLABIC}`, replacement: \"ə$1\" },\n\t\t\t{ name: \"Syllabic consonant\", pattern: `([^aeiou])${IPA.SYLLABIC_ALT}`, replacement: \"ə$1\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Schwa\",\n\t\tregex: [\n\t\t\t{ name: \"Final rhotic schwa\", pattern: \"əw(?=[#\\\\s])\", replacement: \"a\" },\n\t\t\t{ name: \"Final schwa\", pattern: \"ə(?=[#\\\\s])\", replacement: \"a\" },\n\t\t\t{ name: \"Delete word-initial unstressed schwa\", pattern: \"(?\u003C=[#\\\\s])(?\u003C!['ˈˌ])ə\\\\.\", replacement: \"\" },\n\t\t\t{ name: \"Assimilate schwas to preceding vowel\", pattern: `([aeiou])([^\\\\s]*)\\\\.([^aeiou]*)ə`, replacement: \"$1$2.$3$1\" },\n\t\t\t{ name: \"Assimilate leading schwas to next vowel\", pattern: \"ə(?=[^aeiouə]*(?:\\\\.[^aeiouə]*ə)*\\\\.[^aeiou]*([aeiou]))\", replacement: \"$1\" },\n\t\t\t{ name: \"Misc schwa\", pattern: \"ə\", replacement: \"a\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Metathesis\",\n\t\tregex: [\n\t\t\t{ name: \"Metathesis of coda consonant and onset nasal\", pattern: `([^aeioun])\\\\.n(?=[aeiou]+([jw${IPA.NONSYLLABIC}])?n)`, replacement: \"n.$1\" },\n\t\t\t{ name: \"Shift nasal to coda to avoid cluster\", pattern: `(?\u003C=[^aeioun]\\\\.)(n)([aeiou]+${IPA.NONSYLLABIC}?)(?!\\\\.?[nm])`, replacement: \"$2$1\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Glides and Diphthongs\",\n\t\tregex: [\n\t\t\t{ name: \"Reduce weak high front vowel in diphthong\", pattern: `(?\u003C=[aeiou])i${IPA.NONSYLLABIC}?|i${IPA.NONSYLLABIC}?(?=[aeiou])`, replacement: \"j\" },\n\t\t\t{ name: \"Reduce weak high back vowel in diphthong\", pattern: `(?\u003C=[aeiou])u${IPA.NONSYLLABIC}?|u${IPA.NONSYLLABIC}?(?=[aeiou])`, replacement: \"w\" },\n\t\t\t{ name: \"Expand non-initial syllable with [j] using dipthong with [w]\", pattern: \"(?\u003C![#\\\\s])([^aeiou#\\\\s\\\\.ˈ'ˌ])j([aeiou])w(?=[.#//s])\", replacement: \"$1$2ju\" },\n\t\t\t{ name: \"Expand non-initial syllable with [w] using diphthong with [j]\", pattern: \"(?\u003C![#\\\\s])([^aeiou#\\\\s\\\\.ˈ'ˌ])w([aeiou])j(?=[.#//s])\", replacement: \"$1$2wi\" },\n\t\t\t{ name: \"Expand non-initial syllable with [j] using dipthong\", pattern: \"(?\u003C![#\\\\s])([^aeiou#\\\\s\\\\.ˈ'ˌ])j([aeiou])([aeo])\", replacement: \"$1$2j$3\" },\n\t\t\t{ name: \"Expand non-initial syllable with [w] using diphthong\", pattern: \"(?\u003C![#\\\\s])([^aeiou#\\\\s\\\\.ˈ'ˌ])w([aeiou])([ae])\", replacement: \"$1$2w$3\" },\n\t\t\t{ name: \"Expand non-initial syllable with [w]\", pattern: \"(?\u003C![#\\\\s])([^aeiou#\\\\s\\\\.ˈ'ˌ])w(?=[aeiou])\", replacement: \"$1u.w\" },\n\t\t\t{ name: \"Expand non-initial syllable with [j]\", pattern: \"(?\u003C![#\\\\s])([^aeiou#\\\\s\\\\.ˈ'ˌ])j(?=[aeiou])\", replacement: \"$1i.j\" },\n\t\t\t{ name: \"Non-syllabic low vowels\", pattern: `[a]${IPA.NONSYLLABIC}`, replacement: \"\"},\n\t\t\t{ name: \"Non-syllabic front vowels\", pattern: `(?\u003C=[aeiou])[ie](${IPA.NONSYLLABIC})|[ie](${IPA.NONSYLLABIC})(?=[aeiou])`, replacement: \"j\"},\n\t\t\t{ name: \"Non-syllabic back vowels\", pattern: `(?\u003C=[aeiou])[ou](${IPA.NONSYLLABIC})|[ou](${IPA.NONSYLLABIC})(?=[aeiou])`, replacement: \"w\"},\n\t\t\t{ name: \"Diphthong reduction\", pattern: \"(?\u003C=[aeiou])[aeiou]\", replacement: \"\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Vowel and Stress Markings\",\n\t\tregex: [\n\t\t\t{ name: \"Remove stress markings\", pattern: \"['ˈˌ]\", replacement: \"\" },\n\t\t\t{ name: \"Remove non-syllabic vowel markings\", pattern: `${IPA.NONSYLLABIC}`, replacement: \"\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Consonant Clusters\",\n\t\tregex: [\n\t\t\t{ name: \"Preserve nasal in previous empty coda\", pattern: \"\\\\.n(?=[^aeioumn])\", replacement: \"n.\" },\n\t\t\t{ name: \"Preserve plosive over approximant in cluster\", pattern: \"(?\u003C=[ptkn])(w|l|j)\", replacement: \"\" },\n\t\t\t{ name: \"Preserve last consonant in cluster\", pattern: \"([mnptkswlj])(?=[mnptkswlj])\", replacement: \"\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Codas\",\n\t\tregex: [\n\t\t\t{ name: \"Preserve coda consonant in following empty onset\", pattern: \"([^aeiou])(n*)\\\\.([aeiou])\", replacement: \"$2.$1$3\" },\n\t\t\t{ name: \"Move coda to empty onset\", pattern: \"(?\u003C=[aeioun]\\\\.)([aeiou])([^aeioun#\\\\.\\\\s])(?=[.#\\\\s])\", replacement: \"$2$1\" },\n\t\t\t{ name: \"Remove coda consonants\", pattern: \"[^aeioun#.\\\\s]+(?=[^aeiou]*[\\\\.#\\\\s])\", replacement: \"\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Illegal Sequences\",\n\t\tregex: [\n\t\t\t{ name: \"Resolve illegal sequence [ti] to [si]\", pattern: \"ti\", replacement: \"si\" },\n\t\t\t{ name: \"Reduce illegal sequence [wo]\", pattern: \"wo\", replacement: \"o\" },\n\t\t\t{ name: \"Reduce illegal sequence [wu]\", pattern: \"wu\", replacement: \"u\" },\n\t\t\t{ name: \"Reduce illegal sequence [ji]\", pattern: \"ji\", replacement: \"i\" },\n\t\t\t{ name: \"Remove coda in illegal sequence [n.m]\", pattern: \"n\\\\.m\", replacement: \".m\" },\n\t\t\t{ name: \"Remove coda in illegal sequence [n.n]\", pattern: \"n\\\\.n\", replacement: \".n\" }\n\t\t]\n\t},\n\t{\n\t\tcategory: \"Vowel Hiatus\",\n\t\tregex: [\n\t\t\t{ name: \"Insert [w] before [a] after non-front vowel\", pattern: \"(?\u003C=[aou]\\\\.)a\", replacement: \"wa\" },\n\t\t\t{ name: \"Insert [j] before [a] after front vowel\", pattern: \"(?\u003C=[ie]\\\\.)a\", replacement: \"ja\" },\n\t\t\t{ name: \"Insert [w] before [e] after back vowel\", pattern: \"(?\u003C=[ou]\\\\.)e\", replacement: \"we\" },\n\t\t\t{ name: \"Insert [j] before [e] after non-back vowel\", pattern: \"(?\u003C=[aei]\\\\.)e\", replacement: \"je\" },\n\t\t\t{ name: \"Resolve hiatus with [w] before [i]\", pattern: \"(?\u003C=[aeiou]\\\\.)i\", replacement: \"wi\" },\n\t\t\t{ name: \"Resolve hiatus with [j] before [o]\", pattern: \"(?\u003C=[aeiou]\\\\.)o\", replacement: \"jo\" },\n\t\t\t{ name: \"Resolve hiatus with [j] before [u]\", pattern: \"(?\u003C=[aeiou]\\\\.)u\", replacement: \"ju\" }\n\t\t]\n\t}\n];\n\nfunction tokiponize(n){\n//\tconst history = [];\n\t\n\t//Clean whitespace\n\tn = n.replace(/\\s/g, \" \").trim();\n\t//Boundary marking\n\tn = \"#\" + n + \"#\";\n\t//Remove IPA brackets\n\tn = n.replace(/[\\/\\[\\]]/g, \"\");\n\t//Diacritic separation\n\tn = n.normalize(\"NFD\");\n\t//Fix stress markings without boundary\n\tn = n.replace(/(?\u003C![.#\\s])(['ˈˌ])/g, \".$1\");\n\n\t//Rules loop\n\trules.forEach((step) =\u003E {\n\n\t\tconst category = {\n\t\t\tcategory: step.category,\n\t\t\trules: []\n\t\t};\n\t\t\n\t\tstep.regex.forEach((rule) =\u003E {\n\t\t\t//Get matches of rule\n\t\t\tconst matches = [...n.matchAll(new RegExp(rule.pattern, \"g\"))]\n\t\t\t\t.map(match =\u003E match[0].replace(/#/g, \"\")); // Get full match without boundary mark\n\t\t\t\n\t\t\t//Execute replacement if it exists\n\t\t\tif (rule.replacement !== undefined) {\n\t\t\t\tn = n.replace(new RegExp(rule.pattern, rule.flag ?? \"g\"), rule.replacement);\n\t\t\t}\n\n\t\t\t//Add to rule log if executed\n\t\t\tif (matches.length \u003E 0){\n\t\t\t\tcategory.rules.push({\n\t\t\t\t\tname: rule.name,\n\t\t\t\t\tmatches: matches,\n\t\t\t\t\t...(rule.replacement !== undefined \u0026\u0026 { result: n.replace(/#/g, \"\") }), // Add results without boundary marks if rule has replacement\n\t\t\t\t\t...(rule.type !== undefined \u0026\u0026 { type: rule.type }), // Add rule type if it exists\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t//Log category\n\t\t/*\n\t\tif (category.rules.length \u003E 0) {\n\t\t\thistory.push(category);\n\t\t}\n\t\t*/\n\t});\n\n\t//Removal of dividing marks\n\tn = n.replace(/[#\\.]/g,\"\");\n\n\treturn n;\n}\n\nfunction Z30901( Z30901K1 ) {\n\treturn tokiponize(Z30901K1);\n}"
        }
    },
    "Z2K3": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11",
            {
                "Z1K1": "Z11",
                "Z11K1": "Z1002",
                "Z11K2": "tokiponise, JS"
            }
        ]
    },
    "Z2K4": {
        "Z1K1": "Z32",
        "Z32K1": [
            "Z31"
        ]
    },
    "Z2K5": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11"
        ]
    }
}