diff --git a/__mocks__/fs-extra.js b/__mocks__/fs-extra.js new file mode 100644 index 00000000..50ff1d5f --- /dev/null +++ b/__mocks__/fs-extra.js @@ -0,0 +1,379 @@ +/* eslint-disable no-throw-literal */ +/* eslint-disable no-unused-expressions */ + +import path from 'path-extra'; +import _ from 'lodash'; +const fsActual = require.requireActual('fs-extra'); // for copying test files into mock +const fs = jest.genMockFromModule('fs-extra'); +let mockFS = Object.create(null); + +/** @deprecated */ +function __setMockFS(newMockFS) { + mockFS = newMockFS; +} + +function __resetMockFS() { + mockFS = Object.create(null); +} + +/** + * This is a custom function that our tests can use during setup to specify + * what the files on the "mock" filesystem should look like when any of the + * `fs` APIs are used. + * @param {Array} newMockFiles + */ +function __setMockDirectories(newMockFiles) { + mockFS = Object.create(null); + + for (const file in newMockFiles) { + const dir = path.dirname(file); + + if (!mockFS[dir]) { + mockFS[dir] = []; + } + mockFS[dir].push(path.basename(file)); + } +} + +/** + * A custom version of `readdirSync` that reads from the special mocked out + * file list set via __setMockDirectories + * @param {String} directoryPath + */ +function readdirSync(directoryPath) { + if (statSync(directoryPath).isDirectory()) { + return mockFS[directoryPath]; + } + return []; +} + +function readdir(directoryPath) { + return Promise.resolve(readdirSync(directoryPath)); +} + +function writeFileSync(filePath, data) { + addFileToParentDirectory(filePath); + mockFS[filePath] = data; +} + +function readFileSync(filePath) { + if (!existsSync(filePath)) { + throw 'File could not be read: ' + filePath; + } + + if (typeof filePath !== 'string') { + throw 'fail'; + } + + const data = mockFS[filePath]; + + // TRICKY: readFileSync should always return a string + if (typeof data === 'object' && data !== null) { + return JSON.stringify(data); + } else { + return data; + } +} + +function readFile(filePath) { + return new Promise(function (resolve, reject) { + try { + resolve(readFileSync(filePath)); + } catch (e) { + reject(e); + } + }); +} + +function outputFileSync(filePath, data) { + addFileToParentDirectory(filePath); + mockFS[filePath] = data; +} + +function outputFile(filePath, data) { + return new Promise(function (resolve) { + outputFileSync(filePath, data); + resolve(); + }); +} + +function __dumpMockFS() { + const fsList = JSON.stringify(mockFS, null, 2); + console.log('mock FS:\n' + fsList); +} + +/** + * create subdirs and add file name to them + * @param filePath + */ +function addFileToParentDirectory(filePath) { + const dir = path.dirname(filePath); + const filename = path.basename(filePath); + + if (filename) { + if (!mockFS[dir]) { + mockFS[dir] = []; + addFileToParentDirectory(dir); + } + + if (mockFS[dir].indexOf(filename) < 0) { + mockFS[dir].push(filename); + } + } +} + +function outputJsonSync(filePath, data) { + addFileToParentDirectory(filePath); + mockFS[filePath] = _.cloneDeep(data); +} + +function outputJson(filePath, data) { + return new Promise(function (resolve) { + outputJsonSync(filePath, data); + resolve(); + }); +} + +function readJsonSync(filePath) { + if (!existsSync(filePath)) { + throw 'File could not be read: ' + filePath; + } + + const data = mockFS[filePath]; + // clone data so changes to object do not affect object in file system + const clonedData = JSON.parse(typeof data === 'string' ? data : JSON.stringify(data)); + return clonedData; +} + +function readJson(filePath) { + return new Promise(function (resolve, reject) { + try { + resolve(readJsonSync(filePath)); + } catch (e) { + reject(e); + } + }); +} + +function existsSync(path) { + const exists = mockFS[path] !== '' ? !!mockFS[path] : true; + return exists; +} + +function exists(path) { + return Promise.resolve(existsSync(path)); +} + +function removeSync(path) { + Object.keys(mockFS).forEach((element) => { + element.includes(path) ? delete mockFS[element] : null; + }); +} + +function remove(path) { + return new Promise(function (resolve) { + removeSync(path); + resolve(); + }); +} + +function renameSync(oldPath, newPath) { + writeFileSync(newPath, readFileSync(oldPath)); + removeSync(oldPath); +} + +function rename(oldPath, newPath) { + return new Promise(function (resolve) { + renameSync(oldPath, newPath); + resolve(); + }); +} + +function copySync(srcPath, destinationPath) { + const isDir = statSync(srcPath).isDirectory(); + + if (isDir) { + ensureDirSync(destinationPath); + const files = readdirSync(srcPath); + + for (let f of files) { + copySync(path.join(srcPath,f), path.join(destinationPath,f)); + } + } else { // not directory + addFileToParentDirectory(destinationPath); + mockFS[destinationPath] = _.cloneDeep(mockFS[srcPath]); + } +} + +function ensureDirSync(path) { + if (!mockFS[path]) { + mockFS[path] = []; + } + addFileToParentDirectory(path); +} + +function Stats(path, exists, isDir) { + this.path = path; + this.exists = exists; + this.isDir = isDir; + this.atime = 'Not-a-real-date'; + this.isDirectory = () => { + const isDir = this.exists && this.isDir; + return isDir; + }; + this.isFile = () => { + const isFile = this.exists && !this.isDir; + return isFile; + }; +} + +/** + * ensure this actually contains an array of file names (strings) + * @param path + * @return {arg is Array} + */ +function isValidDirectory(path) { + const dir = mockFS[path]; + let isDir = Array.isArray(dir); + + if (isDir) { // make sure it's an array of paths (strings) and not objects (such as json object stored) + const failedItem = dir.findIndex((item) => (typeof item !== 'string')); + isDir = (failedItem < 0); // valid if failed item not found + } + return isDir; +} + +/** + * only minimal implementation of fs.Stats: isDirectory() and isFile() + * @param path + */ +function statSync(path) { + const exists = existsSync(path); + const isDir = (exists && isValidDirectory(path)); + return new Stats(path, exists, isDir); +} + +/** + * @description convertes linux style separators to OS specific separators + * @param {string} filePath + * @return {string} converted path + */ +function __correctSeparatorsFromLinux(filePath) { + const result = filePath.split('/').join(path.sep); + return result; +} + +/** + * @description - copies list of files from local file system into mock File system + * @param {array} copyFiles - array of paths (in linux format) relative to source path + * @param {string} sourceFolder - source folder of files to copy (in linux format) + * @param {string} mockDestinationFolder - destination folder for copied files {string} in mock File system + */ +function __loadFilesIntoMockFs(copyFiles, sourceFolder, mockDestinationFolder) { + const mockDestinationFolder_ = __correctSeparatorsFromLinux(mockDestinationFolder); + const sourceFolder_ = __correctSeparatorsFromLinux(sourceFolder ); + + for (let copyFile of copyFiles) { + const filePath2 = path.join(sourceFolder_, __correctSeparatorsFromLinux(copyFile)); + let fileData = null; + const isDir = fsActual.statSync(filePath2).isDirectory(); + + if (!isDir) { + fileData = fsActual.readFileSync(filePath2).toString(); + } + + let dirPath = mockDestinationFolder_; + fs.ensureDirSync(dirPath); + const parts = copyFile.split('/'); + const endCount = parts.length - 1; + + for (let i = 0; i < endCount; i++) { + const part = parts[i]; + dirPath = path.join(dirPath, part); + fs.ensureDirSync(dirPath); + } + + if (!isDir) { + const filePath = path.join(mockDestinationFolder_, parts.join(path.sep)); + // console.log("Copying File: " + filePath); + fs.writeFileSync(filePath, fileData); + } else { + __loadDirIntoMockFs(filePath2, path.join(mockDestinationFolder, copyFile)); + } + } +} + +/** + * @description - recursively copies folder from local file system into mock File system + * @param {string} sourceFolder - source folder of files to copy (in linux format) + * @param {string} mockDestinationFolder - destination folder for copied files {string} in mock File system + */ +function __loadDirIntoMockFs(sourceFolder, mockDestinationFolder) { + const mockDestinationFolder_ = __correctSeparatorsFromLinux(mockDestinationFolder); + fs.ensureDirSync(mockDestinationFolder_); + const sourceFolder_ = __correctSeparatorsFromLinux(sourceFolder); + // console.log("Copying Directory: " + sourceFolder_); + const files = fsActual.readdirSync(sourceFolder_); + + for (let file of files) { + const sourceFilePath = path.join(sourceFolder, file); + const mockFilePath = path.join(mockDestinationFolder_, file); + const isDir = fsActual.statSync(sourceFilePath).isDirectory(); + + if (!isDir) { + const fileData = fsActual.readFileSync(sourceFilePath).toString(); + // console.log("Copying Subfile: " + mockFilePath); + fs.writeFileSync(mockFilePath, fileData); + } else { + // console.log("Entering Subdir: " + mockFilePath); + __loadDirIntoMockFs( sourceFilePath, mockFilePath); + } + } +} + +function moveSync(source, destination) { + copySync(source, destination); + removeSync(source); +} + +fs.__files = () => mockFS; +fs.__dumpMockFS = __dumpMockFS; +fs.__setMockDirectories = __setMockDirectories; +fs.__setMockFS = __setMockFS; +fs.__resetMockFS = __resetMockFS; +fs.__actual = fsActual; // to access actual file system +fs.__loadFilesIntoMockFs = __loadFilesIntoMockFs; +fs.__correctSeparatorsFromLinux = __correctSeparatorsFromLinux; +fs.__loadDirIntoMockFs = __loadDirIntoMockFs; +fs.readdirSync = jest.fn(readdirSync); +fs.readdir = readdir; +fs.writeFileSync = writeFileSync; +fs.readFileSync = jest.fn(readFileSync); +fs.readFile = readFile; +fs.writeJSONSync = outputJsonSync; +fs.outputJsonSync = jest.fn(outputJsonSync); +fs.outputJSONSync = jest.fn(outputJsonSync); +fs.outputJson = outputJson; +fs.outputJSON = outputJson; +fs.readJsonSync = jest.fn(readJsonSync); +fs.readJSONSync = readJsonSync; +fs.readJson = readJson; +fs.readJSON = readJson; +fs.existsSync = jest.fn(existsSync); +fs.exists = exists; +fs.pathExists = exists; +fs.pathExistsSync = jest.fn(existsSync); +fs.outputFileSync = outputFileSync; +fs.outputFile = outputFile; +fs.removeSync = removeSync; +fs.remove = remove; +fs.copySync = jest.fn(copySync); +fs.renameSync = renameSync; +fs.rename = rename; +fs.ensureDirSync = ensureDirSync; +fs.statSync = statSync; +fs.fstatSync = statSync; +fs.lstatSync = jest.fn(statSync); +fs.moveSync = moveSync; + +module.exports = fs; diff --git a/__tests__/Container.test.js b/__tests__/Container.test.js index 2234b4e3..655e0512 100644 --- a/__tests__/Container.test.js +++ b/__tests__/Container.test.js @@ -34,6 +34,7 @@ const props = { goToNext: jest.fn(), goToPrevious: jest.fn(), onInvalidCheck: jest.fn(), + readProjectDataSync: jest.fn(), }, }; diff --git a/__tests__/ResourcesHelpers.test.js b/__tests__/ResourcesHelpers.test.js new file mode 100644 index 00000000..6cf0edaf --- /dev/null +++ b/__tests__/ResourcesHelpers.test.js @@ -0,0 +1,116 @@ +/* eslint-env jest */ +import path from 'path'; +import fs from 'fs-extra'; +// helpers +import { getThelpsManifestRelation } from '../src/helpers/resourcesHelpers'; +// constants +import { + TRANSLATION_WORDS, + TRANSLATION_NOTES, + USER_RESOURCES_PATH, +} from '../src/common/constants'; +jest.mock('fs-extra'); + + + +describe('getThelpsManifest()', () => { + beforeEach(() => { + // reset mock filesystem data + fs.__resetMockFS(); + }); + + it('getThelpsManifest should return null if manifest not found', () => { + // given + const glID = 'en'; + const toolName = TRANSLATION_WORDS; + const expectedRelation = null; + + // when + const tsvRelation = getThelpsManifestRelation(glID, toolName); + + // then + expect(tsvRelation).toEqual(expectedRelation); + }); + + it('getThelpsManifest should return null if glID is empty', () => { + // given + const sourceResourcesPath = path.join( '__tests__/__fixtures__' ); + const copyResourceFiles = [TRANSLATION_WORDS]; + const destFolder = path.join(USER_RESOURCES_PATH, 'en', 'translationHelps'); + fs.__loadFilesIntoMockFs(copyResourceFiles, sourceResourcesPath, destFolder); + const glID = ''; + const toolName = TRANSLATION_WORDS; + const expectedRelation = null; + + // when + const tsvRelation = getThelpsManifestRelation(glID, toolName); + + // then + expect(tsvRelation).toEqual(expectedRelation); + }); + + it('getThelpsManifest should return null if tooName is empty', () => { + // given + const sourceResourcesPath = path.join( '__tests__/__fixtures__' ); + const copyResourceFiles = [TRANSLATION_WORDS]; + const destFolder = path.join(USER_RESOURCES_PATH, 'en', 'translationHelps'); + fs.__loadFilesIntoMockFs(copyResourceFiles, sourceResourcesPath, destFolder); + const glID = 'en'; + const toolName = ''; + const expectedRelation = null; + + // when + const tsvRelation = getThelpsManifestRelation(glID, toolName); + + // then + expect(tsvRelation).toEqual(expectedRelation); + }); + + it('getThelpsManifest should work for TW', () => { + // given + const sourceResourcesPath = path.join( '__tests__/__fixtures__' ); + const copyResourceFiles = [TRANSLATION_WORDS]; + const destFolder = path.join(USER_RESOURCES_PATH, 'en', 'translationHelps'); + fs.__loadFilesIntoMockFs(copyResourceFiles, sourceResourcesPath, destFolder); + const glID = 'en'; + const toolName = TRANSLATION_WORDS; + const expectedRelation = [ + 'en/ult', + 'en/ust', + 'en/obs', + 'en/tn', + 'en/tq', + ]; + + // when + const tsvRelation = getThelpsManifestRelation(glID, toolName); + + // then + expect(tsvRelation).toEqual(expectedRelation); + }); + + it('getThelpsManifest should work for TN', () => { + // given + const sourceResourcesPath = path.join( '__tests__/__fixtures__' ); + const copyResourceFiles = [TRANSLATION_NOTES]; + const destFolder = path.join(USER_RESOURCES_PATH, 'en', 'translationHelps'); + fs.__loadFilesIntoMockFs(copyResourceFiles, sourceResourcesPath, destFolder); + const glID = 'en'; + const toolName = TRANSLATION_NOTES; + const expectedRelation = [ + 'en/ult', + 'en/ust', + ]; + + // when + const tsvRelation = getThelpsManifestRelation(glID, toolName); + + // then + expect(tsvRelation).toEqual(expectedRelation); + }); +}); + +// +// helpers +// + diff --git a/__tests__/__fixtures__/translationNotes/v15/manifest.json b/__tests__/__fixtures__/translationNotes/v15/manifest.json new file mode 100644 index 00000000..e8257679 --- /dev/null +++ b/__tests__/__fixtures__/translationNotes/v15/manifest.json @@ -0,0 +1,1067 @@ +{ + "dublin_core": { + "conformsto": "rc0.2", + "contributor": [ + "Door43 World Missions Community", + "Aaron Fenlason", + "Abner Bauman", + "Adam Van Goor", + "Alan Bird", + "Alan Borkenhagen", + "Alfred Van Dellen", + "Alice Wright", + "Allen Bair", + "Allyson Presswood Nance", + "Amanda Adams", + "Andrew Belcher", + "Andrew Johnson", + "Andrew Rice", + "Angelo Palo", + "Anita Moreau", + "April Linton", + "Aurora Lee", + "Barbara Summers", + "Barbara White", + "Becky Hancock", + "Beryl Carpenter", + "Bethany Fenlason", + "Betty Forbes", + "Bianca Elliott", + "Bill Cleveland", + "Bill Pruett", + "Bob Britting", + "Bram van den Heuvel", + "Brian Metzger", + "Bruce Bridges", + "Bruce Collier", + "Bruce Smith", + "Caleb Worgess", + "Carlyle Kilmore", + "Carol Pace", + "Carol Heim", + "Caroline Crawford", + "Caroline Fleming", + "Caroline S Wong", + "Carol Lee", + "Carol Moyer", + "Carolyn Lafferty", + "Catherine C Newton", + "Charese Jackson", + "Charlotte Gibson", + "Charlotte Hobbs", + "Cheryl A Chojnacki", + "Cheryl Stieben", + "Cheryl Warren", + "Christian Berry", + "Christine Harrison", + "Clairmene Pascal", + "Connie Bryan", + "Connie Goss", + "Craig Balden", + "Craig Lins", + "Craig Scott", + "Cynthia J Puckett", + "Dale Hahs", + "Dale Masser", + "Daniel Lauk", + "Daniel Summers", + "Darlene M Hopkins", + "Darlene Silas", + "David Boerschlein", + "David F Withee", + "David Glover", + "David J Forbes", + "David Mullen", + "David N Hanley", + "David Sandlin", + "David Shortess", + "David Smith", + "David Whisler", + "Debbie Nispel", + "Debbie Piper", + "Deborah Bartow", + "Deborah Bush", + "Deborah Miniard", + "Dennis Jackson", + "Dianne Forrest", + "Donna Borkenhagen", + "Donna Mullis", + "Douglas Hayes", + "Drew Curley", + "Ed Davis", + "Edgar Navera", + "Edward Kosky", + "Edward Quigley", + "Elaine VanRegenmorter", + "Elizabeth Nataly Silvestre Herbas", + "Ellen Lee", + "Emeline Thermidor", + "Emily Lee", + "Esther Roman", + "Esther Trew", + "Esther Zirk", + "Ethel Lynn Baker", + "Evangeline Puen", + "Evelyn Wildgust", + "Fletcher Coleman", + "Freda Dibble", + "Gail Spell", + "Gary Greer", + "Gary Shogren", + "Gay Ellen Stulp", + "Gene Gossman", + "George Arlyn Briggs", + "Gerald L. Naughton", + "Glen Tallent", + "Grace Balwit", + "Grace Bird", + "Greg Stoffregen", + "Gretchen Stencil", + "Hallie Miller", + "Harry Harriss", + "Heather Hicks", + "Helen Morse", + "Hendrik deVries", + "Henry Bult", + "Henry Whitney", + "Hilary O'Sullivan", + "Ibrahim Audu", + "Ines Gipson", + "Irene J Dodson", + "Jackie Jones", + "Jacqueline Bartley", + "James Giddens", + "James Pedersen", + "James Pohlig", + "James Roe", + "Janet O'Herron", + "Janice Connor", + "Jaqueline Rotruck", + "Jeanette Friesen", + "Jeff Graf", + "Jeff Kennedy", + "Jeff Martin", + "Jennifer Cunneen", + "Jenny Thomas", + "Jerry Lund", + "Jessica Lauk", + "Jim Frederick", + "Jim Lee", + "Jimmy Warren", + "Jim Rotruck", + "Jim Swartzentruber", + "Jody Garcia", + "Joe Chater", + "Joel Bryan", + "Joey Howell", + "John Anderson", + "John Geddis", + "John D Rogers", + "John Hutchins", + "John Luton", + "John Pace", + "John P Tornifolio", + "Jolene Valeu", + "Jon Haahr", + "Joseph Fithian", + "Joseph Greene", + "Joseph Wharton", + "Joshua Berkowitz", + "Joshua Calhoun", + "Joshua Rister", + "Josh Wondra", + "Joy Anderson", + "Joyce Jacobs", + "Joyce Pedersen", + "JT Crowder", + "Judi Brodeen", + "Judith Cline", + "Judith C Yon", + "Julia N Bult", + "Patty Li", + "Julie Susanto", + "Kahar Barat", + "Kannahi Sellers", + "Kara Anderson", + "Karen Davie", + "Karen Dreesen", + "Karen Fabean", + "Karen Riecks", + "Karen Smith", + "Karen Turner", + "Kathleen Glover", + "Kathryn Hendrix", + "Kathy Mentink", + "Katrina Geurink", + "Kay Myers", + "Kelly Strong", + "Ken Haugh", + "Kim Puterbaugh", + "Kristin Butts Page", + "Kristin Rinne", + "Kwesi Opoku-debrah", + "Langston Spell", + "Larry Sallee", + "Lawrence Lipe", + "Lee Sipe", + "Leonard Smith", + "Lester Harper", + "Lia Hadley", + "Linda Buckman", + "Linda Dale Barton", + "Linda Havemeier", + "Linda Homer", + "Linda Lee Sebastien", + "Linn Peterson", + "Liz Dakota", + "Lloyd Box", + "Luis Keelin", + "Madeline Kilmore", + "Maggie D Paul", + "Marc Nelson", + "Mardi Welo", + "Margo Hoffman", + "Marilyn Cook", + "Marjean Swann", + "Marjorie Francis", + "Mark Albertini", + "Mark Chapman", + "Mark Thomas", + "Marselene Norton", + "Mary Jane Davis", + "Mary Jean Stout", + "Mary Landon", + "Mary Scarborough", + "Megan Kidwell", + "Melissa Roe", + "Merton Dibble", + "Meseret Abraham-Zemede", + "Michael Bush", + "Michael Connor", + "Michael Francis", + "Michael Geurink", + "Mike Tisdell", + "Mickey White", + "Miel Horrilleno", + "Monique Greer", + "Morgan Mellette", + "Morris Anderson", + "Nancy C. Naughton", + "Nancy Neu", + "Nancy VanCott", + "Neal Snook", + "Nicholas Scovil", + "Nick Dettman", + "Nils Friberg", + "Noah Crabtree", + "Pamela B Johnston", + "Pamela Nungesser", + "Pamela Roberts", + "Pam Gullifer", + "Pat Ankney", + "Pat Giddens", + "Patricia Brougher", + "Patricia Carson", + "Patricia Cleveland", + "Patricia Foster", + "Patricia Middlebrooks", + "Paul Mellema", + "Paula Carlson", + "Paula Oestreich", + "Paul Holloway", + "Paul Nungesser", + "Peggy Anderson", + "Peggyrose Swartzentruber", + "Peter Polloni", + "Phillip Harms", + "Phyllis Mortensen", + "Priscilla Enggren", + "Rachel Agheyisi", + "Rachel Ropp", + "Raif Turner", + "Ray Puen", + "Reina Y Mora", + "Rene Bahrenfuss", + "Renee Triplett", + "Rhonda Bartels", + "Richard Beatty", + "Richard Moreau", + "Richard Rutter", + "Richard Stevens", + "Rick Keaton", + "Robby Little", + "Robert W Johnson", + "Rochelle Hook", + "Rodney White", + "Rolaine Franz", + "Ronald D Hook", + "Rosario Baria", + "Roxann Carey", + "Roxanne Pittard", + "Ruben Michael Garay", + "Russell Isham", + "Russ Perry", + "Ruth Calo", + "Ruth E Withee", + "Ruth Montgomery", + "Ryan Blizek", + "Sam Todd", + "Samuel Njuguna", + "Sandy Anderson", + "Sandy Blanes", + "Sara Giesmann", + "Sara Van Cott (Barnes)", + "Sharon Johnson", + "Sharon Peterson", + "Sharon Shortess", + "Shelly Harms", + "Sherie Nelson", + "Sherman Sebastien", + "Sherry Mosher", + "Stacey Swanson", + "Steve Gibbs", + "Steve Mercier", + "Susan Langohr", + "Susan Quigley", + "Susan Snook", + "Suzanne Richards", + "Sylvia Thomas", + "Sze Suze Lau", + "Tabitha Price", + "Tammy L Enns", + "Tammy White", + "Teresa Everett-Leone", + "Teresa Linn", + "Terri Collins", + "Theresa Baker", + "Thomas Jopling", + "Thomas Nickell", + "Thomas Warren", + "Tim Coleman", + "Tim Ingram", + "Tim Linn", + "Tim Lovestrand", + "Tim Mentink", + "Tom Penry", + "Tom William Warren", + "Toni Shuma", + "Tracie Pogue", + "Tricia Coffman", + "Vicki Ivester", + "Victoria G DeKraker", + "Victor M Prieto", + "Vivian Kamph", + "Vivian Richardson", + "Ward Pyles", + "Warren Blaisdell", + "Wayne Homer", + "Wendy Coleman", + "Wendy Colon", + "Wilbur Zirk", + "Wil Gipson", + "William Carson", + "William Cline", + "William Dickerson", + "William Smitherman", + "William Wilder", + "Yvonne Tallent" + ], + "creator": "Door43 World Missions Community", + "description": "Open-licensed exegetical notes that provide historical, cultural, and linguistic information for translators. It provides translators and checkers with pertinent, just-in-time information to help them make the best possible translation decisions.", + "format": "text/tsv", + "identifier": "tn", + "issued": "2019-05-21", + "language": { + "direction": "ltr", + "identifier": "en", + "title": "English" + }, + "modified": "2019-05-21", + "publisher": "unfoldingWord", + "relation": [ + "en/ult", + "en/ust" + ], + "rights": "CC BY-SA 4.0", + "source": [ + { + "identifier": "tn", + "language": "en", + "version": "15" + } + ], + "subject": "TSV Translation Notes", + "title": "unfoldingWord® Translation Notes", + "type": "help", + "version": "15" + }, + "checking": { + "checking_entity": [ + "unfoldingWord" + ], + "checking_level": "3" + }, + "projects": [ + { + "title": "Genesis unfoldingWord® Translation Notes", + "versification": "", + "identifier": "gen", + "sort": 1, + "path": "./en_tn_01-GEN.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Exodus unfoldingWord® Translation Notes", + "versification": "", + "identifier": "exo", + "sort": 2, + "path": "./en_tn_02-EXO.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Leviticus unfoldingWord® Translation Notes", + "versification": "", + "identifier": "lev", + "sort": 3, + "path": "./en_tn_03-LEV.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Numbers unfoldingWord® Translation Notes", + "versification": "", + "identifier": "num", + "sort": 4, + "path": "./en_tn_04-NUM.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Deuteronomy unfoldingWord® Translation Notes", + "versification": "", + "identifier": "deu", + "sort": 5, + "path": "./en_tn_05-DEU.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Joshua unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jos", + "sort": 6, + "path": "./en_tn_06-JOS.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Judges unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jdg", + "sort": 7, + "path": "./en_tn_07-JDG.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Ruth unfoldingWord® Translation Notes", + "versification": "", + "identifier": "rut", + "sort": 8, + "path": "./en_tn_08-RUT.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "1 Samuel unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1sa", + "sort": 9, + "path": "./en_tn_09-1SA.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "2 Samuel unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2sa", + "sort": 10, + "path": "./en_tn_10-2SA.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "1 Kings unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1ki", + "sort": 11, + "path": "./en_tn_11-1KI.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "2 Kings unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2ki", + "sort": 12, + "path": "./en_tn_12-2KI.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "1 Chronicles unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1ch", + "sort": 13, + "path": "./en_tn_13-1CH.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "2 Chronicles unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2ch", + "sort": 14, + "path": "./en_tn_14-2CH.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Ezra unfoldingWord® Translation Notes", + "versification": "", + "identifier": "ezr", + "sort": 15, + "path": "./en_tn_15-EZR.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Nehemiah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "neh", + "sort": 16, + "path": "./en_tn_16-NEH.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Esther unfoldingWord® Translation Notes", + "versification": "", + "identifier": "est", + "sort": 17, + "path": "./en_tn_17-EST.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Job unfoldingWord® Translation Notes", + "versification": "", + "identifier": "job", + "sort": 18, + "path": "./en_tn_18-JOB.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Psalms unfoldingWord® Translation Notes", + "versification": "", + "identifier": "psa", + "sort": 19, + "path": "./en_tn_19-PSA.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Proverbs unfoldingWord® Translation Notes", + "versification": "", + "identifier": "pro", + "sort": 20, + "path": "./en_tn_20-PRO.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Ecclesiastes unfoldingWord® Translation Notes", + "versification": "", + "identifier": "ecc", + "sort": 21, + "path": "./en_tn_21-ECC.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Song of Solomon unfoldingWord® Translation Notes", + "versification": "", + "identifier": "sng", + "sort": 22, + "path": "./en_tn_22-SNG.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Isaiah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "isa", + "sort": 23, + "path": "./en_tn_23-ISA.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Jeremiah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jer", + "sort": 24, + "path": "./en_tn_24-JER.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Lamentations unfoldingWord® Translation Notes", + "versification": "", + "identifier": "lam", + "sort": 25, + "path": "./en_tn_25-LAM.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Ezekiel unfoldingWord® Translation Notes", + "versification": "", + "identifier": "ezk", + "sort": 26, + "path": "./en_tn_26-EZK.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Daniel unfoldingWord® Translation Notes", + "versification": "", + "identifier": "dan", + "sort": 27, + "path": "./en_tn_27-DAN.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Hosea unfoldingWord® Translation Notes", + "versification": "", + "identifier": "hos", + "sort": 28, + "path": "./en_tn_28-HOS.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Joel unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jol", + "sort": 29, + "path": "./en_tn_29-JOL.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Amos unfoldingWord® Translation Notes", + "versification": "", + "identifier": "amo", + "sort": 30, + "path": "./en_tn_30-AMO.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Obadiah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "oba", + "sort": 31, + "path": "./en_tn_31-OBA.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Jonah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jon", + "sort": 32, + "path": "./en_tn_32-JON.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Micah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "mic", + "sort": 33, + "path": "./en_tn_33-MIC.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Nahum unfoldingWord® Translation Notes", + "versification": "", + "identifier": "nam", + "sort": 34, + "path": "./en_tn_34-NAM.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Habakkuk unfoldingWord® Translation Notes", + "versification": "", + "identifier": "hab", + "sort": 35, + "path": "./en_tn_35-HAB.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Zephaniah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "zep", + "sort": 36, + "path": "./en_tn_36-ZEP.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Haggai unfoldingWord® Translation Notes", + "versification": "", + "identifier": "hag", + "sort": 37, + "path": "./en_tn_37-HAG.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Zechariah unfoldingWord® Translation Notes", + "versification": "", + "identifier": "zec", + "sort": 38, + "path": "./en_tn_38-ZEC.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Malachi unfoldingWord® Translation Notes", + "versification": "", + "identifier": "mal", + "sort": 39, + "path": "./en_tn_39-MAL.tsv", + "categories": [ + "bible-ot" + ] + }, + { + "title": "Matthew unfoldingWord® Translation Notes", + "versification": "", + "identifier": "mat", + "sort": 40, + "path": "./en_tn_41-MAT.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Mark unfoldingWord® Translation Notes", + "versification": "", + "identifier": "mrk", + "sort": 41, + "path": "./en_tn_42-MRK.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Luke unfoldingWord® Translation Notes", + "versification": "", + "identifier": "luk", + "sort": 42, + "path": "./en_tn_43-LUK.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "John unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jhn", + "sort": 43, + "path": "./en_tn_44-JHN.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Acts unfoldingWord® Translation Notes", + "versification": "", + "identifier": "act", + "sort": 44, + "path": "./en_tn_45-ACT.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Romans unfoldingWord® Translation Notes", + "versification": "", + "identifier": "rom", + "sort": 45, + "path": "./en_tn_46-ROM.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "1 Corinthians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1co", + "sort": 46, + "path": "./en_tn_47-1CO.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "2 Corinthians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2co", + "sort": 47, + "path": "./en_tn_48-2CO.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Galatians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "gal", + "sort": 48, + "path": "./en_tn_49-GAL.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Ephesians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "eph", + "sort": 49, + "path": "./en_tn_50-EPH.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Philippians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "php", + "sort": 50, + "path": "./en_tn_51-PHP.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Colossians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "col", + "sort": 51, + "path": "./en_tn_52-COL.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "1 Thessalonians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1th", + "sort": 52, + "path": "./en_tn_53-1TH.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "2 Thessalonians unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2th", + "sort": 53, + "path": "./en_tn_54-2TH.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "1 Timothy unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1ti", + "sort": 54, + "path": "./en_tn_55-1TI.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "2 Timothy unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2ti", + "sort": 55, + "path": "./en_tn_56-2TI.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Titus unfoldingWord® Translation Notes", + "versification": "", + "identifier": "tit", + "sort": 56, + "path": "./en_tn_57-TIT.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Philemon unfoldingWord® Translation Notes", + "versification": "", + "identifier": "phm", + "sort": 57, + "path": "./en_tn_58-PHM.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Hebrews unfoldingWord® Translation Notes", + "versification": "", + "identifier": "heb", + "sort": 58, + "path": "./en_tn_59-HEB.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "James unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jas", + "sort": 59, + "path": "./en_tn_60-JAS.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "1 Peter unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1pe", + "sort": 60, + "path": "./en_tn_61-1PE.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "2 Peter unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2pe", + "sort": 61, + "path": "./en_tn_62-2PE.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "1 John unfoldingWord® Translation Notes", + "versification": "", + "identifier": "1jn", + "sort": 62, + "path": "./en_tn_63-1JN.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "2 John unfoldingWord® Translation Notes", + "versification": "", + "identifier": "2jn", + "sort": 63, + "path": "./en_tn_64-2JN.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "3 John unfoldingWord® Translation Notes", + "versification": "", + "identifier": "3jn", + "sort": 64, + "path": "./en_tn_65-3JN.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Jude unfoldingWord® Translation Notes", + "versification": "", + "identifier": "jud", + "sort": 65, + "path": "./en_tn_66-JUD.tsv", + "categories": [ + "bible-nt" + ] + }, + { + "title": "Revelation unfoldingWord® Translation Notes", + "versification": "", + "identifier": "rev", + "sort": 66, + "path": "./en_tn_67-REV.tsv", + "categories": [ + "bible-nt" + ] + } + ], + "catalog_modified_time": "2019-05-21T19:48:33+00:00" +} diff --git a/__tests__/__fixtures__/translationWords/v10/manifest.json b/__tests__/__fixtures__/translationWords/v10/manifest.json new file mode 100644 index 00000000..5a9b09e1 --- /dev/null +++ b/__tests__/__fixtures__/translationWords/v10/manifest.json @@ -0,0 +1,66 @@ +{ + "dublin_core": { + "conformsto": "rc0.2", + "contributor": [ + "Andrew Belcher", + "David Book", + "Jesse Griffin, BA Biblical Studies, MA Biblical Languages", + "Henry Whitney, Bible translator, Papua New Guinea, 1982–2000", + "Larry Sallee, Th.M Dallas Theological Seminary, D.Min. Columbia Biblical Seminary", + "Lizz Carlton", + "Jan Zanutto", + "Matthew Latham", + "Perry Oakes, PhD in Old Testament, MA in Linguistics", + "Richard Joki", + "Door43 World Missions Community" + ], + "creator": "Door43 World Missions Community", + "description": "A basic Bible lexicon that provides translators with clear, concise definitions and translation suggestions for every important word in the Bible. It provides translators and checkers with essential lexical information to help them make the best possible translation decisions.", + "format": "text/markdown", + "identifier": "tw", + "issued": "2019-05-17", + "language": { + "identifier": "en", + "title": "English", + "direction": "ltr" + }, + "modified": "2019-05-17", + "publisher": "unfoldingWord", + "relation": [ + "en/ult", + "en/ust", + "en/obs", + "en/tn", + "en/tq" + ], + "rights": "CC BY-SA 4.0", + "source": [ + { + "identifier": "tw", + "language": "en", + "version": "10" + } + ], + "subject": "Translation Words", + "title": "unfoldingWord® Translation Words", + "type": "dict", + "version": "10" + }, + "checking": { + "checking_entity": [ + "unfoldingWord" + ], + "checking_level": "3" + }, + "projects": [ + { + "categories": null, + "identifier": "bible", + "path": "./bible", + "sort": 0, + "title": "unfoldingWord® Translation Words", + "versification": null + } + ], + "catalog_modified_time": "2019-05-17T19:25:28+00:00" +} diff --git a/__tests__/gatewayLanguageHelpers.test.js b/__tests__/gatewayLanguageHelpers.test.js new file mode 100644 index 00000000..26aa1080 --- /dev/null +++ b/__tests__/gatewayLanguageHelpers.test.js @@ -0,0 +1,1038 @@ +/* eslint-env jest */ +// helpers +import _ from 'lodash'; +import * as gatewayLanguageHelpers from '../src/helpers/gatewayLanguageHelpers'; + +describe('checkAreayHelpers.bibleIdSort', () => { + test('Test ordering of Bible IDs - new sort order', () => { + // given + const bibleIds = ['asv', 'esv', 'ulb', 'ust', 'ult', 'udb', 'irv', 'aaa', 'zzz', 'glt']; + const expectedSortedBibleIds = ['glt', 'irv', 'ult', 'ulb', 'aaa', 'asv', 'esv', 'udb', 'ust', 'zzz']; + + // when + const sortedBibleIds = bibleIds.sort(gatewayLanguageHelpers.bibleIdSort); + + // then + expect(sortedBibleIds).toEqual(expectedSortedBibleIds); + }); +}); + +describe('gatewayLanguageHelpers.getAlignedGLText', () => { + const verseObjects = [ + { + tag: 'zaln', + type: 'milestone', + strong: 'G14870', + lemma: 'εἰ', + morph: 'Gr,CS,,,,,,,,', + occurrence: 1, + occurrences: 1, + content: 'εἴ', + children: [ + { + tag: 'zaln', + type: 'milestone', + strong: 'G51000', + lemma: 'τις', + morph: 'Gr,RI,,,,NMS,', + occurrence: 1, + occurrences: 1, + content: 'τίς', + children: [ + { + text: 'An', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + { + text: 'elder', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G15100', + lemma: 'εἰμί', + morph: 'Gr,V,IPA3,,S,', + occurrence: 1, + occurrences: 1, + content: 'ἐστιν', + children: [ + { + text: 'must', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + { + text: 'be', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G04100', + lemma: 'ἀνέγκλητος', + morph: 'Gr,NP,,,,NMS,', + occurrence: 1, + occurrences: 1, + content: 'ἀνέγκλητος', + children: [ + { + text: 'without', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + { + text: 'blame', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + type: 'text', + text: ',', + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G04350', + lemma: 'ἀνήρ', + morph: 'Gr,N,,,,,NMS,', + occurrence: 1, + occurrences: 1, + content: 'ἀνήρ', + children: [ + { + text: 'the', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + { + text: 'husband', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G15200', + lemma: 'εἷς', + morph: 'Gr,EN,,,,GFS,', + occurrence: 1, + occurrences: 1, + content: 'μιᾶς', + children: [ + { + text: 'of', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 2, + }, + { + text: 'one', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G11350', + lemma: 'γυνή', + morph: 'Gr,N,,,,,GFS,', + occurrence: 1, + occurrences: 1, + content: 'γυναικὸς', + children: [ + { + text: 'wife', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + type: 'text', + text: ',', + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G21920', + lemma: 'ἔχω', + morph: 'Gr,V,PPA,NMS,', + occurrence: 1, + occurrences: 1, + content: 'ἔχων', + children: [ + { + text: 'with', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G41030', + lemma: 'πιστός', + morph: 'Gr,NS,,,,ANP,', + occurrence: 1, + occurrences: 1, + content: 'πιστά', + children: [ + { + text: 'faithful', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G50430', + lemma: 'τέκνον', + morph: 'Gr,N,,,,,ANP,', + occurrence: 1, + occurrences: 1, + content: 'τέκνα', + children: [ + { + text: 'children', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G33610', + lemma: 'μή', + morph: 'Gr,D,,,,,,,,,', + occurrence: 1, + occurrences: 1, + content: 'μὴ', + children: [ + { + text: 'not', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G17220', + lemma: 'ἐν', + morph: 'Gr,P,,,,,D,,,', + occurrence: 1, + occurrences: 1, + content: 'ἐν', + children: [ + { + tag: 'zaln', + type: 'milestone', + strong: 'G27240', + lemma: 'κατηγορία', + morph: 'Gr,N,,,,,DFS,', + occurrence: 1, + occurrences: 1, + content: 'κατηγορίᾳ', + children: [ + { + text: 'accused', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G08100', + lemma: 'ἀσωτία', + morph: 'Gr,N,,,,,GFS,', + occurrence: 1, + occurrences: 1, + content: 'ἀσωτίας', + children: [ + { + text: 'of', + tag: 'w', + type: 'word', + occurrence: 2, + occurrences: 2, + }, + { + text: 'reckless', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + { + text: 'behavior', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G22280', + lemma: 'ἤ', + morph: 'Gr,CC,,,,,,,,', + occurrence: 1, + occurrences: 1, + content: 'ἢ', + children: [ + { + text: 'or', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + tag: 'zaln', + type: 'milestone', + strong: 'G05060', + lemma: 'ἀνυπότακτος', + morph: 'Gr,NP,,,,ANP,', + occurrence: 1, + occurrences: 1, + content: 'ἀνυπότακτα', + children: [ + { + text: 'undisciplined', + tag: 'w', + type: 'word', + occurrence: 1, + occurrences: 1, + }, + ], + }, + { + type: 'text', + text: '. \n', + }, + ]; + const verseObjects2 = replaceTextInVerseObjects(verseObjects, 'blame', 'guilt');_.cloneDeep(verseObjects); + + test('should return text from ult and ignore hi reference in tsv_relation', () => { + // given + const contextId = { + groupId: 'blameless', + occurrence: 1, + quote: 'ἀνέγκλητος', + reference: { + bookId: 'tit', + chapter: 1, + verse: 6, + }, + strong: ['G04100'], + }; + const bibles = { + 'ult': { 1: { 6: { verseObjects: verseObjects } } }, + 'zzz': { 1: { 6: { verseObjects: verseObjects2 } } }, + 'ulb': [], + }; + const expectedAlignedGLText = 'without blame'; + const tsv_relation = [ + 'hi/zzz', + 'en/ust', + 'en/obs', + 'el-x-koine/ugnt?v=0.13', + 'hbo/uhb?v=2.1.14', + ]; + const glID = 'en'; + + // when + const alignedGLText = gatewayLanguageHelpers.getAlignedGLTextHelper( contextId, bibles, glID, tsv_relation); + + // then + expect(alignedGLText).toEqual(expectedAlignedGLText); + }); + + test('should return text from tsv_relation and not ult', () => { + // given + const contextId = { + groupId: 'blameless', + occurrence: 1, + quote: 'ἀνέγκλητος', + reference: { + bookId: 'tit', + chapter: 1, + verse: 6, + }, + strong: ['G04100'], + }; + const bibles = { + 'ult': { 1: { 6: { verseObjects: verseObjects } } }, + 'zzz': { 1: { 6: { verseObjects: verseObjects2 } } }, + 'ulb': [], + }; + const expectedAlignedGLText = 'without guilt'; + const tsv_relation = [ + 'en/zzz', + 'en/ust', + 'en/obs', + 'el-x-koine/ugnt?v=0.13', + 'hbo/uhb?v=2.1.14', + ]; + const glID = 'en'; + + // when + const alignedGLText = gatewayLanguageHelpers.getAlignedGLTextHelper( contextId, bibles, glID, tsv_relation); + + // then + expect(alignedGLText).toEqual(expectedAlignedGLText); + }); + + test('should return text from ult and NOT the ulb', () => { + // given + const contextId = { + groupId: 'blameless', + occurrence: 1, + quote: 'ἀνέγκλητος', + reference: { + bookId: 'tit', + chapter: 1, + verse: 6, + }, + strong: ['G04100'], + }; + const bibles = { + 'ult': { 1: { 6: { verseObjects: verseObjects } } }, + 'ulb': [], + }; + const expectedAlignedGLText = 'without blame'; + + // when + const alignedGLText = gatewayLanguageHelpers.getAlignedGLTextHelper( contextId, bibles); + + // then + expect(alignedGLText).toEqual(expectedAlignedGLText); + }); + + test('should return text from ulb', () => { + // given + const contextId = { + groupId: 'blameless', + occurrence: 1, + quote: 'ἀνέγκλητος', + reference: { + bookId: 'tit', + chapter: 1, + verse: 6, + }, + strong: ['G04100'], + }; + const bibles = { 'ulb': { 1: { 6: { verseObjects: verseObjects } } } }; + const expectedAlignedGLText = 'without blame'; + + // when + const alignedGLText = gatewayLanguageHelpers.getAlignedGLTextHelper( contextId, bibles); + + // then + expect(alignedGLText).toEqual(expectedAlignedGLText); + }); + + test('should handle array of words for quote', () => { + // given + const verseObjects = [ + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G24430', + 'lemma': 'ἵνα', + 'morph': 'Gr,CS,,,,,,,,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'ἵνα', + 'children': [ + { + 'text': 'that', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G20680', + 'lemma': 'ἐσθίω', + 'morph': 'Gr,V,SPA2,,P,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'ἔσθητε', + 'children': [ + { + 'text': 'you', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 2, + }, + { + 'text': 'may', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + { + 'text': 'eat', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G25320', + 'lemma': 'καί', + 'morph': 'Gr,CC,,,,,,,,', + 'occurrence': 1, + 'occurrences': 2, + 'content': 'καὶ', + 'children': [ + { + 'text': 'and', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 2, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G40950', + 'lemma': 'πίνω', + 'morph': 'Gr,V,SPA2,,P,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'πίνητε', + 'children': [ + { + 'text': 'drink', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G19090', + 'lemma': 'ἐπί', + 'morph': 'Gr,P,,,,,G,,,', + 'occurrence': 1, + 'occurrences': 2, + 'content': 'ἐπὶ', + 'children': [ + { + 'text': 'at', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G14730', + 'lemma': 'ἐγώ', + 'morph': 'Gr,RP,,,1G,S,', + 'occurrence': 1, + 'occurrences': 2, + 'content': 'μου', + 'children': [ + { + 'text': 'my', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 2, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G35880', + 'lemma': 'ὁ', + 'morph': 'Gr,EA,,,,GFS,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'τῆς', + 'children': [ + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G51320', + 'lemma': 'τράπεζα', + 'morph': 'Gr,N,,,,,GFS,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'τραπέζης', + 'children': [ + { + 'text': 'table', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G17220', + 'lemma': 'ἐν', + 'morph': 'Gr,P,,,,,D,,,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'ἐν', + 'children': [ + { + 'text': 'in', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G14730', + 'lemma': 'ἐγώ', + 'morph': 'Gr,RP,,,1G,S,', + 'occurrence': 2, + 'occurrences': 2, + 'content': 'μου', + 'children': [ + { + 'text': 'my', + 'tag': 'w', + 'type': 'word', + 'occurrence': 2, + 'occurrences': 2, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G35880', + 'lemma': 'ὁ', + 'morph': 'Gr,EA,,,,DFS,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'τῇ', + 'children': [ + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G09320', + 'lemma': 'βασιλεία', + 'morph': 'Gr,N,,,,,DFS,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'βασιλείᾳ', + 'children': [ + { + 'text': 'kingdom', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'type': 'text', + 'text': ',', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G25320', + 'lemma': 'καί', + 'morph': 'Gr,CC,,,,,,,,', + 'occurrence': 2, + 'occurrences': 2, + 'content': 'καὶ', + 'children': [ + { + 'text': 'and', + 'tag': 'w', + 'type': 'word', + 'occurrence': 2, + 'occurrences': 2, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G25210', + 'lemma': 'κάθημαι', + 'morph': 'Gr,V,IPM2,,P,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'καθῆσθε', + 'children': [ + { + 'text': 'you', + 'tag': 'w', + 'type': 'word', + 'occurrence': 2, + 'occurrences': 2, + }, + { + 'text': 'will', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + { + 'text': 'sit', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G19090', + 'lemma': 'ἐπί', + 'morph': 'Gr,P,,,,,G,,,', + 'occurrence': 2, + 'occurrences': 2, + 'content': 'ἐπὶ', + 'children': [ + { + 'text': 'on', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G23620', + 'lemma': 'θρόνος', + 'morph': 'Gr,N,,,,,GMP,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'θρόνων', + 'children': [ + { + 'text': 'thrones', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G29190', + 'lemma': 'κρίνω', + 'morph': 'Gr,V,PPA,NMP,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'κρίνοντες', + 'children': [ + { + 'text': 'judging', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G35880', + 'lemma': 'ὁ', + 'morph': 'Gr,EA,,,,AFP,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'τὰς', + 'children': [ + { + 'text': 'the', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G14270', + 'lemma': 'δώδεκα', + 'morph': 'Gr,EN,,,,AFP,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'δώδεκα', + 'children': [ + { + 'text': 'twelve', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G54430', + 'lemma': 'φυλή', + 'morph': 'Gr,N,,,,,AFP,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'φυλὰς', + 'children': [ + { + 'text': 'tribes', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G35880', + 'lemma': 'ὁ', + 'morph': 'Gr,EA,,,,GMS,', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'τοῦ', + 'children': [ + { + 'text': 'of', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'tag': 'zaln', + 'type': 'milestone', + 'strong': 'G24740', + 'lemma': 'Ἰσραήλ', + 'morph': 'Gr,N,,,,,GMSI', + 'occurrence': 1, + 'occurrences': 1, + 'content': 'Ἰσραήλ', + 'children': [ + { + 'text': 'Israel', + 'tag': 'w', + 'type': 'word', + 'occurrence': 1, + 'occurrences': 1, + }, + ], + 'endTag': 'zaln-e\\*', + }, + { + 'type': 'text', + 'text': '.', + }, + { + 'tag': 's5', + 'nextChar': '\n', + 'type': 'section', + }, + { + 'tag': 'p', + 'type': 'paragraph', + 'text': ' \n', + }, + ]; + const contextId = { + 'reference': { + 'bookId': 'luk', + 'chapter': 22, + 'verse': 30, + }, + 'groupId': '12tribesofisrael', + 'quote': [ + { + 'word': 'δώδεκα', + 'occurrence': 1, + }, + { + 'word': 'φυλὰς', + 'occurrence': 1, + }, + { + 'word': 'κρίνοντες', + 'occurrence': 1, + }, + { + 'word': 'τοῦ', + 'occurrence': 1, + }, + { + 'word': 'Ἰσραήλ', + 'occurrence': 1, + }, + ], + 'strong': [ + 'G14270', + 'G54430', + 'G29190', + 'G35880', + 'G24740', + ], + 'occurrence': 1, + }; + const bibles = { 'ult': { 22: { 30: { verseObjects: verseObjects } } } }; + const expectedAlignedGLText = 'judging … twelve tribes of Israel'; + + // when + const alignedGLText = gatewayLanguageHelpers.getAlignedGLTextHelper( contextId, bibles); + + // then + expect(alignedGLText).toEqual(expectedAlignedGLText); + }); +}); + +// +// Helpers +// + +function replaceTextInVerseObjects(verseObjects, findText, replaceText) { + const verseObjects_ = _.cloneDeep(verseObjects); + + for (let verseObject of verseObjects_) { + if (verseObject.text === findText) { + verseObject.text = replaceText; + } + + if (verseObject.children) { // check for nesting + const newChildren = replaceTextInVerseObjects(verseObject.children, findText, replaceText); + verseObject.children = newChildren; + } + } + return verseObjects_; +} diff --git a/package-lock.json b/package-lock.json index c4363c9d..c7322d9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "checking-tool-wrapper", - "version": "5.2.0", + "version": "5.3.0-alpha.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -6136,9 +6136,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash._reinterpolate": { "version": "3.0.0", diff --git a/package.json b/package.json index 03b266b9..73161dc2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "checking-tool-wrapper", "description": "Checking tool wrapper for translationCore App", - "version": "5.2.0", + "version": "5.3.0", "main": "lib/index.js", "scripts": { "lint": "eslint ./src", @@ -65,8 +65,10 @@ "eslint-plugin-react": "7.14.3", "eslint-plugin-react-hooks": "2.0.1", "file-loader": "3.0.1", + "fs-extra": "4.0.3", "jest": "24.9.0", "jest-transform-stub": "2.0.0", + "lodash": "4.17.15", "prettier": "1.18.2", "react": "16.8.6", "react-addons-test-utils": "15.6.2", diff --git a/src/Container.js b/src/Container.js index 2fd35aeb..cc83fe86 100644 --- a/src/Container.js +++ b/src/Container.js @@ -5,6 +5,7 @@ import { createTcuiTheme, TcuiThemeProvider } from 'tc-ui-toolkit'; import { connect } from 'react-redux'; // helpers import * as settingsHelper from './helpers/settingsHelper'; +import { getThelpsManifestRelation } from './helpers/resourcesHelpers'; // components import GroupMenuContainer from './containers/GroupMenuContainer'; import VerseCheckWrapper from './components/VerseCheckWrapper'; @@ -21,6 +22,7 @@ import { getGatewayLanguageCode, getCurrentPaneSettings, getGatewayLanguageBibles, + getCurrentToolName, } from './selectors'; import { getAlignedGLTextHelper } from './helpers/gatewayLanguageHelpers'; @@ -124,7 +126,9 @@ export const mapStateToProps = (state, ownProps) => { const gatewayLanguageCode = getGatewayLanguageCode(ownProps); const contextId = getContextId(state); const glBibles = getGatewayLanguageBibles(ownProps); - const gatewayLanguageQuote = getAlignedGLTextHelper(contextId, glBibles); + const toolName = getCurrentToolName(ownProps); + const tsvRelation = getThelpsManifestRelation(gatewayLanguageCode, toolName); + const gatewayLanguageQuote = getAlignedGLTextHelper(contextId, glBibles, gatewayLanguageCode, tsvRelation); const tc = getTcState(ownProps); const toolApi = getToolApi(ownProps); diff --git a/src/helpers/gatewayLanguageHelpers.js b/src/helpers/gatewayLanguageHelpers.js index 91ed9647..8402cfe0 100644 --- a/src/helpers/gatewayLanguageHelpers.js +++ b/src/helpers/gatewayLanguageHelpers.js @@ -2,14 +2,15 @@ import { getAlignedText } from 'tc-ui-toolkit'; /** - * Returns the gateway langauge code and quote. + * Returns the gateway language code and quote. * @param {string} gatewayLanguageCode - gateway language code. * @param {object} contextId - context id. * @param {object} glBibles - gateway language bibles. + * @param {array|null} tsvRelation - list of relationship items in manifest * @return {{gatewayLanguageCode: *, gatewayLanguageQuote: *}} */ -export const getGatewayLanguageCodeAndQuote = (gatewayLanguageCode, contextId, glBibles) => { - const gatewayLanguageQuote = getAlignedGLTextHelper(contextId, glBibles); +export const getGatewayLanguageCodeAndQuote = (gatewayLanguageCode, contextId, glBibles, tsvRelation) => { + const gatewayLanguageQuote = getAlignedGLTextHelper(contextId, glBibles, gatewayLanguageCode, tsvRelation); return { gatewayLanguageCode, @@ -21,13 +22,36 @@ export const getGatewayLanguageCodeAndQuote = (gatewayLanguageCode, contextId, g * get the selected text from the GL resource for this context * @param {*} contextId - current context id. * @param {*} glBibles - gateway language Bibles. + * @param {string} glID - current GL + * @param {array|null} tsvRelation - list of relationship items in manifest */ -export function getAlignedGLTextHelper(contextId, glBibles) { +export function getAlignedGLTextHelper(contextId, glBibles, glID = '', tsvRelation = null) { if (contextId) { if (!contextId.quote || !glBibles || !glBibles || !Object.keys(glBibles).length) { return contextId.quote || ''; } + if (Array.isArray(tsvRelation)) { // look for GL text in TSV relations + for (let relation of tsvRelation) { + const parts = relation.split('/'); + + if ((parts.length === 2) && (parts[0] === glID)) { // make sure it is for same gl and has the expected number of levels + let bibleId = parts[1]; + bibleId = bibleId.split('?')[0]; + const bible = glBibles[bibleId]; + + if (bible) { // if bible present, see if we can find GL text + const alignedText = getAlignedTextFromBible(contextId, bible); + + if (alignedText) { + return alignedText; // we succeeded and we are done + } + } + } + } + } + + // fall back to searching for GL text in default priority const sortedBibleIds = Object.keys(glBibles).sort(bibleIdSort); for (let i = 0; i < sortedBibleIds.length; ++i) { @@ -44,12 +68,12 @@ export function getAlignedGLTextHelper(contextId, glBibles) { } /** - * Return book code with highest precidence + * Return book code with highest precedence * @param {*} a - First book code of 2 * @param {*} b - second book code */ export function bibleIdSort(a, b) { - const biblePrecedence = ['udb', 'ust', 'ulb', 'ult', 'irv']; // these should come first in this order if more than one aligned Bible, from least to greatest + const biblePrecedence = ['ulb', 'ult', 'irv', 'glt']; // TRICKY: we search in this order if more than one aligned Bible for GL, the last in this list is the first checked if (biblePrecedence.indexOf(a) === biblePrecedence.indexOf(b)) { return (a < b ? -1 : a > b ? 1 : 0); diff --git a/src/helpers/resourcesHelpers.js b/src/helpers/resourcesHelpers.js index e0e0c8c9..74d2c532 100644 --- a/src/helpers/resourcesHelpers.js +++ b/src/helpers/resourcesHelpers.js @@ -8,12 +8,54 @@ import { USER_RESOURCES_PATH, NT_ORIG_LANG, OT_ORIG_LANG, + TRANSLATION_HELPS, } from '../common/constants'; import { isOriginalLanguage, isOldTestament, } from './bibleHelpers'; +/** + * gets the relation from manifest file for tool + * @param {string} glID + * @param {string} toolName + * @return {null|[]} relation array + */ +export function getThelpsManifestRelation(glID, toolName) { + const tHelpsManifest = getThelpsManifest(glID, toolName); + const tsvRelation = tHelpsManifest && (tHelpsManifest.tsv_relation || (tHelpsManifest.dublin_core && tHelpsManifest.dublin_core.relation)); + return tsvRelation; +} + +/** + * gets the manifest file for tool + * @param {string} glID + * @param {string} toolName + * @return {null|{}} manifest object + */ +export function getThelpsManifest(glID, toolName) { + if ( glID && toolName) { + const resourcePath = path.join(USER_RESOURCES_PATH, glID, TRANSLATION_HELPS, toolName); + const latestVersion = getLatestVersion(resourcePath); + + if (latestVersion) { + const pathToBibleManifestFile = path.join(latestVersion, 'manifest.json'); + + try { + const manifestExists = fs.existsSync(pathToBibleManifestFile); + + if (manifestExists) { + const manifest = fs.readJsonSync(pathToBibleManifestFile); + return manifest; + } + } catch (error) { + console.error(`getThelpsManifest(${glID}, ${toolName}) - error getting manifest at ${pathToBibleManifestFile}`, error); + } + } + } + return null; +} + /** * Populates resourceList with resources that can be used in scripture pane * @param {array} resourceList - array to be populated with resources diff --git a/src/selectors/index.js b/src/selectors/index.js index f11d29e0..4b59d0f0 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -4,8 +4,6 @@ import * as fromGrouspIndex from '../state/reducers/groupsIndexReducer'; import * as fromGroupsData from '../state/reducers/groupsDataReducer'; import * as fromGroupMenu from '../state/reducers/groupMenuReducer'; import * as fromContextId from '../state/reducers/contextIdReducer'; -// helpers -import { getAlignedGLTextHelper } from '../helpers/gatewayLanguageHelpers'; // constants import { DEFAULT_MAX_SELECTIONS, @@ -53,12 +51,6 @@ export const getBookmarksReducer = (state) => export const getSelections = (state) => state.tool.selectionsReducer.selections; -export const getAlignedGLText = (state, ownProps) => { - const contextId = getContextId(state); - const glBibles = getGatewayLanguageBibles(ownProps); - - return getAlignedGLTextHelper(contextId, glBibles); -}; export const getProjectManifest = (ownProps) => ownProps.tc.projectDetailsReducer.manifest; export const getGatewayLanguageCode = (ownProps) => ownProps.tc.gatewayLanguageCode || ''; export const getCurrentToolName = (ownProps) => ownProps.tc.currentToolName;