UNPKG

sedra-model

Version:

Sedra models and related utility functions

2,059 lines (2,007 loc) 68.8 kB
/** @module sedraModel */ /** * @file Sedra models and related utility functions * @version 1.2.0 * @author Greg Borota * @copyright (c) 2017 Greg Borota. * @license MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // https://peshitta.github.io // https://sedra.bethmardutho.org/about/fonts // http://cal1.cn.huc.edu/searching/fullbrowser.html (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.sedraModel = {}))); }(this, (function (exports) { 'use strict'; /** * Word Type enumeration * @static * @const * @type { Array.<string> } */ var wordType = Object.freeze([ 'Normal', 'Parenthesized', 'Bracketed', 'HighFrequency' // e.g. propositions ]); /** * Vowel enumeration * @static * @const * @type { Array.<string> } */ var vowel = Object.freeze(['', 'a', 'o', 'e', 'i', 'u']); /** * Word Number enumeration * @static * @const * @type { Array.<string> } */ var wordNumber = Object.freeze(['', 'Singular', 'Plural']); /** * Word Gender enumeration * @static * @const * @type { Array.<string> } */ var wordGender = Object.freeze([ '', 'Common', 'Masculine', 'Feminine' ]); /** * Word Form enumeration * @static * @const * @type { Array.<string> } */ var wordForm = Object.freeze([ '', 'Peal', 'Ethpeal', 'Pael', 'Ethpael', 'Aphel', 'Ettaphal', 'Shaphel', 'Eshtaphal', 'Saphel', 'Estaphal', 'Pauel', 'Ethpaual', 'Paiel', 'Ethpaial', 'Palpal', 'Ethpalpal', 'Palpel', 'Ethpalpal1', 'Pamel', 'Ethpamal', 'Parel', 'Ethparal', 'Pali', 'Ethpali', 'Pahli', 'Ethpahli', 'Taphel', 'Ethaphal' ]); /** * Root records, e.g. 0:2,"AB","ab |A",0 * Id is the position in the containing array so it is not stored * * @static * @param { string } root e.g. "AB" * @param { string } sort e.g. "ab |A" * @param { number } attributes 16-bit map * @returns { Root } Sedra Root row */ var makeRoot = function (root, sort, attributes) { return Object.freeze( Object.create(null, { root: { value: root, enumerable: true }, sort: { value: sort, enumerable: true }, attributes: { value: attributes, enumerable: true } }) ); }; /** * Build Root Attribute object * @static * @param { boolean } seyame true if root has seyame * @param { string } rootType word type enumeration * @returns { RootAttribute } Root Attribute object */ var makeRootAttribute = function (seyame, rootType) { return Object.freeze( Object.create(null, { seyame: { value: seyame, enumerable: true }, rootType: { value: rootType, enumerable: true } }) ); }; /** * Get Root Attribute object from root attribute bit map * @static * @param { number } attributes 16-bit map * @returns { RootAttribute } Root Attribute object */ var getRootAttribute = function (attributes) { return makeRootAttribute( !!(0x1 & attributes), // 0 SEYAME FLAG wordType[(0x6 & attributes) >>> 1] // 1-2 ROOT TYPE ); }; /** * Return flatten root object with parsed attribute values * @static * @param { number } id the id of current root object * @param { Root } root root raw object * @returns { FlatRoot } the flatten root model */ var getRoot = function (id, root) { if (root) { var attributes = getRootAttribute(root.attributes); return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, root: { value: root.root, enumerable: true }, sort: { value: root.sort, enumerable: true }, seyame: { value: attributes.seyame, enumerable: true }, rootType: { value: attributes.rootType, enumerable: true } }) ); } return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, root: { value: null, enumerable: true }, sort: { value: null, enumerable: true }, seyame: { value: null, enumerable: true }, rootType: { value: null, enumerable: true } }) ); }; /** * Lexeme Grammatical Category enumeration * @static * @const * @type { Array.<string> } */ var lexemeGrammaticalCategory = Object.freeze([ 'Verb', 'ParticipleAdjective', 'Denominative', 'Substantive', 'Noun', 'Pronoun', 'ProperNoun', 'Numeral', 'Adjective', 'Particle', 'Idiom', 'Adverb-)iTt', 'AdjectiveOfPlace', 'Adverb' ]); /** * Lexeme First Suffix enumeration * @static * @const * @type { Array.<string> } */ var lexemeFirstSuffix = Object.freeze([ '', 'to)', 'To)', 'no)', 'ono)', 'iTno)', 'wuno)', 'tono)', 'twuno)', 'wuso)', 'oro)', 'qono)', 'yin' ]); /** * Second Second Suffix enumeration * @static * @const * @type { Array.<string> } */ var lexemeSecondSuffix = Object.freeze(['', 'oTo)', 'iTto)']); /** * Lexeme Third Suffix enumeration * @static * @const * @type { Array.<string> } */ var lexemeThirdSuffix = Object.freeze(['', 'wuto)', 'o)iTt']); /** * Lexeme Prefix enumeration * @static * @const * @type { Array.<string> } */ var lexemePrefix = Object.freeze(['', 'm', 't', '$']); /** * Lexeme Radical Type enumeration * @static * @const * @type { Array.<string> } */ var lexemeRadicalType = Object.freeze([ '', 'Bi', 'Tri', 'FourRadical', 'FiveRadical', 'SixRadical', 'Compound' ]); /** * Lexeme Form enumeration * @static * @const * @type { Array.<string> } */ var lexemeForm = Object.freeze([ '', 'Peal', 'Ethpeal', 'Pael', 'Ethpael', 'Aphel', 'Ettaphal', 'Shaphel', 'Eshtaphal', 'Saphel', 'Estaphal', 'P', 'Ethp', 'Palpel', 'Ethpalpal', 'Pamel' // ??? not documented ]); /** * Lexeme records, e.g. 1:2,0:2,"ABA",41960448,16 * Id is the position in the array so it is not stored * * @static * @param { number } rootId Root Address, e.g. 2 * @param { string } lexeme e.g. "ABA" * @param { number } morphologicalType 32-bit map * @param { number } attributes 16-bit map * @returns { Lexeme } Sedra Lexeme row */ var makeLexeme = function (rootId, lexeme, morphologicalType, attributes) { return Object.freeze( Object.create(null, { rootId: { value: rootId, enumerable: true }, lexeme: { value: lexeme, enumerable: true }, morphologicalType: { value: morphologicalType, enumerable: true }, attributes: { value: attributes, enumerable: true } }) ); }; /** * Build Lexeme Attribute object * @static * @param { boolean } seyame true if lexeme has seyame * @param { string } wordType word type enumeration * @param { string } grammaticalCategory grammatical category enumeration * @param { boolean } listing not clear yet what this is used for * @returns { LexemeAttribute } Lexeme Attribute object */ var makeLexemeAttribute = function ( seyame, wordType$$1, grammaticalCategory, listing ) { return Object.freeze( Object.create(null, { seyame: { value: seyame, enumerable: true }, wordType: { value: wordType$$1, enumerable: true }, grammaticalCategory: { value: grammaticalCategory, enumerable: true }, listing: { value: listing, enumerable: true } // TODO not documented, need to figure out }) ); }; /** * Get Lexeme Attribute object from lexeme attribute bit map * @static * @param { number } attributes 16-bit map * @returns { LexemeAttribute } Lexeme Attribute object */ var getLexemeAttribute = function (attributes) { return makeLexemeAttribute( !!(0x1 & attributes), // 0 SEYAME FLAG wordType[(0x2 & attributes) >>> 1], // 1 WORD TYPE lexemeGrammaticalCategory[(0x3c & attributes) >>> 2], // 2-5 GRAMMATICAL CATEGORY !!(0x40 & (attributes >>> 6)) // 6 ? ); }; /** * Build Lexeme Morphological Type object * @static * @param { string } firstSuffix First suffix enumeration * @param { string } secondSuffix Second suffix enumeration * @param { string } thirdSuffix Third suffix enumeration * @param { string } prefix M, T, ? enumeration * @param { string } firstVowel First Vowel * @param { string } secondVowel Second Vowel * @param { string } thirdVowel Third Vowel * @param { string } fourthVowel Forth Vowel * @param { number } vowelCount Total no of vowels in lexeme * @param { string } radicalType Radical type enumeration * @param { string } form Word form enumeration * @returns { LexemeMorphologicalType } Lexeme Morphological Type object */ var makeLexemeMorphologicalType = function ( firstSuffix, secondSuffix, thirdSuffix, prefix, firstVowel, secondVowel, thirdVowel, fourthVowel, vowelCount, radicalType, form ) { return Object.freeze( Object.create(null, { firstSuffix: { value: firstSuffix, enumerable: true }, secondSuffix: { value: secondSuffix, enumerable: true }, thirdSuffix: { value: thirdSuffix, enumerable: true }, prefix: { value: prefix, enumerable: true }, firstVowel: { value: firstVowel, enumerable: true }, secondVowel: { value: secondVowel, enumerable: true }, thirdVowel: { value: thirdVowel, enumerable: true }, fourthVowel: { value: fourthVowel, enumerable: true }, vowelCount: { value: vowelCount, enumerable: true }, radicalType: { value: radicalType, enumerable: true }, form: { value: form, enumerable: true } }) ); }; /** * Get Lexeme Morphological Type object from lexeme bit map * @static * @param { number } morphologicalType Morphological Type 32-bit map * @returns { LexemeMorphologicalType } Lexeme Morphological Type object */ var getLexemeMorphologicalType = function (morphologicalType) { return makeLexemeMorphologicalType( lexemeFirstSuffix[0xf & morphologicalType], // 0-3 First SUFFIX lexemeSecondSuffix[(0x30 & morphologicalType) >>> 4], // 4-5 SECOND SUFFIX lexemeThirdSuffix[(0xc0 & morphologicalType) >>> 6], // 6-7 THIRD SUFFIX lexemePrefix[(0x300 & morphologicalType) >>> 8], // 8-9 PREFIX vowel[(0x1c00 & morphologicalType) >>> 10], // 10-12 FIRST VOWEL vowel[(0xe000 & morphologicalType) >>> 13], // 13-15 SECOND VOWEL vowel[(0x70000 & morphologicalType) >>> 16], // 16-18 THIRD VOWEL vowel[(0x380000 & morphologicalType) >>> 19], // 19-21 FOURTH VOWEL (0x1c00000 & morphologicalType) >>> 22, // 22-24 Total no of vowels in lexeme lexemeRadicalType[(0xe000000 & morphologicalType) >>> 25], // 25-27 RADICAL TYPE lexemeForm[(0xf0000000 & morphologicalType) >>> 28] // 28-31 FORM ); }; /** * Return flatten lexeme object with parsed attribute and morphological values * @static * @param { number } id the id of current lexeme object * @param { Lexeme } lexeme lexeme raw object * @param { Array.<Root> } roots root list * @returns { FlatLexeme } the flatten lexeme model */ var getLexeme = function (id, lexeme, roots) { if (lexeme) { var attributes = getLexemeAttribute(lexeme.attributes); var morphologicalType = getLexemeMorphologicalType( lexeme.morphologicalType ); return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, rootId: { value: lexeme.rootId, enumerable: true }, root: { value: roots && roots[lexeme.rootId] ? roots[lexeme.rootId].root : null, enumerable: true }, lexeme: { value: lexeme.lexeme, enumerable: true }, firstSuffix: { value: morphologicalType.firstSuffix, enumerable: true }, secondSuffix: { value: morphologicalType.secondSuffix, enumerable: true }, thirdSuffix: { value: morphologicalType.thirdSuffix, enumerable: true }, prefix: { value: morphologicalType.prefix, enumerable: true }, firstVowel: { value: morphologicalType.firstVowel, enumerable: true }, secondVowel: { value: morphologicalType.secondVowel, enumerable: true }, thirdVowel: { value: morphologicalType.thirdVowel, enumerable: true }, fourthVowel: { value: morphologicalType.fourthVowel, enumerable: true }, vowelCount: { value: morphologicalType.vowelCount, enumerable: true }, radicalType: { value: morphologicalType.radicalType, enumerable: true }, form: { value: morphologicalType.form, enumerable: true }, seyame: { value: attributes.seyame, enumerable: true }, wordType: { value: attributes.wordType, enumerable: true }, grammaticalCategory: { value: attributes.grammaticalCategory, enumerable: true }, listing: { value: attributes.listing, enumerable: true } }) ); } return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, rootId: { value: null, enumerable: true }, root: { value: null, enumerable: true }, lexeme: { value: null, enumerable: true }, firstSuffix: { value: null, enumerable: true }, secondSuffix: { value: null, enumerable: true }, thirdSuffix: { value: null, enumerable: true }, prefix: { value: null, enumerable: true }, firstVowel: { value: null, enumerable: true }, secondVowel: { value: null, enumerable: true }, thirdVowel: { value: null, enumerable: true }, fourthVowel: { value: null, enumerable: true }, vowelCount: { value: null, enumerable: true }, radicalType: { value: null, enumerable: true }, form: { value: null, enumerable: true }, seyame: { value: null, enumerable: true }, wordType: { value: null, enumerable: true }, grammaticalCategory: { value: null, enumerable: true }, listing: { value: null, enumerable: true } }) ); }; /** * Word Suffix Gender enumeration * @static * @const * @type { Array.<string> } */ var wordSuffixGender = Object.freeze([ 'CommonOrNone', 'Masculine', 'Feminine' ]); /** * Word Suffix Person enumeration * @static * @const * @type { Array.<string> } */ var wordSuffixPerson = Object.freeze(['', 'Third', 'Second', 'First']); /** * Word Suffix Number enumeration * @static * @const * @type { Array.<string> } */ var wordSuffixNumber = Object.freeze(['SingularOrNone', 'Plural']); /** * Word Suffix Type enumeration * @static * @const * @type { Array.<string> } */ var wordSuffixType = Object.freeze(['', 'Suffix', 'Contraction']); /** * Word Person enumeration * @static * @const * @type { Array.<string> } */ var wordPerson = Object.freeze(['', 'Third', 'Second', 'First']); /** * Word State enumeration * @static * @const * @type { Array.<string> } */ var wordState = Object.freeze([ '', 'Absolute', 'Construct', 'Emphatic' ]); /** * Word Tense enumeration * @static * @const * @type { Array.<string> } */ var wordTense = Object.freeze([ '', 'Perfect', 'Imperfect', 'Imperative', 'Infinitive', 'ActiveParticiple', 'PassiveParticiple', 'Participles' ]); /** * Word records, e.g. 2:8,1:2,"ABHOH;","AaB,oHaOH_;",7405716,129 * Id is the position in the array so it is not stored * * @static * @param { number } lexemeId Lexeme Address, e.g. 2 * @param { string } word Word, e.g. "ABHOH;" * @param { string } vocalised Vocalised Word, e.g. "AaB,oHaOH_;" * @param { number } morphologicalType 32-bit map * @param { number } attributes 16-bit map * @returns { Word } Sedra Word row */ var makeWord = function ( lexemeId, word, vocalised, morphologicalType, attributes ) { return Object.freeze( Object.create(null, { lexemeId: { value: lexemeId, enumerable: true }, word: { value: word, enumerable: true }, vocalised: { value: vocalised, enumerable: true }, morphologicalType: { value: morphologicalType, enumerable: true }, attributes: { value: attributes, enumerable: true } }) ); }; /** * Build Word Attribute object * @static * @param { boolean } seyame true if word has seyame * @param { number } listing Undocumented * @param { boolean } enclitic true if word has enclitics * @param { boolean } lexeme true if current word is lexeme * @returns { WordAttribute } Word Attribute object */ var makeWordAttribute = function (seyame, listing, enclitic, lexeme) { return Object.freeze( Object.create(null, { seyame: { value: seyame, enumerable: true }, listing: { value: listing, enumerable: true }, // TODO not documented, need to figure out enclitic: { value: enclitic, enumerable: true }, lexeme: { value: lexeme, enumerable: true } }) ); }; /** * Get Word Attribute object from word attribute bit map * @static * @param { number } attributes 16-bit map * @returns { WordAttribute } Word Attribute object */ var getWordAttribute = function (attributes) { return makeWordAttribute( !!(0x1 & attributes), // 0 SEYAME FLAG (0x1e & attributes) >>> 1, // 1-4 ignore !!(0x20 & attributes), // 5 ENCLITIC FLAG !!(0x40 & attributes) // 6 LEXEME FLAG ); }; /** * Build Word Morphological Type object * @static * @param { string } suffixGender Word Suffix Gender enumeration * @param { string } suffixPerson Word Suffix Person enumeration * @param { string } suffixNumber Word Suffix Number enumeration * @param { string } suffixType Word Suffix Type enumeration * @param { number } prefixCode Word Prefix Code * @param { string } gender Word Gender enumeration * @param { string } person Word Person enumeration * @param { string } number Word Number enumeration * @param { string } state Word State enumeration * @param { string } tense Word Tense enumeration * @param { string } form Word Form enumeration * @returns { WordMorphologicalType } Word Morphological Type object */ var makeWordMorphologicalType = function ( suffixGender, suffixPerson, suffixNumber, suffixType, prefixCode, gender, person, number, state, tense, form ) { return Object.freeze( Object.create(null, { suffixGender: { value: suffixGender, enumerable: true }, suffixPerson: { value: suffixPerson, enumerable: true }, suffixNumber: { value: suffixNumber, enumerable: true }, suffixType: { value: suffixType, enumerable: true }, prefixCode: { value: prefixCode, enumerable: true }, gender: { value: gender, enumerable: true }, person: { value: person, enumerable: true }, number: { value: number, enumerable: true }, state: { value: state, enumerable: true }, tense: { value: tense, enumerable: true }, form: { value: form, enumerable: true } }) ); }; /** * Get Word Morphological Type object from word bit map * @static * @param { number } attributes Morphological Type 32-bit map * @returns { WordMorphologicalType } Word Morphological Type object */ var getWordMorphologicalType = function (attributes) { return makeWordMorphologicalType( // 0-1 <RESERVED> wordSuffixGender[(0xc & attributes) >>> 2], // 2-3 SUFFIX GENDER wordSuffixPerson[(0x30 & attributes) >>> 4], // 4-5 SUFFIX PERSON wordSuffixNumber[(0x40 & attributes) >>> 6], // 6 SUFFIX NUMBER wordSuffixType[(0x180 & attributes) >>> 7], // 7-8 SUFFIX/CONTRACTION (0x7e00 & attributes) >>> 9, // 9-14 PREFIX CODE wordGender[(0x18000 & attributes) >>> 15], // 15-16 GENDER wordPerson[(0x60000 & attributes) >>> 17], // 17-18 PERSON wordNumber[(0x180000 & attributes) >>> 19], // 19-20 NUMBER wordState[(0x600000 & attributes) >>> 21], // 21-22 STATE wordTense[(0x3800000 & attributes) >>> 23], // 23-25 TENSE wordForm[(0xfc000000 & attributes) >>> 26] // 26-31 FORM ); }; /** * Return flatten word object with parsed attribute and morphological values * @static * @param { number } id the id of current word object * @param { Word } lexeme word raw object * @param { Array.<Lexeme> } lexemes lexeme list * @returns { FlatWord } the flatten word model */ var getWord = function (id, word, lexemes) { if (word) { var attributes = getWordAttribute(word.attributes); var morphologicalType = getWordMorphologicalType(word.morphologicalType); return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, lexemeId: { value: word.lexemeId, enumerable: true }, lexeme: { value: lexemes && lexemes[word.lexemeId] ? lexemes[word.lexemeId].lexeme : null, enumerable: true }, word: { value: word.word, enumerable: true }, vocalised: { value: word.vocalised, enumerable: true }, suffixGender: { value: morphologicalType.suffixGender, enumerable: true }, suffixPerson: { value: morphologicalType.suffixPerson, enumerable: true }, suffixNumber: { value: morphologicalType.suffixNumber, enumerable: true }, suffixType: { value: morphologicalType.suffixType, enumerable: true }, prefixCode: { value: morphologicalType.prefixCode, enumerable: true }, gender: { value: morphologicalType.gender, enumerable: true }, person: { value: morphologicalType.person, enumerable: true }, number: { value: morphologicalType.number, enumerable: true }, state: { value: morphologicalType.state, enumerable: true }, tense: { value: morphologicalType.tense, enumerable: true }, form: { value: morphologicalType.form, enumerable: true }, seyame: { value: attributes.seyame, enumerable: true }, listing: { value: attributes.listing, enumerable: true }, enclitic: { value: attributes.enclitic, enumerable: true }, isLexeme: { value: attributes.lexeme, enumerable: true } }) ); } return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, lexemeId: { value: null, enumerable: true }, lexeme: { value: null, enumerable: true }, word: { value: null, enumerable: true }, vocalised: { value: null, enumerable: true }, suffixGender: { value: null, enumerable: true }, suffixPerson: { value: null, enumerable: true }, suffixNumber: { value: null, enumerable: true }, suffixType: { value: null, enumerable: true }, prefixCode: { value: null, enumerable: true }, gender: { value: null, enumerable: true }, person: { value: null, enumerable: true }, number: { value: null, enumerable: true }, state: { value: null, enumerable: true }, tense: { value: null, enumerable: true }, form: { value: null, enumerable: true }, seyame: { value: null, enumerable: true }, listing: { value: null, enumerable: true }, enclitic: { value: null, enumerable: true }, isLexeme: { value: null, enumerable: true } }) ); }; /** * Text position enumeration * @static * @const * @type { Array.<string> } */ var textPosition = Object.freeze(['BeforeWord', 'AfterWord']); /** * Font type enumeration * @static * @const * @type { Array.<string> } */ var fontType = Object.freeze(['Normal', 'Italic']); /** * Verb type enumeration * @const * @static * @type { Array.<string> } */ var verbType = Object.freeze(['None', 'Transitive', 'Intransitive']); /** * English meaning, e.g. 3:165,1:97,"cause","without","","",0,0 * Id is the position in the database array so it is not stored * * @static * @param { number } lexemeId Lexeme address, e.g. 97 * @param { string } word Meaning, e.g. "cause" * @param { string } before String before meaning, e.g. "without" (i.e. without cause) * @param { number } after String after meaning, e.g. "" * @param { number } comment Comment, e.g. "" * @param { number } attributes 16-bit map * @param { number } flag 1 bit flag * @returns { English } Sedra English row */ var makeEnglish = function ( lexemeId, word, before, after, comment, attributes, flag ) { return Object.freeze( Object.create(null, { lexemeId: { value: lexemeId, enumerable: true }, word: { value: word, enumerable: true }, before: { value: before, enumerable: true }, after: { value: after, enumerable: true }, comment: { value: comment, enumerable: true }, attributes: { value: attributes, enumerable: true }, flag: { value: flag, enumerable: true } }) ); }; /** * Build English Attribute object * @static * @param { string } commentPosition Comment before or after word meaning * @param { string } commentFont Normal or Italic * @param { string } stringBeforeFont Normal or Italic string before text font * @param { string } stringAfterFont Normal or Italic string after text font * @param { string } verb None, Transitive or Intransitive * @param { string } number Word Number enumeration * @param { string } gender Word Gender enumeration * @param { string } form Word Form enumeration * @returns { EnglishAttribute } English Attribute object */ var makeEnglishAttribute = function ( commentPosition, commentFont, stringBeforeFont, stringAfterFont, verb, number, gender, form ) { return Object.freeze( Object.create(null, { commentPosition: { value: commentPosition, enumerable: true }, commentFont: { value: commentFont, enumerable: true }, stringBeforeFont: { value: stringBeforeFont, enumerable: true }, stringAfterFont: { value: stringAfterFont, enumerable: true }, verbType: { value: verb, enumerable: true }, number: { value: number, enumerable: true }, gender: { value: gender, enumerable: true }, form: { value: form, enumerable: true } }) ); }; /** * Get English Attribute object from english attribute bit map * @static * @param { number } attributes 16-bit map * @returns { EnglishAttribute } English Attribute object */ var getEnglishAttribute = function (attributes) { return makeEnglishAttribute( // 0 <RESERVED> textPosition[(0x2 & attributes) >>> 1], // 1 COMMENT POSITION fontType[(0x4 & attributes) >>> 2], // 2 COMMENT FONT fontType[(0x8 & attributes) >>> 3], // 3 STRING BEFORE FONT fontType[(0x10 & attributes) >>> 4], // 4 STRING AFTER FONT verbType[(0x60 & attributes) >>> 5], // 5-6 VERB TYPE wordNumber[(0x180 & attributes) >>> 7], // 7-8 NUMBER wordGender[(0x600 & attributes) >>> 9], // 9-10 GENDER wordForm[(0xf800 & attributes) >>> 11] // 11-15 FORM ); }; /** * Return flatten english object with parsed attribute values * @static * @param { number } id the id of current english object * @param { English } english english raw object * @param { Array.<Lexeme> } lexemes lexeme list * @returns { FlatEnglish } the flatten english model */ var getEnglish = function (id, english, lexemes) { if (english) { var attributes = getEnglishAttribute(english.attributes); return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, lexemeId: { value: english.lexemeId, enumerable: true }, lexeme: { value: lexemes && lexemes[english.lexemeId] ? lexemes[english.lexemeId].lexeme : null, enumerable: true }, word: { value: english.word, enumerable: true }, before: { value: english.before, enumerable: true }, after: { value: english.after, enumerable: true }, comment: { value: english.comment, enumerable: true }, commentPosition: { value: attributes.commentPosition, enumerable: true }, commentFont: { value: attributes.commentFont, enumerable: true }, stringBeforeFont: { value: attributes.stringBeforeFont, enumerable: true }, stringAfterFont: { value: attributes.stringAfterFont, enumerable: true }, verbType: { value: attributes.verbType, enumerable: true }, number: { value: attributes.number, enumerable: true }, gender: { value: attributes.gender, enumerable: true }, form: { value: attributes.form, enumerable: true }, flag: { value: english.flag, enumerable: true } }) ); } return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, lexemeId: { value: null, enumerable: true }, lexeme: { value: null, enumerable: true }, word: { value: null, enumerable: true }, before: { value: null, enumerable: true }, after: { value: null, enumerable: true }, comment: { value: null, enumerable: true }, commentPosition: { value: null, enumerable: true }, commentFont: { value: null, enumerable: true }, stringBeforeFont: { value: null, enumerable: true }, stringAfterFont: { value: null, enumerable: true }, verbType: { value: null, enumerable: true }, number: { value: null, enumerable: true }, gender: { value: null, enumerable: true }, form: { value: null, enumerable: true }, flag: { value: null, enumerable: true } }) ); }; /** * Etymology Language enumeration * @static * @const * @type { Array.<string> } */ var etymologyLanguage = Object.freeze([ 'Syriac', 'Akkadian', 'Aramaic', 'Arabic', 'Armenian', 'Greek', 'Hebrew', 'Latin', 'Persian', 'Sanskrit' ]); /** * Etymology records, e.g. 4:1,1:1,"a\255h\256r",5 * Id is the position in the array so it is not stored * * @static * @param { number } lexemeId Lexeme address, e.g. 1 * @param { string } word Word Origin, e.g. "a\255h\256r" * @param { number } attributes 16-bit map * @returns { Etymology } Sedra Etymology row */ var makeEtymology = function (lexemeId, word, attributes) { return Object.freeze( Object.create(null, { lexemeId: { value: lexemeId, enumerable: true }, word: { value: word, enumerable: true }, attributes: { value: attributes, enumerable: true } }) ); }; /** * Build Etymology Attribute object * @static * @param { string } language the source language * @param { string } type word type enumeration * @returns { EtymologyAttribute } Etymology Attribute object */ var makeEtymologyAttribute = function (language, type) { return Object.freeze( Object.create(null, { language: { value: language, enumerable: true }, wordType: { value: type, enumerable: true } }) ); }; /** * Get Etymology Attribute object from etymology attribute bit map * @static * @param { number } attributes 16-bit map * @returns { EtymologyAttribute } Etymology Attribute object */ var getEtymologyAttribute = function (attributes) { return makeEtymologyAttribute( etymologyLanguage[0xf & attributes], // 0-3 LANGUAGE wordType[(0x10 & attributes) >>> 4] // 4 TYPE ); }; /** * Return flatten etymology object with parsed attribute values * @static * @param { number } id the id of current etymology object * @param { Etymology } etymology etymology raw object * @param { Array.<Lexeme> } lexemes lexeme list * @returns { FlatEtymology } the flatten etymology model */ var getEtymology = function (id, etymology, lexemes) { if (etymology) { var attributes = getEtymologyAttribute(etymology.attributes); return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, lexemeId: { value: etymology.lexemeId, enumerable: true }, lexeme: { value: lexemes && lexemes[etymology.lexemeId] ? lexemes[etymology.lexemeId].lexeme : null, enumerable: true }, word: { value: etymology.word, enumerable: true }, language: { value: attributes.language, enumerable: true }, wordType: { value: attributes.wordType, enumerable: true } }) ); } return Object.freeze( Object.create(null, { id: { value: id, enumerable: true }, lexemeId: { value: null, enumerable: true }, lexeme: { value: null, enumerable: true }, word: { value: null, enumerable: true }, language: { value: null, enumerable: true }, wordType: { value: null, enumerable: true } }) ); }; var bookPrototype = Object.freeze( Object.create(null, { /** * Get book full English name * @alias module:sedraModel.Book#englishName * @returns { string } English full name */ englishName: { enumerable: true, get: function get() { return this.english[0]; } }, /** * Get book first abbreviated English name * @alias module:sedraModel.Book#englishShortName * @returns { string } English abbreviated name */ englishShortName: { enumerable: true, get: function get() { return this.english[1]; } } }) ); /** * Build a Book object * @static * @param { number } id Book Id * @param { number } peshittaId Book Eastern Peshitta Id * @param { string } name Book Aramaic name * @param { string } vocalised Book vocalised Aramaic name * @param { Array.<string> } english Book English names: full name followed by abbreviations * @param { object } stats Book statistics { chapters, verses, words } * @return { Book } Book object */ var makeBook = function (id, peshittaId, name, vocalised, english, stats) { return Object.freeze( Object.create(bookPrototype, { id: { value: id, enumerable: true }, peshittaId: { value: peshittaId, enumerable: true }, name: { value: name, enumerable: true }, vocalised: { value: vocalised, enumerable: true }, english: { value: english, enumerable: true }, stats: { value: stats, enumerable: true } }) ); }; var m = makeBook; /** * Peshitta books * @static * @const * @type { Array.<string> } */ var books = [ m(0, 0, '', '', ['Old Testament', 'OT']), m(1, 0, '', '', []), m(2, 0, '', '', []), m(3, 0, '', '', []), m(4, 0, '', '', []), m(5, 0, '', '', []), m(6, 0, '', '', []), m(7, 0, '', '', []), m(8, 0, '', '', []), m(9, 0, '', '', []), m(10, 0, '', '', []), m(11, 0, '', '', []), m(12, 0, '', '', []), m(13, 0, '', '', []), m(14, 0, '', '', []), m(15, 0, '', '', []), m(16, 0, '', '', []), m(17, 0, '', '', []), m(18, 0, '', '', []), m(19, 0, '', '', []), m(20, 0, '', '', []), m(21, 0, '', '', []), m(22, 0, '', '', []), m(23, 0, '', '', []), m(24, 0, '', '', []), m(25, 0, '', '', []), m(26, 0, '', '', []), m(27, 0, '', '', []), m(28, 0, '', '', []), m(29, 0, '', '', []), m(30, 0, '', '', []), m(31, 0, '', '', []), m(32, 0, '', '', []), m(33, 0, '', '', []), m(34, 0, '', '', []), m(35, 0, '', '', []), m(36, 0, '', '', []), m(37, 0, '', '', []), m(38, 0, '', '', []), m(39, 0, '', '', []), m(40, 0, '', '', []), m(41, 0, '', '', []), m(42, 0, '', '', []), m(43, 0, '', '', []), m(44, 0, '', '', []), m(45, 0, '', '', []), m(46, 0, '', '', []), m(47, 0, '', '', []), m(48, 0, '', '', []), m(49, 0, '', '', []), m(50, 50, '', '', []), m(51, 51, '', '', ['New Testament', 'NT'], { books: 27, chapters: 260, verses: 7958, words: 109654 }), m(52, 52, 'mty', "mat'ay", ['Matthew', 'Mt', 'Matt', 'Mat'], { chapters: 28, verses: 1071, words: 13980, chapter: { 1: { verses: 25, words: 290 }, 2: { verses: 23, words: 335 }, 3: { verses: 17, words: 239 }, 4: { verses: 25, words: 317 }, 5: { verses: 48, words: 621 }, 6: { verses: 34, words: 486 }, 7: { verses: 29, words: 365 }, 8: { verses: 34, words: 451 }, 9: { verses: 38, words: 470 }, 10: { verses: 42, words: 547 }, 11: { verses: 30, words: 379 }, 12: { verses: 50, words: 675 }, 13: { verses: 58, words: 788 }, 14: { verses: 36, words: 428 }, 15: { verses: 39, words: 490 }, 16: { verses: 28, words: 397 }, 17: { verses: 27, words: 389 }, 18: { verses: 35, words: 513 }, 19: { verses: 30, words: 453 }, 20: { verses: 34, words: 440 }, 21: { verses: 46, words: 672 }, 22: { verses: 46, words: 490 }, 23: { verses: 39, words: 513 }, 24: { verses: 51, words: 595 }, 25: { verses: 46, words: 589 }, 26: { verses: 75, words: 983 }, 27: { verses: 66, words: 799 }, 28: { verses: 20, words: 266 } } }), m(53, 53, 'mrqws', 'marqwOs', ['Mark', 'Mk', 'Mrk', 'Mar', 'Mr'], { chapters: 16, verses: 678, words: 8793, chapter: { 1: { verses: 45, words: 511 }, 2: { verses: 28, words: 400 }, 3: { verses: 35, words: 380 }, 4: { verses: 41, words: 517 }, 5: { verses: 43, words: 531 }, 6: { verses: 56, words: 766 }, 7: { verses: 37, words: 476 }, 8: { verses: 38, words: 494 }, 9: { verses: 50, words: 695 }, 10: { verses: 52, words: 702 }, 11: { verses: 33, words: 467 }, 12: { verses: 44, words: 628 }, 13: { verses: 37, words: 485 }, 14: { verses: 72, words: 945 }, 15: { verses: 47, words: 546 }, 16: { verses: 20, words: 250 } } }), m(54, 54, 'lwq)', 'lwuqo)', ['Luke', 'Lk', 'Luk'], { chapters: 24, verses: 1151, words: 15234, chapter: { 1: { verses: 80, words: 831 }, 2: { verses: 52, words: 625 }, 3: { verses: 38, words: 494 }, 4: { verses: 44, words: 582 }, 5: { verses: 39, words: 567 }, 6: { verses: 49, words: 703 }, 7: { verses: 50, words: 716 }, 8: { verses: 56, words: 866 }, 9: { verses: 62, words: 877 }, 10: { verses: 42, words: 606 }, 11: { verses: 54, words: 797 }, 12: { verses: 59, words: 825 }, 13: { verses: 35, words: 510 }, 14: { verses: 35, words: 484 }, 15: { verses: 32, words: 424 }, 16: { verses: 31, words: 477 }, 17: { verses: 37, words: 460 }, 18: { verses: 43, words: 579 }, 19: { verses: 48, words: 600 }, 20: { verses: 47, words: 563 }, 21: { verses: 38, words: 452 }, 22: { verses: 71, words: 853 }, 23: { verses: 56, words: 714 }, 24: { verses: 53, words: 629 } } }), m(55, 55, 'ywxnn', 'ywuxanon', ['John', 'Jn', 'Joh', 'Jhn'], { chapters: 21, verses: 879, words: 12409, chapter: { 1: { verses: 51, words: 629 }, 2: { verses: 25, words: 311 }, 3: { verses: 36, words: 533 }, 4: { verses: 54, words: 734 }, 5: { verses: 47, words: 675 }, 6: { verses: 71, words: 947 }, 7: { verses: 53, words: 700 }, 8: { verses: 59, words: 887 }, 9: { verses: 41, words: 575 }, 10: { verses: 42, words: 564 }, 11: { verses: 57, words: 734 }, 12: { verses: 50, words: 680 }, 13: { verses: 38, words: 583 }, 14: { verses: 31, words: 444 }, 15: { verses: 27, words: 368 }, 16: { verses: 33, words: 455 }, 17: { verses: 26, words: 376 }, 18: { verses: 40, words: 633 }, 19: { verses: 42, words: 640 }, 20: { verses: 31, words: 452 }, 21: { verses: 25, words: 489 } } }), m(56, 56, 'prksys', 'praksyis', ['Acts', 'Ac', 'Act'], { chapters: 28, verses: 1007, words: 15385, chapter: { 1: { verses: 26, words: 414 }, 2: { verses: 47, words: 633 }, 3: { verses: 26, words: 378 }, 4: { verses: 37, words: 544 }, 5: { verses: 42, words: 646 }, 6: { verses: 15, words: 213 }, 7: { verses: 60, words: 862 }, 8: { verses: 40, words: 590 }, 9: { verses: 43, words: 670 }, 10: { verses: 48, words: 712 }, 11: { verses: 30, words: 416 }, 12: { verses: 25, words: 412 }, 13: { verses: 52, words: 744 }, 14: { verses: 28, words: 420 }, 15: { verses: 41, words: 565 }, 16: { verses: 40, words: 620 }, 17: { verses: 34, words: 609 }, 18: { verses: 28, words: 457 }, 19: { verses: 41, words: 672 }, 20: { verses: 38, words: 558 }, 21: { verses: 40, words: 651 }, 22: { verses: 30, words: 471 }, 23: { verses: 35, words: 541 }, 24: { verses: 27, words: 421 }, 25: { verses: 27, words: 450 }, 26: { verses: 32, words: 522 }, 27: { verses: 44, words: 676 }, 28: { verses: 31, words: 518 } } }), m(57, 60, 'r*hwmy)', 'r*h_wumoye)', ['Romans', 'Ro', 'Rom', 'Rm'], { chapters: 16, verses: 433, words: 5768, chapter: { 1: { verses: 32, words: 424 }, 2: { verses: 29, words: 407 }, 3: { verses: 31, words: 324 }, 4: { verses: 25, words: 326 }, 5: { verses: 21, words: 317 }, 6: { verses: 23, words: 293 }, 7: { verses: 25, words: 390 }, 8: { verses: 39, words: 518 }, 9: { verses: 33, words: 432 }, 10: { verses: 21, words: 260 }, 11: { verses: 36, words: 501 }, 12: { verses: 21, words: 271 }, 13: { verses: 14, words: 234 }, 14: { verses: 23, words: 336 }, 15: { verses: 33, words: 412 }, 16: { verses: 27, words: 323 } } }), m( 58, 61, '). qwr*ynty)', '). qwOr*yint,oye)', [ '1 Corinthians', '1Co', '1 Cor', '1 Co', 'I Co', 'I Cor', 'I Corinthians', '1Cor', '1Corinthians', '1st Corinthians', 'First Corinthians' ], { chapters: 16, verses: 437, words: 5987, chapter: { 1: { verses: 31, words: 382 }, 2: { verses: 16, words: 224 }, 3: { verses: 23, words: 309 }, 4: { verses: 21, words: 301 }, 5: { verses: 13, words: 200 }, 6: { verses: 20, words: 293 }, 7: { verses: 40, words: 619 }, 8: { verses: 13, words: 190 }, 9: { verses: 27, words: 422 }, 10: { verses: 33, words: 420 }, 11: { verses: 34, words: 471 }, 12: { verses: 31, words: 425 }, 13: { verses: 13, words: 185 }, 14: { verses: 40, words: 565 }, 15: { verses: 58, words: 703 }, 16: { verses: 24, words: 278 } } } ), m( 59, 62, 'b. qwr*ynty)', 'b. qwOr*yint,oye)', [ '2 Corinthians', '2Co', '2 Cor', '2 Co', 'II Co', 'II Cor', 'II Corinthians', '2Cor', '2Corinthians', '2nd Corinthians', 'Second Corinthians' ], { chapters: 13, verses: 257, words: 3737, chapter: { 1: { verses: 24, words: 356 }, 2: { verses: 17, words: 230 }, 3: { verses: 18, words: 248 }, 4: { verses: 18, words: 259 }, 5: { verses: 21, words: 286 }, 6: { verses: 18, words: 221 }, 7: { verses: 16, words: 275 }, 8: { verses: 24, words: 316 }, 9: { verses: 15, words: 223 }, 10: { verses: 18, words: 273 }, 11: { verses: 33, words: 466 }, 12: { verses: 21, words: 369 }, 13: { verses: 14, words: 215 } } } ), m(60, 63, 'glTy*)', 'goloToy*e)', ['Galatians', 'Ga', 'Gal'], { chapters: 6, verses: 149, words: 1940, chapter: { 1: { verses: 24, words: 301 }, 2: { verses: 21, words: 348 }, 3: { verses: 29, words: 401 }, 4: { verses: 31, words: 376 }, 5: { verses: 26, words: 297 }, 6: { verses: 18, words: 217 } } }), m(61, 64, ')psy*)', ')epEsy*e)', ['Ephesians', 'Ep', 'Eph', 'Ephes'], { chapters: 6, verses: 155, words: 1774, chapter: { 1: { verses: 23, words: 257 }, 2: { verses: 22, words: 267 }, 3: { verses: 21, words: 223 }, 4: { verses: 32, words: 357 }, 5: { verses: 33, words: 379 }, 6: { verses: 24, words: 291 } } }), m( 62, 65, 'pylypsy*)', 'pyilyipEsoy*e)', ['Philippians', 'Pp', 'Phil', 'Php'], { chapters: 4, verses: 104, words: 1326, chapter: { 1: { verses: 30, words: 371 }, 2: { verses: 30, words: 377 }, 3: { verses: 21, words: 295 }, 4: { verses: 23, words: 283 } } } ), m(63, 66, 'qwl*sy)', 'qwl*sy)', ['Colossians', 'Co', 'Col'], { chapters: 4, verses: 95, words: 1133, chapter: { 1: { verses: 29, words: 356 }, 2: { verses: 23, words: 283 }, 3: { verses: 25, words: 284 }, 4: { verses: 18, words: 210 } } }), m( 64, 67, '). tsl*wnyqy)', "). t'esol*wOnyiqoye)", [ '1 Thessalonians', '1Th', '1 Thess', '1 Thes', '1 Th', 'I Thess', 'I Thes', 'I Th', 'I Thessalonians', '1Thess', '1Thes', '1Thessalonians', '1st Thessalonians', '1st Thess', 'First Thessalonians', 'First Thess' ], { chapters: 5, verses: 89, words: 1117, chapter: { 1: { verses: 10, words: 139 }, 2: { verses: 20, words: 299 }, 3: { verses: 13, words: 171