UNPKG

beygla

Version:

<h1 align="center"> Beygla </h1>

254 lines (247 loc) 18 kB
const NO_DECLENSION = "0;,,,"; const NO_DECLENSION_MARKER = "~"; const isChar = (c) => c === "-" || c.toLowerCase() !== c.toUpperCase(); const validTerminator = (c) => ["!", "_"].indexOf(c) !== -1; function deserializeTrie(str) { let i = 0; const char = () => str.substr(i, 1); const next = () => i++; function deserializeLeaf() { function returnValue(c, value) { if (!validTerminator(c)) throw new Error("INV_TER: " + c); return [{ value, children: {} }, c === "!"]; } const firstChar = char(); if (firstChar === NO_DECLENSION_MARKER) { next(); // Move beyond terminator return returnValue(firstChar, NO_DECLENSION); } const parts = []; for (let i = 0;; i++) { let part = ""; let c = char(); while (isChar(c)) { part += c; next(); c = char(); } // 'c' is terminator or separator parts.push(part); next(); // Move beyond terminator or separator if (i === 3) { return returnValue(c, parts.join(",")); } // 'c' should be terminator if (c !== ",") throw new Error("INV_SEP: " + c); } } function deserializeKey() { let key = ""; let c = char(); while (isChar(c)) { key += c; next(); c = char(); } if (c !== ":") throw new Error("INV_COL: " + c); next(); // Move past ':' to value return key; } function deserializeObject() { next(); // Move to first property const children = {}; while (true) { const key = deserializeKey(); const [child, done] = deserialize(); children[key] = child; if (!done) continue; const c = char(); // Should be terminator next(); // Move past terminator if (!validTerminator(c)) throw new Error("INV_TER: " + c); return [{ value: "", children }, c === "!"]; } } function deserialize() { const c = char(); if (c === "{") { return deserializeObject(); } return deserializeLeaf(); } return deserialize()[0]; } function extractDeclension(trie, name) { let node = trie; for (const char of name.split("").reverse()) { const next = node.children[char]; if (next) { if (next.value) { // We've reached a leaf node, return the value return next.value; } // Non-leaf node. Keep traversing the trie node = next; continue; } // If there is no next node for the current character, and the // current node is not a leaf node, we are either: // // 1. at a dead end // 2. the next node is a "union leaf node" // // If 'node.children' looks like so: // // { // abc: { ... }, // d: { ... }, // } // // Then 'abc' is an example of a union leaf node. If 'char' is // one of the characters that comprises the key, then the union // leaf node contains the value we're looking for. // for (const key of Object.keys(node.children)) { for (let i = 0; i < key.length; i++) { if (key.substr(i, 1) === char) { return node.children[key].value; } } } // We are at a dead end. break; } return null; } var serializedInput = "{e:{n:{ein:,,,_r:,,,s!_t:{t:,,,_n:,,,s!_cghim:,,,!_t:{r:{ö:{j:{b:ört,örtu,örtu,artar_B:ört,ört,ört,artar!!_aeo:,,,s!_n:{e:{r:{Aó:,,,s_e:,,i,s!_Bcv:,,,s!_a:,,,s!_ó:{j:,u,u,ar_Bn:,,,ar!_s:{ú:,,i,s_en:,,,s_iá:,,,ar!_e:{ijrí:,i,i,ar_b:,u,u,ar_f:,,i,s!_t:{ió:,,,ar_o:,,,s!_í:{mr:,,,ar_v:,i,i,ar!_iou:,,,ar_ak:,,,s_l:,,i,s_é:,i,i,ar!_n:{o:{m:{í:{S:,,i,ar_T:,,i,s!_Aað:,,i,s_ó:,,,s_r:,,i,ar!_l:{ií:,,,s_ó:,,i,s!_e:{d:,,,s_L:,,i,s!_s:{a:,,i,ar_m:,,,ar!_dr:,,i,s_tí:,,,s_k:,,i,ar_V:,,,ar!_a:{i:{l:{u:,,,s_l:,,,!_rt:,,,s!_j:{l:{i:{K:,,,s_L:,,i,s!!_m:,,,s!_v:{IÍ:,,i,s_S:,,,s!_t:{a:{n:,,,s_N:,,i,s!_s:{i:,,i,s_o:,,,s!_r:,,i,s!_DJeklrÍí:,,,s_fhm:,,i,s_d:,,i,ar!_r:{ö:{j:jörn,jörn,irni,jörns_H:örn,örn,örn,arnar_r:örn,örn,erni,arnar!_á:,,i,s_Ö:Örn,Örn,Erni,Arnar!_n:{i:{l:{a:inn,in,ni,ins_r:,,,ar!_e:n,,i,s_Ff:,,,s_rtáð:inn,in,ni,ins_gn:n,,,s!_u:{ð:{u:n,,i,s_Ii:,i,i,ar!_t:{ö:unn,un,ni,uns_ó:,i,i,ar!_glnrsÍæ:,i,i,ar!_a:{m:{t:{s:{u:,,,s_i:,,i,s!_r:,,i,s!_r:{euÁ:,,i,s_o:,,,s!_ð:{iu:,,i,s_r:,,,s!_glnsæíú:,,i,s_i:,,,s!_hó:,,i,s_ð:n,,i,s!_A:,,,_áú:n,,i,s_ö:önn,önn,önn,annar!_ú:{r:,u,u,ar_R:,,,ar!_i:{gtvw:,,,s_Veklr:,,,ar!_í:{r:{Aa:,,,ar_gt:,u,u,ar!_l:{a:{d:{n:,,,ar_í:,,,!_MSjt:,,,ar_g:,,,s!_k:{n:,,,s_s:,,,ar!_Hginrstyáðó:,,,ar_E:,u,u,ar!_m:{a:,,,s_s:,,,ar!_t:{s:,u,u,ar_n:,,,s!_LRk:,,,ar!_u:{ð:,,i,s_gj:,,,ar!_e:{r:{aÍ:,,,ar_ö:,,,s!_t:{s:,u,u,ar_r:,,,s!_lm:,,,ar_bghí:,,,s!_f:{ö:öfn,öfn,öfn,afnar_eo:,,,ar_a:,,i,s!_á:{r:{F:,,,ar_ð:,,i,s!_d:,,i,ar_fj:,,i,s_R:,,,ar!_g:{e:{r:,,,ar_R:,,i,s!_ö:ögn,ögn,ögn,agnar_a:,,i,s_Ö:Ögn,Ögn,Ögn,Agnar!_ó:,,i,s_h:,,,s_y:,,,jar!_a:{l:{g:{A:Agla,Öglu,Öglu,Öglu_EU:a,u,u,u!_l:{e:{b:{a:{n:Annabella,Önnubellu,Önnubellu,Önnubellu_rs:a,u,u,u!!_n:{iníóú:a,u,u,u_o:,u,u,u!_BHNstí:a,u,u,u!_A:Alla,Öllu,Öllu,Öllu_EiyÚ:a,u,u,u_a:alla,öllu,öllu,öllu!_t:{a:atla,ötlu,ötlu,ötlu_A:Atla,Ötlu,Ötlu,Ötlu_s:a,u,u,u!_r:{Eeu:a,u,u,u_a:arla,örlu,örlu,örlu!_beikosuyÓáæíóú:a,u,u,u_a:ala,ölu,ölu,ölu!_d:{d:{A:Adda,Öddu,Öddu,Öddu_EIOeio:a,u,u,u_a:adda,öddu,öddu,öddu!_l:{A:Alda,Öldu,Öldu,Öldu_iou:a,u,u,u_a:alda,öldu,öldu,öldu!_n:{a:anda,öndu,öndu,öndu_Iiu:a,u,u,u!_A:Ada,Ödu,Ödu,Ödu_IeiÍÓí:a,u,u,u_g:agda,ögdu,ögdu,ögdu!_n:{n:{A:Anna,Önnu,Önnu,Önnu_IUeiouú:a,u,u,u_a:anna,önnu,önnu,önnu!_r:{A:Arna,Örnu,Örnu,Örnu_EeiÁ:a,u,u,u_a:arna,örnu,örnu,örnu!_g:{iö:a,u,u,u_a:agna,ögnu,ögnu,ögnu!_IUefilotÍíðóú:a,u,u,u_a:ana,önu,önu,önu!_t:{r:{ei:a,u,u,u_a:arta,örtu,örtu,örtu!_n:{a:anta,öntu,öntu,öntu_e:a,u,u,u!_a:ata,ötu,ötu,ötu_egikstéíóú:a,u,u,u_l:alta,öltu,öltu,öltu!_h:{t:{r:{e:a,u,u,u_a:artha,örthu,örthu,örthu!_a:atha,öthu,öthu,öthu!!_ð:{r:{euó:a,u,u,u_a:arða,örðu,örðu,örðu!_g:Agða,Ögðu,Ögðu,Ögðu_Iiyíú:a,u,u,u!_b:{l:Alba,Ölbu,Ölbu,Ölbu_bem:a,u,u,u!_r:{d:{n:{a:andra,öndru,öndru,öndru_A:Andra,Öndru,Öndru,Öndru_Ii:a,u,u,u!!_t:{ekí:a,u,u,u_a:atra,ötru,ötru,ötru!_A:Ara,Öru,Öru,Öru_efiruáíóý:a,u,u,u_a:ara,öru,öru,öru_s:,,,!_í:{r:{a:{m:{a:Annamaría,Önnumaríu,Önnumaríu,Önnumaríu_i:a,u,u,u!_DM:a,u,u,u!_AKdeo:a,u,u,u!_DFMScdfghlmnpsvx:a,u,u,u!_f:{l:{A:Alfa,Ölfu,Ölfu,Ölfu_EYeiÚ:a,u,u,u!_eíóú:a,u,u,u_a:afa,öfu,öfu,öfu!_s:{í:{l:{AE:a,u,u,u_a:Annalísa,Önnulísu,Önnulísu,Önnulísu!_DLvú:a,u,u,u!_ó:{r:Annarósa,Önnurósu,Önnurósu,Önnurósu_R:a,u,u,u!_s:{A:Assa,Össu,Össu,Össu_ei:a,u,u,u!_n:{a:ansa,önsu,önsu,önsu_e:a,u,u,u!_r:{a:arsa,örsu,örsu,örsu_Yi:a,u,u,u!_eilÁÆÓ:a,u,u,u!_m:{l:{A:Alma,Ölmu,Ölmu,Ölmu_Eeiá:a,u,u,u_a:,,,!_r:{a:arma,örmu,örmu,örmu_Io:a,u,u,u!_m:{EIi:a,u,u,u_a:amma,ömmu,ömmu,ömmu!_eÍÝíó:a,u,u,u!_k:{l:{Eeio:a,u,u,u_a:alka,ölku,ölku,ölku!_n:{i:a,u,u,u_a:anka,önku,önku,önku!_eikrsáíó:a,u,u,u_a:aka,öku,öku,öku!_j:{n:{A:Anja,Önju,Önju,Önju_EYioy:a,u,u,u_a:anja,önju,önju,önju!_k:{s:{A:Askja,Öskju,Öskju,Öskju_E:a,u,u,u!_k:a,u,u,u!_r:{IYi:a,u,u,u_a:arja,örju,örju,örju!_aglsuyæð:a,u,u,u!_v:{l:{EYiö:a,u,u,u_a:alva,ölvu,ölvu,ölvu!_A:Ava,Övu,Övu,Övu_EegikrÍí:a,u,u,u_a:ava,övu,övu,övu!_g:{g:{eio:a,u,u,u_a:agga,öggu,öggu,öggu!_eilnou:a,u,u,u_a:aga,ögu,ögu,ögu!_ú:{D:a,u,u,u_s:,,,!_p:{r:{a:arpa,örpu,örpu,örpu_I:a,u,u,u!_mp:a,u,u,u!_ceizÚó:a,u,u,u_y:anya,önyu,önyu,önyu!_l:{e:{a:{g:,,,ar_fhkmnrs:,,,s!_d:{A:,,,s_E:,,,ar!_t:{r:,,,s_s:,,,ar!_ó:{B:,,,ar_J:,,,s!_inrsxíú:,,,s_bhk:,,,ar_v:,,i,s!_i:{b:{i:,,,_á:,,,ar!_cms:,,,s_d:,,,ar!_l:{i:{g:{E:Egill,Egil,Agli,Egils_nr:ill,il,li,ils!_B:,,,s_fkr:ill,il,li,ils_t:etill,etil,atli,etils_L:,,,ar!_eáæ:l,,i,s_u:ull,ul,li,uls_a:,,i,s_ö:öll,öll,öll,allar!_s:{í:{v:aldakvísl,öldukvísl,öldukvísl,öldukvíslar_g:,,i,s!!_mæíó:,,,ar_r:,,i,s_a:,,,s!_m:{a:{í:{L:,,,s_r:,,,ar!_i:{r:,,,ar_l:,,,s!_dhró:,,,s_j:,,,ar!_eilruí:,,,s_ó:,,,ar!_i:{r:{AadefgimrtÓáóúý:i,a,a,a_y:,,,!_g:{g:{e:{B:i,a,a,a_k:i,ja,ja,ja!_Uaiouö:i,a,a,a!_alnou:i,a,a,a!_x:{Ua:i,a,a,a_Ö:Öxi,Öxi,Öxi,Axar!_bdfjklmnpstvðóú:i,a,a,a_u:i,ja,ja,ja_a:,,,s!_ý:{n:{n:{e:{BDHV:,,,jar_J:,ju,ju,jar!_Aaiou:,,,jar_áó:,ju,ju,jar!_ó:{n:,,,s_J:,,,jar!_g:{a:{D:,ju,ju,jar_MR:,,,jar!_ir:,ju,ju,jar!_dfklrstæéð:,ju,ju,jar_o:,,,s!_v:{en:,,,s_l:,,,jar!_r:{r:{iu:,,,jar_a:,,,s!_n:,,,s_au:,,,jar!_dglmst:,,,jar!_f:{l:{ó:{d:{A:,,,s_ú:,,i,s!_ð:,,,s!_o:,,,s!_i:{e:{l:,,,ar_L:,,,s!_Ss:,,,jar!_í:,,,ar_aeu:,,,s_ú:,u,u,ar_ö:öf,öfu,öfu,afar!_h:{cp:,,,s_t:,,,ar!_g:{r:{e:{b:{n:{aeinrí:,,,s_u:,,i,s!_s:{Áíó:,,,s_s:,,i,s!_d:{l:,,i,s_n:,,,s!_m:{l:,,,s_u:,,i,s!_g:{n:{I:,,,s_y:,,i,s!_u:,,,s!_æ:{n:,,i,s_S:,,,s!_Efilrtyð:,,,s_ó:,,i,s!_B:,,,s!_o:{b:{dgilnrstyæð:,u,u,ar_ef:,,,ar!_B:,,,ar_e:,,,s!_ö:örg,örgu,örgu,argar_a:,,i,s!_i:{e:,u,u,ar_v:,,,s!_n:{i:{l:{l:,,,s_r:,,i,s!_mnr:,,,s!!_g:{ö:ögg,ögg,ögg,aggar_i:,,,jar!_u:,u,u,ar_í:,,,s!_r:{u:{g:{n:{iæ:ur,,i,s_e:ur,,,s!_g:{euy:ur,,i,s_ö:ur,,,s!_i:{e:ur,,i,s_V:,,,s!_ruy:ur,,i,s_a:agur,ag,egi,ags_í:ur,,,s!_ð:{i:{v:{lnty:ur,,i,ar_g:ur,,i,s!_e:ur,i,i,ar_Em:ur,,i,s_r:ur,,i,ar!_r:{a:{v:{ð:{u:ur,,i,s_áóö:ur,,i,ar!_lnrstá:ur,,i,ar_g:ur,,i,s!_bghkr:ur,,i,s!_ö:{HMVh:örður,örð,erði,arðar_j:jörður,jörð,irði,jarðar!_Ue:ur,i,i,ar_uáó:ur,,i,ar!_ö:{r:ur,,i,ar_l:ur,,,s_H:öður,öð,eði,aðar!_e:{r:{f:{gn:ur,,i,s_lð:ur,,i,ar!!!_u:{a:ur,i,i,ar_f:örfuður,örfuð,örfuði,arfaðar!_a:{k:ur,,i,ar_l:ur,,i,s!_íú:ur,i,i,ar_áó:ur,,i,s_ý:ur,,,s!_d:{n:{i:{v:ur,,i,ar_Tl:ur,,i,s!_uá:ur,,i,ar_ae:ur,,i,s!_l:{a:{n:{r:ur,,i,ar_ó:ur,,i,s!_v:{t:{s:{Á:ur,,i,ar_i:ur,,i,s!!_s:{Á:ur,,i,ar_Ó:ur,,i,s!_r:{i:ur,,i,s_o:ur,,i,ar!_giknæ:ur,,i,s!_BGb:ur,ur,ri,urs_jmró:ur,,i,s!_ei:ur,i,i,ar_E:ur,,i,s_u:ur,,i,ar_ö:jöldur,jöld,ildi,jaldar!_d:ur,,i,s!_k:{a:{lþ:ur,,i,s_V:ur,ur,ri,urs!_eisuáí:ur,,i,s_r:örkur,örk,erki,arkar!_n:{n:{i:ur,,i,s_Uu:ur,i,i,ar!_ay:ur,,i,s!_m:{l:{áó:ur,,i,s_I:ur,i,i,ar!_iruyíóú:ur,,i,s!_f:{l:{ÁÚóú:ur,,i,s_EYe:ur,i,i,ar!_í:{l:ur,,i,s_v:ur,ur,ri,urs!_aióú:ur,,i,s!_t:{r:{a:ur,,i,s_ö:jörtur,jört,irti,jartar!_s:{ae:ur,,i,s_ö:östur,öst,esti,astar!_t:{e:ur,,i,s_ö:öttur,ött,etti,attar_ó:ur,,i,ar!_afiuóú:ur,,i,s_Oeé:ur,ur,ri,urs!_l:{a:{D:ur,,,s_FV:ur,,i,s!_lo:ur,,i,s!_h:,,i,s_p:ur,,i,s_sz:,,i,ar!_a:{m:{n:{n:,,,s_iy:,,i,s!_t:{s:{eiu:,,i,s_Á:,,,s!_r:,,i,s!_s:{Á:,,,s_Í:,,i,s!_g:{r:,,,s_a:,,,ar_in:,,i,s!_i:{elr:,,i,s_dg:,,,s!_a:{h:ar,ar,ri,ars_H:,,i,s_T:,,,ar!_í:{l:,,,s_r:,,i,s!_ð:{i:{r:,,,s_e:,,i,s!_uóú:,,i,s!_dlryÓó:,,i,s_e:,,,s!_s:{eÁÍæó:,,i,s_a:,,,s!_dfghjklnprtvxðó:,,i,s_M:,,,s!_i:{e:{g:,,i,s_G:,,,s!_dgklmnrstvð:r,,,s!_e:{h:{t:{s:,,,ar_ú:,,,s!_p:,,,s!_t:{s:{E:,,,ar_i:,,,s!_x:,,i,s_elú:,,,s!_g:{gl:,,,s_n:,,,ar!_PVbdfnpsvz:,,,s!_o:{ghmní:,,,s_t:,,i,s!_r:{a:r,,i,s_ö:örr,örr,erri,arrar_y:r,,,s_Ý:r,i,i,ar!_ó:{dnþ:,,i,s_DThÞ:,,,s!_y:{e:{rÞ:r,,,s_R:,,,s!_t:,,,s!_ú:{ht:,,i,s_k:,,,s!_á:{Mr:r,,,s_k:,,i,s_KL:,,,s_V:,,,ar!_í:,,,s_æéý:r,,,s_ö:ör,öru,öru,arar_d:r,,i,s_ÍÝ:,i,i,ar!_s:{í:{d:{a:{n:,i,i,ar_r:,,,ar!_dfglmnrstyæéíðó:,i,i,ar!_l:{A:,i,i,ar_l:,,i,ar!_r:{A:,i,i,ar_a:,,,ar!_D:,,,ar!_e:{n:{r:{A:,,i,ar_a:,,i,s!_g:,i,i,ar_An:,,i,ar_f:,,i,s!_r:{d:,,i,ar_A:,,,ar!_l:{r:{a:{h:,,,_K:,,i,ar!!_ú:,,i,ar!_d:{e:,,i,s_í:,i,i,ar!_m:{a:,,,_r:,,i,!_s:{ó:,,,_m:,,i,ar!_J:,,,_tv:,,i,ar!_u:{m:{e:,,i,s_s:,,i,ar!_n:{aíú:,,i,ar_e:,,,ar!_defghprí:,,i,ar!_n:{e:{Jmr:,,,_t:,,i,!_o:,,,ar_a:,,,!_a:{l:{t:,,i,ar_o:,,i,!_m:{o:,,,_uó:,,i,ar!_ejkníóý:,,i,ar_t:,,,ar!_i:{r:{Ao:,,,ar_Í:,i,i,ar!_lms:,,,ar_n:,,,_v:,,i,s!_l:{i:{g:,,i,_GN:,,,!_e:{i:,,i,ar_í:,,,!_í:,,,!_s:{Á:,,,_o:,,i,!_á:{l:{u:,,i,ar_r:,,i,s!!_ó:,,,ar_oéú:,,i,ar_rt:,,,_Á:,,,s!_y:{e:{d:{l:,ju,ju,jar_n:,,,jar!_r:{Aauáó:,ju,ju,jar_r:,,,jar!_m:{girtð:,,,jar_lmuíó:,ju,ju,jar!_l:{ntx:,,,s_alrsáó:,ju,ju,jar_e:,,,jar!_g:{n:{I:,ju,ju,jar_i:,,,jar!_goru:,ju,ju,jar_l:,,,jar!_ð:{i:{r:,ju,ju,jar_V:,,,jar!_a:,ju,ju,jar!_Mfknstvó:,ju,ju,jar!_n:{o:,,,s_n:,,,jar!_r:{nr:,,,s_a:,,,jar!_l:{l:{o:,,,jar_i:,,,s!!_E:,,,jar!_d:{l:{a:{n:{r:,,i,ar_oó:,,,s_y:,,i,s!_v:{t:,,i,ar_nsæð:,,i,s_E:,,,s!_r:{e:,,,s_a:,,i,s!_m:,,,s_b:,,i,s!_o:{n:,,i,s_fs:,,,ar_hp:,,,s!_u:,,,ar_i:,i,i,ar!_n:{a:{l:,,i,s_n:,,,s!_iu:,,,ar_e:,,,s!_r:{a:{h:{n:{r:,,i,s_io:,,,s!_c:,,,s!_lnvw:,,,s_g:,,,ar!!_e:,,,s_im:,,,ar_d:ödd,ödd,ödd,addar!_ð:{r:{a:{ghv:,,i,s_n:,,,s!!_í:{v:,,,s_r:,i,i,ar!_á:{r:{l:,i,i,ar_n:,,i,s!_N:,,,ar!_e:,,,s_ö:öð,öð,öð,aðar_ó:,,,ar!_k:{r:{ö:örk,örk,örk,arkar_a:,,i,s_Ö:Örk,Örk,Örk,Arkar!_i:{r:{dlnð:,,i,s_Etú:,,,s!_n:,,,s_E:,,,ar_e:,,,ur!_e:{r:{bú:,,,s_t:,,i,s!!_í:{v:{ð:{ú:,,,s_i:,,,ur!_ry:,,,ur!!_ö:ök,öku,öku,akar_sá:,,,ar_acno:,,,s_l:,,i,s_k:ökk,ökk,ökk,akkar!_í:{n:{ó:{n:,,,s_J:,,,ar!_í:,,,ar!_m:{a:,,,ar_oó:,,,!_bdfrs:,,,ar_lv:,,,s!_ó:{k:{ik:,,,ar_r:,,,s!_g:{ó:,,,ar_gú:,,,s!_r:{a:,,,ar_e:,,,s!_dentí:,,,s_l:,,,ar!_p:{eio:,,,s_p:öpp,öpp,öpp,appar_s:Ösp,Ösp,Ösp,Aspar!_v:{i:{L:,,,ar_S:,,,jar!_a:,,,s_í:,,,ar!_xz:,,,_á:,,,r_bcjoé:,,,s!!"; // We can't hard-code this to something like "@@input@@" because // rollup considers that to be dead code and eliminates it. // // Anyway, this will be replaced with a constant in builds. var mode = "names"; // Set to either 'names' or 'addresses' in builds const trie = deserializeTrie(serializedInput); const casesIs = ["nf", "þf", "þgf", "ef"]; const casesEn = ["nom", "acc", "dat", "gen"]; function getCaseIndex(caseStr) { const indexIs = casesIs.indexOf(caseStr); if (indexIs !== -1) return indexIs; const indexEn = casesEn.indexOf(caseStr); if (indexEn !== -1) return indexEn; return 0; // Fall back to 0 if an invalid case was provided } function declineName(name, declension, caseStr) { const appendices = declension.split(","); const subtraction = appendices[0].length; const caseIndex = getCaseIndex(caseStr); // Should not happen, but prefer being safe if (!Number.isFinite(subtraction) || appendices.length !== 4) return name; const root = name.substr(0, name.length - subtraction); return root + appendices[caseIndex]; } let predicate; function setPredicate(pred) { predicate = pred; } function applyCaseToName(caseStr, name) { if (mode === "names") { const namesThatEndWithSon = ["Samson", "Jason"]; const endsWithSon = namesThatEndWithSon.indexOf(name) !== -1; if (!endsWithSon) { for (const [ending, declension] of [ ["son", "on,on,yni,onar"], ["dóttir", "ir,ur,ur,ur"], ["bur", ",,i,s"], ]) { if (!name.endsWith(ending)) continue; name = name.split(ending)[0]; return name + declineName(ending, declension, caseStr); } } } const declension = getDeclensionForName(name); if (declension && (!predicate || predicate(name))) name = declineName(name, declension, caseStr); return name; } /** * Applies a case to a source name provided in the nominative * case (nefnifall). * * @example * ```tsx * applyCase("ef", "Jóhann"); * //=> "Jóhannesar" * * applyCase("þgf", "Helga Fríða Smáradóttir"); * //=> "Helgu Fríðu Smáradóttur" * ``` * * The name provided must be an Icelandic name in the nominative case * (nefnifall). Otherwise, an unexpected output is likely. * * The supported cases are: * * - Nominative `nom` (nefnifall `nf` in Icelandic) * - Accusative `acc` (þolfall `þf` in Icelandic) * - Dative `dat` (þágufall `þgf` in Icelandic) * - Genitive `gen` (eignarfall `ef` in Icelandic) * * Note that superfluous whitespace is not retained: * * @example * ```tsx * applyCase("þf", " \n Hildigerður Oddný\tPatreksdóttir \n\n"); * //=> "Hildigerði Oddnýju Patreksdóttur" * ``` * * @param name - An Icelandic name in the nominative case (nefnifall) * @param caseStr - The case to apply to the name to, e.g. `þf` */ function applyCase(caseStr, name) { return name .split(/\s+/) .filter(Boolean) .map((name) => { if (mode === "names") return applyCaseToName(caseStr, name); return name .split("-") .map((name) => applyCaseToName(caseStr, name)) .join("-"); }) .join(" "); } function getDeclensionForName(name) { if (name.split(/\s+/).length > 1) throw new Error("Name must not include whitespace"); const declension = extractDeclension(trie, name); if (declension) { // Ensure that the declension applies to the name. This guard is useful when // the subtraction is longer than the path to the declension. // // For example, consider this: // // { // "path": "ya", // "children": {}, // "keys": ["Tanya"], // "value": "4;anya,önyu,önyu,önyu" // } // // The name 'Maya' matches this path, but applying the declension erases the // entire name. const appendices = declension.split(","); if (!name.endsWith(appendices[0])) return null; } return declension; } export { applyCase, getDeclensionForName, setPredicate };