From 8df9b3252ef19e183b46d632046e23cc67118260 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Thu, 11 Feb 2021 15:41:02 +1300 Subject: [PATCH 01/16] Prevent some irrelevant README errors --- package.json | 2 +- src/core/annotation-row-check.js | 6 ++--- src/core/field-link-check.js | 5 +++-- src/core/field-text-check.js | 22 ++++++++++++------- src/core/field-text-check.md | 2 +- src/core/getApi.js | 8 +++---- src/core/markdown-text-check.js | 5 +++-- src/core/plain-text-check.js | 7 ++++-- src/core/tn-table-row-check.js | 6 ++--- src/core/usfm-text-check.js | 4 ++-- src/core/utilities.js | 12 +++++----- src/core/yaml-text-check.js | 4 ++-- .../book-package-check/checkBookPackage.js | 4 ++-- src/demos/notice-processing1.md | 2 +- src/demos/notice-processing2.md | 2 +- src/demos/notice-processing3.md | 2 +- 16 files changed, 52 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 3c1f94a59..cad47a48b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "1.1.2", + "version": "1.1.3_alpha1", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/core/annotation-row-check.js b/src/core/annotation-row-check.js index 29b642cc7..5a4d909f6 100644 --- a/src/core/annotation-row-check.js +++ b/src/core/annotation-row-check.js @@ -8,7 +8,7 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const ANNOTATION_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.6'; +// const ANNOTATION_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.7'; const NUM_EXPECTED_ANNOTATION_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_ANNOTATION_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation'; @@ -122,7 +122,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // We don’t currently use the allowedLinks parameter - // functionLog(`checkAnnotationTSVDataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + // functionLog(`checkAnnotationTSVDataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); parameterAssert(rowID !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); parameterAssert(typeof rowID === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); // parameterAssert(fieldName !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); @@ -184,7 +184,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; - const octfResultObject = checkTextField(fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field diff --git a/src/core/field-link-check.js b/src/core/field-link-check.js index 77e80e029..37b2896af 100644 --- a/src/core/field-link-check.js +++ b/src/core/field-link-check.js @@ -3,7 +3,7 @@ import { cachedGetFileUsingFullURL } from './getApi'; import { userLog, parameterAssert } from './utilities'; -const LINK_VALIDATOR_VERSION_STRING = '0.3.4'; +const LINK_VALIDATOR_VERSION_STRING = '0.3.5'; export async function startLiveLinksCheck(linksList, existingNoticeList, callbackFunction) { @@ -108,8 +108,9 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField } // Ok, we have something in our field + const languageCode = ''; if (linkOptions.otherTextAllowed) - result = checkTextField('link', fieldName, fieldText, true, optionalFieldLocation, checkingOptions); + result = checkTextField(languageCode, 'link', fieldName, fieldText, true, optionalFieldLocation, checkingOptions); // Parameter nonsense check if (linkOptions.allowedCount > 0 && linkOptions.expectedCount > linkOptions.allowedCount) diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index d28d236c5..2e77e133f 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -1,12 +1,13 @@ import { DEFAULT_EXTRACT_LENGTH, OPEN_CLOSE_PUNCTUATION_PAIRS, BAD_CHARACTER_COMBINATIONS, isWhitespace, countOccurrences } from './text-handling-functions' -import { parameterAssert } from './utilities'; +import { debugLog, parameterAssert } from './utilities'; -// const FIELD_TEXT_VALIDATOR_VERSION_STRING = '0.3.4'; +// const FIELD_TEXT_VALIDATOR_VERSION_STRING = '0.3.5'; /** * @description -- Does basic checks for small errors like leading/trailing spaces, etc. + * @param {string} languageCode -- can be an empty string * @param {string} fieldType -- classification, e.g., TSV, USFM, YAML, link, markdown, raw * @param {string} fieldName -- used for identification * @param {string} fieldText -- the field being checked @@ -14,7 +15,7 @@ import { parameterAssert } from './utilities'; * @param {string} optionalFieldLocation -- used to inform where this field is located * @param {Object} checkingOptions */ -export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions) { +export function checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions) { // We assume that checking for compulsory fields is done elsewhere // Returns a single notice list @@ -26,6 +27,9 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op // location: the detailed location string // (Returned in this way for more intelligent processing at a higher level) // functionLog(`checkTextField(${fieldName}, ${fieldText.length.toLocaleString()} chars, ${allowedLinks}, '${optionalFieldLocation}')…`); + parameterAssert(languageCode !== undefined, "checkTextField: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkTextField: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(languageCode !== 'unfoldingWord', `checkTextField: 'languageCode' ${languageCode} parameter should be not be 'unfoldingWord'`); parameterAssert(fieldType !== undefined, "checkTextField: 'fieldType' parameter should be defined"); parameterAssert(typeof fieldType === 'string', `checkTextField: 'fieldType' parameter should be a string not a '${typeof fieldType}': ${fieldType}`); parameterAssert(fieldType !== '', `checkTextField: 'fieldType' ${fieldType} parameter should be not be an empty string`); @@ -93,9 +97,9 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op let characterIndex; if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 895) && (characterIndex = fieldText.indexOf('\u200B')) >= 0) { - const charCount = countOccurrences(fieldText,'\u200B'); - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u200B/g, '‼') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 895, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1?'':'s'} found`, characterIndex, extract, location: ourLocation }); + const charCount = countOccurrences(fieldText, '\u200B'); + const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u200B/g, '‼') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 895, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, characterIndex, extract, location: ourLocation }); suggestion = suggestion.replace(/\u200B/g, ''); // Or should it be space ??? } @@ -400,8 +404,10 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op let regexResultArray; while ((regexResultArray = leftRegex.exec(fieldText))) if ((fieldType !== 'markdown' || regexResultArray[0][0] !== '_') - && (fieldType !== 'YAML' || leftChar !== '{')) { - // debugLog(`Got misplaced left ${leftChar} in ${fieldType} ${fieldName} '${fieldText}':`, JSON.stringify(regexResultArray)); + && (fieldType !== 'YAML' || leftChar !== '{') + // TODO: We have to allow for a blank language code until we change checkPlainText() + && (languageCode !== 'en' || regexResultArray[0][2] !== 's' || fieldText.indexOf('(s)') === -1)) { + debugLog(`Got misplaced '${languageCode}' left ${leftChar} in ${fieldType} ${fieldName} '${fieldText}': ${JSON.stringify(regexResultArray)}`); let thisPriority = 717, thisMessage = `Misplaced ${leftChar} character`; if (leftChar === '(' && regexResultArray[0][2] === 's') { thisPriority = 17; thisMessage = `Possible misplaced ${leftChar} character`; } // Lower priority for words like 'thing(s)' if (!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < thisPriority) diff --git a/src/core/field-text-check.md b/src/core/field-text-check.md index 4025f0999..6b421afe3 100644 --- a/src/core/field-text-check.md +++ b/src/core/field-text-check.md @@ -27,7 +27,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; diff --git a/src/core/getApi.js b/src/core/getApi.js index 154bece8a..527c3250f 100644 --- a/src/core/getApi.js +++ b/src/core/getApi.js @@ -5,10 +5,10 @@ import { setup } from 'axios-cache-adapter'; import JSZip from 'jszip'; import * as books from './books'; import { clearCheckedArticleCache } from './tn-links-check'; -import { userLog, parameterAssert } from './utilities'; +import { functionLog, userLog, parameterAssert } from './utilities'; -// const GETAPI_VERSION_STRING = '0.6.7'; +// const GETAPI_VERSION_STRING = '0.6.8'; const MAX_INDIVIDUAL_FILES_TO_DOWNLOAD = 5; // More than this and it downloads the zipfile for the entire repo @@ -235,7 +235,7 @@ export async function preloadReposIfNecessary(username, languageCode, bookIDList // NOTE: We preload TA and TW by default because we are likely to have many links to those repos // We preload TQ by default because it has thousands of files (17,337), so individual file fetches might be slow // even for one book which might have several hundred files. - userLog(`preloadReposIfNecessary(${username}, ${languageCode}, ${bookIDList} (${typeof bookID}), ${branch}, [${repoList}])…`); + functionLog(`preloadReposIfNecessary(${username}, ${languageCode}, ${bookIDList} (${typeof bookID}), ${branch}, [${repoList}])…`); let success = true; const repos_ = [...repoList]; @@ -468,7 +468,7 @@ export async function cachedGetRepositoryZipFile({ username, repository, branch async function downloadRepositoryZipFile({ username, repository, branch }) { - userLog(`downloadRepositoryZipFile(${username}, ${repository}, ${branch})…`); + functionLog(`downloadRepositoryZipFile(${username}, ${repository}, ${branch})…`); // RJH removed this 2Oct2020 -- what’s the point -- it just slows things down -- // if it needs to be checked, should be checked before this point // const repoExists = await repositoryExistsOnDoor43({ username, repository }); diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 7715c3e4e..8e2a87621 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -5,7 +5,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { userLog, parameterAssert } from './utilities'; -const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.4.5'; +const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.4.6'; const IMAGE_REGEX = new RegExp('!\\[([^\\]]+?)\\]\\(([^ \\]]+?)\\)', 'g'); @@ -30,6 +30,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe // functionLog(`checkMarkdownText(${textName}, ${markdownText.length}, ${givenLocation})…`); parameterAssert(languageCode !== undefined, "checkMarkdownText: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkMarkdownText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(languageCode !== 'unfoldingWord', `checkMarkdownText: 'languageCode' ${languageCode} parameter should be not be 'unfoldingWord'`); parameterAssert(textOrFileName !== undefined, "checkMarkdownText: 'textOrFileName' parameter should be defined"); parameterAssert(typeof textOrFileName === 'string', `checkMarkdownText: 'textOrFileName' parameter should be a string not a '${typeof textOrFileName}': ${textOrFileName}`); parameterAssert(markdownText !== undefined, "checkMarkdownText: 'markdownText' parameter should be defined"); @@ -107,7 +108,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe parameterAssert(optionalFieldLocation !== undefined, "cMdT ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cMdT ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const dbtcResultObject = checkTextField('markdown', fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions); + const dbtcResultObject = checkTextField(languageCode, 'markdown', fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions); // If we need to put everything through addNotice, e.g., for debugging or filtering // process results line by line diff --git a/src/core/plain-text-check.js b/src/core/plain-text-check.js index 56ec66c1b..a0fce2bd3 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -4,7 +4,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { parameterAssert } from './utilities'; -const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.3.11'; +const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.3.12'; /** @@ -19,6 +19,8 @@ export function checkPlainText(textType, textName, plainText, givenLocation, che /* This function is optimised for checking the entire text, i.e., all lines. It is used in checkFileContents() in book-package-check.js + TODO: Should languageCode also be a parameter here? (affects other programs using the API) + Returns a result object containing a successList and a noticeList */ // functionLog(`checkPlainText(${textName}, (${plainText.length} chars), ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); @@ -71,6 +73,7 @@ export function checkPlainText(textType, textName, plainText, givenLocation, che cptResult.noticeList.push(noticeObject); } + const languageCode = ''; function ourCheckTextField(lineNumber, fieldText, allowedLinks, optionalFieldLocation, checkingOptions) { /** * @description - checks the given text field and processes the returned results @@ -94,7 +97,7 @@ export function checkPlainText(textType, textName, plainText, givenLocation, che parameterAssert(optionalFieldLocation !== undefined, "cPT ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cPT ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const resultObject = checkTextField(textType, '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); + const resultObject = checkTextField(languageCode, textType, '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field diff --git a/src/core/tn-table-row-check.js b/src/core/tn-table-row-check.js index 9c282fdc1..4d5f9034e 100644 --- a/src/core/tn-table-row-check.js +++ b/src/core/tn-table-row-check.js @@ -8,7 +8,7 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.7'; +// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.8'; const NUM_EXPECTED_TN_TSV_FIELDS = 9; // so expects 8 tabs per line const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote'; @@ -113,7 +113,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // We don’t currently use the allowedLinks parameter - // functionLog(`checkTN_TSVDataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + // functionLog(`checkTN_TSVDataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); parameterAssert(rowID !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); parameterAssert(typeof rowID === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); // parameterAssert(fieldName !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); @@ -175,7 +175,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'OccurrenceNote' ? 'markdown' : 'raw'; - const octfResultObject = checkTextField(fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index b004eca45..b4c80d91a 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -8,7 +8,7 @@ import { userLog, parameterAssert, dataAssert, ourParseInt } from './utilities'; import { removeDisabledNotices } from './disabled-notices'; -// const USFM_VALIDATOR_VERSION_STRING = '0.8.2'; +// const USFM_VALIDATOR_VERSION_STRING = '0.8.3'; const VALID_LINE_START_CHARACTERS = `([“‘`; // '{' gets added for STs @@ -519,7 +519,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex parameterAssert(fieldLocation !== undefined, "cUSFM ourCheckTextField: 'fieldLocation' parameter should be defined"); parameterAssert(typeof fieldLocation === 'string', `cUSFM ourCheckTextField: 'fieldLocation' parameter should be a string not a '${typeof fieldLocation}'`); - const dbtcResultObject = checkTextField(fieldType, fieldName, fieldText, allowedLinks, fieldLocation, checkingOptions); + const dbtcResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, fieldLocation, checkingOptions); // Process noticeList line by line to filter out potential false positives // for this particular kind of text field diff --git a/src/core/utilities.js b/src/core/utilities.js index 129dd9c95..b0a37493e 100644 --- a/src/core/utilities.js +++ b/src/core/utilities.js @@ -9,7 +9,7 @@ export function userLog(logString, optionalParameter2) { if (optionalParameter2) userLog(`userLog note: we have a 2nd parameter: '${optionalParameter2}' after '${logString}'`); // We can remove them all by disabling the next line - console.log(logString); + console.log(`uw-content-validation: ${logString}`); } @@ -21,7 +21,7 @@ export function userLog(logString, optionalParameter2) { export function debugLog(logString, optionalParameter2) { if (optionalParameter2) debugLog(`debugLog note: we have a 2nd parameter: '${optionalParameter2}' after '${logString}'`); // We can remove them all by disabling the next line - console.log(logString); + console.log(`uw-content-validation debug: ${logString}`); } @@ -33,7 +33,7 @@ export function debugLog(logString, optionalParameter2) { export function functionLog(logString, optionalParameter2) { if (optionalParameter2) functionLog(`functionLog note: we have a 2nd parameter: '${optionalParameter2}' after '${logString}'`); // We can remove them all by disabling the next line - console.log(logString); + console.log(`uw-content-validation function call: ${logString}`); } @@ -44,7 +44,7 @@ export function functionLog(logString, optionalParameter2) { */ export function parameterAssert(truthStatement, optionalMessage) { // We can remove them all by disabling the next line - console.assert(truthStatement, optionalMessage); + console.assert(truthStatement, `uw-content-validation parameterAssert: ${optionalMessage}`); } @@ -55,7 +55,7 @@ export function parameterAssert(truthStatement, optionalMessage) { */ export function logicAssert(truthStatement, optionalMessage) { // We can remove them all by disabling the next line - console.assert(truthStatement, optionalMessage); + console.assert(truthStatement, `uw-content-validation logicAssert: ${optionalMessage}`); } @@ -66,7 +66,7 @@ export function logicAssert(truthStatement, optionalMessage) { */ export function dataAssert(truthStatement, optionalMessage) { // We can remove them all by disabling the next line - console.assert(truthStatement, optionalMessage); + console.assert(truthStatement, `uw-content-validation dataAssert: ${optionalMessage}`); } diff --git a/src/core/yaml-text-check.js b/src/core/yaml-text-check.js index 61cf1faba..c4cd753f4 100644 --- a/src/core/yaml-text-check.js +++ b/src/core/yaml-text-check.js @@ -6,7 +6,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { parameterAssert } from './utilities'; -const YAML_VALIDATOR_VERSION_STRING = '0.4.2'; +const YAML_VALIDATOR_VERSION_STRING = '0.4.3'; export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, checkingOptions) { @@ -91,7 +91,7 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c parameterAssert(optionalFieldLocation !== undefined, "cYt ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cYt ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const resultObject = checkTextField('YAML', '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); + const resultObject = checkTextField(languageCode, 'YAML', '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); // Concat is faster if we don’t need to process each notice individually // cytResult.noticeList = cytResult.noticeList.concat(resultObject.noticeList); diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index 43829a056..f4a8bc1e2 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -6,7 +6,7 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { checkRepo } from '../repo-check/checkRepo'; -// const BP_VALIDATOR_VERSION_STRING = '0.5.5'; +// const BP_VALIDATOR_VERSION_STRING = '0.5.6'; const MANIFEST_FILENAME = 'manifest.yaml'; @@ -240,7 +240,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult } } if (markdownFileContent) { - const cmtResultObject = await checkMarkdownText(username, repoName, markdownFileContent, markdownLocation, checkingOptions); + const cmtResultObject = await checkMarkdownText(languageCode, repoName, markdownFileContent, markdownLocation, checkingOptions); // debugLog(`ourCheckMarkdown checkMarkdownText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); // debugLog(`ourCheckMarkdown checkMarkdownText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); // NOTE: We ignore the returned success messages here diff --git a/src/demos/notice-processing1.md b/src/demos/notice-processing1.md index 72dbe38e4..8db7e0241 100644 --- a/src/demos/notice-processing1.md +++ b/src/demos/notice-processing1.md @@ -41,7 +41,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; const processOptions = { diff --git a/src/demos/notice-processing2.md b/src/demos/notice-processing2.md index d38fcefb0..e3d199b01 100644 --- a/src/demos/notice-processing2.md +++ b/src/demos/notice-processing2.md @@ -41,7 +41,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; const processOptions = { diff --git a/src/demos/notice-processing3.md b/src/demos/notice-processing3.md index 0594844ee..918fe11f5 100644 --- a/src/demos/notice-processing3.md +++ b/src/demos/notice-processing3.md @@ -41,7 +41,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; const processOptions = { From 4852a54b517e1ea92b253f4f3be6edd88a41e69d Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Fri, 12 Feb 2021 14:27:16 +1300 Subject: [PATCH 02/16] Major structural changes to handle new TSV formats --- README.md | 2 +- noticeList.txt | 465 +++++++++------- package.json | 2 +- src/core/file-text-check.js | 4 +- src/core/index.js | 12 +- ...n-row-check.js => notes-tsv7-row-check.js} | 230 ++++---- ...n-row-check.md => notes-tsv7-row-check.md} | 18 +- ...ble-check.js => notes-tsv7-table-check.js} | 73 +-- ...ble-check.md => notes-tsv7-table-check.md} | 22 +- src/core/plain-text-check.js | 10 +- src/core/plain-text-check.md | 2 +- src/core/questions-tsv5-row-check.js | 505 +++++++++++++++++ src/core/questions-tsv5-row-check.md | 80 +++ src/core/questions-tsv5-table-check.js | 263 +++++++++ src/core/questions-tsv5-table-check.md | 78 +++ ...able-row-check.js => tn-tsv9-row-check.js} | 4 +- ...able-row-check.md => tn-tsv9-row-check.md} | 2 +- ...e-text-check.js => tn-tsv9-table-check.js} | 50 +- ...e-text-check.md => tn-tsv9-table-check.md} | 12 +- src/core/twl-tsv6-row-check.js | 512 ++++++++++++++++++ src/core/twl-tsv6-row-check.md | 80 +++ src/core/twl-tsv6-table-check.js | 263 +++++++++ src/core/twl-tsv6-table-check.md | 78 +++ .../book-package-check/checkBookPackage.js | 5 +- src/demos/file-check/checkFileContents.js | 24 +- styleguide.config.js | 36 +- yarn.lock | 158 +++--- 27 files changed, 2493 insertions(+), 497 deletions(-) rename src/core/{annotation-row-check.js => notes-tsv7-row-check.js} (67%) rename src/core/{annotation-row-check.md => notes-tsv7-row-check.md} (96%) rename src/core/{annotation-table-check.js => notes-tsv7-table-check.js} (82%) rename src/core/{annotation-table-check.md => notes-tsv7-table-check.md} (95%) create mode 100644 src/core/questions-tsv5-row-check.js create mode 100644 src/core/questions-tsv5-row-check.md create mode 100644 src/core/questions-tsv5-table-check.js create mode 100644 src/core/questions-tsv5-table-check.md rename src/core/{tn-table-row-check.js => tn-tsv9-row-check.js} (99%) rename src/core/{tn-tsv-table-row-check.md => tn-tsv9-row-check.md} (99%) rename src/core/{tn-table-text-check.js => tn-tsv9-table-check.js} (85%) rename src/core/{tn-tsv-table-text-check.md => tn-tsv9-table-check.md} (97%) create mode 100644 src/core/twl-tsv6-row-check.js create mode 100644 src/core/twl-tsv6-row-check.md create mode 100644 src/core/twl-tsv6-table-check.js create mode 100644 src/core/twl-tsv6-table-check.md diff --git a/README.md b/README.md index b7b57cbdd..e33ac74e6 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ There is provision for checking to be altered and/or sped-up when the calling ap - `cutoffPriorityLevel`: an integer which can define notices to not be detected—defaults to 0 so none are dropped. Note that this will also affect the `suggestion` response. (Only partially implemented at present, so drops some but not all low priority notices.) - `suppressNoticeDisablingFlag`: Defaults to `false`, i.e., to removing (thus suppressing) notices for warnings which are expected in certain files and hence we don’t want them displayed. Note that this is always set to `true` for the demos (because they suppress these notices later—see the `showDisabledNoticesFlag` below). - Currently this supressing is only done in the (exported) `checkTN_TSVText` and `checkAnnotationRows` functions which we know to be called by [tC Create](https://github.com/unfoldingWord/tc-create-app) as well as `checkManifestText`, `checkMarkdownText`, `checkPlainText`, `checkTN_TSVText`, `checkUSFMText`, and `checkYAMLText` called by the [Content Validation App](https://github.com/unfoldingWord-box3/content-validation-app). + Currently this supressing is only done in the (exported) `checkTN_TSV9Table` and `checkNotesTSV7Table` functions which we know to be called by [tC Create](https://github.com/unfoldingWord/tc-create-app) as well as `checkManifestText`, `checkMarkdownText`, `checkPlainText`, `checkTN_TSV9Table`, `checkUSFMText`, and `checkYAMLText` called by the [Content Validation App](https://github.com/unfoldingWord-box3/content-validation-app). Most of the high-level demonstrations allow a choice of one of three display formats for notices: diff --git a/noticeList.txt b/noticeList.txt index 0538e216c..c352548df 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,70 +1,80 @@ -Last updated 2021-02-06 09:28:25.706367 by makeNoticeList.py -Got 357 notices: - checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 259 +Last updated 2021-02-12 12:59:19.363735 by makeNoticeList.py +Got 452 notices: + checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 264 languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, extract: rest, C, V, location: lineLocation from usfm-text-check.js line 927 marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 955 `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, extract: line[0], location: ourLocation from usfm-text-check.js line 1,034 C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,127 - const notice = 95, "Unexpected trailing space(s)", extract, location: ourLocation ; from field-text-check.js line 186 - notice from field-text-check.js line 189 - notice = 124, "Unexpected double spaces", extract, location: ourLocation ; from field-text-check.js line 220 - notice = 224, "Multiple unexpected double spaces", details: `$doubleCount occurrences—only first is displayed`, extract, location: ourLocation ; from field-text-check.js line 222 - notice from field-text-check.js line 226 - const notice = 580, "Unexpected narrow non-break space character", extract, location: ourLocation ; from field-text-check.js line 250 - notice from field-text-check.js line 253 - const notice = 177, `Unexpected doubled $punctChar characters`, extract, location: ourLocation ; from field-text-check.js line 285 - notice from field-text-check.js line 288 - const notice = 191, `Unexpected $punctChar character after space`, extract, location: ourLocation ; from field-text-check.js line 304 - notice from field-text-check.js line 307 - const notice = 192, `Unexpected space after $punctChar character`, extract, location: ourLocation ; from field-text-check.js line 333 - notice from field-text-check.js line 336 - const notice = 193, `Unexpected $punctChar character at end of line`, extract, location: ourLocation ; from field-text-check.js line 351 - notice from field-text-check.js line 354 - thisPriority, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from field-text-check.js line 395 - thisPriority, thisMessage, extract: regexResultArray[0], location: ourLocation from field-text-check.js line 408 - leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from plain-text-check.js line 235 - 999, "checkRepo function FAILED", repoName, extract: checkRepoError, location: repoName from RepoCheck.js line 106 + const notice = 95, "Unexpected trailing space(s)", extract, location: ourLocation ; from field-text-check.js line 190 + notice from field-text-check.js line 193 + notice = 124, "Unexpected double spaces", extract, location: ourLocation ; from field-text-check.js line 224 + notice = 224, "Multiple unexpected double spaces", details: `$doubleCount occurrences—only first is displayed`, extract, location: ourLocation ; from field-text-check.js line 226 + notice from field-text-check.js line 230 + const notice = 580, "Unexpected narrow non-break space character", extract, location: ourLocation ; from field-text-check.js line 254 + notice from field-text-check.js line 257 + const notice = 177, `Unexpected doubled $punctChar characters`, extract, location: ourLocation ; from field-text-check.js line 289 + notice from field-text-check.js line 292 + const notice = 191, `Unexpected $punctChar character after space`, extract, location: ourLocation ; from field-text-check.js line 308 + notice from field-text-check.js line 311 + const notice = 192, `Unexpected space after $punctChar character`, extract, location: ourLocation ; from field-text-check.js line 337 + notice from field-text-check.js line 340 + const notice = 193, `Unexpected $punctChar character at end of line`, extract, location: ourLocation ; from field-text-check.js line 355 + notice from field-text-check.js line 358 + thisPriority, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from field-text-check.js line 399 + thisPriority, thisMessage, extract: regexResultArray[0], location: ourLocation from field-text-check.js line 414 + leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from plain-text-check.js line 240 + 999, "checkRepo function FAILED", repoName, extract: checkRepoError, location: repoName from RepoCheck.js line 107 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 174 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 235 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 383 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 576 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 602 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 382 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 575 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 601 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 178 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 239 - 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 387 - 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 578 - 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 606 - 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 263 - 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 88 - 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 113 - 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 131 - 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 119 - 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 135 - 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 125 - 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 139 + 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 386 + 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 577 + 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 605 + 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 268 + 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 94 + 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 117 + 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 136 + 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 123 + 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 140 + 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 129 + 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 144 990, "Unable to load file", details: `username=$username`, repoName, filename ], elapsedSeconds: 0 ; from FileCheck.js line 63 989, "Unable to find/load repository", location: ourLocation from checkRepo.js line 186 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 248 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_ANNOTATION_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 229 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 248 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 230 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 229 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 229 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, extract, location: ourLocation from usfm-text-check.js line 1,111 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 676 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-table-row-check.js line 559 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_ANNOTATION_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from annotation-row-check.js line 533 - 979, "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-table-row-check.js line 357 - 979, "Invalid book identifier passed to checkAnnotationTSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from annotation-row-check.js line 339 - 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, extract: B, location: ourRowLocation from tn-table-row-check.js line 372 - 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-table-row-check.js line 375 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, extract: C, location: ourRowLocation from tn-table-row-check.js line 380 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from annotation-row-check.js line 357 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 412 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 393 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 505 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 533 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 559 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 533 + 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 339 + 979, "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv5-row-check.js line 339 + 979, "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 357 + 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 339 + 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, extract: B, location: ourRowLocation from tn-tsv9-row-check.js line 372 + 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 375 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from twl-tsv6-row-check.js line 357 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from questions-tsv5-row-check.js line 357 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, extract: C, location: ourRowLocation from tn-tsv9-row-check.js line 380 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from notes-tsv7-row-check.js line 357 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from twl-tsv6-row-check.js line 393 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from questions-tsv5-row-check.js line 393 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-tsv9-row-check.js line 412 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from notes-tsv7-row-check.js line 393 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 199 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 269 950, "tC cannot yet process '*' language code", characterIndex, extract, location: ourLocation from tn-links-check.js line 226 - 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 288 - 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 286 - 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 178 + 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 293 + 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 291 + 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 943, `USFM3 toJSON Check doesn’t pass`, location: ourLocation from usfm-js-check.js line 91 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,161 939, "Key is missing for project", details: keyName, extract: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 688 @@ -74,8 +84,10 @@ Got 357 notices: 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 641 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 639 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 163 - 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 486 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from annotation-row-check.js line 473 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 445 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 473 + 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 486 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 473 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, extract, location: ourLocation from orig-quote-check.js line 332 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 374 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 377 @@ -95,7 +107,7 @@ Got 357 notices: 903, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 902, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 293 900, "Bad parameter: should be given a valid book abbreviation", extract: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 66 - 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1?'':'s' found`, characterIndex, extract, location: ourLocation from field-text-check.js line 98 + 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, extract, location: ourLocation from field-text-check.js line 102 889, `Unable to find TA link`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 888, `Error loading TA link`, extract: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 887, `Linked TA article seems empty`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 @@ -121,7 +133,7 @@ Got 357 notices: 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 829 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 288 - 849, `Unexpected '$badCharCombination' character combination`, characterIndex, extract, location: ourLocation from field-text-check.js line 364 + 849, `Unexpected '$badCharCombination' character combination`, characterIndex, extract, location: ourLocation from field-text-check.js line 368 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 @@ -141,75 +153,116 @@ Got 357 notices: 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 883 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 385 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 362 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 390 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 367 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 400 + 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 362 + 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 362 + 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 385 + 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 362 + 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 367 + 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 367 + 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 390 + 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 367 + 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 380 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, extract: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 822, "Expected field to contain an integer", characterIndex: 3, extract: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 380 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 405 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 386 - 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-table-row-check.js line 408 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from annotation-row-check.js line 389 + 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 380 + 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 400 + 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 380 + 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 386 + 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 386 + 821, "Bad chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 405 + 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 386 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 389 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv5-row-check.js line 389 + 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 408 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 389 819, "Missing compulsory USFM line", extract: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 - 814, "Invalid zero verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 417 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 398 - 813, "Invalid large verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 421 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 402 - 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-table-row-check.js line 423 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 404 - 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-table-row-check.js line 427 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from annotation-row-check.js line 408 - 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-table-row-check.js line 430 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from annotation-row-check.js line 411 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-table-row-check.js line 500 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from annotation-row-check.js line 487 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-table-row-check.js line 505 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from annotation-row-check.js line 492 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-table-text-check.js line 227 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from annotation-table-check.js line 208 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-table-row-check.js line 461 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from annotation-row-check.js line 447 - 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-table-row-check.js line 466 - 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from annotation-row-check.js line 452 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', extract: regexResultArray[1], location: ourRowLocation from tn-table-row-check.js line 539 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from annotation-row-check.js line 512 - 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-table-row-check.js line 433 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 414 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-table-row-check.js line 436 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from annotation-row-check.js line 417 - 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 195 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from twl-tsv6-row-check.js line 398 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from questions-tsv5-row-check.js line 398 + 814, "Invalid zero verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-tsv9-row-check.js line 417 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from notes-tsv7-row-check.js line 398 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from twl-tsv6-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from questions-tsv5-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-tsv9-row-check.js line 421 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 404 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 404 + 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 423 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 404 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 408 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv5-row-check.js line 408 + 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 427 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 408 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 411 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv5-row-check.js line 411 + 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 430 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 411 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 459 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from questions-tsv5-row-check.js line 487 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 500 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 487 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 464 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 492 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 505 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 492 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 227 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 209 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv5-table-check.js line 208 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from notes-tsv7-table-check.js line 208 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 447 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 461 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 447 + 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 452 + 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 466 + 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from questions-tsv5-row-check.js line 512 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', extract: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 539 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 512 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 414 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 414 + 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 433 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 414 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 417 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 417 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 436 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 417 + 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 200 776, 'Unexpected " straight quote character', details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 750 775, "Unexpected ' straight quote character", details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 755 - 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 202 - 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 164 - 772, `Unexpected trailing word-joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 159 - 771, `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 142 - 770, `Unexpected leading word-joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 138 + 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 207 + 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 168 + 772, `Unexpected trailing word-joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 163 + 771, `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 146 + 770, `Unexpected leading word-joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 142 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, Math.max(9, extractLength))$rest.length > extractLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,087 - 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, extract, location: ourLocation from plain-text-check.js line 220 + 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, extract, location: ourLocation from plain-text-check.js line 225 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, Math.max(9, extractLength))$rest.length > extractLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,089 - 765, "Unexpected link", characterIndex, extract, location: ourLocation from field-text-check.js line 435 + 765, "Unexpected link", characterIndex, extract, location: ourLocation from field-text-check.js line 441 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, extract: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, Math.max(9, extractLength))$rest.length > extractLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 702 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-table-row-check.js line 491 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from annotation-row-check.js line 478 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-table-row-check.js line 482 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from annotation-row-check.js line 469 - 749, "Markdown image link seems faulty", lineNumber, extract: fetchLink, location: lineLocation from markdown-text-check.js line 139 - 748, "Error fetching markdown image link", lineNumber, extract: fetchLink, location: lineLocation from markdown-text-check.js line 148 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from tn-table-text-check.js line 107 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from annotation-table-check.js line 90 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-table-text-check.js line 122 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from annotation-table-check.js line 106 - 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 177 - 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 180 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 450 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from questions-tsv5-row-check.js line 478 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 491 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 478 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 441 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 469 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 482 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 469 + 749, "Markdown image link seems faulty", lineNumber, extract: fetchLink, location: lineLocation from markdown-text-check.js line 140 + 748, "Error fetching markdown image link", lineNumber, extract: fetchLink, location: lineLocation from markdown-text-check.js line 149 + 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 107 + 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from twl-tsv6-table-check.js line 91 + 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv5-table-check.js line 90 + 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from notes-tsv7-table-check.js line 90 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-tsv9-table-check.js line 122 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from twl-tsv6-table-check.js line 107 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from questions-tsv5-table-check.js line 106 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 106 + 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 177 + 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 180 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, extract: totalLink, location: ourLocation from tn-links-check.js line 353 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 483 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 535 @@ -225,30 +278,50 @@ Got 357 notices: 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, extract: totalLink, location: ourLocation from tn-links-check.js line 440 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, extract: totalLink, location: ourLocation from tn-links-check.js line 547 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, extract: totalLink, location: ourLocation from tn-links-check.js line 599 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-table-text-check.js line 204 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from annotation-table-check.js line 185 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 223 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 204 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-table-text-check.js line 191 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from annotation-table-check.js line 172 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 195 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 176 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 197 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 178 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 201 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-table-text-check.js line 213 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 182 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from annotation-table-check.js line 194 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-table-text-check.js line 217 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from annotation-table-check.js line 198 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 233 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 214 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 231 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 212 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 204 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 186 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv5-table-check.js line 185 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from notes-tsv7-table-check.js line 185 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 223 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 205 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 204 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 204 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-tsv9-table-check.js line 191 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from twl-tsv6-table-check.js line 173 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from questions-tsv5-table-check.js line 172 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from notes-tsv7-table-check.js line 172 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 195 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 177 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 176 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 176 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 197 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 179 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 178 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 178 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 201 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-tsv9-table-check.js line 213 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 183 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from twl-tsv6-table-check.js line 195 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 182 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from questions-tsv5-table-check.js line 194 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 182 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from notes-tsv7-table-check.js line 194 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-tsv9-table-check.js line 217 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from twl-tsv6-table-check.js line 199 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from questions-tsv5-table-check.js line 198 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from notes-tsv7-table-check.js line 198 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 233 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 215 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 214 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 214 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 231 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 213 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 212 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 212 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, extract: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 - 716, `Misplaced $rightChar character`, extract: regexResultArray[0], location: ourLocation from field-text-check.js line 416 + 716, `Misplaced $rightChar character`, extract: regexResultArray[0], location: ourLocation from field-text-check.js line 422 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 952 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, extract, location: ourLocation from usfm-text-check.js line 1,020 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 718 @@ -269,64 +342,84 @@ Got 357 notices: 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"'+leftoverLinksList2[0]+'"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from tn-links-check.js line 737 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"'+leftoverLinksList1[0]+'"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from tn-links-check.js line 731 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 254 - 638, "Only found whitespace", location: ourLocation from field-text-check.js line 104 - 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 123 + 638, "Only found whitespace", location: ourLocation from field-text-check.js line 108 + 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 128 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, extract, location: ourLocation from usfm-text-check.js line 990 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 111 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 143 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 151 - 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 152 - 583, "Unexpected newLine character", characterIndex, extract, location: ourLocation from field-text-check.js line 232 - 582, "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation from field-text-check.js line 238 - 581, "Unexpected non-break space character", characterIndex, extract, location: ourLocation from field-text-check.js line 244 + 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 153 + 583, "Unexpected newLine character", characterIndex, extract, location: ourLocation from field-text-check.js line 236 + 582, "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation from field-text-check.js line 242 + 581, "Unexpected non-break space character", characterIndex, extract, location: ourLocation from field-text-check.js line 248 555, "Possible missing chapter number in markdown Bible link", extract: totalLink, location: ourLocation from tn-links-check.js line 347 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-table-text-check.js line 211 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from annotation-table-check.js line 192 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-table-text-check.js line 189 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from annotation-table-check.js line 170 - 539, "File starts with empty line", characterIndex, extract, location: ourLocation from plain-text-check.js line 145 - 538, "File ends without newline character", characterIndex, extract, location: ourLocation from plain-text-check.js line 150 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-tsv9-table-check.js line 211 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from twl-tsv6-table-check.js line 193 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from questions-tsv5-table-check.js line 192 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from notes-tsv7-table-check.js line 192 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-tsv9-table-check.js line 189 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from twl-tsv6-table-check.js line 171 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from questions-tsv5-table-check.js line 170 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from notes-tsv7-table-check.js line 170 + 539, "File starts with empty line", characterIndex, extract, location: ourLocation from plain-text-check.js line 150 + 538, "File ends without newline character", characterIndex, extract, location: ourLocation from plain-text-check.js line 155 519, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 518, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 517, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, extract, location: ourLocation from tn-links-check.js line 222 - 441, `Unknown linkType parameter`, extract: linkType from field-link-check.js line 134 + 441, `Unknown linkType parameter`, extract: linkType from field-link-check.js line 135 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 106 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 950 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,124 - 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, extract, location: ourLocation from markdown-text-check.js line 246 + 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, extract, location: ourLocation from markdown-text-check.js line 247 375, "Ellipsis without surrounding snippet", location: ourLocation from orig-quote-check.js line 325 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1?'':'s' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-table-row-check.js line 470 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1?'':'s' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 512 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1?'':'s' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 527 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1?'':'s' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from annotation-row-check.js line 457 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1?'':'s' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 499 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-table-row-check.js line 454 - 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 515 - 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 530 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from annotation-row-check.js line 438 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 502 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 471 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 457 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 499 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 470 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 512 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 527 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 457 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 499 + 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 474 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 438 + 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 502 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 454 + 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 515 + 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 530 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 438 + 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 502 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 684 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 948 - 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 148 - 282, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 214 - 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 545 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 519 + 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 149 + 282, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 215 + 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 491 + 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 519 + 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 545 + 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 256, "Possibly missing current copyright year", details: fullYearString, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 262 218, "Using deprecated USFM marker", extract: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 - 195, `Unexpected $punctChar character at start of line`, characterIndex, extract, location: ourLocation from field-text-check.js line 315 - 179, "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 260 - 178, "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 266 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-table-row-check.js line 443 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from annotation-row-check.js line 424 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-table-row-check.js line 445 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from annotation-row-check.js line 426 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from tn-table-row-check.js line 447 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from annotation-row-check.js line 428 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from tn-table-row-check.js line 449 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from annotation-row-check.js line 430 - 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 207 + 195, `Unexpected $punctChar character at start of line`, characterIndex, extract, location: ourLocation from field-text-check.js line 319 + 179, "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 264 + 178, "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 270 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 424 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 443 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 424 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 426 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 426 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 428 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 428 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 430 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 430 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 + 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 208 159, "Should use proper ellipse character (not periods)", characterIndex, extract, location: ourLocation from orig-quote-check.js line 249 158, "Unexpected space(s) beside ellipse character", characterIndex, extract, location: ourLocation from orig-quote-check.js line 258 157, "Unexpected space(s) beside ↔ divider character", characterIndex, extract, location: ourLocation from orig-quote-check.js line 265 @@ -338,22 +431,24 @@ Got 357 notices: 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 526 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 584 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 634 - 138, "File ends with additional blank line(s)", characterIndex, extract, location: ourLocation from plain-text-check.js line 155 - 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 116 - 110, `Unexpected leading spaces`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 133 - 109, `Unexpected leading space`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 135 - 107, "Unexpected leading line break", characterIndex: 0, extract, location: ourLocation from field-text-check.js line 174 - 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, extract, location: ourLocation from field-text-check.js line 207 + 138, "File ends with additional blank line(s)", characterIndex, extract, location: ourLocation from plain-text-check.js line 160 + 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 117 + 110, `Unexpected leading spaces`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 137 + 109, `Unexpected leading space`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 139 + 107, "Unexpected leading line break", characterIndex: 0, extract, location: ourLocation from field-text-check.js line 178 + 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, extract, location: ourLocation from field-text-check.js line 211 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,165 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 248 - 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 186 - 94, "Unexpected trailing space(s) before break", characterIndex, extract, location: ourLocation from field-text-check.js line 194 - 93, "Unexpected trailing space(s) before line break", characterIndex, extract, location: ourLocation from field-text-check.js line 199 + 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 184 + 94, "Unexpected trailing space(s) before break", characterIndex, extract, location: ourLocation from field-text-check.js line 198 + 93, "Unexpected trailing space(s) before line break", characterIndex, extract, location: ourLocation from field-text-check.js line 203 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,117 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,119 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 468 - 64, "Unexpected leading space(s) after break", characterIndex, extract, location: ourLocation from field-text-check.js line 148 - 63, "Unexpected leading space(s) after line break", characterIndex, extract, location: ourLocation from field-text-check.js line 153 + 64, "Unexpected leading space(s) after break", characterIndex, extract, location: ourLocation from field-text-check.js line 152 + 63, "Unexpected leading space(s) after line break", characterIndex, extract, location: ourLocation from field-text-check.js line 157 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, extract: fieldText, location: ourLocation from orig-quote-check.js line 298 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-table-text-check.js line 260 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from annotation-table-check.js line 241 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 260 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 242 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv5-table-check.js line 241 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 241 diff --git a/package.json b/package.json index cad47a48b..8a5fc1b76 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "1.1.3_alpha1", + "version": "2.0.0_alpha1", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/core/file-text-check.js b/src/core/file-text-check.js index fa8847029..e4ff6aca1 100644 --- a/src/core/file-text-check.js +++ b/src/core/file-text-check.js @@ -1,7 +1,7 @@ import { checkPlainText } from './plain-text-check'; import { parameterAssert } from './utilities'; -// const FILE_TEXT_VALIDATOR_VERSION_STRING = '0.3.0'; +// const FILE_TEXT_VALIDATOR_VERSION_STRING = '0.3.1'; export function checkTextfileContents(languageCode, fileType, filename, fileText, optionalFileLocation, checkingOptions) { @@ -71,7 +71,7 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText parameterAssert(typeof plainText === 'string', `cPT ourCheckPlainText: 'plainText' parameter should be a string not a '${typeof plainText}'`); parameterAssert(checkingOptions !== undefined, "cPT ourCheckPlainText: 'checkingOptions' parameter should be defined"); - const resultObject = checkPlainText(textType, textFilename, plainText, givenLocation, checkingOptions); + const resultObject = checkPlainText(languageCode, textType, textFilename, plainText, givenLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field diff --git a/src/core/index.js b/src/core/index.js index 044abe3ac..80d7efb03 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -3,16 +3,20 @@ export * from './utilities'; export * from './getApi'; export * from './text-handling-functions'; -export * from './annotation-row-check'; -export * from './annotation-table-check'; export * from './field-text-check'; export * from './file-text-check'; export * from './markdown-text-check'; export * from './markdown-file-contents-check'; export * from './manifest-text-check'; +export * from './notes-tsv7-row-check'; +export * from './notes-tsv7-table-check'; export * from './plain-text-check'; +export * from './questions-tsv5-row-check'; +export * from './questions-tsv5-table-check'; export * from './tn-links-check'; -export * from './tn-table-row-check'; -export * from './tn-table-text-check'; +export * from './tn-tsv9-row-check'; +export * from './tn-tsv9-table-check'; +export * from './twl-tsv6-row-check'; +export * from './twl-tsv6-table-check'; export * from './usfm-text-check'; export * from './yaml-text-check'; diff --git a/src/core/annotation-row-check.js b/src/core/notes-tsv7-row-check.js similarity index 67% rename from src/core/annotation-row-check.js rename to src/core/notes-tsv7-row-check.js index 5a4d909f6..b01da8a36 100644 --- a/src/core/annotation-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -8,10 +8,10 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const ANNOTATION_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.7'; +// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.7'; -const NUM_EXPECTED_ANNOTATION_TSV_FIELDS = 7; // so expects 6 tabs per line -const EXPECTED_ANNOTATION_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation'; +const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line +const EXPECTED_NOTES_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; const LC_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'; const LC_ALPHABET_PLUS_DIGITS = 'abcdefghijklmnopqrstuvwxyz0123456789'; @@ -24,7 +24,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * * @description - Checks one TSV data row of translation notes (TN2) * @param {string} languageCode - the language code, e.g., 'en' - * @param {string} annotationType - TN2, TQ2, TWL, SN, or SQ -- allows more specific checks + * @param {string} repoCode - TN2, or SN -- allows more specific checks * @param {string} line - the TSV line to be checked * @param {string} bookID - 3-character UPPERCASE USFM book identifier or 'OBS' * @param {string} givenC - chapter number or (for OBS) story number string @@ -33,12 +33,12 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * @param {Object} checkingOptions - may contain extractLength parameter * @return {Object} - containing noticeList */ -export async function checkAnnotationTSVDataRow(languageCode, annotationType, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { +export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { /* This function is only for checking one data row and the function doesn’t assume that it has any previous context. - TN2, TQ2, TWL, SN, or SQ - being translation or study notes, questions, or word-links. + TN2, or SN + being translation or study notes. bookID is a three-character UPPERCASE USFM book identifier or 'OBS' so givenC and givenV are usually chapter number and verse number @@ -48,23 +48,23 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li Returns an object containing the noticeList. */ - // functionLog(`checkAnnotationTSVDataRow(${languageCode}, ${annotationType}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); - parameterAssert(languageCode !== undefined, "checkAnnotationTSVDataRow: 'languageCode' parameter should be defined"); - parameterAssert(typeof languageCode === 'string', `checkAnnotationTSVDataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(line !== undefined, "checkAnnotationTSVDataRow: 'line' parameter should be defined"); - parameterAssert(typeof line === 'string', `checkAnnotationTSVDataRow: 'line' parameter should be a string not a '${typeof line}'`); - parameterAssert(bookID !== undefined, "checkAnnotationTSVDataRow: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkAnnotationTSVDataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkAnnotationTSVDataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkAnnotationTSVDataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkAnnotationTSVDataRow: '${bookID}' is not a valid USFM book identifier`); - // parameterAssert(givenC !== undefined, "checkAnnotationTSVDataRow: 'givenC' parameter should be defined"); - if (givenC) parameterAssert(typeof givenC === 'string', `checkAnnotationTSVDataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); - // parameterAssert(givenV !== undefined, "checkAnnotationTSVDataRow: 'givenV' parameter should be defined"); - if (givenV) parameterAssert(typeof givenV === 'string', `checkAnnotationTSVDataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); - parameterAssert(givenRowLocation !== undefined, "checkAnnotationTSVDataRow: 'givenRowLocation' parameter should be defined"); - parameterAssert(typeof givenRowLocation === 'string', `checkAnnotationTSVDataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); - parameterAssert(givenRowLocation.indexOf('true') === -1, "checkAnnotationTSVDataRow: 'givenRowLocation' parameter should not be 'true'"); + // functionLog(`checkNotesTSV7DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkNotesTSV7DataRow: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkNotesTSV7DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(line !== undefined, "checkNotesTSV7DataRow: 'line' parameter should be defined"); + parameterAssert(typeof line === 'string', `checkNotesTSV7DataRow: 'line' parameter should be a string not a '${typeof line}'`); + parameterAssert(bookID !== undefined, "checkNotesTSV7DataRow: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkNotesTSV7DataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkNotesTSV7DataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkNotesTSV7DataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesTSV7DataRow: '${bookID}' is not a valid USFM book identifier`); + // parameterAssert(givenC !== undefined, "checkNotesTSV7DataRow: 'givenC' parameter should be defined"); + if (givenC) parameterAssert(typeof givenC === 'string', `checkNotesTSV7DataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); + // parameterAssert(givenV !== undefined, "checkNotesTSV7DataRow: 'givenV' parameter should be defined"); + if (givenV) parameterAssert(typeof givenV === 'string', `checkNotesTSV7DataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); + parameterAssert(givenRowLocation !== undefined, "checkNotesTSV7DataRow: 'givenRowLocation' parameter should be defined"); + parameterAssert(typeof givenRowLocation === 'string', `checkNotesTSV7DataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); + parameterAssert(givenRowLocation.indexOf('true') === -1, "checkNotesTSV7DataRow: 'givenRowLocation' parameter should not be 'true'"); let ourRowLocation = givenRowLocation; if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; @@ -85,22 +85,22 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li * @param {string} extract - short extract from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkAnnotationTSVDataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); - parameterAssert(noticeObject.priority !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'priority' parameter should be defined"); - parameterAssert(typeof noticeObject.priority === 'number', `checkAnnotationTSVDataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); - parameterAssert(noticeObject.message !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'message' parameter should be defined"); - parameterAssert(typeof noticeObject.message === 'string', `checkAnnotationTSVDataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); - // parameterAssert(lineNumber !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'lineNumber' parameter should be defined"); - // parameterAssert(typeof lineNumber === 'number', `checkAnnotationTSVDataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); - // parameterAssert(characterIndex !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'characterIndex' parameter should be defined"); - if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkAnnotationTSVDataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkAnnotationTSVDataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); - parameterAssert(noticeObject.location !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'location' parameter should be defined"); - parameterAssert(typeof noticeObject.location === 'string', `checkAnnotationTSVDataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + // functionLog(`checkNotesTSV7DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + parameterAssert(noticeObject.priority !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `checkNotesTSV7DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `checkNotesTSV7DataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(lineNumber !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'lineNumber' parameter should be defined"); + // parameterAssert(typeof lineNumber === 'number', `checkNotesTSV7DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); + // parameterAssert(characterIndex !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkNotesTSV7DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(extract !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkNotesTSV7DataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + parameterAssert(noticeObject.location !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `checkNotesTSV7DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); // Also uses the given bookID,C,V, parameters from the main function call - // noticeObject.debugChain = noticeObject.debugChain ? `checkAnnotationTSVDataRow ${noticeObject.debugChain}` : `checkAnnotationTSVDataRow(${annotationType})`; + // noticeObject.debugChain = noticeObject.debugChain ? `checkNotesTSV7DataRow ${noticeObject.debugChain}` : `checkNotesTSV7DataRow(${repoCode})`; drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); } @@ -122,18 +122,18 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // We don’t currently use the allowedLinks parameter - // functionLog(`checkAnnotationTSVDataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Annotation', "checkAnnotationTSVDataRow ourMarkdownTextChecks: Only run this check on Annotations") - parameterAssert(fieldText !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(allowedLinks === true || allowedLinks === false, "checkAnnotationTSVDataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); - parameterAssert(rowLocation !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); - parameterAssert(typeof rowLocation === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkNotesTSV7DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Note', "checkNotesTSV7DataRow ourMarkdownTextChecks: Only run this check on Notes") + parameterAssert(fieldText !== undefined, "checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkNotesTSV7DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); @@ -171,19 +171,19 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // Updates the global list of notices - // functionLog(`checkAnnotationTSVDataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkAnnotationTSVDataRow ourCheckTextField: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkAnnotationTSVDataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkAnnotationTSVDataRow ourCheckTextField: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkAnnotationTSVDataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldText !== undefined, "checkAnnotationTSVDataRow ourCheckTextField: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkAnnotationTSVDataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(allowedLinks === true || allowedLinks === false, "checkAnnotationTSVDataRow ourCheckTextField: allowedLinks parameter must be either true or false"); - parameterAssert(rowLocation !== undefined, "checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be defined"); - parameterAssert(typeof rowLocation === 'string', `checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - - const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; + // functionLog(`checkNotesTSV7DataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourCheckTextField: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourCheckTextField: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkNotesTSV7DataRow ourCheckTextField: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkNotesTSV7DataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkNotesTSV7DataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkNotesTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkNotesTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const fieldType = fieldName === 'Note' ? 'markdown' : 'raw'; const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following @@ -204,14 +204,14 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // Updates the global list of notices - // functionLog(`checkAnnotationTSVDataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkNotesTSV7DataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const coqResultObject = await checkSupportReferenceInTA(fieldName, taLinkText, rowLocation, { ...checkingOptions, taRepoLanguageCode: languageCode, expectFullLink: true }); @@ -235,16 +235,16 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // Updates the global list of notices - // functionLog(`checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldText !== undefined, "checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(occurrence !== undefined, "checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); - parameterAssert(typeof occurrence === 'string', `checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(occurrence !== undefined, "checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); + parameterAssert(typeof occurrence === 'string', `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); @@ -266,14 +266,14 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // Updates the global list of notices - // functionLog(`checkAnnotationTSVDataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Annotation', `checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Annotation' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkAnnotationTSVDataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkNotesTSV7DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Note', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Note' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); @@ -309,8 +309,8 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // end of ourCheckTNLinksToOutside function - // Main code for checkAnnotationTSVDataRow function - if (line === EXPECTED_ANNOTATION_HEADING_LINE) // Assume it must be ok + // Main code for checkNotesTSV7DataRow function + if (line === EXPECTED_NOTES_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place let extractLength; @@ -336,15 +336,15 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } catch (tlcNCerror) { - addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkAnnotationTSVDataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); + addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); } } const haveGoodBookID = numChaptersThisBook !== undefined; let fields = line.split('\t'); let RIDSuggestion, SRSuggestion, QSuggestion, OSuggestion, ASuggestion; - if (fields.length === NUM_EXPECTED_ANNOTATION_TSV_FIELDS) { - const [reference, rowID, tags, supportReference, quote, occurrence, annotation] = fields; + if (fields.length === NUM_EXPECTED_NOTES_TSV_FIELDS) { + const [reference, rowID, tags, supportReference, quote, occurrence, note] = fields; // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; @@ -436,7 +436,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li if (supportReference.length) { // need to check TN2 against TA if (isWhitespace(supportReference)) addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation }); - else if (annotationType === 'TN2') { // More than just whitespace + else if (repoCode === 'TN2') { // More than just whitespace const supportReferenceArticlePart = supportReference.replace('rc://*/ta/man/translate/', ''); // debugLog("supportReferenceArticlePart", supportReferenceArticlePart); if (!supportReferenceArticlePart.startsWith('figs-') @@ -448,7 +448,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li SRSuggestion = ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, checkingOptions); if (checkingOptions?.disableAllLinkFetchingFlag !== true) await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, checkingOptions); - if (annotation.indexOf(supportReference) < 0) + if (note.indexOf(supportReference) < 0) addNoticePartial({ priority: 787, message: "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); } let characterIndex; @@ -469,7 +469,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); } else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (annotationType === 'TN2' && V !== 'intro' && occurrence !== '0') + if (repoCode === 'TN2' && V !== 'intro' && occurrence !== '0') addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); if (occurrence.length) { // This should usually be a digit @@ -493,33 +493,33 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li OSuggestion = '1'; } - if (annotation.length) { - if (annotation.indexOf('\u200B') >= 0) { - const charCount = countOccurrences(supportReference, '\u200B'); - addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + if (note.length) { + if (note.indexOf('\u200B') >= 0) { + const charCount = countOccurrences(note, '\u200B'); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Note', rowID, location: ourRowLocation }); } - if (isWhitespace(annotation)) - addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + if (isWhitespace(note)) + addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation }); else { // More than just whitespace - ASuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', annotation, true, ourRowLocation, checkingOptions); - await ourCheckTNLinksToOutside(rowID, 'Annotation', annotation, ourRowLocation, linkCheckingOptions); + ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', note, true, ourRowLocation, checkingOptions); + await ourCheckTNLinksToOutside(rowID, 'Note', note, ourRowLocation, linkCheckingOptions); let regexResultArray; - while ((regexResultArray = TA_REGEX.exec(annotation))) { + while ((regexResultArray = TA_REGEX.exec(note))) { // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) if (supportReference !== adjustedLink && V !== 'intro') { const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', extract: adjustedLink, location: ourRowLocation }); } } } } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (annotationType === 'TN2') - addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + if (repoCode === 'TN2') + addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Note', rowID, location: ourRowLocation }); - // 7 [reference, rowID, tags, supportReference, quote, occurrence, annotation] - const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${SRSuggestion === undefined ? supportReference : SRSuggestion}\t${QSuggestion === undefined ? quote : QSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${ASuggestion === undefined ? annotation : ASuggestion}`; + // 7 [reference, rowID, tags, supportReference, quote, occurrence, note] + const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${SRSuggestion === undefined ? supportReference : SRSuggestion}\t${QSuggestion === undefined ? quote : QSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${ASuggestion === undefined ? note : ASuggestion}`; if (suggestion !== line) { // debugLog(`Had annotation ${line}`); // debugLog(`Sug annotation ${suggestion}`); @@ -530,11 +530,11 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // Have a go at getting some of the first fields out of the row let rowID = '????'; try { rowID = fields[1]; } catch { } - addNoticePartial({ priority: 984, message: `Found wrong number of TSV fields (expected ${NUM_EXPECTED_ANNOTATION_TSV_FIELDS})`, details: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, rowID, location: ourRowLocation }); + addNoticePartial({ priority: 984, message: `Found wrong number of TSV fields (expected ${NUM_EXPECTED_NOTES_TSV_FIELDS})`, details: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, rowID, location: ourRowLocation }); } - // debugLog(` checkAnnotationTSVDataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); - // debugLog("checkAnnotationTSVDataRow result is", JSON.stringify(drResult)); + // debugLog(` checkNotesTSV7DataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkNotesTSV7DataRow result is", JSON.stringify(drResult)); return drResult; // object with noticeList and possibly suggestion only } -// end of checkAnnotationTSVDataRow function +// end of checkNotesTSV7DataRow function diff --git a/src/core/annotation-row-check.md b/src/core/notes-tsv7-row-check.md similarity index 96% rename from src/core/annotation-row-check.md rename to src/core/notes-tsv7-row-check.md index 9c8f50735..a89b1ba6d 100644 --- a/src/core/annotation-row-check.md +++ b/src/core/notes-tsv7-row-check.md @@ -11,12 +11,12 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkAnnotationTSVDataRow } from './annotation-row-check'; +import { checkNotesTSV7DataRow } from './notes-tsv7-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples const lineE = ""; -const lineH = "Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation"; +const lineH = "Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote"; const lineN = "Peace on Earth, good will to all men/people!"; const lineG = "2:3\tw3r5\t\t1\t\tThis is an optional note"; const lineB1 = "2:3\tw3r5\t\t1\t\t<br>Boo"; @@ -43,19 +43,19 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - annotationType: 'TN2', + repoCode: 'TN2', tableLineName : 'lineA9', tableLine : lineA9, bookID : 'GEN', C:'1', V:'2', givenLocation : 'that was supplied', } -function CheckAnnotationRow(props) { - const { languageCode, annotationType, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; +function CheckNotesRow(props) { + const { languageCode, repoCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkAnnotationTSVDataRow is an ASYNC function + // We need the following construction because checkNotesTSV7DataRow is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -63,7 +63,7 @@ function CheckAnnotationRow(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {tableLineName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkAnnotationTSVDataRow(languageCode, annotationType, tableLine, bookID, C, V, givenLocation, checkingOptions); + const rawResults = await checkNotesTSV7DataRow(languageCode, repoCode, tableLine, bookID, C, V, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableLineName}: "{tableLine.substr(0,256)}…"<br/><br/> @@ -74,7 +74,7 @@ function CheckAnnotationRow(props) { }, []); // end of useEffect part return results; -} // end of CheckAnnotationRow function +} // end of CheckNotesRow function -<CheckAnnotationRow data={data}/> +<CheckNotesRow data={data}/> ``` diff --git a/src/core/annotation-table-check.js b/src/core/notes-tsv7-table-check.js similarity index 82% rename from src/core/annotation-table-check.js rename to src/core/notes-tsv7-table-check.js index da5a1b088..1d170e684 100644 --- a/src/core/annotation-table-check.js +++ b/src/core/notes-tsv7-table-check.js @@ -1,17 +1,27 @@ import * as books from './books/books'; import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' -import { checkAnnotationTSVDataRow } from './annotation-row-check'; +import { checkNotesTSV7DataRow } from './notes-tsv7-row-check'; import { removeDisabledNotices } from './disabled-notices'; -import { parameterAssert } from './utilities'; +import { functionLog, parameterAssert } from './utilities'; -const ANNOTATION_TABLE_VALIDATOR_VERSION_STRING = '0.3.1'; +const NOTES_TABLE_VALIDATOR_VERSION_STRING = '0.3.1'; -const NUM_EXPECTED_ANNOTATION_TSV_FIELDS = 7; // so expects 6 tabs per line -const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation'; +const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line +const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; -export async function checkAnnotationRows(languageCode, annotationType, bookID, filename, tableText, givenLocation, checkingOptions) { +/** + * + * @param {string} languageCode + * @param {string} repoCode -- 'TN' or 'SN' + * @param {string} bookID + * @param {string} filename + * @param {string} tableText + * @param {string} givenLocation + * @param {Object} checkingOptions + */ +export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -20,16 +30,17 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, Returns a result object containing a successList and a noticeList */ - // functionLog(`checkAnnotationRows(${languageCode}, ${annotationType}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); - parameterAssert(languageCode !== undefined, "checkAnnotationRows: 'languageCode' parameter should be defined"); - parameterAssert(typeof languageCode === 'string', `checkAnnotationRows: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(bookID !== undefined, "checkAnnotationRows: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkAnnotationRows: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkAnnotationRows: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkAnnotationRows: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkAnnotationRows: '${bookID}' is not a valid USFM book identifier`); - parameterAssert(givenLocation !== undefined, "checkAnnotationRows: 'givenLocation' parameter should be defined"); - parameterAssert(typeof givenLocation === 'string', `checkAnnotationRows: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); + functionLog(`checkNotesTSV7Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkNotesTSV7Table: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkNotesTSV7Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode === 'TN' || repoCode === 'SN', `checkTWL_TSV6Table: repoCode expected 'TN' or 'SN' not '${repoCode}'`); + parameterAssert(bookID !== undefined, "checkNotesTSV7Table: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkNotesTSV7Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkNotesTSV7Table: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkNotesTSV7Table: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesTSV7Table: '${bookID}' is not a valid USFM book identifier`); + parameterAssert(givenLocation !== undefined, "checkNotesTSV7Table: 'givenLocation' parameter should be defined"); + parameterAssert(typeof givenLocation === 'string', `checkNotesTSV7Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -37,11 +48,11 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, const carResult = { successList: [], noticeList: [] }; function addSuccessMessage(successString) { - // functionLog(`checkAnnotationRows success: ${successString}`); + // functionLog(`checkNotesTSV7Table success: ${successString}`); carResult.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkAnnotationRows notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkNotesTSV7Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); @@ -57,8 +68,8 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - if (noticeObject.debugChain) noticeObject.debugChain = `checkAnnotationRows ${noticeObject.debugChain}`; - carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: annotationType }); + if (noticeObject.debugChain) noticeObject.debugChain = `checkNotesTSV7Table ${noticeObject.debugChain}`; + carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: repoCode }); } @@ -98,7 +109,7 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, let rowIDList = [], uniqueRowList = []; let numVersesThisChapter = 0; for (let n = 0; n < lines.length; n++) { - // functionLog(`checkAnnotationRows checking line ${n}: ${JSON.stringify(lines[n])}`); + // functionLog(`checkNotesTSV7Table checking line ${n}: ${JSON.stringify(lines[n])}`); if (n === 0) { if (lines[0] === EXPECTED_TN_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); @@ -108,13 +119,13 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, else // not the header { let fields = lines[n].split('\t'); - if (fields.length === NUM_EXPECTED_ANNOTATION_TSV_FIELDS) { + if (fields.length === NUM_EXPECTED_NOTES_TSV_FIELDS) { // eslint-disable-next-line no-unused-vars - const [reference, rowID, tags, supportReference, quote, occurrence, annotation] = fields; + const [reference, rowID, tags, supportReference, quote, occurrence, note] = fields; const [C, V] = reference.split(':') // Use the row check to do most basic checks - const drResultObject = await checkAnnotationTSVDataRow(languageCode, annotationType, lines[n], bookID, C, V, ourLocation, checkingOptions); + const drResultObject = await checkNotesTSV7DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); @@ -226,13 +237,13 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_ANNOTATION_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_NOTES_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } if (!checkingOptions?.suppressNoticeDisablingFlag) { - // functionLog(`checkAnnotationRows: calling removeDisabledNotices(${carResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); + // functionLog(`checkNotesTSV7Table: calling removeDisabledNotices(${carResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); carResult.noticeList = removeDisabledNotices(carResult.noticeList); } @@ -242,11 +253,11 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); if (carResult.noticeList) - addSuccessMessage(`checkAnnotationRows v${ANNOTATION_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkNotesTSV7Table v${NOTES_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); else - addSuccessMessage(`No errors or warnings found by checkAnnotationRows v${ANNOTATION_TABLE_VALIDATOR_VERSION_STRING}`) - // debugLog(` checkAnnotationRows returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); - // debugLog("checkAnnotationRows result is", JSON.stringify(carResult)); + addSuccessMessage(`No errors or warnings found by checkNotesTSV7Table v${NOTES_TABLE_VALIDATOR_VERSION_STRING}`) + // debugLog(` checkNotesTSV7Table returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkNotesTSV7Table result is", JSON.stringify(carResult)); return carResult; } -// end of checkAnnotationRows function +// end of checkNotesTSV7Table function diff --git a/src/core/annotation-table-check.md b/src/core/notes-tsv7-table-check.md similarity index 95% rename from src/core/annotation-table-check.md rename to src/core/notes-tsv7-table-check.md index 8eb48d505..fa96612be 100644 --- a/src/core/annotation-table-check.md +++ b/src/core/notes-tsv7-table-check.md @@ -11,11 +11,11 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkAnnotationRows } from './annotation-table-check'; +import { checkNotesTSV7Table } from './notes-tsv7-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Text samples -const textA = `Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation +const textA = `Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote 2:3\tw3r5\t\t\t\t1\t<br>Boo 99:3\tw3r5\t\t\t\t1\tBad chapter number 2:boo\tw3r5\t\t\t\t1\tBad verse number @@ -25,7 +25,7 @@ const textA = `Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotat 2:3\tw3r5\t\t\t\t17\tNote7 2:3\tw3r5\t\t\tBad ellipse...\t1\tNote8 2:3\tw3r5\t\t\t\t1\t<br>Boo hoo,, lost my shoe !`; -const textG = `Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation +const textG = `Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote front:intro\td9wn\t\t\t\t0\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; const lineA2 = "1:intro\tzb6f\t\t\t\t0\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist. 1:1\tf2mg\t\t\t0\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story. @@ -40,7 +40,7 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - annotationType: 'TN2', + repoCode: 'TN2', tableTextName : 'textG', tableText : textG, bookID : 'GEN', @@ -48,20 +48,20 @@ const data = { givenLocation : 'that was supplied', } -function CheckAnnotationRows(props) { - const { languageCode, annotationType, bookID, filename, tableText, tableTextName, givenLocation } = props.data; +function checkNotesTSV7Table(props) { + const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkAnnotationRows is an ASYNC function + // We need the following construction because checkNotesTSV7Table is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 (async () => { // Display our "waiting" message - setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {annotationType} for {tableTextName} <b>{bookID}</b>…</p>); + setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {repoCode} for {tableTextName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkAnnotationRows(languageCode, annotationType, bookID, filename, tableText, givenLocation, checkingOptions); + const rawResults = await checkNotesTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> @@ -72,7 +72,7 @@ function CheckAnnotationRows(props) { }, []); // end of useEffect part return results; -} // end of CheckAnnotationRows function +} // end of checkNotesTSV7Table function -<CheckAnnotationRows data={data}/> +<checkNotesTSV7Table data={data}/> ``` diff --git a/src/core/plain-text-check.js b/src/core/plain-text-check.js index a0fce2bd3..41f66805c 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -4,7 +4,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { parameterAssert } from './utilities'; -const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.3.12'; +const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.4.0'; /** @@ -15,15 +15,18 @@ const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.3.12'; * @param {string} givenLocation * @param {Object} checkingOptions */ -export function checkPlainText(textType, textName, plainText, givenLocation, checkingOptions) { +export function checkPlainText(languageCode, textType, textName, plainText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire text, i.e., all lines. It is used in checkFileContents() in book-package-check.js TODO: Should languageCode also be a parameter here? (affects other programs using the API) - + Returns a result object containing a successList and a noticeList */ // functionLog(`checkPlainText(${textName}, (${plainText.length} chars), ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkPlainText: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkPlainText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(languageCode !== 'markdown' && languageCode !== 'USFM' && languageCode !== 'YAML' && languageCode !== 'text' && languageCode !== 'raw' && languageCode !== 'unfoldingWord', `checkPlainText: 'languageCode' ${languageCode} parameter should be not be '${languageCode}'`); parameterAssert(textType !== undefined, "checkPlainText: 'textType' parameter should be defined"); parameterAssert(typeof textType === 'string', `checkPlainText: 'textType' parameter should be a string not a '${typeof textType}': ${textType}`); parameterAssert(textType === 'markdown' || textType === 'USFM' || textType === 'YAML' || textType === 'text' || textType === 'raw', `checkPlainText: unrecognised 'textType' parameter: '${textType}'`); @@ -73,7 +76,6 @@ export function checkPlainText(textType, textName, plainText, givenLocation, che cptResult.noticeList.push(noticeObject); } - const languageCode = ''; function ourCheckTextField(lineNumber, fieldText, allowedLinks, optionalFieldLocation, checkingOptions) { /** * @description - checks the given text field and processes the returned results diff --git a/src/core/plain-text-check.md b/src/core/plain-text-check.md index a4c89fc60..e2c567ab6 100644 --- a/src/core/plain-text-check.md +++ b/src/core/plain-text-check.md @@ -43,7 +43,7 @@ const chosenText = textSB; const chosenTextName = 'textSB'; const checkingOptions = {}; -const rawResults = checkPlainText('raw', chosenTextName, chosenText, 'that was supplied', checkingOptions); +const rawResults = checkPlainText('en', 'raw', chosenTextName, chosenText, 'that was supplied', checkingOptions); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done plain text checks"]; diff --git a/src/core/questions-tsv5-row-check.js b/src/core/questions-tsv5-row-check.js new file mode 100644 index 000000000..13c3633de --- /dev/null +++ b/src/core/questions-tsv5-row-check.js @@ -0,0 +1,505 @@ +import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' +import * as books from './books/books'; +// import { checkTextField } from './field-text-check'; +import { checkMarkdownText } from './markdown-text-check'; +// import { checkSupportReferenceInTA } from './ta-reference-check'; +import { checkTNLinksToOutside } from './tn-links-check'; +// import { checkOriginalLanguageQuote } from './orig-quote-check'; +import { parameterAssert } from './utilities'; + + +// const QUESTIONS_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.0'; + +const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 5; // so expects 4 tabs per line +const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse'; + +const LC_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'; +const LC_ALPHABET_PLUS_DIGITS = 'abcdefghijklmnopqrstuvwxyz0123456789'; +const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz0123456789-'; + +// const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\]', 'g'); + + +/** + * + * @description - Checks one TSV data row of translation notes (TN2) + * @param {string} languageCode - the language code, e.g., 'en' + * @param {string} repoCode - TN2, TQ2, TWL, SN, or SQ -- allows more specific checks + * @param {string} line - the TSV line to be checked + * @param {string} bookID - 3-character UPPERCASE USFM book identifier or 'OBS' + * @param {string} givenC - chapter number or (for OBS) story number string + * @param {string} givenV - verse number or (for OBS) frame number string + * @param {string} givenRowLocation - description of where the line is located + * @param {Object} checkingOptions - may contain extractLength parameter + * @return {Object} - containing noticeList + */ +export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { + /* This function is only for checking one data row + and the function doesn’t assume that it has any previous context. + + TN2, TQ2, TWL, SN, or SQ + being translation or study notes, questions, or word-links. + + bookID is a three-character UPPERCASE USFM book identifier or 'OBS' + so givenC and givenV are usually chapter number and verse number + but can be story number and frame number for OBS. + + It’s designed to be able to quickly show errors for a single row being displayed/edited. + + Returns an object containing the noticeList. + */ + // functionLog(`checkQuestionsTSV5DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkQuestionsTSV5DataRow: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV5DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(line !== undefined, "checkQuestionsTSV5DataRow: 'line' parameter should be defined"); + parameterAssert(typeof line === 'string', `checkQuestionsTSV5DataRow: 'line' parameter should be a string not a '${typeof line}'`); + parameterAssert(bookID !== undefined, "checkQuestionsTSV5DataRow: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkQuestionsTSV5DataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkQuestionsTSV5DataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkQuestionsTSV5DataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkQuestionsTSV5DataRow: '${bookID}' is not a valid USFM book identifier`); + // parameterAssert(givenC !== undefined, "checkQuestionsTSV5DataRow: 'givenC' parameter should be defined"); + if (givenC) parameterAssert(typeof givenC === 'string', `checkQuestionsTSV5DataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); + // parameterAssert(givenV !== undefined, "checkQuestionsTSV5DataRow: 'givenV' parameter should be defined"); + if (givenV) parameterAssert(typeof givenV === 'string', `checkQuestionsTSV5DataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); + parameterAssert(givenRowLocation !== undefined, "checkQuestionsTSV5DataRow: 'givenRowLocation' parameter should be defined"); + parameterAssert(typeof givenRowLocation === 'string', `checkQuestionsTSV5DataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); + parameterAssert(givenRowLocation.indexOf('true') === -1, "checkQuestionsTSV5DataRow: 'givenRowLocation' parameter should not be 'true'"); + + let ourRowLocation = givenRowLocation; + if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; + + const linkCheckingOptions = { ...checkingOptions }; + linkCheckingOptions.taRepoLanguageCode = languageCode; + + let drResult = { noticeList: [] }; + + function addNoticePartial(noticeObject) { + /** + * @description - adds a new notice entry, adding bookID,C,V to the given fields + * @param {Number} priority - notice priority from 1 (lowest) to 999 (highest) + * @param {string} message - the text of the notice message + * @param {string} rowID - 4-character row ID field + * @param {Number} lineNumber - one-based line number + * @param {Number} characterIndex - zero-based index of where the issue occurs in the line + * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} location - description of where the issue is located + */ + // functionLog(`checkQuestionsTSV5DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + parameterAssert(noticeObject.priority !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(lineNumber !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'lineNumber' parameter should be defined"); + // parameterAssert(typeof lineNumber === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); + // parameterAssert(characterIndex !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(extract !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + parameterAssert(noticeObject.location !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + // Also uses the given bookID,C,V, parameters from the main function call + // noticeObject.debugChain = noticeObject.debugChain ? `checkQuestionsTSV5DataRow ${noticeObject.debugChain}` : `checkQuestionsTSV5DataRow(${repoCode})`; + drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); + } + + async function ourMarkdownTextChecks(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { + /** + * @description - checks the given markdown field and processes the returned results + * @param {string} rowID - 4-character row ID field + * @param {string} fieldName - name of the field being checked + * @param {string} fieldText - the actual text of the field being checked + * @param {} allowedLinks - true if links are allowed in the field, otherwise false + * @param {string} rowLocation - description of where the line is located + * @param {Object} checkingOptions - parameters that might affect the check + */ + // Does markdown checks for small errors like leading/trailing spaces, etc. + + // We assume that checking for compulsory fields is done elsewhere + + // Updates the global list of notices + + // We don’t currently use the allowedLinks parameter + + // functionLog(`checkQuestionsTSV5DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Annotation', "checkQuestionsTSV5DataRow ourMarkdownTextChecks: Only run this check on Annotations") + parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(cmtResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of omtcResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); + // NOTE: Ellipses in Annotation have the normal meaning + // not like the specialised meaning in the Quote snippet fields + if (noticeEntry.priority !== 178 && noticeEntry.priority !== 179 // unexpected space after ellipse, ellipse after space + && !noticeEntry.message.startsWith("Unexpected … character after space") // 191 + ) + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + return omtcResultObject.suggestion; // There may or may not be one! + } + // end of ourMarkdownTextChecks function + + // function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { + // /** + // * @description - checks the given text field and processes the returned results + // * @param {string} rowID - 4-character row ID field + // * @param {string} fieldName - name of the field being checked + // * @param {string} fieldText - the actual text of the field being checked + // * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false + // * @param {string} rowLocation - description of where the line is located + // * @param {Object} checkingOptions - parameters that might affect the check + // */ + // // Does basic checks for small errors like leading/trailing spaces, etc. + + // // We assume that checking for compulsory fields is done elsewhere + + // // Updates the global list of notices + + // // functionLog(`checkQuestionsTSV5DataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'fieldText' parameter should be defined"); + // parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + // parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV5DataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + // parameterAssert(rowLocation !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + // parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + // const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; + // const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + + // // Choose only ONE of the following + // // This is the fast way of append the results from this field + // // result.noticeList = result.noticeList.concat(dbtcResultObject.noticeList); + // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // // process results line by line + // for (const noticeEntry of octfResultObject.noticeList) { + // // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); + // addNoticePartial({ ...noticeEntry, rowID, fieldName }); + // } + // return octfResultObject.suggestion; // There may or may not be one! + // } + // // end of ourCheckTextField function + + // async function ourCheckSupportReferenceInTA(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // // Checks that the TA reference can be found + + // // Updates the global list of notices + + // // functionLog(`checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); + // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + // const coqResultObject = await checkSupportReferenceInTA(fieldName, taLinkText, rowLocation, { ...checkingOptions, taRepoLanguageCode: languageCode, expectFullLink: true }); + + // // Choose only ONE of the following + // // This is the fast way of append the results from this field + // // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // // process results line by line + // for (const noticeEntry of coqResultObject.noticeList) { + // // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckSupportReferenceInTA notice length=${Object.keys(noticeEntry).length}`); + // addNoticePartial({ ...noticeEntry, rowID, fieldName }); + // } + // } + // // end of ourCheckSupportReferenceInTA function + + + // async function ourCheckTNOriginalLanguageQuote(rowID, fieldName, fieldText, occurrence, rowLocation, checkingOptions) { + // // Checks that the Hebrew/Greek quote can be found in the original texts + + // // Uses the bookID,C,V values from the main function call + + // // Updates the global list of notices + + // // functionLog(`checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); + // parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + // parameterAssert(occurrence !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); + // parameterAssert(typeof occurrence === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); + // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + // const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + + // // Choose only ONE of the following + // // This is the fast way of append the results from this field + // // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // // process results line by line + // for (const noticeEntry of coqResultObject.noticeList) { + // // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); + // addNoticePartial({ ...noticeEntry, rowID, fieldName }); + // } + // } + // // end of ourCheckTNOriginalLanguageQuote function + + + async function ourCheckTNLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // Checks that the TA/TW/Bible reference can be found + + // Updates the global list of notices + + // functionLog(`checkQuestionsTSV5DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Annotation', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Annotation' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + + const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + // debugLog("coqResultObject", JSON.stringify(coqResultObject)); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const coqNoticeEntry of coqResultObject.noticeList) { + if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is + else // For our direct checks, we add the repoCode as an extra value + addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); + } + // The following is needed coz we might be checking the linked TA and/or TW articles + if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) + if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; + else drResult.checkedFileCount = coqResultObject.checkedFileCount; + if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) + if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; + else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; + if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of coqResultObject.checkedRepoNames) + try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } + catch { drResult.checkedRepoNames = [checkedRepoName]; } + if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) + try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } + catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } + // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); + } + // end of ourCheckTNLinksToOutside function + + + // Main code for checkQuestionsTSV5DataRow function + if (line === EXPECTED_QUESTIONS_HEADING_LINE) // Assume it must be ok + return drResult; // We can’t detect if it’s in the wrong place + + let extractLength; + try { + extractLength = checkingOptions?.extractLength; + } catch (tlcELerror) { } + if (typeof extractLength !== 'number' || isNaN(extractLength)) { + extractLength = DEFAULT_EXTRACT_LENGTH; + // debugLog(`Using default extractLength=${extractLength}`); + } + // else + // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); + // const halfLength = Math.floor(extractLength / 2); // rounded down + // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + + const lowercaseBookID = bookID.toLowerCase(); + let numChaptersThisBook; + if (bookID === 'OBS') + numChaptersThisBook = 50; // There's 50 Open Bible Stories + else { + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in question-row-check"); + try { + numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; + } catch (tlcNCerror) { + addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); + } + } + const haveGoodBookID = numChaptersThisBook !== undefined; + + let fields = line.split('\t'); + let RIDSuggestion, QSuggestion, ASuggestion; + if (fields.length === NUM_EXPECTED_QUESTIONS_TSV_FIELDS) { + const [reference, rowID, tags, question, answer] = fields; + // let withString = ` with '${rowID}'${inString}`; + // let CV_withString = ` ${C}:${V}${withString}`; + // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; + + // Check the fields one-by-one + const [C, V] = reference.split(':'); + let numVersesThisChapter, haveGoodChapterNumber; + if (C.length) { + if (C !== givenC) + addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation }); + if (C === 'front') { } + else if (/^\d+$/.test(C)) { + let intC = Number(C); + if (intC === 0) { + addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + haveGoodChapterNumber = false; + } + // TODO: Does this next section need rewriting (see verse check below)??? + else if (intC > numChaptersThisBook) { + addNoticePartial({ priority: 823, message: `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + haveGoodChapterNumber = false; + } + if (lowercaseBookID === 'obs') + numVersesThisChapter = 99; // Set to maximum expected number of frames + else { + try { + numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); + haveGoodChapterNumber = true; + } catch (tlcNVerror) { + if (!haveGoodBookID) + // addNoticePartial({priority:500, "Invalid chapter number", rowLocation); + // else + addNoticePartial({ priority: 822, message: "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + haveGoodChapterNumber = false; + } + } + } + else + addNoticePartial({ priority: 821, message: "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + } + else + addNoticePartial({ priority: 820, message: "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:${V}${ourRowLocation}` }); + + if (V.length) { + if (V !== givenV) + addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + if (bookID === 'OBS' || V === 'intro') { } + else if (/^\d+$/.test(V)) { + let intV = Number(V); + if (intV === 0 && bookID !== 'PSA') // Psalms have \d as verse zero + addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + else { + if (haveGoodChapterNumber) { + if (intV > numVersesThisChapter) + addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + } else + addNoticePartial({ priority: 812, message: "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation }); + } + } + else + addNoticePartial({ priority: 811, message: "Bad verse number", rowID, fieldName: 'Reference', location: ` '${V}'${ourRowLocation}` }); + } + else + addNoticePartial({ priority: 810, message: "Missing verse number", rowID, fieldName: 'Reference', location: ` after ${C}:?${ourRowLocation}` }); + + if (!rowID.length) + addNoticePartial({ priority: 779, message: "Missing row ID field", fieldName: 'Reference', location: ourRowLocation }); + else { + if (rowID.length !== 4) { + addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + if (rowID.length > 4) RIDSuggestion = rowID.substring(0, 5); + else { // must be < 4 + RIDSuggestion = rowID; + while (RIDSuggestion.length < 4) RIDSuggestion += LC_ALPHABET_PLUS_DIGITS[Math.floor(Math.random() * LC_ALPHABET_PLUS_DIGITS.length)];; + } + } else if (LC_ALPHABET.indexOf(rowID[0]) < 0) + addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + else if (LC_ALPHABET_PLUS_DIGITS.indexOf(rowID[3]) < 0) + addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[1]) < 0) + addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation }); + else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[2]) < 0) + addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation }); + } + + if (tags.length) + ; + + if (question.length) { + if (question.indexOf('\u200B') >= 0) { + const charCount = countOccurrences(question, '\u200B'); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + } + if (isWhitespace(question)) + addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + else { // More than just whitespace + ASuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', question, true, ourRowLocation, checkingOptions); + await ourCheckTNLinksToOutside(rowID, 'Annotation', question, ourRowLocation, linkCheckingOptions); + // let regexResultArray; + // while ((regexResultArray = TA_REGEX.exec(question))) { + // // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); + // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) + // if (supportReference !== adjustedLink && V !== 'intro') { + // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" + // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + // } + // } + } + } + else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? + if (repoCode === 'TN2') + addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + + if (answer.length) { + if (answer.indexOf('\u200B') >= 0) { + const charCount = countOccurrences(answer, '\u200B'); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + } + if (isWhitespace(answer)) + addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + else { // More than just whitespace + ASuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', answer, true, ourRowLocation, checkingOptions); + await ourCheckTNLinksToOutside(rowID, 'Annotation', answer, ourRowLocation, linkCheckingOptions); + // let regexResultArray; + // while ((regexResultArray = TA_REGEX.exec(answer))) { + // // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); + // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) + // if (supportReference !== adjustedLink && V !== 'intro') { + // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" + // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + // } + // } + } + } + else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? + if (repoCode === 'TN2') + addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + + // 7 [reference, rowID, tags, question, answer] + const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${QSuggestion === undefined ? question : QSuggestion}\t${ASuggestion === undefined ? answer : ASuggestion}`; + if (suggestion !== line) { + // debugLog(`Had question ${line}`); + // debugLog(`Sug question ${suggestion}`); + drResult.suggestion = suggestion; + } + + } else { // wrong number of fields in the row + // Have a go at getting some of the first fields out of the row + let rowID = '????'; + try { rowID = fields[1]; } catch { } + addNoticePartial({ priority: 984, message: `Found wrong number of TSV fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, details: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, rowID, location: ourRowLocation }); + } + + // debugLog(` checkQuestionsTSV5DataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkQuestionsTSV5DataRow result is", JSON.stringify(drResult)); + return drResult; // object with noticeList and possibly suggestion only +} +// end of checkQuestionsTSV5DataRow function diff --git a/src/core/questions-tsv5-row-check.md b/src/core/questions-tsv5-row-check.md new file mode 100644 index 000000000..cd5a336f1 --- /dev/null +++ b/src/core/questions-tsv5-row-check.md @@ -0,0 +1,80 @@ +## Annotation (TSV) Row Check Sandbox + +This function checks one tab-separated line for typical formatting errors. + +It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) + +These raw notice components can then be filtered and/or sorted as required by the calling program, and then divided into a list of errors and a list of warnings or whatever as desired. + +```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + +import React, { useState, useEffect } from 'react'; +import { checkQuestionsTSV7DataRow } from './questions-tsv5-row-check'; +import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; + +// Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples +const lineE = ""; +const lineH = "Reference\tID\tTags\tQuestion\tResponse"; +const lineN = "Peace on Earth, good will to all men/people!"; +const lineG = "2:3\tw3r5\t\t1\t\tThis is an optional note"; +const lineB1 = "2:3\tw3r5\t\t1\t\t<br>Boo"; +const lineB2 = "99:3\tw3r5\t\t1\t\tBoo"; +const lineB3 = "2:boo\tw3r5\t\t1\t\tNote3"; +const lineB4 = "2:3\tw3r5q\t\t1\t\tNote4"; +const lineB5 = "2:3\tw3r5\tLaugh\t\t1\t\tNote5"; +const lineB6 = "2:3\tw3r5\t\tCan’t remember\t1\t\tNote6"; +const lineB7 = "2:3\tw3r5\t\t17\t\tNote7"; +const lineB8 = "2:3\tw3r5\t\t1\tBad ellipse...\tNote8"; +const lineB9 = "2:3\tw3r\t\t1\t\t<br>Boo hoo,, lost my shoe !"; +const lineV = "200:9\tW-3r5\tLaugh\t\t17\tBad ellipse...\t<br>Boo hoo,,<br> lost my shoe !"; +const lineA1 = "front:intro\td9wn\t\t\t0\t\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; +const lineA2 = "1:intro\tzb6f\t\t\t0\t\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist."; +const lineA3 = "1:1\tf2mg\t\t0\t\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story."; +const lineA4 = "1:3\td7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA5 = "1:5\tjc2d\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. (See: [[rc://en/ta/man/translate/figs-merism]])"; +const lineA6 = "1:6\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA7 = "1:8\tss9r\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://en/ta/man/translate/figs-merism]])"; +const lineA8 = "1:9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://en/ta/man/translate/figs-activepassive]] and [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA9 = "1:9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md)."; + +const data = { + // You can choose any of the above lines here + // (to demonstrate differing results) + languageCode: 'en', + repoCode: 'TN2', + tableLineName : 'lineA9', + tableLine : lineA9, + bookID : 'GEN', C:'1', V:'2', + givenLocation : 'that was supplied', +} + +function CheckQuestionsRow(props) { + const { languageCode, repoCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; + + const [results, setResults] = useState(null); + + // We need the following construction because checkQuestionsTSV7DataRow is an ASYNC function + useEffect(() => { + // Use an IIFE (Immediately Invoked Function Expression) + // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 + (async () => { + // Display our "waiting" message + setResults(<p style={{ color: 'magenta' }}>Checking {tableLineName} <b>{bookID}</b>…</p>); + const checkingOptions = {}; + const rawResults = await checkQuestionsTSV7DataRow(languageCode, repoCode, tableLine, bookID, C, V, givenLocation, checkingOptions); + setResults( + <div> + <b>Check</b> {tableLineName}: "{tableLine.substr(0,256)}…"<br/><br/> + <RenderRawResults results={rawResults} /> + </div> + ); + })(); // end of async part in unnamedFunction + }, []); // end of useEffect part + + return results; +} // end of CheckQuestionsRow function + +<CheckQuestionsRow data={data}/> +``` diff --git a/src/core/questions-tsv5-table-check.js b/src/core/questions-tsv5-table-check.js new file mode 100644 index 000000000..4abb03bfe --- /dev/null +++ b/src/core/questions-tsv5-table-check.js @@ -0,0 +1,263 @@ +import * as books from './books/books'; +import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { checkQuestionsTSV5DataRow } from './questions-tsv5-row-check'; +import { removeDisabledNotices } from './disabled-notices'; +import { functionLog, parameterAssert } from './utilities'; + + +const QUESTIONS_TABLE_VALIDATOR_VERSION_STRING = '0.1.0'; + +const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 5; // so expects 4 tabs per line +const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse'; + + +/** + * + * @param {string} languageCode + * @param {string} repoCode -- 'TQ' or 'SQ' + * @param {string} bookID + * @param {string} filename + * @param {string} tableText + * @param {string} givenLocation + * @param {Object} checkingOptions + */ +export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions) { + /* This function is optimised for checking the entire file, i.e., all rows. + + It also has the advantage of being able to compare one row with the previous one. + + bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. + + Returns a result object containing a successList and a noticeList + */ + functionLog(`checkQuestionsTSV5Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkQuestionsTSV5Table: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV5Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode === 'TQ' || repoCode === 'SQ', `checkTWL_TSV6Table: repoCode expected 'TQ' or 'SQ' not '${repoCode}'`); + parameterAssert(bookID !== undefined, "checkQuestionsTSV5Table: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkQuestionsTSV5Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkQuestionsTSV5Table: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkQuestionsTSV5Table: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkQuestionsTSV5Table: '${bookID}' is not a valid USFM book identifier`); + parameterAssert(givenLocation !== undefined, "checkQuestionsTSV5Table: 'givenLocation' parameter should be defined"); + parameterAssert(typeof givenLocation === 'string', `checkQuestionsTSV5Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); + + let ourLocation = givenLocation; + if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; + + const carResult = { successList: [], noticeList: [] }; + + function addSuccessMessage(successString) { + // functionLog(`checkQuestionsTSV5Table success: ${successString}`); + carResult.successList.push(successString); + } + function addNoticePartial(noticeObject) { + // functionLog(`checkQuestionsTSV5Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `TSV addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(C !== undefined, "ATSV addNoticePartial: 'C' parameter should be defined"); + if (noticeObject.C) parameterAssert(typeof noticeObject.C === 'string', `TSV addNoticePartial: 'C' parameter should be a string not a '${typeof noticeObject.C}': ${noticeObject.C}`); + // parameterAssert(V !== undefined, "ATSV addNoticePartial: 'V' parameter should be defined"); + if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `TSV addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); + // parameterAssert(characterIndex !== undefined, "ATSV addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `TSV addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(extract !== undefined, "ATSV addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + if (noticeObject.debugChain) noticeObject.debugChain = `checkQuestionsTSV5Table ${noticeObject.debugChain}`; + carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: repoCode }); + } + + + let extractLength; + try { + extractLength = checkingOptions?.extractLength; + } catch (ttcError) { } + if (typeof extractLength !== 'number' || isNaN(extractLength)) { + extractLength = DEFAULT_EXTRACT_LENGTH; + // debugLog(`Using default extractLength=${extractLength}`); + } + // else + // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); + // const halfLength = Math.floor(extractLength / 2); // rounded down + // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + + let lowercaseBookID = bookID.toLowerCase(); + let numChaptersThisBook = 0; + if (bookID === 'OBS') + numChaptersThisBook = 50; // There's 50 Open Bible Stories + else { + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-table-check"); + try { + numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; + } + catch { + if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. + addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + } + } + + let lines = tableText.split('\n'); + // debugLog(` '${location}' has ${lines.length.toLocaleString()} total lines (expecting ${NUM_EXPECTED_TN_FIELDS} fields in each line)`); + + let lastC = '', lastV = ''; + let rowIDList = [], uniqueRowList = []; + let numVersesThisChapter = 0; + for (let n = 0; n < lines.length; n++) { + // functionLog(`checkQuestionsTSV5Table checking line ${n}: ${JSON.stringify(lines[n])}`); + if (n === 0) { + if (lines[0] === EXPECTED_QUESTIONS_HEADING_LINE) + addSuccessMessage(`Checked TSV header ${ourLocation}`); + else + addNoticePartial({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); + } + else // not the header + { + let fields = lines[n].split('\t'); + if (fields.length === NUM_EXPECTED_QUESTIONS_TSV_FIELDS) { + // eslint-disable-next-line no-unused-vars + const [reference, rowID, tags, question, answer] = fields; + const [C, V] = reference.split(':') + + // Use the row check to do most basic checks + const drResultObject = await checkQuestionsTSV5DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(firstResult.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const drNoticeEntry of drResultObject.noticeList) + if (drNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + carResult.noticeList.push(drNoticeEntry); // Just copy the complete notice as is + else + addNoticePartial({ ...drNoticeEntry, lineNumber: n + 1 }); + // The following is needed coz we might be checking the linked TA and/or TW articles + if (drResultObject.checkedFileCount && drResultObject.checkedFileCount > 0) + if (typeof carResult.checkedFileCount === 'number') carResult.checkedFileCount += drResultObject.checkedFileCount; + else carResult.checkedFileCount = drResultObject.checkedFileCount; + if (drResultObject.checkedFilesizes && drResultObject.checkedFilesizes > 0) + if (typeof carResult.checkedFilesizes === 'number') carResult.checkedFilesizes += drResultObject.checkedFilesizes; + else carResult.checkedFilesizes = drResultObject.checkedFilesizes; + if (drResultObject.checkedRepoNames && drResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of drResultObject.checkedRepoNames) + try { if (carResult.checkedRepoNames.indexOf(checkedRepoName) < 0) carResult.checkedRepoNames.push(checkedRepoName); } + catch { carResult.checkedRepoNames = [checkedRepoName]; } + if (drResultObject.checkedFilenameExtensions && drResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of drResultObject.checkedFilenameExtensions) + try { if (carResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) carResult.checkedFilenameExtensions.push(checkedFilenameExtension); } + catch { carResult.checkedFilenameExtensions = [checkedFilenameExtension]; } + // if (ttResult.checkedFilenameExtensions) userLog("ttResult", JSON.stringify(ttResult)); + + // So here we only have to check against the previous and next fields for out-of-order problems and duplicate problems + if (C !== lastC || V !== lastV) { + rowIDList = []; // ID's only need to be unique within each verse + uniqueRowList = []; // Same for these + } + + // TODO: Check if we need this at all (even though tC 3.0 can’t display these "duplicate" notes) + // Check for duplicate notes + const uniqueID = C + V + question + answer; // This combination should not be repeated + // if (uniqueRowList.includes(uniqueID)) + // addNoticePartial({ priority: 880, C, V, message: `Duplicate note`, rowID, lineNumber: n + 1, location: ourLocation }); + // if (uniqueRowList.includes(uniqueID)) + // addNoticePartial({ priority: 80, C, V, message: `Note: tC 3.0 won’t display duplicate note`, rowID, lineNumber: n + 1, location: ourLocation }); + uniqueRowList.push(uniqueID); + + if (C) { + if (C === 'front') { } + else if (/^\d+$/.test(C)) { + let intC = Number(C); + if (C !== lastC) + if (lowercaseBookID === 'obs') + numVersesThisChapter = 99; // Set to maximum expected number of frames + else + numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); + if (intC === 0) + addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + if (intC > numChaptersThisBook) + addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + if (/^\d+$/.test(lastC)) { + let lastintC = Number(lastC); + if (intC < lastintC) + addNoticePartial({ priority: 736, C, V, message: "Receding chapter number", details: `'${C}' after '${lastC}'`, rowID, lineNumber: n + 1, location: ourLocation }); + else if (intC > lastintC + 1) + addNoticePartial({ priority: 735, C, V, message: "Advancing chapter number", details: `'${C}' after '${lastC}'`.rowID, lineNumber: n + 1, location: ourLocation }); + } + } + else + addNoticePartial({ priority: 734, C, V, message: "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation }); + } + else + addNoticePartial({ priority: 739, C, V, message: "Missing chapter number", rowID, lineNumber: n + 1, location: ` after ${lastC}:${V}${ourLocation}` }); + + if (V) { + if (V === 'intro') { } + else if (/^\d+$/.test(V)) { + let intV = Number(V); + if (intV === 0 && bookID !== 'PSA') // Psalms have \d titles + addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + if (intV > numVersesThisChapter) + addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + if (/^\d+$/.test(lastV)) { + let lastintV = Number(lastV); + if (C === lastC && intV < lastintV) + addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + // else if (intV > lastintV + 1) + // addNoticePartial({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); + } + } + else + addNoticePartial({ priority: 738, C, V, message: "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation }); + + } + else + addNoticePartial({ priority: 790, C, V, message: "Missing verse number", rowID, lineNumber: n + 1, location: ` after ${C}:${lastV}${ourLocation}` }); + + if (rowID) { + if (rowIDList.includes(rowID)) + addNoticePartial({ priority: 729, C, V, message: `Duplicate '${rowID}' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation }); + } else + addNoticePartial({ priority: 730, C, V, message: "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation }); + + + lastC = C; lastV = V; + + } else // wrong number of fields in the row + // if (n === lines.length - 1) // it’s the last line + // userLog(` Line ${n}: Has ${fields.length} field(s) instead of ${NUM_EXPECTED_TN_FIELDS}: ${EXPECTED_QUESTIONS_HEADING_LINE.replace(/\t/g, ', ')}`); + // else + if (n !== lines.length - 1) { // it’s not the last line + // Have a go at getting some of the first fields out of the line + let reference = '?:?', C = '?', V = '?', rowID = '????'; + try { reference = fields[0]; } catch { } + try { rowID = fields[1]; } catch { } + try { [C, V] = reference.split(':'); } catch { } + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + } + } + } + + if (!checkingOptions?.suppressNoticeDisablingFlag) { + // functionLog(`checkQuestionsTSV5Table: calling removeDisabledNotices(${carResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); + carResult.noticeList = removeDisabledNotices(carResult.noticeList); + } + + if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 20) + && checkingOptions?.disableAllLinkFetchingFlag) + addNoticePartial({ priority: 20, message: "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation }); + + addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); + if (carResult.noticeList) + addSuccessMessage(`checkQuestionsTSV5Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); + else + addSuccessMessage(`No errors or warnings found by checkQuestionsTSV5Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING}`) + // debugLog(` checkQuestionsTSV5Table returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkQuestionsTSV5Table result is", JSON.stringify(carResult)); + return carResult; +} +// end of checkQuestionsTSV5Table function diff --git a/src/core/questions-tsv5-table-check.md b/src/core/questions-tsv5-table-check.md new file mode 100644 index 000000000..1f84f41f7 --- /dev/null +++ b/src/core/questions-tsv5-table-check.md @@ -0,0 +1,78 @@ +## Annotation (TSV) Table Text Check Sandbox + +This function checks the given block of annotation (TSV) table lines for typical formatting errors. + +It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) + +These raw notice components can then be filtered and/or sorted as required by the calling program, and then divided into a list of errors and a list of warnings or whatever as desired. + +```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + +import React, { useState, useEffect } from 'react'; +import { checkNotesTSV7Table } from './questions-tsv5-table-check'; +import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; + +// Text samples +const textA = `Reference\tID\tTags\tQuestion\tResponse +2:3\tw3r5\t\t\t\t1\t<br>Boo +99:3\tw3r5\t\t\t\t1\tBad chapter number +2:boo\tw3r5\t\t\t\t1\tBad verse number +2:3\tw3r5q\t\t\t\t1\tNote4 +2:3\tw3r5\t\tLaugh\t\t\t1\tNote5 +2:3\tw3r5\t\t\tCan’t remember\t\t1\tNote6 +2:3\tw3r5\t\t\t\t17\tNote7 +2:3\tw3r5\t\t\tBad ellipse...\t1\tNote8 +2:3\tw3r5\t\t\t\t1\t<br>Boo hoo,, lost my shoe !`; +const textG = `Reference\tID\tTags\tQuestion\tResponse +front:intro\td9wn\t\t\t\t0\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; +const lineA2 = "1:intro\tzb6f\t\t\t\t0\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist. +1:1\tf2mg\t\t\t0\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story. +1:3\td7qw\t\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]]) +1:5\tjc2d\t\tfigs-merism\t\t0\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. (See: [[rc://en/ta/man/translate/figs-merism]]) +1:6\turb3\t\tfigs-imperative\t\t0\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://en/ta/man/translate/figs-imperative]]) +1:8\tss9r\t\tfigs-merism\t\t0\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://en/ta/man/translate/figs-merism]]) +1:9\tzu6f\t\tfigs-activepassive\t\t0\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://en/ta/man/translate/figs-activepassive]] and [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA9 = "1:9\tha33\t\t\t\t0\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md).`; + +const data = { + // You can choose any of the above lines here + // (to demonstrate differing results) + languageCode: 'en', + repoCode: 'TN2', + tableTextName : 'textG', + tableText : textG, + bookID : 'GEN', + filename: 'dummyFilename', + givenLocation : 'that was supplied', +} + +function checkNotesTSV7Table(props) { + const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; + + const [results, setResults] = useState(null); + + // We need the following construction because checkNotesTSV7Table is an ASYNC function + useEffect(() => { + // Use an IIFE (Immediately Invoked Function Expression) + // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 + (async () => { + // Display our "waiting" message + setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {repoCode} for {tableTextName} <b>{bookID}</b>…</p>); + const checkingOptions = {}; + const rawResults = await checkNotesTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); + setResults( + <div> + <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> + <RenderRawResults results={rawResults} /> + </div> + ); + })(); // end of async part in unnamedFunction + }, []); // end of useEffect part + + return results; +} // end of checkNotesTSV7Table function + +<checkNotesTSV7Table data={data}/> +``` diff --git a/src/core/tn-table-row-check.js b/src/core/tn-tsv9-row-check.js similarity index 99% rename from src/core/tn-table-row-check.js rename to src/core/tn-tsv9-row-check.js index 4d5f9034e..8156908b6 100644 --- a/src/core/tn-table-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -8,7 +8,7 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.8'; +// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.7.0'; const NUM_EXPECTED_TN_TSV_FIELDS = 9; // so expects 8 tabs per line const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote'; @@ -24,7 +24,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * * @description - Checks one TSV data row of translation notes (TN2) * @param {string} languageCode - the language code, e.g., 'en' - * @param {string} annotationType - TN2, TQ2, TWL, SN, or SQ -- allows more specific checks + * @param {string} repoCode - TN2, TQ2, TWL, SN, or SQ -- allows more specific checks * @param {string} line - the TSV line to be checked * @param {string} bookID - 3-character UPPERCASE USFM book identifier or 'OBS' * @param {string} givenC - chapter number or (for OBS) story number string diff --git a/src/core/tn-tsv-table-row-check.md b/src/core/tn-tsv9-row-check.md similarity index 99% rename from src/core/tn-tsv-table-row-check.md rename to src/core/tn-tsv9-row-check.md index 63c961a04..822991129 100644 --- a/src/core/tn-tsv-table-row-check.md +++ b/src/core/tn-tsv9-row-check.md @@ -11,7 +11,7 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkTN_TSVDataRow } from './tn-table-row-check'; +import { checkTN_TSVDataRow } from './tn-tsv9-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples diff --git a/src/core/tn-table-text-check.js b/src/core/tn-tsv9-table-check.js similarity index 85% rename from src/core/tn-table-text-check.js rename to src/core/tn-tsv9-table-check.js index 497b60f1f..a21f1db38 100644 --- a/src/core/tn-table-text-check.js +++ b/src/core/tn-tsv9-table-check.js @@ -1,11 +1,11 @@ import * as books from './books/books'; import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' -import { checkTN_TSVDataRow } from './tn-table-row-check'; +import { checkTN_TSVDataRow } from './tn-tsv9-row-check'; import { removeDisabledNotices } from './disabled-notices'; import { debugLog, parameterAssert } from './utilities'; -const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.3.3'; +const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.4.0'; const NUM_EXPECTED_TN_TSV_FIELDS = 9; // so expects 8 tabs per line const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote'; @@ -20,7 +20,7 @@ const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOr * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkTN_TSVText(languageCode, bookID, filename, tableText, givenLocation, checkingOptions) { +export async function checkTN_TSV9Table(languageCode, bookID, filename, tableText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -29,17 +29,17 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, Returns a result object containing a successList and a noticeList */ - // functionLog(`checkTN_TSVText(${languageCode}, ${bookID}, ${filename}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); - parameterAssert(languageCode !== undefined, "checkTN_TSVText: 'languageCode' parameter should be defined"); - parameterAssert(typeof languageCode === 'string', `checkTN_TSVText: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(bookID !== undefined, "checkTN_TSVText: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkTN_TSVText: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkTN_TSVText: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkTN_TSVText: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(books.isValidBookID(bookID), `checkTN_TSVText: '${bookID}' is not a valid USFM book identifier`); - parameterAssert(givenLocation !== undefined, "checkTN_TSVText: 'givenLocation' parameter should be defined"); - parameterAssert(typeof givenLocation === 'string', `checkTN_TSVText: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); - parameterAssert(checkingOptions !== undefined, "checkTN_TSVText: 'checkingOptions' parameter should be defined"); + // functionLog(`checkTN_TSV9Table(${languageCode}, ${bookID}, ${filename}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkTN_TSV9Table: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkTN_TSV9Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(bookID !== undefined, "checkTN_TSV9Table: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkTN_TSV9Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkTN_TSV9Table: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkTN_TSV9Table: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(books.isValidBookID(bookID), `checkTN_TSV9Table: '${bookID}' is not a valid USFM book identifier`); + parameterAssert(givenLocation !== undefined, "checkTN_TSV9Table: 'givenLocation' parameter should be defined"); + parameterAssert(typeof givenLocation === 'string', `checkTN_TSV9Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); + parameterAssert(checkingOptions !== undefined, "checkTN_TSV9Table: 'checkingOptions' parameter should be defined"); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -51,7 +51,7 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, * @param {string} successString */ function addSuccessMessage(successString) { - // functionLog(`checkTN_TSVText success: ${successString}`); + // functionLog(`checkTN_TSV9Table success: ${successString}`); ttResult.successList.push(successString); } /** @@ -59,7 +59,7 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, * @param {Object} noticeObject */ function addNoticePartial(noticeObject) { - // functionLog(`checkTN_TSVText notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkTN_TSV9Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "TSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "TSV addNoticePartial: 'message' parameter should be defined"); @@ -74,10 +74,10 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); parameterAssert(noticeObject.location !== undefined, "TSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - if (noticeObject.debugChain) noticeObject.debugChain = `checkTN_TSVText ${noticeObject.debugChain}`; + if (noticeObject.debugChain) noticeObject.debugChain = `checkTN_TSV9Table ${noticeObject.debugChain}`; // NOTE: We only add the repoCode here because this function is called directly by tC Create // and notice disabling currently depends on knowing the repoCode - if (noticeObject.repoCode) debugLog(`checkTN_TSVText.addNoticePartial already had repoCode=${noticeObject.repoCode} (will be lost)`); + if (noticeObject.repoCode) debugLog(`checkTN_TSV9Table.addNoticePartial already had repoCode=${noticeObject.repoCode} (will be lost)`); ttResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: 'TN' }); } @@ -114,7 +114,7 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, let rowIDList = [], uniqueRowList = []; let numVersesThisChapter = 0; for (let n = 0; n < lines.length; n++) { - // functionLog(`checkTN_TSVText checking line ${n}: ${JSON.stringify(lines[n])}`); + // functionLog(`checkTN_TSV9Table checking line ${n}: ${JSON.stringify(lines[n])}`); if (n === 0) { if (lines[0] === EXPECTED_TN_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); @@ -251,7 +251,7 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, } if (!checkingOptions?.suppressNoticeDisablingFlag) { - // functionLog(`checkTN_TSVText: calling removeDisabledNotices(${ttResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); + // functionLog(`checkTN_TSV9Table: calling removeDisabledNotices(${ttResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); ttResult.noticeList = removeDisabledNotices(ttResult.noticeList); } @@ -261,11 +261,11 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); if (ttResult.noticeList) - addSuccessMessage(`checkTN_TSVText v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING} finished with ${ttResult.noticeList.length ? ttResult.noticeList.length.toLocaleString() : "zero"} notice${ttResult.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkTN_TSV9Table v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING} finished with ${ttResult.noticeList.length ? ttResult.noticeList.length.toLocaleString() : "zero"} notice${ttResult.noticeList.length === 1 ? '' : 's'}`); else - addSuccessMessage(`No errors or warnings found by checkTN_TSVText v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING}`) - // debugLog(` checkTN_TSVText returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); - // debugLog("checkTN_TSVText result is", JSON.stringify(result)); + addSuccessMessage(`No errors or warnings found by checkTN_TSV9Table v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING}`) + // debugLog(` checkTN_TSV9Table returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkTN_TSV9Table result is", JSON.stringify(result)); return ttResult; } -// end of checkTN_TSVText function +// end of checkTN_TSV9Table function diff --git a/src/core/tn-tsv-table-text-check.md b/src/core/tn-tsv9-table-check.md similarity index 97% rename from src/core/tn-tsv-table-text-check.md rename to src/core/tn-tsv9-table-check.md index 390746bf5..4d496ce25 100644 --- a/src/core/tn-tsv-table-text-check.md +++ b/src/core/tn-tsv9-table-check.md @@ -11,7 +11,7 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkTN_TSVText } from './tn-table-text-check'; +import { checkTN_TSV9Table } from './tn-tsv9-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Text samples @@ -47,12 +47,12 @@ const data = { givenLocation : 'that was supplied', } -function CheckTN_TSVText(props) { +function checkTN_TSV9Table(props) { const { languageCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkTN_TSVText is an ASYNC function + // We need the following construction because checkTN_TSV9Table is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -60,7 +60,7 @@ function CheckTN_TSVText(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {tableTextName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkTN_TSVText(languageCode, bookID, filename, tableText, givenLocation, checkingOptions); + const rawResults = await checkTN_TSV9Table(languageCode, bookID, filename, tableText, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> @@ -71,7 +71,7 @@ function CheckTN_TSVText(props) { }, []); // end of useEffect part return results; -} // end of CheckTN_TSVText function +} // end of checkTN_TSV9Table function -<CheckTN_TSVText data={data}/> +<checkTN_TSV9Table data={data}/> ``` diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js new file mode 100644 index 000000000..8a0204dde --- /dev/null +++ b/src/core/twl-tsv6-row-check.js @@ -0,0 +1,512 @@ +import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' +import * as books from './books/books'; +import { checkTextField } from './field-text-check'; +import { checkMarkdownText } from './markdown-text-check'; +// import { checkSupportReferenceInTA } from './ta-reference-check'; +import { checkTNLinksToOutside } from './tn-links-check'; +import { checkOriginalLanguageQuote } from './orig-quote-check'; +import { parameterAssert } from './utilities'; + + +// const TWL_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.0'; + +const NUM_EXPECTED_TWL_TSV_FIELDS = 6; // so expects 5 tabs per line +const EXPECTED_TWL_HEADING_LINE = 'Reference\tID\tTags\tQuote\tOccurrence\tTWLink'; + +const LC_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'; +const LC_ALPHABET_PLUS_DIGITS = 'abcdefghijklmnopqrstuvwxyz0123456789'; +const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz0123456789-'; + + +/** + * + * @description - Checks one TSV data row of translation notes (TN2) + * @param {string} languageCode - the language code, e.g., 'en' + * @param {string} repoCode - 'TWL' -- keeps parameter set consistent with other similar functions + * @param {string} line - the TSV line to be checked + * @param {string} bookID - 3-character UPPERCASE USFM book identifier or 'OBS' + * @param {string} givenC - chapter number or (for OBS) story number string + * @param {string} givenV - verse number or (for OBS) frame number string + * @param {string} givenRowLocation - description of where the line is located + * @param {Object} checkingOptions - may contain extractLength parameter + * @return {Object} - containing noticeList + */ +export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { + /* This function is only for checking one data row + and the function doesn’t assume that it has any previous context. + + TWL being translation word-links. + + bookID is a three-character UPPERCASE USFM book identifier or 'OBS' + so givenC and givenV are usually chapter number and verse number + but can be story number and frame number for OBS. + + It’s designed to be able to quickly show errors for a single row being displayed/edited. + + Returns an object containing the noticeList. + */ + // functionLog(`checkTWL_TSV6DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkTWL_TSV6DataRow: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkTWL_TSV6DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode === 'TWL', `checkTWL_TSV6DataRow: repoCode expected 'TWL not '${repoCode}'`); + parameterAssert(line !== undefined, "checkTWL_TSV6DataRow: 'line' parameter should be defined"); + parameterAssert(typeof line === 'string', `checkTWL_TSV6DataRow: 'line' parameter should be a string not a '${typeof line}'`); + parameterAssert(bookID !== undefined, "checkTWL_TSV6DataRow: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkTWL_TSV6DataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkTWL_TSV6DataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkTWL_TSV6DataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkTWL_TSV6DataRow: '${bookID}' is not a valid USFM book identifier`); + // parameterAssert(givenC !== undefined, "checkTWL_TSV6DataRow: 'givenC' parameter should be defined"); + if (givenC) parameterAssert(typeof givenC === 'string', `checkTWL_TSV6DataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); + // parameterAssert(givenV !== undefined, "checkTWL_TSV6DataRow: 'givenV' parameter should be defined"); + if (givenV) parameterAssert(typeof givenV === 'string', `checkTWL_TSV6DataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); + parameterAssert(givenRowLocation !== undefined, "checkTWL_TSV6DataRow: 'givenRowLocation' parameter should be defined"); + parameterAssert(typeof givenRowLocation === 'string', `checkTWL_TSV6DataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); + parameterAssert(givenRowLocation.indexOf('true') === -1, "checkTWL_TSV6DataRow: 'givenRowLocation' parameter should not be 'true'"); + + let ourRowLocation = givenRowLocation; + if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; + + const linkCheckingOptions = { ...checkingOptions }; + linkCheckingOptions.taRepoLanguageCode = languageCode; + + let drResult = { noticeList: [] }; + + function addNoticePartial(noticeObject) { + /** + * @description - adds a new notice entry, adding bookID,C,V to the given fields + * @param {Number} priority - notice priority from 1 (lowest) to 999 (highest) + * @param {string} message - the text of the notice message + * @param {string} rowID - 4-character row ID field + * @param {Number} lineNumber - one-based line number + * @param {Number} characterIndex - zero-based index of where the issue occurs in the line + * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} location - description of where the issue is located + */ + // functionLog(`checkTWL_TSV6DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + parameterAssert(noticeObject.priority !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `checkTWL_TSV6DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `checkTWL_TSV6DataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(lineNumber !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'lineNumber' parameter should be defined"); + // parameterAssert(typeof lineNumber === 'number', `checkTWL_TSV6DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); + // parameterAssert(characterIndex !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkTWL_TSV6DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(extract !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkTWL_TSV6DataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + parameterAssert(noticeObject.location !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `checkTWL_TSV6DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + // Also uses the given bookID,C,V, parameters from the main function call + // noticeObject.debugChain = noticeObject.debugChain ? `checkTWL_TSV6DataRow ${noticeObject.debugChain}` : `checkTWL_TSV6DataRow(${repoCode})`; + drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); + } + + async function ourMarkdownTextChecks(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { + /** + * @description - checks the given markdown field and processes the returned results + * @param {string} rowID - 4-character row ID field + * @param {string} fieldName - name of the field being checked + * @param {string} fieldText - the actual text of the field being checked + * @param {} allowedLinks - true if links are allowed in the field, otherwise false + * @param {string} rowLocation - description of where the line is located + * @param {Object} checkingOptions - parameters that might affect the check + */ + // Does markdown checks for small errors like leading/trailing spaces, etc. + + // We assume that checking for compulsory fields is done elsewhere + + // Updates the global list of notices + + // We don’t currently use the allowedLinks parameter + + // functionLog(`checkTWL_TSV6DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Annotation', "checkTWL_TSV6DataRow ourMarkdownTextChecks: Only run this check on Annotations") + parameterAssert(fieldText !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkTWL_TSV6DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(cmtResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of omtcResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); + // NOTE: Ellipses in Annotation have the normal meaning + // not like the specialised meaning in the Quote snippet fields + if (noticeEntry.priority !== 178 && noticeEntry.priority !== 179 // unexpected space after ellipse, ellipse after space + && !noticeEntry.message.startsWith("Unexpected … character after space") // 191 + ) + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + return omtcResultObject.suggestion; // There may or may not be one! + } + // end of ourMarkdownTextChecks function + + function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { + /** + * @description - checks the given text field and processes the returned results + * @param {string} rowID - 4-character row ID field + * @param {string} fieldName - name of the field being checked + * @param {string} fieldText - the actual text of the field being checked + * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false + * @param {string} rowLocation - description of where the line is located + * @param {Object} checkingOptions - parameters that might affect the check + */ + // Does basic checks for small errors like leading/trailing spaces, etc. + + // We assume that checking for compulsory fields is done elsewhere + + // Updates the global list of notices + + // functionLog(`checkTWL_TSV6DataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckTextField: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourCheckTextField: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkTWL_TSV6DataRow ourCheckTextField: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkTWL_TSV6DataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkTWL_TSV6DataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkTWL_TSV6DataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkTWL_TSV6DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; + const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(dbtcResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of octfResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + return octfResultObject.suggestion; // There may or may not be one! + } + // end of ourCheckTextField function + + /* + async function ourCheckSupportReferenceInTA(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // Checks that the TA reference can be found + + // Updates the global list of notices + + // functionLog(`checkTWL_TSV6DataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const coqResultObject = await checkSupportReferenceInTA(fieldName, taLinkText, rowLocation, { ...checkingOptions, taRepoLanguageCode: languageCode, expectFullLink: true }); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of coqResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckSupportReferenceInTA notice length=${Object.keys(noticeEntry).length}`); + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + } + // end of ourCheckSupportReferenceInTA function + */ + + + async function ourCheckTNOriginalLanguageQuote(rowID, fieldName, fieldText, occurrence, rowLocation, checkingOptions) { + // Checks that the Hebrew/Greek quote can be found in the original texts + + // Uses the bookID,C,V values from the main function call + + // Updates the global list of notices + + // functionLog(`checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(occurrence !== undefined, "checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); + parameterAssert(typeof occurrence === 'string', `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of coqResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + } + // end of ourCheckTNOriginalLanguageQuote function + + + async function ourCheckTNLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // Checks that the TA/TW/Bible reference can be found + + // Updates the global list of notices + + // functionLog(`checkTWL_TSV6DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Annotation', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Annotation' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + + const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + // debugLog("coqResultObject", JSON.stringify(coqResultObject)); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const coqNoticeEntry of coqResultObject.noticeList) { + if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is + else // For our direct checks, we add the repoCode as an extra value + addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); + } + // The following is needed coz we might be checking the linked TA and/or TW articles + if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) + if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; + else drResult.checkedFileCount = coqResultObject.checkedFileCount; + if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) + if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; + else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; + if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of coqResultObject.checkedRepoNames) + try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } + catch { drResult.checkedRepoNames = [checkedRepoName]; } + if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) + try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } + catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } + // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); + } + // end of ourCheckTNLinksToOutside function + + + // Main code for checkTWL_TSV6DataRow function + if (line === EXPECTED_TWL_HEADING_LINE) // Assume it must be ok + return drResult; // We can’t detect if it’s in the wrong place + + let extractLength; + try { + extractLength = checkingOptions?.extractLength; + } catch (tlcELerror) { } + if (typeof extractLength !== 'number' || isNaN(extractLength)) { + extractLength = DEFAULT_EXTRACT_LENGTH; + // debugLog(`Using default extractLength=${extractLength}`); + } + // else + // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); + // const halfLength = Math.floor(extractLength / 2); // rounded down + // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + + const lowercaseBookID = bookID.toLowerCase(); + let numChaptersThisBook; + if (bookID === 'OBS') + numChaptersThisBook = 50; // There's 50 Open Bible Stories + else { + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-row-check"); + try { + numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; + } catch (tlcNCerror) { + addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); + } + } + const haveGoodBookID = numChaptersThisBook !== undefined; + + let fields = line.split('\t'); + let RIDSuggestion, QSuggestion, OSuggestion, LSuggestion; + if (fields.length === NUM_EXPECTED_TWL_TSV_FIELDS) { + const [reference, rowID, tags, quote, occurrence, TWLink] = fields; + // let withString = ` with '${rowID}'${inString}`; + // let CV_withString = ` ${C}:${V}${withString}`; + // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; + + // Check the fields one-by-one + const [C, V] = reference.split(':'); + let numVersesThisChapter, haveGoodChapterNumber; + if (C.length) { + if (C !== givenC) + addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation }); + if (C === 'front') { } + else if (/^\d+$/.test(C)) { + let intC = Number(C); + if (intC === 0) { + addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + haveGoodChapterNumber = false; + } + // TODO: Does this next section need rewriting (see verse check below)??? + else if (intC > numChaptersThisBook) { + addNoticePartial({ priority: 823, message: `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + haveGoodChapterNumber = false; + } + if (lowercaseBookID === 'obs') + numVersesThisChapter = 99; // Set to maximum expected number of frames + else { + try { + numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); + haveGoodChapterNumber = true; + } catch (tlcNVerror) { + if (!haveGoodBookID) + // addNoticePartial({priority:500, "Invalid chapter number", rowLocation); + // else + addNoticePartial({ priority: 822, message: "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + haveGoodChapterNumber = false; + } + } + } + else + addNoticePartial({ priority: 821, message: "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + } + else + addNoticePartial({ priority: 820, message: "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:${V}${ourRowLocation}` }); + + if (V.length) { + if (V !== givenV) + addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + if (bookID === 'OBS' || V === 'intro') { } + else if (/^\d+$/.test(V)) { + let intV = Number(V); + if (intV === 0 && bookID !== 'PSA') // Psalms have \d as verse zero + addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + else { + if (haveGoodChapterNumber) { + if (intV > numVersesThisChapter) + addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + } else + addNoticePartial({ priority: 812, message: "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation }); + } + } + else + addNoticePartial({ priority: 811, message: "Bad verse number", rowID, fieldName: 'Reference', location: ` '${V}'${ourRowLocation}` }); + } + else + addNoticePartial({ priority: 810, message: "Missing verse number", rowID, fieldName: 'Reference', location: ` after ${C}:?${ourRowLocation}` }); + + if (!rowID.length) + addNoticePartial({ priority: 779, message: "Missing row ID field", fieldName: 'Reference', location: ourRowLocation }); + else { + if (rowID.length !== 4) { + addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + if (rowID.length > 4) RIDSuggestion = rowID.substring(0, 5); + else { // must be < 4 + RIDSuggestion = rowID; + while (RIDSuggestion.length < 4) RIDSuggestion += LC_ALPHABET_PLUS_DIGITS[Math.floor(Math.random() * LC_ALPHABET_PLUS_DIGITS.length)];; + } + } else if (LC_ALPHABET.indexOf(rowID[0]) < 0) + addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + else if (LC_ALPHABET_PLUS_DIGITS.indexOf(rowID[3]) < 0) + addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[1]) < 0) + addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation }); + else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[2]) < 0) + addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation }); + } + + if (tags.length) + ; + + if (quote.length) { // need to check UTN against UHB and UGNT + QSuggestion = ourCheckTextField(rowID, 'Quote', quote, false, ourRowLocation, checkingOptions); + if (occurrence.length) + await ourCheckTNOriginalLanguageQuote(rowID, 'Quote', quote, occurrence, ourRowLocation, checkingOptions); + else + addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); + } + else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? + if (repoCode === 'TN2' && V !== 'intro' && occurrence !== '0') + addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); + + if (occurrence.length) { // This should usually be a digit + if (occurrence === '0') { // zero means that it doesn’t occur + if (quote.length) { + addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + OSuggestion = '1'; + } + // if (V !== 'intro') + // addNoticePartial({priority:500, message:"Invalid zero occurrence field", rowID, location:rowLocation); + } + else if (occurrence === '-1') // TODO check the special conditions when this can occur??? + ; + else if ('1234567'.indexOf(occurrence) < 0) { // it’s not one of these integers + addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + OSuggestion = '1'; + } + } + else if (quote.length) { + addNoticePartial({ priority: 791, message: `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation }); + OSuggestion = '1'; + } + + if (TWLink.length) { + if (TWLink.indexOf('\u200B') >= 0) { + const charCount = countOccurrences(TWLink, '\u200B'); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + } + if (isWhitespace(TWLink)) + addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + else { // More than just whitespace + LSuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', TWLink, true, ourRowLocation, checkingOptions); + await ourCheckTNLinksToOutside(rowID, 'Annotation', TWLink, ourRowLocation, linkCheckingOptions); + // let regexResultArray; + // while ((regexResultArray = TA_REGEX.exec(TWLink))) { + // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); + // // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) + // // if (supportReference !== adjustedLink && V !== 'intro') { + // // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" + // // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + // // } + // } + } + } + else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? + if (repoCode === 'TN2') + addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + + // 7 [reference, rowID, tags, quote, occurrence, TWLink] + const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${QSuggestion === undefined ? quote : QSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${LSuggestion === undefined ? TWLink : LSuggestion}`; + if (suggestion !== line) { + // debugLog(`Had annotation ${line}`); + // debugLog(`Sug annotation ${suggestion}`); + drResult.suggestion = suggestion; + } + + } else { // wrong number of fields in the row + // Have a go at getting some of the first fields out of the row + let rowID = '????'; + try { rowID = fields[1]; } catch { } + addNoticePartial({ priority: 984, message: `Found wrong number of TSV fields (expected ${NUM_EXPECTED_TWL_TSV_FIELDS})`, details: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, rowID, location: ourRowLocation }); + } + + // debugLog(` checkTWL_TSV6DataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkTWL_TSV6DataRow result is", JSON.stringify(drResult)); + return drResult; // object with noticeList and possibly suggestion only +} +// end of checkTWL_TSV6DataRow function diff --git a/src/core/twl-tsv6-row-check.md b/src/core/twl-tsv6-row-check.md new file mode 100644 index 000000000..533a692c9 --- /dev/null +++ b/src/core/twl-tsv6-row-check.md @@ -0,0 +1,80 @@ +## Annotation (TSV) Row Check Sandbox + +This function checks one tab-separated line for typical formatting errors. + +It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) + +These raw notice components can then be filtered and/or sorted as required by the calling program, and then divided into a list of errors and a list of warnings or whatever as desired. + +```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + +import React, { useState, useEffect } from 'react'; +import { checkTWL_TSV7DataRow } from './twl-tsv6-row-check'; +import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; + +// Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples +const lineE = ""; +const lineH = "Reference\tID\tTags\tQuote\tOccurrence\tTWLink"; +const lineN = "Peace on Earth, good will to all men/people!"; +const lineG = "2:3\tw3r5\t\t1\t\tThis is an optional note"; +const lineB1 = "2:3\tw3r5\t\t1\t\t<br>Boo"; +const lineB2 = "99:3\tw3r5\t\t1\t\tBoo"; +const lineB3 = "2:boo\tw3r5\t\t1\t\tNote3"; +const lineB4 = "2:3\tw3r5q\t\t1\t\tNote4"; +const lineB5 = "2:3\tw3r5\tLaugh\t\t1\t\tNote5"; +const lineB6 = "2:3\tw3r5\t\tCan’t remember\t1\t\tNote6"; +const lineB7 = "2:3\tw3r5\t\t17\t\tNote7"; +const lineB8 = "2:3\tw3r5\t\t1\tBad ellipse...\tNote8"; +const lineB9 = "2:3\tw3r\t\t1\t\t<br>Boo hoo,, lost my shoe !"; +const lineV = "200:9\tW-3r5\tLaugh\t\t17\tBad ellipse...\t<br>Boo hoo,,<br> lost my shoe !"; +const lineA1 = "front:intro\td9wn\t\t\t0\t\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; +const lineA2 = "1:intro\tzb6f\t\t\t0\t\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist."; +const lineA3 = "1:1\tf2mg\t\t0\t\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story."; +const lineA4 = "1:3\td7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA5 = "1:5\tjc2d\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. (See: [[rc://en/ta/man/translate/figs-merism]])"; +const lineA6 = "1:6\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA7 = "1:8\tss9r\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://en/ta/man/translate/figs-merism]])"; +const lineA8 = "1:9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://en/ta/man/translate/figs-activepassive]] and [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA9 = "1:9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md)."; + +const data = { + // You can choose any of the above lines here + // (to demonstrate differing results) + languageCode: 'en', + repoCode: 'TN2', + tableLineName : 'lineA9', + tableLine : lineA9, + bookID : 'GEN', C:'1', V:'2', + givenLocation : 'that was supplied', +} + +function CheckTWLRow(props) { + const { languageCode, repoCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; + + const [results, setResults] = useState(null); + + // We need the following construction because checkTWL_TSV7DataRow is an ASYNC function + useEffect(() => { + // Use an IIFE (Immediately Invoked Function Expression) + // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 + (async () => { + // Display our "waiting" message + setResults(<p style={{ color: 'magenta' }}>Checking {tableLineName} <b>{bookID}</b>…</p>); + const checkingOptions = {}; + const rawResults = await checkTWL_TSV7DataRow(languageCode, repoCode, tableLine, bookID, C, V, givenLocation, checkingOptions); + setResults( + <div> + <b>Check</b> {tableLineName}: "{tableLine.substr(0,256)}…"<br/><br/> + <RenderRawResults results={rawResults} /> + </div> + ); + })(); // end of async part in unnamedFunction + }, []); // end of useEffect part + + return results; +} // end of CheckTWLRow function + +<CheckTWLRow data={data}/> +``` diff --git a/src/core/twl-tsv6-table-check.js b/src/core/twl-tsv6-table-check.js new file mode 100644 index 000000000..d8b75faed --- /dev/null +++ b/src/core/twl-tsv6-table-check.js @@ -0,0 +1,263 @@ +import * as books from './books/books'; +import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { checkTWL_TSV6DataRow } from './twl-tsv6-row-check'; +import { removeDisabledNotices } from './disabled-notices'; +import { functionLog, parameterAssert } from './utilities'; + + +const TWL_TABLE_VALIDATOR_VERSION_STRING = '0.1.0'; + +const NUM_EXPECTED_TWL_TSV_FIELDS = 6; // so expects 5 tabs per line +const EXPECTED_TWL_HEADING_LINE = 'Reference\tID\tTags\tQuote\tOccurrence\tTWLink'; + + +/** + * + * @param {string} languageCode + * @param {string} repoCode - 'TWL' + * @param {string} bookID + * @param {string} filename + * @param {string} tableText + * @param {string} givenLocation + * @param {Object} checkingOptions + */ +export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions) { + /* This function is optimised for checking the entire file, i.e., all rows. + + It also has the advantage of being able to compare one row with the previous one. + + bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. + + Returns a result object containing a successList and a noticeList + */ + functionLog(`checkTWL_TSV6Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkTWL_TSV6Table: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkTWL_TSV6Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode === 'TWL', `checkTWL_TSV6Table: repoCode expected 'TWL' not '${repoCode}'`); + parameterAssert(bookID !== undefined, "checkTWL_TSV6Table: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkTWL_TSV6Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkTWL_TSV6Table: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkTWL_TSV6Table: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkTWL_TSV6Table: '${bookID}' is not a valid USFM book identifier`); + parameterAssert(givenLocation !== undefined, "checkTWL_TSV6Table: 'givenLocation' parameter should be defined"); + parameterAssert(typeof givenLocation === 'string', `checkTWL_TSV6Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); + + let ourLocation = givenLocation; + if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; + + const carResult = { successList: [], noticeList: [] }; + + function addSuccessMessage(successString) { + // functionLog(`checkTWL_TSV6Table success: ${successString}`); + carResult.successList.push(successString); + } + function addNoticePartial(noticeObject) { + // functionLog(`checkTWL_TSV6Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `TSV addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(C !== undefined, "ATSV addNoticePartial: 'C' parameter should be defined"); + if (noticeObject.C) parameterAssert(typeof noticeObject.C === 'string', `TSV addNoticePartial: 'C' parameter should be a string not a '${typeof noticeObject.C}': ${noticeObject.C}`); + // parameterAssert(V !== undefined, "ATSV addNoticePartial: 'V' parameter should be defined"); + if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `TSV addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); + // parameterAssert(characterIndex !== undefined, "ATSV addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `TSV addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(extract !== undefined, "ATSV addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + if (noticeObject.debugChain) noticeObject.debugChain = `checkTWL_TSV6Table ${noticeObject.debugChain}`; + carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: repoCode }); + } + + + let extractLength; + try { + extractLength = checkingOptions?.extractLength; + } catch (ttcError) { } + if (typeof extractLength !== 'number' || isNaN(extractLength)) { + extractLength = DEFAULT_EXTRACT_LENGTH; + // debugLog(`Using default extractLength=${extractLength}`); + } + // else + // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); + // const halfLength = Math.floor(extractLength / 2); // rounded down + // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + + let lowercaseBookID = bookID.toLowerCase(); + let numChaptersThisBook = 0; + if (bookID === 'OBS') + numChaptersThisBook = 50; // There's 50 Open Bible Stories + else { + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-table-check"); + try { + numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; + } + catch { + if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. + addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + } + } + + let lines = tableText.split('\n'); + // debugLog(` '${location}' has ${lines.length.toLocaleString()} total lines (expecting ${NUM_EXPECTED_TN_FIELDS} fields in each line)`); + + let lastC = '', lastV = ''; + let rowIDList = [], uniqueRowList = []; + let numVersesThisChapter = 0; + for (let n = 0; n < lines.length; n++) { + // functionLog(`checkTWL_TSV6Table checking line ${n}: ${JSON.stringify(lines[n])}`); + if (n === 0) { + if (lines[0] === EXPECTED_TWL_HEADING_LINE) + addSuccessMessage(`Checked TSV header ${ourLocation}`); + else + addNoticePartial({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); + } + else // not the header + { + let fields = lines[n].split('\t'); + if (fields.length === NUM_EXPECTED_TWL_TSV_FIELDS) { + // eslint-disable-next-line no-unused-vars + const [reference, rowID, tags, quote, occurrence, TWLLink] = fields; + const [C, V] = reference.split(':') + + // Use the row check to do most basic checks + const drResultObject = await checkTWL_TSV6DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(firstResult.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const drNoticeEntry of drResultObject.noticeList) + if (drNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + carResult.noticeList.push(drNoticeEntry); // Just copy the complete notice as is + else + addNoticePartial({ ...drNoticeEntry, lineNumber: n + 1 }); + // The following is needed coz we might be checking the linked TA and/or TW articles + if (drResultObject.checkedFileCount && drResultObject.checkedFileCount > 0) + if (typeof carResult.checkedFileCount === 'number') carResult.checkedFileCount += drResultObject.checkedFileCount; + else carResult.checkedFileCount = drResultObject.checkedFileCount; + if (drResultObject.checkedFilesizes && drResultObject.checkedFilesizes > 0) + if (typeof carResult.checkedFilesizes === 'number') carResult.checkedFilesizes += drResultObject.checkedFilesizes; + else carResult.checkedFilesizes = drResultObject.checkedFilesizes; + if (drResultObject.checkedRepoNames && drResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of drResultObject.checkedRepoNames) + try { if (carResult.checkedRepoNames.indexOf(checkedRepoName) < 0) carResult.checkedRepoNames.push(checkedRepoName); } + catch { carResult.checkedRepoNames = [checkedRepoName]; } + if (drResultObject.checkedFilenameExtensions && drResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of drResultObject.checkedFilenameExtensions) + try { if (carResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) carResult.checkedFilenameExtensions.push(checkedFilenameExtension); } + catch { carResult.checkedFilenameExtensions = [checkedFilenameExtension]; } + // if (ttResult.checkedFilenameExtensions) userLog("ttResult", JSON.stringify(ttResult)); + + // So here we only have to check against the previous and next fields for out-of-order problems and duplicate problems + if (C !== lastC || V !== lastV) { + rowIDList = []; // ID's only need to be unique within each verse + uniqueRowList = []; // Same for these + } + + // TODO: Check if we need this at all (even though tC 3.0 can’t display these "duplicate" notes) + // Check for duplicate notes + const uniqueID = C + V + quote + occurrence; // This combination should not be repeated + // if (uniqueRowList.includes(uniqueID)) + // addNoticePartial({ priority: 880, C, V, message: `Duplicate note`, rowID, lineNumber: n + 1, location: ourLocation }); + // if (uniqueRowList.includes(uniqueID)) + // addNoticePartial({ priority: 80, C, V, message: `Note: tC 3.0 won’t display duplicate note`, rowID, lineNumber: n + 1, location: ourLocation }); + uniqueRowList.push(uniqueID); + + if (C) { + if (C === 'front') { } + else if (/^\d+$/.test(C)) { + let intC = Number(C); + if (C !== lastC) + if (lowercaseBookID === 'obs') + numVersesThisChapter = 99; // Set to maximum expected number of frames + else + numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); + if (intC === 0) + addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + if (intC > numChaptersThisBook) + addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + if (/^\d+$/.test(lastC)) { + let lastintC = Number(lastC); + if (intC < lastintC) + addNoticePartial({ priority: 736, C, V, message: "Receding chapter number", details: `'${C}' after '${lastC}'`, rowID, lineNumber: n + 1, location: ourLocation }); + else if (intC > lastintC + 1) + addNoticePartial({ priority: 735, C, V, message: "Advancing chapter number", details: `'${C}' after '${lastC}'`.rowID, lineNumber: n + 1, location: ourLocation }); + } + } + else + addNoticePartial({ priority: 734, C, V, message: "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation }); + } + else + addNoticePartial({ priority: 739, C, V, message: "Missing chapter number", rowID, lineNumber: n + 1, location: ` after ${lastC}:${V}${ourLocation}` }); + + if (V) { + if (V === 'intro') { } + else if (/^\d+$/.test(V)) { + let intV = Number(V); + if (intV === 0 && bookID !== 'PSA') // Psalms have \d titles + addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + if (intV > numVersesThisChapter) + addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + if (/^\d+$/.test(lastV)) { + let lastintV = Number(lastV); + if (C === lastC && intV < lastintV) + addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + // else if (intV > lastintV + 1) + // addNoticePartial({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); + } + } + else + addNoticePartial({ priority: 738, C, V, message: "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation }); + + } + else + addNoticePartial({ priority: 790, C, V, message: "Missing verse number", rowID, lineNumber: n + 1, location: ` after ${C}:${lastV}${ourLocation}` }); + + if (rowID) { + if (rowIDList.includes(rowID)) + addNoticePartial({ priority: 729, C, V, message: `Duplicate '${rowID}' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation }); + } else + addNoticePartial({ priority: 730, C, V, message: "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation }); + + + lastC = C; lastV = V; + + } else // wrong number of fields in the row + // if (n === lines.length - 1) // it’s the last line + // userLog(` Line ${n}: Has ${fields.length} field(s) instead of ${NUM_EXPECTED_TN_FIELDS}: ${EXPECTED_TWL_HEADING_LINE.replace(/\t/g, ', ')}`); + // else + if (n !== lines.length - 1) { // it’s not the last line + // Have a go at getting some of the first fields out of the line + let reference = '?:?', C = '?', V = '?', rowID = '????'; + try { reference = fields[0]; } catch { } + try { rowID = fields[1]; } catch { } + try { [C, V] = reference.split(':'); } catch { } + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TWL_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + } + } + } + + if (!checkingOptions?.suppressNoticeDisablingFlag) { + // functionLog(`checkTWL_TSV6Table: calling removeDisabledNotices(${carResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); + carResult.noticeList = removeDisabledNotices(carResult.noticeList); + } + + if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 20) + && checkingOptions?.disableAllLinkFetchingFlag) + addNoticePartial({ priority: 20, message: "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation }); + + addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); + if (carResult.noticeList) + addSuccessMessage(`checkTWL_TSV6Table v${TWL_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); + else + addSuccessMessage(`No errors or warnings found by checkTWL_TSV6Table v${TWL_TABLE_VALIDATOR_VERSION_STRING}`) + // debugLog(` checkTWL_TSV6Table returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkTWL_TSV6Table result is", JSON.stringify(carResult)); + return carResult; +} +// end of checkTWL_TSV6Table function diff --git a/src/core/twl-tsv6-table-check.md b/src/core/twl-tsv6-table-check.md new file mode 100644 index 000000000..10039d2c3 --- /dev/null +++ b/src/core/twl-tsv6-table-check.md @@ -0,0 +1,78 @@ +## Annotation (TSV) Table Text Check Sandbox + +This function checks the given block of annotation (TSV) table lines for typical formatting errors. + +It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) + +These raw notice components can then be filtered and/or sorted as required by the calling program, and then divided into a list of errors and a list of warnings or whatever as desired. + +```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + +import React, { useState, useEffect } from 'react'; +import { checkNotesTSV7Table } from './twl-tsv6-table-check'; +import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; + +// Text samples +const textA = `Reference\tID\tTags\tQuote\tOccurrence\tTWLink +2:3\tw3r5\t\t\t\t1\t<br>Boo +99:3\tw3r5\t\t\t\t1\tBad chapter number +2:boo\tw3r5\t\t\t\t1\tBad verse number +2:3\tw3r5q\t\t\t\t1\tNote4 +2:3\tw3r5\t\tLaugh\t\t\t1\tNote5 +2:3\tw3r5\t\t\tCan’t remember\t\t1\tNote6 +2:3\tw3r5\t\t\t\t17\tNote7 +2:3\tw3r5\t\t\tBad ellipse...\t1\tNote8 +2:3\tw3r5\t\t\t\t1\t<br>Boo hoo,, lost my shoe !`; +const textG = `Reference\tID\tTags\tQuote\tOccurrence\tTWLink +front:intro\td9wn\t\t\t\t0\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; +const lineA2 = "1:intro\tzb6f\t\t\t\t0\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist. +1:1\tf2mg\t\t\t0\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story. +1:3\td7qw\t\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]]) +1:5\tjc2d\t\tfigs-merism\t\t0\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. (See: [[rc://en/ta/man/translate/figs-merism]]) +1:6\turb3\t\tfigs-imperative\t\t0\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://en/ta/man/translate/figs-imperative]]) +1:8\tss9r\t\tfigs-merism\t\t0\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://en/ta/man/translate/figs-merism]]) +1:9\tzu6f\t\tfigs-activepassive\t\t0\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://en/ta/man/translate/figs-activepassive]] and [[rc://en/ta/man/translate/figs-imperative]])"; +const lineA9 = "1:9\tha33\t\t\t\t0\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md).`; + +const data = { + // You can choose any of the above lines here + // (to demonstrate differing results) + languageCode: 'en', + repoCode: 'TN2', + tableTextName : 'textG', + tableText : textG, + bookID : 'GEN', + filename: 'dummyFilename', + givenLocation : 'that was supplied', +} + +function checkNotesTSV7Table(props) { + const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; + + const [results, setResults] = useState(null); + + // We need the following construction because checkNotesTSV7Table is an ASYNC function + useEffect(() => { + // Use an IIFE (Immediately Invoked Function Expression) + // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 + (async () => { + // Display our "waiting" message + setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {repoCode} for {tableTextName} <b>{bookID}</b>…</p>); + const checkingOptions = {}; + const rawResults = await checkNotesTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); + setResults( + <div> + <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> + <RenderRawResults results={rawResults} /> + </div> + ); + })(); // end of async part in unnamedFunction + }, []); // end of useEffect part + + return results; +} // end of checkNotesTSV7Table function + +<checkNotesTSV7Table data={data}/> +``` diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index f4a8bc1e2..889477a0f 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -368,9 +368,8 @@ export async function checkBookPackage(username, languageCode, bookID, setResult } else { // For repos other than OBS and TQ, we only have one file to check let repoFileContent; try { - const path = repoName.endsWith('-annotations') ? `${bookID}/${filename}` : filename; - // debugLog("checkBookPackage about to fetch fileContent for", username, repoName, adjustedBranch, path); - repoFileContent = await getFile_({ username, repository: repoName, path, branch: adjustedBranch }); + // debugLog("checkBookPackage about to fetch fileContent for", username, repoName, adjustedBranch, filename); + repoFileContent = await getFile_({ username, repository: repoName, path: filename, branch: adjustedBranch }); // debugLog("checkBookPackage fetched fileContent for", username, repoName, adjustedBranch, filename, typeof repoFileContent, repoFileContent.length); checkedFilenames.push(filename); totalCheckedSize += repoFileContent.length; diff --git a/src/demos/file-check/checkFileContents.js b/src/demos/file-check/checkFileContents.js index 6f22ec871..aa82f963a 100644 --- a/src/demos/file-check/checkFileContents.js +++ b/src/demos/file-check/checkFileContents.js @@ -1,12 +1,13 @@ import * as books from '../../core/books/books'; import { - userLog, parameterAssert, + userLog, functionLog, parameterAssert, formRepoName, - checkUSFMText, checkMarkdownFileContents, checkPlainText, checkYAMLText, checkManifestText, checkTN_TSVText, checkAnnotationRows + checkUSFMText, checkMarkdownFileContents, checkPlainText, checkYAMLText, checkManifestText, + checkTN_TSV9Table, checkNotesTSV7Table, checkQuestionsTSV5Table, checkTWL_TSV6Table, } from '../../core'; -// const CHECK_FILE_CONTENTS_VERSION_STRING = '0.3.1'; +// const CHECK_FILE_CONTENTS_VERSION_STRING = '0.4.0'; /** @@ -23,7 +24,7 @@ import { export async function checkFileContents(username, languageCode, repoCode, branch, filename, fileContent, givenLocation, checkingOptions) { // Determine the file type from the filename extension // and return the results of checking that kind of file text - // functionLog(`checkFileContents(${username}, ${languageCode}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + functionLog(`checkFileContents(${username}, ${languageCode}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(username !== undefined, "checkFileContents: 'username' parameter should be defined"); parameterAssert(typeof username === 'string', `checkFileContents: 'username' parameter should be a string not a '${typeof username}': ${username}`); parameterAssert(languageCode !== undefined, "checkFileContents: 'languageCode' parameter should be defined"); @@ -55,10 +56,15 @@ export async function checkFileContents(username, languageCode, repoCode, branch // functionLog(`checkFileContents have TSV bookID=${bookID}`); parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); if (filename.startsWith(`${languageCode}_`) || filenameMain.startsWith('en_')) - checkFileResult = await checkTN_TSVText(languageCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = await checkTN_TSV9Table(languageCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); else { - const annotationType = filenameMain.substring(4).toUpperCase(); - checkFileResult = await checkAnnotationRows(languageCode, annotationType, bookID, filename, fileContent, ourCFLocation, checkingOptions); + const repoCode = filenameMain.substring(4).toUpperCase(); + let checkFunction = { + TN: checkNotesTSV7Table, SN: checkNotesTSV7Table, + TQ: checkQuestionsTSV5Table, SQ: checkQuestionsTSV5Table, + TWL: checkTWL_TSV6Table, + }[repoCode]; + checkFileResult = await checkFunction(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); } } else if (filenameLower.endsWith('.usfm')) { @@ -78,13 +84,13 @@ export async function checkFileContents(username, languageCode, repoCode, branch } else if (filenameLower.endsWith('.md')) checkFileResult = checkMarkdownFileContents(languageCode, filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower.endsWith('.txt')) - checkFileResult = checkPlainText('text', filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkPlainText(languageCode, 'text', filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower === 'manifest.yaml') checkFileResult = await checkManifestText(username, formRepoName(languageCode, repoCode), branch, fileContent, ourCFLocation, checkingOptions); // don’t know username or branch else if (filenameLower.endsWith('.yaml')) checkFileResult = checkYAMLText(languageCode, filename, fileContent, ourCFLocation, checkingOptions); else { - checkFileResult = checkPlainText('raw', filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkPlainText(languageCode, 'raw', filename, fileContent, ourCFLocation, checkingOptions); checkFileResult.noticeList.unshift({ priority: 995, message: "File extension is not recognized, so treated as plain text.", filename, location: filename }); } // functionLog(`checkFileContents got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); diff --git a/styleguide.config.js b/styleguide.config.js index ea4e996e6..b659fd09e 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -123,13 +123,23 @@ let sections = [ // content: 'src/core/README.md', sections: [ { - name: 'Annotation table check', - content: 'src/core/annotation-table-check.md', + name: 'TQ/SQ TSV5 table check', + content: 'src/core/questions-tsv5-table-check.md', // description: '' }, { - name: 'TN TSV table check', - content: 'src/core/tn-tsv-table-text-check.md', + name: 'TWLLinks TSV6 table check', + content: 'src/core/twl-tsv6-table-check.md', + // description: '' + }, + { + name: 'TN/SN TSV7 table check', + content: 'src/core/notes-tsv7-table-check.md', + // description: '' + }, + { + name: 'TN TSV9 table check', + content: 'src/core/tn-tsv9-table-check.md', // description: '' }, { @@ -197,13 +207,23 @@ let sections = [ // content: 'src/core/README.md', sections: [ { - name: 'Annotation row check', - content: 'src/core/annotation-row-check.md', + name: 'TQ/SQ TSV5 row check', + content: 'src/core/questions-tsv5-row-check.md', + // description: '' + }, + { + name: 'TWLinks TSV6 row check', + content: 'src/core/twl-tsv6-row-check.md', + // description: '' + }, + { + name: 'TN/SN TSV7 row check', + content: 'src/core/notes-tsv7-row-check.md', // description: '' }, { - name: 'TN TSV table row check', - content: 'src/core/tn-tsv-table-row-check.md', + name: 'TN TSV9 table row check', + content: 'src/core/tn-tsv9-row-check.md', // description: '' }, { diff --git a/yarn.lock b/yarn.lock index d0462acb0..ed4ada9e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@babel/cli@^7.12.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.13.tgz#ae2c6a75fa43f3db4bca0659799b0dfca3f5212b" - integrity sha512-Zto3HPeE0GRmaxobUl7NvFTo97NKe1zdAuWqTO8oka7nE0IIqZ4CFvuRZe1qf+ZMd7eHMhwqrecjwc10mjXo/g== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.16.tgz#bde5bc5118d90e539603abcd37938c5f0fd6c87a" + integrity sha512-cKWkNCxbpjSuYLbdeJs4kOnyW1E2D65pu7SodXDOkzahIN/wSgT8geIqf6+pJTgCo47zrOMGcJTmjSFe5WKYwQ== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -68,15 +68,15 @@ source-map "^0.5.0" "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.13.tgz#b73a87a3a3e7d142a66248bf6ad88b9ceb093425" - integrity sha512-BQKE9kXkPlXHPeqissfxo0lySWJcYdEP0hdtJOH/iJfDdhOCcgtNCjftCJg3qqauB4h+lz2N6ixM++b9DN1Tcw== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.16.tgz#8c6ba456b23b680a6493ddcfcd9d3c3ad51cab7c" + integrity sha512-t/hHIB504wWceOeaOoONOhu+gX+hpjfeN6YRBT209X/4sibZQfSF1I0HFRRlBe97UZZosGx5XwUg1ZgNbelmNw== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.13" + "@babel/generator" "^7.12.15" "@babel/helper-module-transforms" "^7.12.13" "@babel/helpers" "^7.12.13" - "@babel/parser" "^7.12.13" + "@babel/parser" "^7.12.16" "@babel/template" "^7.12.13" "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" @@ -88,7 +88,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.13", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": +"@babel/generator@^7.12.13", "@babel/generator@^7.12.15", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": version "7.12.15" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== @@ -112,31 +112,31 @@ "@babel/helper-explode-assignable-expression" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.12.13", "@babel/helper-compilation-targets@^7.8.7": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.13.tgz#d689cdef88810aa74e15a7a94186f26a3d773c98" - integrity sha512-dXof20y/6wB5HnLOGyLh/gobsMvDNoekcC+8MCV2iaTd5JemhFkPD73QB+tK3iFC9P0xJC73B6MvKkyUfS9cCw== +"@babel/helper-compilation-targets@^7.12.16", "@babel/helper-compilation-targets@^7.8.7": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.16.tgz#6905238b4a5e02ba2d032c1a49dd1820fe8ce61b" + integrity sha512-dBHNEEaZx7F3KoUYqagIhRIeqyyuI65xMndMZ3WwGwEBI609I4TleYQHcrS627vbKyNTXqShoN+fvYD9HuQxAg== dependencies: "@babel/compat-data" "^7.12.13" - "@babel/helper-validator-option" "^7.12.11" + "@babel/helper-validator-option" "^7.12.16" browserslist "^4.14.5" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.12.13", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.13.tgz#0f1707c2eec1a4604f2a22a6fb209854ef2a399a" - integrity sha512-Vs/e9wv7rakKYeywsmEBSRC9KtmE7Px+YBlESekLeJOF0zbGUicGfXSNi3o+tfXSNS48U/7K9mIOOCR79Cl3+Q== +"@babel/helper-create-class-features-plugin@^7.12.13", "@babel/helper-create-class-features-plugin@^7.12.16", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.16.tgz#955d5099fd093e5afb05542190f8022105082c61" + integrity sha512-KbSEj8l9zYkMVHpQqM3wJNxS1d9h3U9vm/uE5tpjMbaj3lTp+0noe3KPsV5dSD9jxKnf9jO9Ip9FX5PKNZCKow== dependencies: "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.12.13" + "@babel/helper-member-expression-to-functions" "^7.12.16" "@babel/helper-optimise-call-expression" "^7.12.13" "@babel/helper-replace-supers" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-create-regexp-features-plugin@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.13.tgz#0996d370a92896c612ae41a4215544bd152579c0" - integrity sha512-XC+kiA0J3at6E85dL5UnCYfVOcIZ834QcAY0TIpgUVnz0zDzg+0TtvZTnJ4g9L1dPRGe30Qi03XCIS4tYCLtqw== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.16.tgz#3b31d13f39f930fad975e151163b7df7d4ffe9d3" + integrity sha512-jAcQ1biDYZBdaAxB4yg46/XirgX7jBDiMHDbwYQOgtViLBXGxJpZQ24jutmBqAIB/q+AwB6j+NbBXjKxEY8vqg== dependencies: "@babel/helper-annotate-as-pure" "^7.12.13" regexpu-core "^4.7.1" @@ -171,10 +171,10 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-member-expression-to-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.13.tgz#c5715695b4f8bab32660dbdcdc2341dec7e3df40" - integrity sha512-B+7nN0gIL8FZ8SvMcF+EPyB21KnCcZHQZFczCxbiNGV/O0rsrSBlWGLzmtBJ3GMjSVMIm4lpFhR+VdVBuIsUcQ== +"@babel/helper-member-expression-to-functions@^7.12.13", "@babel/helper-member-expression-to-functions@^7.12.16": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.16.tgz#41e0916b99f8d5f43da4f05d85f4930fa3d62b22" + integrity sha512-zYoZC1uvebBFmj1wFAlXwt35JLEgecefATtKp20xalwEK8vHAixLBXTGxNrVGEmTT+gzOThUgr8UEdgtalc1BQ== dependencies: "@babel/types" "^7.12.13" @@ -257,10 +257,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== -"@babel/helper-validator-option@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" - integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== +"@babel/helper-validator-option@^7.12.16": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.16.tgz#f73cbd3bbba51915216c5dea908e9b206bb10051" + integrity sha512-uCgsDBPUQDvzr11ePPo4TVEocxj8RXjUVSC/Y8N1YpVAI/XDdUwGJu78xmlGhTxj2ntaWM7n9LQdRtyhOzT2YQ== "@babel/helper-wrap-function@^7.12.13": version "7.12.13" @@ -290,10 +290,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.15.tgz#2b20de7f0b4b332d9b119dd9c33409c538b8aacf" - integrity sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.16", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" + integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== "@babel/plugin-proposal-async-generator-functions@^7.12.13", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.12.13" @@ -329,12 +329,12 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-decorators" "^7.8.3" -"@babel/plugin-proposal-dynamic-import@^7.12.1", "@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" - integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== +"@babel/plugin-proposal-dynamic-import@^7.12.16", "@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.16.tgz#b9f33b252e3406d492a15a799c9d45a9a9613473" + integrity sha512-yiDkYFapVxNOCcBfLnsb/qdsliroM+vc3LHiZwS4gh7pFjo5Xq3BDhYBNn3H3ao+hWPvqeeTdU+s+FIvokov+w== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-dynamic-import" "^7.8.0" "@babel/plugin-proposal-export-namespace-from@^7.12.13": @@ -418,10 +418,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.13", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.13.tgz#63a7d805bc8ce626f3234ee5421a2a7fb23f66d9" - integrity sha512-0ZwjGfTcnZqyV3y9DSD1Yk3ebp+sIUpT2YDqP8hovzaNZnQq2Kd7PEqa6iOIUDBXBt7Jl3P7YAcEIL5Pz8u09Q== +"@babel/plugin-proposal-optional-chaining@^7.12.16", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.16.tgz#600c7531f754186b0f2096e495a92da7d88aa139" + integrity sha512-O3ohPwOhkwji5Mckb7F/PJpJVJY3DpPsrt/F0Bk40+QMk9QpAIqeGusHWqu/mYqsM8oBa6TziL/2mbERWsUZjg== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" @@ -782,11 +782,11 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-transform-react-jsx-development@^7.12.12", "@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" - integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.16.tgz#af187e749d123b54ae49bc7e034057a0c1d4d568" + integrity sha512-GOp5SkMC4zhHwLbOSYhF+WpIZSf5bGzaKQTT9jWkemJRDM/CE6FtPydXjEYO3pHcna2Zjvg4mQ1lfjOR/4jsaQ== dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.12" + "@babel/plugin-transform-react-jsx" "^7.12.16" "@babel/plugin-transform-react-jsx-self@^7.9.0": version "7.12.13" @@ -802,10 +802,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.12.13", "@babel/plugin-transform-react-jsx@^7.9.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.13.tgz#6c9f993b9f6fb6f0e32a4821ed59349748576a3e" - integrity sha512-hhXZMYR8t9RvduN2uW4sjl6MRtUhzNE726JvoJhpjhxKgRUVkZqTsA0xc49ALZxQM7H26pZ/lLvB2Yrea9dllA== +"@babel/plugin-transform-react-jsx@^7.12.13", "@babel/plugin-transform-react-jsx@^7.12.16", "@babel/plugin-transform-react-jsx@^7.9.1": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.16.tgz#07c341e02a3e4066b00413534f30c42519923230" + integrity sha512-dNu0vAbIk8OkqJfGtYF6ADk6jagoyAl+Ks5aoltbAlfoKv8d6yooi3j+kObeSQaCj9PgN6KMZPB90wWyek5TmQ== dependencies: "@babel/helper-annotate-as-pure" "^7.12.13" "@babel/helper-module-imports" "^7.12.13" @@ -891,11 +891,11 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-transform-typescript@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.13.tgz#8bcb5dd79cb8bba690d6920e19992d9228dfed48" - integrity sha512-z1VWskPJxK9tfxoYvePWvzSJC+4pxXr8ArmRm5ofqgi+mwpKg6lvtomkIngBYMJVnKhsFYVysCQLDn//v2RHcg== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.16.tgz#3f30b829bdd15683f71c32fa31330c2af8c1b732" + integrity sha512-88hep+B6dtDOiEqtRzwHp2TYO+CN8nbAV3eh5OpBGPsedug9J6y1JwLKzXRIGGQZDC8NlpxpQMIIxcfIW96Wgw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.13" + "@babel/helper-create-class-features-plugin" "^7.12.16" "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-typescript" "^7.12.13" @@ -981,18 +981,18 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.4.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.13.tgz#3aa2d09cf7d255177538dff292ac9af29ad46525" - integrity sha512-JUVlizG8SoFTz4LmVUL8++aVwzwxcvey3N0j1tRbMAXVEy95uQ/cnEkmEKHN00Bwq4voAV3imQGnQvpkLAxsrw== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.16.tgz#16710e3490e37764b2f41886de0a33bc4ae91082" + integrity sha512-BXCAXy8RE/TzX416pD2hsVdkWo0G+tYd16pwnRV4Sc0fRwTLRS/Ssv8G5RLXUGQv7g4FG7TXkdDJxCjQ5I+Zjg== dependencies: "@babel/compat-data" "^7.12.13" - "@babel/helper-compilation-targets" "^7.12.13" + "@babel/helper-compilation-targets" "^7.12.16" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-validator-option" "^7.12.11" + "@babel/helper-validator-option" "^7.12.16" "@babel/plugin-proposal-async-generator-functions" "^7.12.13" "@babel/plugin-proposal-class-properties" "^7.12.13" - "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.16" "@babel/plugin-proposal-export-namespace-from" "^7.12.13" "@babel/plugin-proposal-json-strings" "^7.12.13" "@babel/plugin-proposal-logical-assignment-operators" "^7.12.13" @@ -1000,7 +1000,7 @@ "@babel/plugin-proposal-numeric-separator" "^7.12.13" "@babel/plugin-proposal-object-rest-spread" "^7.12.13" "@babel/plugin-proposal-optional-catch-binding" "^7.12.13" - "@babel/plugin-proposal-optional-chaining" "^7.12.13" + "@babel/plugin-proposal-optional-chaining" "^7.12.16" "@babel/plugin-proposal-private-methods" "^7.12.13" "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" "@babel/plugin-syntax-async-generators" "^7.8.0" @@ -1838,9 +1838,9 @@ "@types/node" "*" "@types/graceful-fs@^4.1.2": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753" - integrity sha512-mWA/4zFQhfvOA8zWkXobwJvBD7vzcxgrOQ0J5CH1votGqdq9m7+FwtGaqyCZqC3NyyBkc9z4m+iry4LlqcMWJg== + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== dependencies: "@types/node" "*" @@ -1901,9 +1901,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.14.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" - integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ== + version "14.14.26" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.26.tgz#e40df24c957568f350cca04e63bfb1e1556d1cbf" + integrity sha512-skWxepWOs+VArEBWd2S/VR3wUavioIIx9/HzW+UJiIjtwa6+kNXdsOeq7FfxDXf56hIcL0ieo2brwMgBJ1+lhw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -4895,9 +4895,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.662" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.662.tgz#43305bcf88a3340feb553b815d6fd7466659d5ee" - integrity sha512-IGBXmTGwdVGUVTnZ8ISEvkhDfhhD+CDFndG4//BhvDcEtPYiVrzoB+rzT/Y12OQCf5bvRCrVmrUbGrS9P7a6FQ== + version "1.3.663" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.663.tgz#dd54adfd8d7f0e01b80d236c6e232efbaa0c686c" + integrity sha512-xkVkzHj6k3oRRGlmdgUCCLSLhtFYHDCTH7SeK+LJdJjnsLcrdbpr8EYmfMQhez3V/KPO5UScSpzQ0feYX6Qoyw== elliptic@^6.5.3: version "6.5.4" @@ -6956,7 +6956,7 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.1.0: +is-core-module@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== @@ -11804,11 +11804,11 @@ resolve@1.15.0: path-parse "^1.0.6" resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2, resolve@^1.8.1: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== dependencies: - is-core-module "^2.1.0" + is-core-module "^2.2.0" path-parse "^1.0.6" restore-cursor@^2.0.0: @@ -13234,9 +13234,9 @@ type@^1.0.1: integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f" - integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.2.0.tgz#3edd448793f517d8b9dd108b486a043f5befd91f" + integrity sha512-M/u37b4oSGlusaU8ZB96BfFPWQ8MbsZYXB+kXGMiDj6IKinkcNaQvmirBuWj8mAXqP6LYn1rQvbTYum3yPhaOA== typedarray-to-buffer@^3.1.5: version "3.1.5" From aea18d208f7c33615567ff69375a74ed0e843cbf Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Fri, 12 Feb 2021 15:28:32 +1300 Subject: [PATCH 03/16] Rename extract to excerpt to match CV app --- README.md | 4 +- noticeList.txt | 637 +++++++++--------- .../fixtures/unfoldingWord/en_tn/README.md | 2 +- src/core/BCS-usfm-grammar-check.js | 40 +- src/core/disabled-notices.js | 4 +- src/core/field-link-check.js | 22 +- src/core/field-text-check.js | 164 ++--- src/core/file-text-check.js | 28 +- src/core/manifest-text-check.js | 32 +- src/core/manifest-text-check.md | 2 +- src/core/markdown-file-contents-check.js | 24 +- src/core/markdown-text-check.js | 34 +- src/core/notes-tsv7-row-check.js | 64 +- src/core/notes-tsv7-table-check.js | 38 +- src/core/orig-quote-check.js | 96 +-- src/core/plain-text-check.js | 66 +- src/core/questions-tsv5-row-check.js | 58 +- src/core/questions-tsv5-table-check.js | 38 +- src/core/ta-reference-check.js | 30 +- src/core/text-handling-functions.js | 2 +- src/core/tn-links-check.js | 120 ++-- src/core/tn-tsv9-row-check.js | 66 +- src/core/tn-tsv9-table-check.js | 38 +- src/core/twl-tsv6-row-check.js | 60 +- src/core/twl-tsv6-table-check.js | 38 +- src/core/usfm-js-check.js | 12 +- src/core/usfm-text-check.js | 164 ++--- src/core/yaml-text-check.js | 24 +- src/core/yaml-text-check.md | 2 +- src/demos/RenderProcessedResults.js | 14 +- .../AllBookPackagesCheck.js | 4 +- src/demos/all-book-packages-check/README.md | 4 +- .../book-package-check/BookPackageCheck.js | 4 +- src/demos/book-package-check/README.md | 4 +- .../book-package-check/checkBookPackage.js | 16 +- .../book-packages-check/BookPackagesCheck.js | 4 +- src/demos/book-packages-check/README.md | 4 +- .../book-packages-check/checkBookPackages.js | 10 +- src/demos/file-check/FileCheck.js | 4 +- src/demos/file-check/README.md | 4 +- .../GlBookPackageCheck.js | 4 +- src/demos/gl-book-package-check/README.md | 4 +- src/demos/notice-processing-functions.js | 10 +- src/demos/notice-processing1.md | 2 +- src/demos/notice-processing2.md | 2 +- src/demos/notice-processing3.md | 2 +- src/demos/repo-check/README.md | 4 +- src/demos/repo-check/RepoCheck.js | 6 +- src/demos/repo-check/checkRepo.js | 6 +- 49 files changed, 1007 insertions(+), 1014 deletions(-) diff --git a/README.md b/README.md index e33ac74e6..b39d1d105 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ All of the following fields may be missing or undefined, i.e., they’re all opt 1. `lineNumber`: A one-based line number in the file (if available) 1. `fieldName`: name of TSV field (if relevant) 1. `characterIndex`: A **zero-based** integer character index which indicates the position of the error in the given text (line or field) (if available) -1. `extract`: An excerpt (if available) from the checked text which indicates the area containing the problem. Where helpful, some character substitutions have already been made, for example, if the notice is about spaces, it is generally helpful to display spaces as a visible character in an attempt to best highlight the issue to the user. (The length of the extract defaults to ten characters, but is settable as an option.) +1. `excerpt`: An excerpt (if available) from the checked text which indicates the area containing the problem. Where helpful, some character substitutions have already been made, for example, if the notice is about spaces, it is generally helpful to display spaces as a visible character in an attempt to best highlight the issue to the user. (The length of the excerpt defaults to ten characters, but is settable as an option.) 1. `location`: A string indicating the context of the notice, e.g., "in line 17 of 'someBook.usfm'". (Still not completely sure what should be left in this string now that we have added optional `repoName`, `filename`, `rowID`, `lineNumber`, `fieldName` fields.) 1. `extra`: for a check that looks in multiple repos, this contains extra identifying information (typically the `repoCode`) to help the user determine what resource/repo/file that the notice applies to (which, in the demos, is then often prepended to the `message`). @@ -105,7 +105,7 @@ There is provision for checking to be altered and/or sped-up when the calling ap - `taRepoUsername`, `taRepoBranchName`: these two fields can be used to specify the username/organisation and/or the branch/tag name for fetching the TA files for checking - `taRepoLanguageCode`, and `taRepoSectionName`: can be used to specify how the `SupportReference` field is checked in TA—defaults are 'en' and 'translate' - `twRepoUsername`, `twRepoBranchName`: these two fields can be used to specify the username/organisation and/or the branch/tag name for fetching the TW files for checking -- `extractLength`: an integer which defines how long excerpts of lines containing errors should be—the default is 15 characters—the package attempts to place the error in the middle of the extract +- `excerptLength`: an integer which defines how long excerpts of lines containing errors should be—the default is 15 characters—the package attempts to place the error in the middle of the excerpt - `cutoffPriorityLevel`: an integer which can define notices to not be detected—defaults to 0 so none are dropped. Note that this will also affect the `suggestion` response. (Only partially implemented at present, so drops some but not all low priority notices.) - `suppressNoticeDisablingFlag`: Defaults to `false`, i.e., to removing (thus suppressing) notices for warnings which are expected in certain files and hence we don’t want them displayed. Note that this is always set to `true` for the demos (because they suppress these notices later—see the `showDisabledNoticesFlag` below). diff --git a/noticeList.txt b/noticeList.txt index c352548df..50ce8db55 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,29 +1,29 @@ -Last updated 2021-02-12 12:59:19.363735 by makeNoticeList.py -Got 452 notices: +Last updated 2021-02-12 15:28:05.179431 by makeNoticeList.py +Got 445 notices: checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 264 - languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, extract: rest, C, V, location: lineLocation from usfm-text-check.js line 927 + languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 927 marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 955 - `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, extract: line[0], location: ourLocation from usfm-text-check.js line 1,034 + `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,034 C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,127 - const notice = 95, "Unexpected trailing space(s)", extract, location: ourLocation ; from field-text-check.js line 190 + const notice = 95, "Unexpected trailing space(s)", excerpt, location: ourLocation ; from field-text-check.js line 190 notice from field-text-check.js line 193 - notice = 124, "Unexpected double spaces", extract, location: ourLocation ; from field-text-check.js line 224 - notice = 224, "Multiple unexpected double spaces", details: `$doubleCount occurrences—only first is displayed`, extract, location: ourLocation ; from field-text-check.js line 226 + notice = 124, "Unexpected double spaces", excerpt, location: ourLocation ; from field-text-check.js line 224 + notice = 224, "Multiple unexpected double spaces", details: `$doubleCount occurrences—only first is displayed`, excerpt, location: ourLocation ; from field-text-check.js line 226 notice from field-text-check.js line 230 - const notice = 580, "Unexpected narrow non-break space character", extract, location: ourLocation ; from field-text-check.js line 254 + const notice = 580, "Unexpected narrow non-break space character", excerpt, location: ourLocation ; from field-text-check.js line 254 notice from field-text-check.js line 257 - const notice = 177, `Unexpected doubled $punctChar characters`, extract, location: ourLocation ; from field-text-check.js line 289 + const notice = 177, `Unexpected doubled $punctChar characters`, excerpt, location: ourLocation ; from field-text-check.js line 289 notice from field-text-check.js line 292 - const notice = 191, `Unexpected $punctChar character after space`, extract, location: ourLocation ; from field-text-check.js line 308 + const notice = 191, `Unexpected $punctChar character after space`, excerpt, location: ourLocation ; from field-text-check.js line 308 notice from field-text-check.js line 311 - const notice = 192, `Unexpected space after $punctChar character`, extract, location: ourLocation ; from field-text-check.js line 337 + const notice = 192, `Unexpected space after $punctChar character`, excerpt, location: ourLocation ; from field-text-check.js line 337 notice from field-text-check.js line 340 - const notice = 193, `Unexpected $punctChar character at end of line`, extract, location: ourLocation ; from field-text-check.js line 355 + const notice = 193, `Unexpected $punctChar character at end of line`, excerpt, location: ourLocation ; from field-text-check.js line 355 notice from field-text-check.js line 358 thisPriority, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from field-text-check.js line 399 - thisPriority, thisMessage, extract: regexResultArray[0], location: ourLocation from field-text-check.js line 414 + thisPriority, thisMessage, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 414 leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from plain-text-check.js line 240 - 999, "checkRepo function FAILED", repoName, extract: checkRepoError, location: repoName from RepoCheck.js line 107 + 999, "checkRepo function FAILED", repoName, excerpt: checkRepoError, location: repoName from RepoCheck.js line 107 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 174 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 235 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 382 @@ -36,154 +36,153 @@ Got 452 notices: 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 605 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 268 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 94 - 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 117 - 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 136 - 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 123 - 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 140 - 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 129 - 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 144 + 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 117 + 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 136 + 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 123 + 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 140 + 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 129 + 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 144 990, "Unable to load file", details: `username=$username`, repoName, filename ], elapsedSeconds: 0 ; from FileCheck.js line 63 989, "Unable to find/load repository", location: ourLocation from checkRepo.js line 186 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 248 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 230 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 229 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, extract: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 229 - 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, extract, location: ourLocation from usfm-text-check.js line 1,111 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 248 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 240 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 240 + 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 240 + 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,111 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 676 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 505 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 533 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 498 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 559 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 533 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 339 979, "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv5-row-check.js line 339 979, "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 357 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 339 - 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, extract: B, location: ourRowLocation from tn-tsv9-row-check.js line 372 + 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 372 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 375 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from twl-tsv6-row-check.js line 357 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from questions-tsv5-row-check.js line 357 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, extract: C, location: ourRowLocation from tn-tsv9-row-check.js line 380 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from notes-tsv7-row-check.js line 357 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from twl-tsv6-row-check.js line 393 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from questions-tsv5-row-check.js line 393 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-tsv9-row-check.js line 412 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from notes-tsv7-row-check.js line 393 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 357 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv5-row-check.js line 357 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 380 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 357 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 393 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 393 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 412 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 393 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 199 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 269 - 950, "tC cannot yet process '*' language code", characterIndex, extract, location: ourLocation from tn-links-check.js line 226 + 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from tn-links-check.js line 226 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 293 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 291 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 943, `USFM3 toJSON Check doesn’t pass`, location: ourLocation from usfm-js-check.js line 91 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,161 - 939, "Key is missing for project", details: keyName, extract: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 688 - 938, `Unable to find project file mentioned in manifest`, extract: projectFilepath, location: ourLocation from manifest-text-check.js line 705 - 937, `Linked project file seems empty`, extract: projectFilepath, location: ourLocation from manifest-text-check.js line 707 - 936, `Error loading manifest project link`, details: trcGCerror, extract: projectFilepath, location: ourLocation from manifest-text-check.js line 709 + 939, "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 688 + 938, `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 705 + 937, `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 707 + 936, `Error loading manifest project link`, details: trcGCerror, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 709 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 641 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 639 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 163 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 445 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 473 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 486 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 473 - 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, extract, location: ourLocation from orig-quote-check.js line 332 - 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 374 - 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 377 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 380 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 383 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 386 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 389 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 392 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation from orig-quote-check.js line 395 - 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, extract, location: ourLocation from orig-quote-check.js line 398 - 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, extract, location: ourLocation from orig-quote-check.js line 319 - 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, extract, location: ourLocation from orig-quote-check.js line 316 - 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, extract, location: lineLocation from usfm-text-check.js line 660 - 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, extract, location: lineLocation from usfm-text-check.js line 716 - 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, extract, location: ourLocation from orig-quote-check.js line 354 - 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, extract, location: ourLocation from orig-quote-check.js line 363 - 903, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 - 902, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 293 - 900, "Bad parameter: should be given a valid book abbreviation", extract: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 66 - 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, extract, location: ourLocation from field-text-check.js line 102 - 889, `Unable to find TA link`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 - 888, `Error loading TA link`, extract: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 - 887, `Linked TA article seems empty`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 - 886, `Unable to find $fieldName TA link`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 248 - 885, `Error loading $fieldName TA link`, extract: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 243 - 884, `Linked $fieldName TA article seems empty`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 250 - 883, `Unable to find $fieldName TW link`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 297 - 882, `Error loading $fieldName TW link`, extract: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 294 - 881, `Linked $fieldName TW article seems empty`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 300 - 879, `Badly formatted Resource Container link`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 - 875, "Unexpected USFM field", details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 763 - 873, `Mismatched $opener$closer fields`, extract: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 567 - 869, "Chapter number out of range", C: chapterNumberString, extract: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 417 - 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, extract: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 456 + 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 332 + 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 374 + 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 377 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 380 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 383 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 386 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 389 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 392 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 395 + 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 398 + 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 319 + 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 316 + 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 660 + 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 716 + 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 354 + 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 363 + 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 + 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 293 + 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 66 + 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 102 + 889, `Unable to find TA link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 + 888, `Error loading TA link`, excerpt: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 + 887, `Linked TA article seems empty`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 + 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 248 + 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 243 + 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 250 + 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 297 + 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 294 + 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 300 + 879, `Badly formatted Resource Container link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 + 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 763 + 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 567 + 869, "Chapter number out of range", C: chapterNumberString, excerpt: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 417 + 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, excerpt: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 456 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 470 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 475 - 857, "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 808 - 856, "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 811 - 855, "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 814 - 854, "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 817 - 854, "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 820 - 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 823 - 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 - 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 829 + 857, "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 808 + 856, "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 811 + 855, "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 814 + 854, "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 817 + 854, "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 820 + 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 823 + 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 + 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 829 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 288 - 849, `Unexpected '$badCharCombination' character combination`, characterIndex, extract, location: ourLocation from field-text-check.js line 368 - 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 - 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 - 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 + 849, `Unexpected '$badCharCombination' character combination`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 368 + 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 + 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 + 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from tn-links-check.js line 745 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from tn-links-check.js line 749 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from tn-links-check.js line 756 - 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 857 - 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 859 - 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 843 - 836, "Seems too few translation \\w attributes", details: `Expected two attributes but only found $attributeCounter`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 845 - 835, "Seems too few original \\k-s attributes", details: `Expected one attribute but only found $attributeCounter`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 862 - 834, "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found $attributeCounter`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 894 - 833, "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 891 - 830, "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 874 - 829, "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 877 - 828, "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 880 - 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 883 - 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 - 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 362 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 362 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 385 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 362 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 367 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 367 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 390 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 367 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 380 - 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, extract: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 - 822, "Expected field to contain an integer", characterIndex: 3, extract: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 380 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 400 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 380 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 386 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 386 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 405 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 386 + 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 857 + 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 859 + 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 843 + 836, "Seems too few translation \\w attributes", details: `Expected two attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 845 + 835, "Seems too few original \\k-s attributes", details: `Expected one attribute but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 862 + 834, "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 894 + 833, "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 891 + 830, "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 874 + 829, "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 877 + 828, "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 880 + 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 883 + 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 + 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 362 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 362 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 385 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 362 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 367 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 367 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 390 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 367 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 380 + 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 + 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 380 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 400 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 380 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 386 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 386 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 405 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 386 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 389 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv5-row-check.js line 389 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 408 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 389 - 819, "Missing compulsory USFM line", extract: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from twl-tsv6-row-check.js line 398 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from questions-tsv5-row-check.js line 398 - 814, "Invalid zero verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-tsv9-row-check.js line 417 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from notes-tsv7-row-check.js line 398 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from twl-tsv6-row-check.js line 402 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from questions-tsv5-row-check.js line 402 - 813, "Invalid large verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-tsv9-row-check.js line 421 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 + 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 398 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 398 + 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 417 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 398 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 421 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 404 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 404 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 423 @@ -196,259 +195,253 @@ Got 452 notices: 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv5-row-check.js line 411 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 430 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 411 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 459 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from questions-tsv5-row-check.js line 487 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 500 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 487 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 459 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 500 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 487 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 464 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 492 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 505 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 492 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 227 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 209 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv5-table-check.js line 208 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from notes-tsv7-table-check.js line 208 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 447 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 461 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 447 - 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 452 - 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 466 - 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from questions-tsv5-row-check.js line 512 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', extract: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 539 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 512 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 219 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv5-table-check.js line 219 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from notes-tsv7-table-check.js line 219 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 461 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 447 + 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 466 + 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 539 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 512 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 414 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 414 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 433 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 414 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 417 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 417 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 436 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 417 - 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 200 - 776, 'Unexpected " straight quote character', details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 750 - 775, "Unexpected ' straight quote character", details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 755 - 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 207 - 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 168 - 772, `Unexpected trailing word-joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 163 - 771, `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 146 - 770, `Unexpected leading word-joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 142 - 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, Math.max(9, extractLength))$rest.length > extractLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,087 - 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, extract, location: ourLocation from plain-text-check.js line 225 - 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, Math.max(9, extractLength))$rest.length > extractLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,089 - 765, "Unexpected link", characterIndex, extract, location: ourLocation from field-text-check.js line 441 - 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 - 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 - 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, extract: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 - 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, Math.max(9, extractLength))$rest.length > extractLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 - 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 - 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 702 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 450 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from questions-tsv5-row-check.js line 478 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 491 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 478 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 417 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 417 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 436 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 417 + 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 200 + 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 750 + 775, "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 755 + 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 207 + 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 168 + 772, `Unexpected trailing word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 163 + 771, `Unexpected leading zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 146 + 770, `Unexpected leading word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 142 + 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,087 + 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation from plain-text-check.js line 225 + 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,089 + 765, "Unexpected link", characterIndex, excerpt, location: ourLocation from field-text-check.js line 441 + 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 + 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 + 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 + 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 + 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 + 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 702 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 450 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 491 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 478 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 441 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 469 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 482 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 469 - 749, "Markdown image link seems faulty", lineNumber, extract: fetchLink, location: lineLocation from markdown-text-check.js line 140 - 748, "Error fetching markdown image link", lineNumber, extract: fetchLink, location: lineLocation from markdown-text-check.js line 149 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 107 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from twl-tsv6-table-check.js line 91 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv5-table-check.js line 90 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from notes-tsv7-table-check.js line 90 + 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 140 + 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 149 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 107 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from twl-tsv6-table-check.js line 101 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv5-table-check.js line 101 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from notes-tsv7-table-check.js line 101 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-tsv9-table-check.js line 122 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from twl-tsv6-table-check.js line 107 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from questions-tsv5-table-check.js line 106 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 106 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from twl-tsv6-table-check.js line 117 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from questions-tsv5-table-check.js line 117 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 117 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 177 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 180 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, extract: totalLink, location: ourLocation from tn-links-check.js line 353 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 483 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 535 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 643 - 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 696 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 359 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, extract: totalLink, location: ourLocation from tn-links-check.js line 396 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, extract: totalLink, location: ourLocation from tn-links-check.js line 435 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 489 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 541 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 593 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 649 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, extract: totalLink, location: ourLocation from tn-links-check.js line 440 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, extract: totalLink, location: ourLocation from tn-links-check.js line 547 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, extract: totalLink, location: ourLocation from tn-links-check.js line 599 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 353 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 483 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 535 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 643 + 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 696 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 359 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 396 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 435 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 489 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 541 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 593 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 649 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 440 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 547 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 599 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 204 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 186 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv5-table-check.js line 185 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from notes-tsv7-table-check.js line 185 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 196 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv5-table-check.js line 196 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from notes-tsv7-table-check.js line 196 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 223 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 205 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 204 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 204 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-tsv9-table-check.js line 191 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from twl-tsv6-table-check.js line 173 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from questions-tsv5-table-check.js line 172 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from notes-tsv7-table-check.js line 172 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 215 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 215 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 215 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 191 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 183 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv5-table-check.js line 183 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 183 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 195 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 177 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 176 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 176 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 187 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 187 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 187 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 197 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 179 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 178 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 178 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 189 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 189 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 189 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 201 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-tsv9-table-check.js line 213 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 183 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from twl-tsv6-table-check.js line 195 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 182 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from questions-tsv5-table-check.js line 194 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 182 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from notes-tsv7-table-check.js line 194 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-tsv9-table-check.js line 217 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from twl-tsv6-table-check.js line 199 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from questions-tsv5-table-check.js line 198 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from notes-tsv7-table-check.js line 198 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 213 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 193 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 205 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 193 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 205 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 193 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 205 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 217 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 209 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 209 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 209 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 233 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 215 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 214 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 214 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 225 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 225 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 225 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 231 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 213 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 212 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 212 - 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 - 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, extract: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 - 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, extract: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 - 716, `Misplaced $rightChar character`, extract: regexResultArray[0], location: ourLocation from field-text-check.js line 422 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 223 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 223 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 223 + 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 + 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 + 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 + 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 422 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 952 - 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, extract, location: ourLocation from usfm-text-check.js line 1,020 - 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 718 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 375 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 412 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 453 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 505 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 563 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 665 - 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 720 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 377 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 414 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 455 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 507 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 565 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 615 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 667 + 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,020 + 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 718 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 375 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 412 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 453 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 505 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 563 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 665 + 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 720 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 377 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 414 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 455 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 507 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 565 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 615 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 667 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"'+leftoverLinksList2[0]+'"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from tn-links-check.js line 737 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"'+leftoverLinksList1[0]+'"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from tn-links-check.js line 731 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 254 638, "Only found whitespace", location: ourLocation from field-text-check.js line 108 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 128 - 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, extract, location: ourLocation from usfm-text-check.js line 990 + 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 990 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 111 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 143 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 151 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 153 - 583, "Unexpected newLine character", characterIndex, extract, location: ourLocation from field-text-check.js line 236 - 582, "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation from field-text-check.js line 242 - 581, "Unexpected non-break space character", characterIndex, extract, location: ourLocation from field-text-check.js line 248 - 555, "Possible missing chapter number in markdown Bible link", extract: totalLink, location: ourLocation from tn-links-check.js line 347 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from tn-tsv9-table-check.js line 211 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from twl-tsv6-table-check.js line 193 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from questions-tsv5-table-check.js line 192 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, extract: V, location: ourLocation from notes-tsv7-table-check.js line 192 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-tsv9-table-check.js line 189 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from twl-tsv6-table-check.js line 171 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from questions-tsv5-table-check.js line 170 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from notes-tsv7-table-check.js line 170 - 539, "File starts with empty line", characterIndex, extract, location: ourLocation from plain-text-check.js line 150 - 538, "File ends without newline character", characterIndex, extract, location: ourLocation from plain-text-check.js line 155 - 519, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 - 518, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 - 517, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 - 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, extract, location: ourLocation from tn-links-check.js line 222 - 441, `Unknown linkType parameter`, extract: linkType from field-link-check.js line 135 + 583, "Unexpected newLine character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 236 + 582, "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 242 + 581, "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 248 + 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from tn-links-check.js line 347 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 211 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 203 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 203 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 203 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 189 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 181 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv5-table-check.js line 181 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 181 + 539, "File starts with empty line", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 150 + 538, "File ends without newline character", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 155 + 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 + 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 + 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 + 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from tn-links-check.js line 222 + 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 135 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 106 - 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 950 + 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 950 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,124 - 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, extract, location: ourLocation from markdown-text-check.js line 247 + 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 247 375, "Ellipsis without surrounding snippet", location: ourLocation from orig-quote-check.js line 325 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 471 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 457 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 499 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 439 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 464 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 470 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 512 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 527 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 457 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 499 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 499 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 474 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 438 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 502 + 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 442 + 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 467 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 454 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 515 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 530 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 438 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 502 + 373, "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 502 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 684 - 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 948 + 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 948 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 149 282, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 215 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 491 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 519 + 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 459 + 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 484 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 545 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 + 274, "Missing Annotation field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 256, "Possibly missing current copyright year", details: fullYearString, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 262 - 218, "Using deprecated USFM marker", extract: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 - 195, `Unexpected $punctChar character at start of line`, characterIndex, extract, location: ourLocation from field-text-check.js line 319 - 179, "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 264 - 178, "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 270 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 424 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 443 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 424 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 426 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 426 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 428 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 428 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 430 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 430 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 + 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 + 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 319 + 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 264 + 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 270 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 424 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 443 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 424 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 426 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 426 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 428 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 428 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 430 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 430 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 208 - 159, "Should use proper ellipse character (not periods)", characterIndex, extract, location: ourLocation from orig-quote-check.js line 249 - 158, "Unexpected space(s) beside ellipse character", characterIndex, extract, location: ourLocation from orig-quote-check.js line 258 - 157, "Unexpected space(s) beside ↔ divider character", characterIndex, extract, location: ourLocation from orig-quote-check.js line 265 - 156, "Unexpected space(s) beside ellipse characters", characterIndex, extract, location: ourLocation from orig-quote-check.js line 272 + 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 249 + 158, "Unexpected space(s) beside ellipse character", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 258 + 157, "Unexpected space(s) beside ↔ divider character", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 265 + 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 272 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 643 - 144, "Unknown Bible book name in TN link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 687 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 337 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 474 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 526 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 584 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 634 - 138, "File ends with additional blank line(s)", characterIndex, extract, location: ourLocation from plain-text-check.js line 160 + 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 687 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 337 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 474 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 526 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 584 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 634 + 138, "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 160 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 117 - 110, `Unexpected leading spaces`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 137 - 109, `Unexpected leading space`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 139 - 107, "Unexpected leading line break", characterIndex: 0, extract, location: ourLocation from field-text-check.js line 178 - 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, extract, location: ourLocation from field-text-check.js line 211 + 110, `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 137 + 109, `Unexpected leading space`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 139 + 107, "Unexpected leading line break", characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 178 + 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, excerpt, location: ourLocation from field-text-check.js line 211 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,165 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 248 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 184 - 94, "Unexpected trailing space(s) before break", characterIndex, extract, location: ourLocation from field-text-check.js line 198 - 93, "Unexpected trailing space(s) before line break", characterIndex, extract, location: ourLocation from field-text-check.js line 203 + 94, "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 198 + 93, "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 203 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,117 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,119 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 468 - 64, "Unexpected leading space(s) after break", characterIndex, extract, location: ourLocation from field-text-check.js line 152 - 63, "Unexpected leading space(s) after line break", characterIndex, extract, location: ourLocation from field-text-check.js line 157 - 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, extract: fieldText, location: ourLocation from orig-quote-check.js line 298 + 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 152 + 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 157 + 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 298 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 260 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 242 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv5-table-check.js line 241 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 241 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 252 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv5-table-check.js line 252 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 252 diff --git a/src/__tests__/fixtures/unfoldingWord/en_tn/README.md b/src/__tests__/fixtures/unfoldingWord/en_tn/README.md index 5a8fbe1bc..81bd9dc30 100644 --- a/src/__tests__/fixtures/unfoldingWord/en_tn/README.md +++ b/src/__tests__/fixtures/unfoldingWord/en_tn/README.md @@ -23,7 +23,7 @@ Each of these options and their caveats are described below. The first two options require you to clone the repository to your computer first. You may do this on the command line or using a program such as SmartGit. After making changes to the files you will need to commit and push your changes to the server and then create a Pull Request to merge them to the `master` branch. -Alternately, you may [download the master branch as a zip file](https://git.door43.org/unfoldingWord/en_tn/archive/master.zip) and extract that locally. After editing you would need to use the upload file feature in DCS to get your changes ready for a Pull Request. +Alternately, you may [download the master branch as a zip file](https://git.door43.org/unfoldingWord/en_tn/archive/master.zip) and excerpt that locally. After editing you would need to use the upload file feature in DCS to get your changes ready for a Pull Request. ### Editing in LibreOffice diff --git a/src/core/BCS-usfm-grammar-check.js b/src/core/BCS-usfm-grammar-check.js index d4b8ba9b7..103186922 100644 --- a/src/core/BCS-usfm-grammar-check.js +++ b/src/core/BCS-usfm-grammar-check.js @@ -1,6 +1,6 @@ import grammar from 'usfm-grammar'; import * as books from '../core/books/books'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { userLog, parameterAssert } from './utilities'; @@ -13,18 +13,18 @@ export function runBCSGrammarCheck(strictnessString, fileText, filename, givenLo // debugLog(`Running ${strictnessString} BCS USFM grammar check${givenLocation} (can take quite a while for a large book)…`); parameterAssert(strictnessString === 'strict' || strictnessString === 'relaxed', `Unexpected strictnessString='${strictnessString}'`); - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (usfmELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength} cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength} cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); // Now create the parser and run the check @@ -40,7 +40,7 @@ export function runBCSGrammarCheck(strictnessString, fileText, filename, givenLo let parseError; parseError = parserMessages._error; // debugLog(` parseError: ${parseError}`); - let ourErrorMessage, lineNumberString, characterIndex, extract; + let ourErrorMessage, lineNumberString, characterIndex, excerpt; // NOTE: The following code is quite fragile // as it depends on the precise format of the error message return from USFMParser let ourErrorObject = {}; @@ -53,23 +53,23 @@ export function runBCSGrammarCheck(strictnessString, fileText, filename, givenLo // debugLog(` regexResult: ${JSON.stringify(regexResult)}`); if (regexResult) { lineNumberString = regexResult[1]; - extract = regexResult[2]; + excerpt = regexResult[2]; } } else if (errorLine.endsWith('^')) { characterIndex = errorLine.indexOf('^') - 8; if (characterIndex < 0) characterIndex = 0; // Just in case - if (extract.length) - extract = (characterIndex > halfLength ? '…' : '') + extract.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < extract.length ? '…' : '') + if (excerpt.length) + excerpt = (characterIndex > halfLength ? '…' : '') + excerpt.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < excerpt.length ? '…' : '') } else ourErrorMessage = errorLine; // We only want the last one } - // debugLog(` ourErrorMessage: '${ourErrorMessage}' lineNumberString=${lineNumberString} characterIndex=${characterIndex} extract='${extract}'`); + // debugLog(` ourErrorMessage: '${ourErrorMessage}' lineNumberString=${lineNumberString} characterIndex=${characterIndex} excerpt='${excerpt}'`); // Some of these "errors" need to be degraded in priority let adjustedPriority = 594; // We don’t make these extra high coz the messages are hard for users to interpret - if (extract === '\\s5' // Temporarily, even though \s5 fields are not valid USFM + if (excerpt === '\\s5' // Temporarily, even though \s5 fields are not valid USFM || ourErrorMessage.startsWith('Expected "f*", "+"') // Might neeed a OHM schema fix? ) adjustedPriority = 294; @@ -77,7 +77,7 @@ export function runBCSGrammarCheck(strictnessString, fileText, filename, givenLo ourErrorObject = { priority: adjustedPriority, message: `USFMGrammar: ${ourErrorMessage}`, filename, - characterIndex, extract, + characterIndex, excerpt, location: givenLocation }; @@ -147,18 +147,18 @@ export function checkUSFMGrammar(bookID, strictnessString, filename, givenText, * @param {Number} priority - notice priority from 1 (lowest) to 999 (highest) * @param {string} message - the text of the notice message * @param {Number} characterIndex - where the issue occurs in the line - * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkUSFMGrammar notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkUSFMGrammar notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cUSFMgr addNotice6to7: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cUSFMgr addNotice6to7: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cUSFMgr addNotice6to7: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cUSFMgr addNotice6to7: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cUSFMgr addNotice6to7: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cUSFMgr addNotice6to7: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cUSFMgr addNotice6to7: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cUSFMgr addNotice6to7: 'extract' parameter should be a string not a '${typeof extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cUSFMgr addNotice6to7: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cUSFMgr addNotice6to7: 'excerpt' parameter should be a string not a '${typeof excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cUSFMgr addNotice6to7: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cUSFMgr addNotice6to7: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); cugResult.noticeList.push({ ...noticeObject, bookID, filename }); diff --git a/src/core/disabled-notices.js b/src/core/disabled-notices.js index a1e9bc7cf..a1f8b282d 100644 --- a/src/core/disabled-notices.js +++ b/src/core/disabled-notices.js @@ -24,8 +24,8 @@ const disabledNotices = [ { repoCode: 'LT', priority: 638, fieldName: '\\p', }, // "Only found whitespace" tC3 outputs trailing spaces here { repoCode: 'ST', priority: 638, fieldName: '\\p', }, // "Only found whitespace" tC3 outputs trailing spaces here - { repoCode: 'LT', priority: 124, extract: '\\p␣␣', }, // "Unexpected double spaces" tC3 outputs trailing spaces here - { repoCode: 'ST', priority: 124, extract: '\\p␣␣', }, // "Unexpected double spaces" tC3 outputs trailing spaces here + { repoCode: 'LT', priority: 124, excerpt: '\\p␣␣', }, // "Unexpected double spaces" tC3 outputs trailing spaces here + { repoCode: 'ST', priority: 124, excerpt: '\\p␣␣', }, // "Unexpected double spaces" tC3 outputs trailing spaces here { repoCode: 'LT', message: "Unexpected space after | character", }, // 192 tC3 outputs an unneeded/unwanted space in \zaln-s { repoCode: 'ST', message: "Unexpected space after | character", }, // 192 tC3 outputs an unneeded/unwanted space in \zaln-s { repoCode: 'LT', priority: 95, }, // "Unexpected trailing space(s)" tC3 outputs trailing spaces all over the place diff --git a/src/core/field-link-check.js b/src/core/field-link-check.js index 37b2896af..7c6020d25 100644 --- a/src/core/field-link-check.js +++ b/src/core/field-link-check.js @@ -15,19 +15,19 @@ export async function startLiveLinksCheck(linksList, existingNoticeList, callbac let result = { noticeList: existingNoticeList }; - function addNoticePartial({ priority, message, characterIndex, extract, location }) { - userLog(`sLLC Link Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + function addNoticePartial({ priority, message, characterIndex, excerpt, location }) { + userLog(`sLLC Link Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(priority !== undefined, "sLLC addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof priority === 'number', `sLLC addNoticePartial: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); parameterAssert(message !== undefined, "sLLC addNoticePartial: 'message' parameter should be defined"); parameterAssert(typeof message === 'string', `sLLC addNoticePartial: 'message' parameter should be a string not a '${typeof message}':${message}`); // parameterAssert(characterIndex!==undefined, "sLLC addNoticePartial: 'characterIndex' parameter should be defined"); if (characterIndex) parameterAssert(typeof characterIndex === 'number', `sLLC addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof characterIndex}': ${characterIndex}`); - // parameterAssert(extract!==undefined, "sLLC addNoticePartial: 'extract' parameter should be defined"); - if (extract) parameterAssert(typeof extract === 'string', `sLLC addNoticePartial: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); + // parameterAssert(excerpt!==undefined, "sLLC addNoticePartial: 'excerpt' parameter should be defined"); + if (excerpt) parameterAssert(typeof excerpt === 'string', `sLLC addNoticePartial: 'excerpt' parameter should be a string not a '${typeof excerpt}': ${excerpt}`); // parameterAssert(location!==undefined, "sLLC addNoticePartial: 'location' parameter should be defined"); // parameterAssert(typeof location==='string', `sLLC addNoticePartial: 'location' parameter should be a string not a '${typeof location}': ${location}`); - result.noticeList.push({ priority, message, characterIndex, extract, location }); + result.noticeList.push({ priority, message, characterIndex, excerpt, location }); } // Now try fetching each link in turn @@ -77,20 +77,20 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField let result = { noticeList: [] }; - function addNoticePartial({ priority, message, characterIndex, extract, location }) { - userLog(`cFLs addNoticePartial: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + function addNoticePartial({ priority, message, characterIndex, excerpt, location }) { + userLog(`cFLs addNoticePartial: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(priority !== undefined, "cFLs addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof priority === 'number', `cFLs addNoticePartial: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); parameterAssert(message !== undefined, "cFLs addNoticePartial: 'message' parameter should be defined"); parameterAssert(typeof message === 'string', `cFLs addNoticePartial: 'message' parameter should be a string not a '${typeof message}': ${message}`); // parameterAssert(characterIndex!==undefined, "cFLs addNoticePartial: 'characterIndex' parameter should be defined"); if (characterIndex) parameterAssert(typeof characterIndex === 'number', `cFLs addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof characterIndex}': ${characterIndex}`); - // parameterAssert(extract!==undefined, "cFLs addNoticePartial: 'extract' parameter should be defined"); - if (extract) parameterAssert(typeof extract === 'string', `cFLs addNoticePartial: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); + // parameterAssert(excerpt!==undefined, "cFLs addNoticePartial: 'excerpt' parameter should be defined"); + if (excerpt) parameterAssert(typeof excerpt === 'string', `cFLs addNoticePartial: 'excerpt' parameter should be a string not a '${typeof excerpt}': ${excerpt}`); parameterAssert(location !== undefined, "cFLs addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof location === 'string', `cFLs addNoticePartial: 'location' parameter should be a string not a '${typeof location}': ${location}`); - result.noticeList.push({ priority, message, characterIndex, extract, location }); + result.noticeList.push({ priority, message, characterIndex, excerpt, location }); } // // Create our more detailed location string by prepending the fieldName @@ -132,7 +132,7 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField else if (linkType === 'naked') linkRegexParts.push('(https*://[^ ]+)'); else - addNoticePartial({ priority: 441, message: `Unknown linkType parameter`, extract: linkType }); + addNoticePartial({ priority: 441, message: `Unknown linkType parameter`, excerpt: linkType }); } } else { // No link types specified linkRegexParts = []; diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index 2e77e133f..75545716f 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, OPEN_CLOSE_PUNCTUATION_PAIRS, BAD_CHARACTER_COMBINATIONS, isWhitespace, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, OPEN_CLOSE_PUNCTUATION_PAIRS, BAD_CHARACTER_COMBINATIONS, isWhitespace, countOccurrences } from './text-handling-functions' import { debugLog, parameterAssert } from './utilities'; @@ -23,7 +23,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al // priority (compulsory): the priority number 0..999 (usually 800+ are errors, lower are warnings) // message (compulsory): the error description string // characterIndex: the 0-based index for the position in the string - // extract: a short extract of the string containing the error (or empty-string if irrelevant) + // excerpt: a short excerpt of the string containing the error (or empty-string if irrelevant) // location: the detailed location string // (Returned in this way for more intelligent processing at a higher level) // functionLog(`checkTextField(${fieldName}, ${fieldText.length.toLocaleString()} chars, ${allowedLinks}, '${optionalFieldLocation}')…`); @@ -52,15 +52,15 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al function addNoticePartial(noticeObject) { // We add the fieldName here - // debugLog(`dBTC Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // debugLog(`dBTC Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "dBTCs addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `dBTCs addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "dBTCs addNoticePartial: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `dBTCs addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "dBTCs addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `dBTCs addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "dBTCs addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `dBTCs addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "dBTCs addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `dBTCs addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "dBTCs addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `dBTCs addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -78,18 +78,18 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al let ourLocation = optionalFieldLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (btcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); let suggestion = fieldText.trim(); @@ -98,8 +98,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 895) && (characterIndex = fieldText.indexOf('\u200B')) >= 0) { const charCount = countOccurrences(fieldText, '\u200B'); - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u200B/g, '‼') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 895, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u200B/g, '‼') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 895, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\u200B/g, ''); // Or should it be space ??? } @@ -111,61 +111,61 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 993) && (characterIndex = fieldText.indexOf('<<<<<<<')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 993, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); + addNoticePartial({ priority: 993, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 992) && (characterIndex = fieldText.indexOf('=======')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 992, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 992, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 991) && (characterIndex = fieldText.indexOf('>>>>>>>>')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 991, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 991, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } } } if (fieldText[0] === ' ') { - const extract = fieldText.substring(0, extractLength).replace(/ /g, '␣') + (fieldText.length > extractLength ? '…' : ''); + const excerpt = fieldText.substring(0, excerptLength).replace(/ /g, '␣') + (fieldText.length > excerptLength ? '…' : ''); if (fieldText[1] === ' ') // spaces plural - addNoticePartial({ priority: 110, message: `Unexpected leading spaces`, characterIndex: 0, extract, location: ourLocation }); + addNoticePartial({ priority: 110, message: `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation }); else - addNoticePartial({ priority: 109, message: `Unexpected leading space`, characterIndex: 0, extract, location: ourLocation }); + addNoticePartial({ priority: 109, message: `Unexpected leading space`, characterIndex: 0, excerpt, location: ourLocation }); } else if (fieldText[0] === '\u2060') { - const extract = fieldText.substring(0, extractLength).replace(/\u2060/g, '‼') + (fieldText.length > extractLength ? '…' : ''); - addNoticePartial({ priority: 770, message: `Unexpected leading word-joiner`, characterIndex: 0, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength).replace(/\u2060/g, '‼') + (fieldText.length > excerptLength ? '…' : ''); + addNoticePartial({ priority: 770, message: `Unexpected leading word-joiner`, characterIndex: 0, excerpt, location: ourLocation }); if (suggestion[0] === '\u2060') suggestion = suggestion.substring(1); } else if (fieldText[0] === '\u200D') { - const extract = fieldText.substring(0, extractLength).replace(/\u200D/g, '‼') + (fieldText.length > extractLength ? '…' : ''); - addNoticePartial({ priority: 771, message: `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength).replace(/\u200D/g, '‼') + (fieldText.length > excerptLength ? '…' : ''); + addNoticePartial({ priority: 771, message: `Unexpected leading zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation }); if (suggestion[0] === '\u200D') suggestion = suggestion.substring(1); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 64) && (characterIndex = fieldText.indexOf('<br> ')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 64, message: "Unexpected leading space(s) after break", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 64, message: "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation }); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 63) && (characterIndex = fieldText.indexOf('\\n ')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 63, message: "Unexpected leading space(s) after line break", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 63, message: "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation }); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 772) && fieldText[fieldText.length - 1] === '\u2060') { - const extract = fieldText.substring(0, extractLength).replace(/\u2060/g, '‼') + (fieldText.length > extractLength ? '…' : ''); - addNoticePartial({ priority: 772, message: `Unexpected trailing word-joiner`, characterIndex: 0, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength).replace(/\u2060/g, '‼') + (fieldText.length > excerptLength ? '…' : ''); + addNoticePartial({ priority: 772, message: `Unexpected trailing word-joiner`, characterIndex: 0, excerpt, location: ourLocation }); if (suggestion[suggestion.length - 1] === '\u2060') suggestion = suggestion.substring(0, suggestion.length - 1); } else if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 773) && fieldText[fieldText.length - 1] === '\u200D') { - const extract = fieldText.substring(0, extractLength).replace(/\u200D/g, '‼') + (fieldText.length > extractLength ? '…' : ''); - addNoticePartial({ priority: 773, message: `Unexpected trailing zero-width joiner`, characterIndex: 0, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength).replace(/\u200D/g, '‼') + (fieldText.length > excerptLength ? '…' : ''); + addNoticePartial({ priority: 773, message: `Unexpected trailing zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation }); if (suggestion[suggestion.length - 1] === '\u200D') suggestion = suggestion.substring(0, suggestion.length - 1); } @@ -174,8 +174,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 107) && (fieldTextLower.substring(0, 2) === '\\n' || fieldTextLower.substring(0, 4) === '<br>' || fieldTextLower.substring(0, 5) === '<br/>' || fieldTextLower.substring(0, 6) === '<br />') && fieldTextLower !== '\\n' && fieldTextLower !== '<br>' && fieldTextLower !== '<br/>' && fieldTextLower !== '<br />') { - const extract = fieldText.substring(0, extractLength) + (fieldText.length > extractLength ? '…' : ''); - addNoticePartial({ priority: 107, message: "Unexpected leading line break", characterIndex: 0, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength) + (fieldText.length > excerptLength ? '…' : ''); + addNoticePartial({ priority: 107, message: "Unexpected leading line break", characterIndex: 0, excerpt, location: ourLocation }); while (suggestion.toLowerCase().substring(0, 2) === '\\n') suggestion = suggestion.substring(2); while (suggestion.toLowerCase().substring(0, 4) === '<br>') suggestion = suggestion.substring(4); while (suggestion.toLowerCase().substring(0, 5) === '<br/>') suggestion = suggestion.substring(5); @@ -186,29 +186,29 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al && fieldText[fieldText.length - 1] === ' ') // Markdown gives meaning to two spaces at the end of a line if (fieldType !== 'markdown' || fieldText.length < 3 || fieldText[fieldText.length - 2] !== ' ' || fieldText[fieldText.length - 3] === ' ') { - const extract = (fieldText.length > extractLength ? '…' : '') + fieldText.substring(fieldText.length - 10).replace(/ /g, '␣'); - const notice = { priority: 95, message: "Unexpected trailing space(s)", extract, location: ourLocation }; + const excerpt = (fieldText.length > excerptLength ? '…' : '') + fieldText.substring(fieldText.length - 10).replace(/ /g, '␣'); + const notice = { priority: 95, message: "Unexpected trailing space(s)", excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = fieldText.length - 1; // characterIndex means nothing for processed USFM addNoticePartial(notice); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 94) && (characterIndex = fieldText.indexOf(' <br')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 94, message: "Unexpected trailing space(s) before break", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 94, message: "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation }); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 93) && (characterIndex = fieldText.indexOf(' \\n')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 93, message: "Unexpected trailing space(s) before line break", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 93, message: "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation }); } // Find trailing line breaks (but not if the whole line is just the line break sequence) if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 104) && (fieldTextLower.substring(fieldTextLower.length - 2) === '\\n' || fieldTextLower.substring(fieldTextLower.length - 4) === '<br>' || fieldTextLower.substring(fieldTextLower.length - 5) === '<br/>' || fieldTextLower.substring(fieldTextLower.length - 6) === '<br />') && fieldTextLower !== '\\n' && fieldTextLower !== '<br>' && fieldTextLower !== '<br/>' && fieldTextLower !== '<br />') { - const extract = (fieldText.length > extractLength ? '…' : '') + fieldText.substring(fieldText.length - 10); - addNoticePartial({ priority: 104, message: "Unexpected trailing line break", characterIndex: fieldText.length - 1, extract, location: ourLocation }); + const excerpt = (fieldText.length > excerptLength ? '…' : '') + fieldText.substring(fieldText.length - 10); + addNoticePartial({ priority: 104, message: "Unexpected trailing line break", characterIndex: fieldText.length - 1, excerpt, location: ourLocation }); while (suggestion.toLowerCase().substring(suggestion.length - 2) === '\\n') suggestion = suggestion.substring(0, suggestion.length - 2); while (suggestion.toLowerCase().substring(suggestion.length - 4) === '<br>') suggestion = suggestion.substring(0, suggestion.length - 4); while (suggestion.toLowerCase().substring(suggestion.length - 5) === '<br/>') suggestion = suggestion.substring(0, suggestion.length - 5); @@ -217,13 +217,13 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 124) && (characterIndex = fieldText.indexOf(' ')) >= 0 && (fieldType !== 'markdown' || characterIndex !== fieldText.length - 2)) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') const doubleCount = countOccurrences(fieldText, ' '); let notice; if (doubleCount === 1) - notice = { priority: 124, message: "Unexpected double spaces", extract, location: ourLocation }; + notice = { priority: 124, message: "Unexpected double spaces", excerpt, location: ourLocation }; else - notice = { priority: 224, message: "Multiple unexpected double spaces", details: `${doubleCount} occurrences—only first is displayed`, extract, location: ourLocation }; + notice = { priority: 224, message: "Multiple unexpected double spaces", details: `${doubleCount} occurrences—only first is displayed`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM if (!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < notice.priority) @@ -232,26 +232,26 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 583) && (characterIndex = fieldText.indexOf('\n')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 583, message: "Unexpected newLine character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 583, message: "Unexpected newLine character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\n/g, ' '); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 582) && (characterIndex = fieldText.indexOf('\r')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 582, message: "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 582, message: "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\r/g, ' '); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 581) && (characterIndex = fieldText.indexOf('\xA0')) >= 0) { // non-break space - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\xA0/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 581, message: "Unexpected non-break space character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\xA0/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 581, message: "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\xA0/g, ' '); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 580) && (characterIndex = fieldText.indexOf('\u202F')) >= 0) { // narrow non-break space - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u202F/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - const notice = { priority: 580, message: "Unexpected narrow non-break space character", extract, location: ourLocation }; + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u202F/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const notice = { priority: 580, message: "Unexpected narrow non-break space character", excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); @@ -260,14 +260,14 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if (fieldName === 'OrigQuote' || fieldName === 'Quote') { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 179) && (characterIndex = fieldText.indexOf(' …')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 179, message: "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 179, message: "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/ …/g, '…'); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 178) && (characterIndex = fieldText.indexOf('… ')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 178, message: "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 178, message: "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/… /g, '…'); } } @@ -285,8 +285,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al doubledPunctuationCheckList += '-'; for (const punctChar of doubledPunctuationCheckList) { if ((characterIndex = fieldText.indexOf(punctChar + punctChar)) >= 0) { - let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - const notice = { priority: 177, message: `Unexpected doubled ${punctChar} characters`, extract, location: ourLocation }; + let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const notice = { priority: 177, message: `Unexpected doubled ${punctChar} characters`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); @@ -304,8 +304,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al for (const punctChar of afterSpaceCheckList) { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 191) && (characterIndex = fieldText.indexOf(' ' + punctChar)) >= 0) { - let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - const notice = { priority: 191, message: `Unexpected ${punctChar} character after space`, extract, location: ourLocation }; + let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const notice = { priority: 191, message: `Unexpected ${punctChar} character after space`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); @@ -315,8 +315,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al && (punctChar !== '!' || fieldType !== 'markdown') // image tag && fieldText[0] === punctChar) { characterIndex = 0; - let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 195, message: `Unexpected ${punctChar} character at start of line`, characterIndex, extract, location: ourLocation }); + let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 195, message: `Unexpected ${punctChar} character at start of line`, characterIndex, excerpt, location: ourLocation }); } } if (fieldType === 'USFM') @@ -333,8 +333,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if (fieldType !== 'YAML') beforeSpaceCheckList += '['; for (const punctChar of beforeSpaceCheckList) { if ((characterIndex = fieldText.indexOf(punctChar + ' ')) >= 0) { - let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - const notice = { priority: 192, message: `Unexpected space after ${punctChar} character`, extract, location: ourLocation }; + let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const notice = { priority: 192, message: `Unexpected space after ${punctChar} character`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); @@ -351,8 +351,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al for (const punctChar of beforeEOLCheckList) { if (punctChar !== '—' && fieldText[fieldText.length - 1] === punctChar) { characterIndex = fieldText.length - 1; - let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - const notice = { priority: 193, message: `Unexpected ${punctChar} character at end of line`, extract, location: ourLocation }; + let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const notice = { priority: 193, message: `Unexpected ${punctChar} character at end of line`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); @@ -364,16 +364,16 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al // Check for bad combinations of characters for (const badCharCombination of BAD_CHARACTER_COMBINATIONS) if ((characterIndex = fieldText.indexOf(badCharCombination)) >= 0) { - let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNoticePartial({ priority: 849, message: `Unexpected '${badCharCombination}' character combination`, characterIndex, extract, location: ourLocation }); + let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + addNoticePartial({ priority: 849, message: `Unexpected '${badCharCombination}' character combination`, characterIndex, excerpt, location: ourLocation }); } // // Check for problems created by tC Create or something // characterIndex = fieldText.indexOf('\\['); // if (characterIndex === -1) characterIndex = fieldText.indexOf('\\]'); // if (characterIndex !== -1) { - // let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - // addNoticePartial({ priority: 849, message: "Unexpected \\[ or \\] characters", characterIndex, extract, location: ourLocation }); + // let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + // addNoticePartial({ priority: 849, message: "Unexpected \\[ or \\] characters", characterIndex, excerpt, location: ourLocation }); // } // if (countOccurrences(fieldText, '(') !== countOccurrences(fieldText, ')')) { @@ -411,7 +411,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al let thisPriority = 717, thisMessage = `Misplaced ${leftChar} character`; if (leftChar === '(' && regexResultArray[0][2] === 's') { thisPriority = 17; thisMessage = `Possible misplaced ${leftChar} character`; } // Lower priority for words like 'thing(s)' if (!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < thisPriority) - addNoticePartial({ priority: thisPriority, message: thisMessage, extract: regexResultArray[0], location: ourLocation }); + addNoticePartial({ priority: thisPriority, message: thisMessage, excerpt: regexResultArray[0], location: ourLocation }); } if (rightChar !== '’') // Can’t check '‘’' coz they might be used as apostrophe while ((regexResultArray = rightRegex.exec(fieldText))) @@ -419,7 +419,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al && (fieldType !== 'YAML' || rightChar !== '}')) { // debugLog(`Got misplaced right ${rightChar} in ${fieldType} ${fieldName} '${fieldText}':`, JSON.stringify(regexResultArray)); if (!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 716) - addNoticePartial({ priority: 716, message: `Misplaced ${rightChar} character`, extract: regexResultArray[0], location: ourLocation }); + addNoticePartial({ priority: 716, message: `Misplaced ${rightChar} character`, excerpt: regexResultArray[0], location: ourLocation }); } } catch { } } @@ -437,8 +437,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if (characterIndex === -1) characterIndex = fieldText.indexOf('.info'); if (characterIndex === -1) characterIndex = fieldText.indexOf('.bible'); if (characterIndex >= 0) { - let extract = `${characterIndex > halfLength ? '…' : ''}${fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus)}${characterIndex + halfLengthPlus < fieldText.length ? '…' : ''}` - addNoticePartial({ priority: 765, message: "Unexpected link", characterIndex, extract, location: ourLocation }); + let excerpt = `${characterIndex > halfLength ? '…' : ''}${fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus)}${characterIndex + halfLengthPlus < fieldText.length ? '…' : ''}` + addNoticePartial({ priority: 765, message: "Unexpected link", characterIndex, excerpt, location: ourLocation }); } } diff --git a/src/core/file-text-check.js b/src/core/file-text-check.js index e4ff6aca1..29f6003b8 100644 --- a/src/core/file-text-check.js +++ b/src/core/file-text-check.js @@ -19,7 +19,7 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText // priority (compulsory): the priority number 0..999 (usually 800+ are errors, lower are warnings) // message (compulsory): the error description string // characterIndex: the 0-based index for the position in the string - // extract: a short extract of the string containing the error (or empty-string if irrelevant) + // excerpt: a short excerpt of the string containing the error (or empty-string if irrelevant) // (Returned in this way for more intelligent processing at a higher level) // functionLog(`checkTextfileContents(${filename}, ${fileText.length.toLocaleString()} chars, '${optionalFileLocation}')…`); parameterAssert(languageCode !== undefined, "checkTextfileContents: 'languageCode' parameter should be defined"); @@ -37,15 +37,15 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText let result = { noticeList: [] }; function addNotice(noticeObject) { - // debugLog(`dBTC Notice: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? ` ${noticeObject.extract}` : ""}${noticeObject.location}`); + // debugLog(`dBTC Notice: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? ` ${noticeObject.excerpt}` : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "dBTCs addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `dBTCs addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "dBTCs addNotice: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `dBTCs addNotice: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "dBTCs addNotice: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `dBTCs addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "dBTCs addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `dBTCs addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "dBTCs addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `dBTCs addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "dBTCs addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `dBTCs addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); if (noticeObject.debugChain) noticeObject.debugChain = `checkTextfileContents(${languageCode}, ${fileType}, ${filename}) ${noticeObject.debugChain}`; @@ -92,18 +92,18 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; /* - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (bfcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); */ @@ -126,8 +126,8 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText // if (ix === -1) ix = fileText.indexOf('.info'); // if (ix === -1) ix = fileText.indexOf('.bible'); // if (ix >= 0) { - // let extract = (ix>halfLength ? '…' : '') + fileText.substring(ix-halfLength, ix+halfLengthPlus) + (ix+halfLengthPlus < fileText.length ? '…' : '') - // addNotice({765, "Unexpected link", ix,extract, ourAtString}); + // let excerpt = (ix>halfLength ? '…' : '') + fileText.substring(ix-halfLength, ix+halfLengthPlus) + (ix+halfLengthPlus < fileText.length ? '…' : '') + // addNotice({765, "Unexpected link", ix,excerpt, ourAtString}); // } // } return result; diff --git a/src/core/manifest-text-check.js b/src/core/manifest-text-check.js index 62d2ee2f0..806328b09 100644 --- a/src/core/manifest-text-check.js +++ b/src/core/manifest-text-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkYAMLText } from './yaml-text-check'; import { cachedGetFile } from './getApi'; import { BibleBookData } from './books/books' @@ -566,18 +566,18 @@ export async function checkManifestText(username, repoName, repoBranch, manifest let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (mfcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const cmtResult = { successList: [], noticeList: [] }; @@ -587,15 +587,15 @@ export async function checkManifestText(username, repoName, repoBranch, manifest cmtResult.successList.push(successString); } function addNotice(noticeObject) { - // functionLog(`checkManifestText Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkManifestText Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cManT addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cManT addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cManT addNotice: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cManT addNotice: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cManT addNotice: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cManT addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cManT addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cManT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cManT addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cManT addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cManT addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cManT addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -685,7 +685,7 @@ export async function checkManifestText(username, repoName, repoBranch, manifest // debugLog("Project keys", JSON.stringify(projectKeys)); for (const keyName of ['identifier', 'path', 'sort']) if (projectKeys.indexOf(keyName) === -1) - addNotice({ priority: 939, message: "Key is missing for project", details: keyName, extract: JSON.stringify(projectEntry), location: ourLocation }); + addNotice({ priority: 939, message: "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation }); const projectFilepath = projectEntry['path']; if (repoName @@ -702,11 +702,11 @@ export async function checkManifestText(username, repoName, repoBranch, manifest projectFileContent = await getFile_({ username, repository: repoName, path: projectFilepath, branch: repoBranch }); // debugLog("Fetched manifest project fileContent for", repoName, projectFilepath, typeof projectFileContent, projectFileContent.length); if (!projectFileContent) - addNotice({ priority: 938, message: `Unable to find project file mentioned in manifest`, extract: projectFilepath, location: ourLocation }); + addNotice({ priority: 938, message: `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation }); else if (projectFileContent.length < 10) - addNotice({ priority: 937, message: `Linked project file seems empty`, extract: projectFilepath, location: ourLocation }); + addNotice({ priority: 937, message: `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation }); } catch (trcGCerror) { - addNotice({ priority: 936, message: `Error loading manifest project link`, details: trcGCerror, extract: projectFilepath, location: ourLocation }); + addNotice({ priority: 936, message: `Error loading manifest project link`, details: trcGCerror, excerpt: projectFilepath, location: ourLocation }); } } } diff --git a/src/core/manifest-text-check.md b/src/core/manifest-text-check.md index b080e92ce..92ae7cbf3 100644 --- a/src/core/manifest-text-check.md +++ b/src/core/manifest-text-check.md @@ -182,7 +182,7 @@ projects: path: './67-REV.usfm' categories: [ 'bible-nt' ] `; -// This is an extract from a media.yaml file: +// This is an excerpt from a media.yaml file: const textB2 = `resource: version: '{latest}' media: diff --git a/src/core/markdown-file-contents-check.js b/src/core/markdown-file-contents-check.js index cad325f1e..892c1dcf6 100644 --- a/src/core/markdown-file-contents-check.js +++ b/src/core/markdown-file-contents-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkMarkdownText } from './markdown-text-check'; import { checkTextfileContents } from './file-text-check'; import { userLog, parameterAssert } from './utilities'; @@ -38,18 +38,18 @@ export function checkMarkdownFileContents(languageCode, markdownFilename, markdo let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (mdtcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog("Using default extractLength=" + extractLength); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog("Using default excerptLength=" + excerptLength); } // else - // debugLog("Using supplied extractLength=" + extractLength, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog("Using supplied excerptLength=" + excerptLength, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog("Using halfLength=" + halfLength, `halfLengthPlus=${halfLengthPlus}`); const result = { successList: [], noticeList: [] }; @@ -59,15 +59,15 @@ export function checkMarkdownFileContents(languageCode, markdownFilename, markdo result.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkMarkdownFileContents addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? " " + extract : ""}${noticeObject.location}`); + // functionLog(`checkMarkdownFileContents addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? " " + excerpt : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cMdT addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cMdT addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cMdT addNoticePartial: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cMdT addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cMdT addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cMdT addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cMdT addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cMdT addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cMdT addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cMdT addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cMdT addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cMdT addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 8e2a87621..8e8ffd5fe 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTextField } from './field-text-check'; import { cachedGetFileUsingFullURL } from '../core/getApi'; import { removeDisabledNotices } from './disabled-notices'; @@ -45,18 +45,18 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (mdtcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog("Using default extractLength=" + extractLength); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog("Using default excerptLength=" + excerptLength); } // else - // debugLog("Using supplied extractLength=" + extractLength, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog("Using supplied excerptLength=" + excerptLength, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog("Using halfLength=" + halfLength, `halfLengthPlus=${halfLengthPlus}`); const result = { successList: [], noticeList: [] }; @@ -66,15 +66,15 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe result.successList.push(successString); } function addNotice(noticeObject) { - // functionLog(`checkMarkdownText addNotice: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? " " + extract : ""}${noticeObject.location}`); + // functionLog(`checkMarkdownText addNotice: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? " " + excerpt : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cMdT addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cMdT addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cMdT addNotice: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cMdT addNotice: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cMdT addNotice: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cMdT addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cMdT addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cMdT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cMdT addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cMdT addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cMdT addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cMdT addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -137,7 +137,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe if (regexResultArray[1] !== 'OBS Image') userLog("This code was only checked for 'OBS Image' links"); const fetchLink = regexResultArray[2]; if (!fetchLink.startsWith('https://')) - addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, extract: fetchLink, location: lineLocation }); + addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { // debugLog(`Need to check existence of ${fetchLink}`); try { @@ -146,7 +146,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe // debugLog("Markdown link fetch got response: ", responseData.length); } catch (flError) { console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); - addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, extract: fetchLink, location: lineLocation }); + addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation }); } } } @@ -242,9 +242,9 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe const count = ((markdownText || '').match(thisRegex) || []).length; // Finds only NON-OVERLAPPING matches hopefully if (count && (count % 2) !== 0) { const characterIndex = markdownText.indexOf(thisField); - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = /*(iy > halfLength ? '…' : '') +*/ markdownText.substring(iy - halfLength, iy + halfLengthPlus) + (iy + halfLengthPlus < markdownText.length ? '…' : '') - addNotice({ priority: 378, message: `Possible mismatched '${thisField}' markdown formatting pairs`, details: `${count.toLocaleString()} total occurrence${count === 1 ? '' : 's'}`, characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = /*(iy > halfLength ? '…' : '') +*/ markdownText.substring(iy - halfLength, iy + halfLengthPlus) + (iy + halfLengthPlus < markdownText.length ? '…' : '') + addNotice({ priority: 378, message: `Possible mismatched '${thisField}' markdown formatting pairs`, details: `${count.toLocaleString()} total occurrence${count === 1 ? '' : 's'}`, characterIndex, excerpt, location: ourLocation }); break; // Only want one warning per text } } diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index b01da8a36..3b7d4b0cc 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; @@ -30,7 +30,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * @param {string} givenC - chapter number or (for OBS) story number string * @param {string} givenV - verse number or (for OBS) frame number string * @param {string} givenRowLocation - description of where the line is located - * @param {Object} checkingOptions - may contain extractLength parameter + * @param {Object} checkingOptions - may contain excerptLength parameter * @return {Object} - containing noticeList */ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { @@ -82,10 +82,10 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID * @param {string} rowID - 4-character row ID field * @param {Number} lineNumber - one-based line number * @param {Number} characterIndex - zero-based index of where the issue occurs in the line - * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkNotesTSV7DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + // functionLog(`checkNotesTSV7DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `checkNotesTSV7DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'message' parameter should be defined"); @@ -94,8 +94,8 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // parameterAssert(typeof lineNumber === 'number', `checkNotesTSV7DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); // parameterAssert(characterIndex !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkNotesTSV7DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkNotesTSV7DataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkNotesTSV7DataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "checkNotesTSV7DataRow addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `checkNotesTSV7DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -313,18 +313,18 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID if (line === EXPECTED_NOTES_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (tlcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -354,17 +354,17 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID let numVersesThisChapter, haveGoodChapterNumber; if (C.length) { if (C !== givenC) - addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation }); + addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation }); if (C === 'front') { } else if (/^\d+$/.test(C)) { let intC = Number(C); if (intC === 0) { - addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } // TODO: Does this next section need rewriting (see verse check below)??? else if (intC > numChaptersThisBook) { - addNoticePartial({ priority: 823, message: `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 823, message: `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } if (lowercaseBookID === 'obs') @@ -377,29 +377,29 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID if (!haveGoodBookID) // addNoticePartial({priority:500, "Invalid chapter number", rowLocation); // else - addNoticePartial({ priority: 822, message: "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 822, message: "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } } } else - addNoticePartial({ priority: 821, message: "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 821, message: "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); } else addNoticePartial({ priority: 820, message: "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:${V}${ourRowLocation}` }); if (V.length) { if (V !== givenV) - addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); if (bookID === 'OBS' || V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d as verse zero - addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); else { if (haveGoodChapterNumber) { if (intV > numVersesThisChapter) - addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); } else addNoticePartial({ priority: 812, message: "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation }); } @@ -414,20 +414,20 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID addNoticePartial({ priority: 779, message: "Missing row ID field", fieldName: 'Reference', location: ourRowLocation }); else { if (rowID.length !== 4) { - addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); if (rowID.length > 4) RIDSuggestion = rowID.substring(0, 5); else { // must be < 4 RIDSuggestion = rowID; while (RIDSuggestion.length < 4) RIDSuggestion += LC_ALPHABET_PLUS_DIGITS[Math.floor(Math.random() * LC_ALPHABET_PLUS_DIGITS.length)];; } } else if (LC_ALPHABET.indexOf(rowID[0]) < 0) - addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS.indexOf(rowID[3]) < 0) - addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[1]) < 0) - addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[2]) < 0) - addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation }); } if (tags.length) @@ -444,12 +444,12 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID && !supportReferenceArticlePart.startsWith('translate-') && !supportReferenceArticlePart.startsWith('writing-') && supportReferenceArticlePart !== 'guidelines-sonofgodprinciples') - addNoticePartial({ priority: 788, message: "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); + addNoticePartial({ priority: 788, message: "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation }); SRSuggestion = ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, checkingOptions); if (checkingOptions?.disableAllLinkFetchingFlag !== true) await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, checkingOptions); if (note.indexOf(supportReference) < 0) - addNoticePartial({ priority: 787, message: "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); + addNoticePartial({ priority: 787, message: "Link to TA should also be in Annotation", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation }); } let characterIndex; if ((characterIndex = supportReference.indexOf('\u200B') !== -1)) { @@ -475,7 +475,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn’t occur if (quote.length) { - addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } // if (V !== 'intro') @@ -484,7 +484,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID else if (occurrence === '-1') // TODO check the special conditions when this can occur??? ; else if ('1234567'.indexOf(occurrence) < 0) { // it’s not one of these integers - addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } } @@ -509,7 +509,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) if (supportReference !== adjustedLink && V !== 'intro') { const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', extract: adjustedLink, location: ourRowLocation }); + addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation }); } } } diff --git a/src/core/notes-tsv7-table-check.js b/src/core/notes-tsv7-table-check.js index 1d170e684..1d0b18627 100644 --- a/src/core/notes-tsv7-table-check.js +++ b/src/core/notes-tsv7-table-check.js @@ -1,5 +1,5 @@ import * as books from './books/books'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkNotesTSV7DataRow } from './notes-tsv7-row-check'; import { removeDisabledNotices } from './disabled-notices'; import { functionLog, parameterAssert } from './utilities'; @@ -52,7 +52,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena carResult.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkNotesTSV7Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkNotesTSV7Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); @@ -63,8 +63,8 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `TSV addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); // parameterAssert(characterIndex !== undefined, "ATSV addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `TSV addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "ATSV addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "ATSV addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `TSV addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -73,18 +73,18 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena } - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (ttcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); @@ -98,7 +98,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${ourLocation}` }); } } @@ -178,9 +178,9 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena else numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (intC > numChaptersThisBook) - addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) @@ -200,13 +200,13 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d titles - addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (intV > numVersesThisChapter) - addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (C === lastC && intV < lastintV) - addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); // else if (intV > lastintV + 1) // addNoticePartial({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } @@ -237,7 +237,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_NOTES_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_NOTES_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/orig-quote-check.js b/src/core/orig-quote-check.js index 9f77866ce..dfae5cfe4 100644 --- a/src/core/orig-quote-check.js +++ b/src/core/orig-quote-check.js @@ -1,5 +1,5 @@ import * as books from '../core/books/books'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { cachedGetFile } from '../core/getApi'; import { debugLog, parameterAssert, ourParseInt } from './utilities'; @@ -59,15 +59,15 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT const colqResult = { noticeList: [] }; function addNotice(noticeObject) { - // functionLog(`checkOriginalLanguageQuote Notice: (priority=${noticeObject.priority}) ${noticeObject.message}${characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? ` ${noticeObject.extract}` : ""}${noticeObject.location}`); + // functionLog(`checkOriginalLanguageQuote Notice: (priority=${noticeObject.priority}) ${noticeObject.message}${characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? ` ${noticeObject.excerpt}` : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cOLQ addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cOLQ addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cOLQ addNotice: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cOLQ addNotice: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cOLQ addNotice: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cOLQ addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cOLQ addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cOLQ addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract} for ${noticeObject.priority}`); + // parameterAssert(excerpt !== undefined, "cOLQ addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cOLQ addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt} for ${noticeObject.priority}`); parameterAssert(noticeObject.location !== undefined, "cOLQ addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cOLQ addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); colqResult.noticeList.push(noticeObject); @@ -219,18 +219,18 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // Main code for checkOriginalLanguageQuote - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (gcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); let occurrence = 1; @@ -245,8 +245,8 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT let characterIndex; if ((characterIndex = fieldText.indexOf('...')) >= 0) { // debugLog(`Bad ellipse characters in '${fieldText}'`); - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNotice({ priority: 159, message: "Should use proper ellipse character (not periods)", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + addNotice({ priority: 159, message: "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation }); } let quoteBits; @@ -254,22 +254,22 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT quoteBits = fieldText.split('…'); if ((characterIndex = fieldText.indexOf(' …')) >= 0 || (characterIndex = fieldText.indexOf('… ')) >= 0) { // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNotice({ priority: 158, message: "Unexpected space(s) beside ellipse character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + addNotice({ priority: 158, message: "Unexpected space(s) beside ellipse character", characterIndex, excerpt, location: ourLocation }); } } else if (fieldText.indexOf('↔') >= 0) { quoteBits = fieldText.split('↔'); if ((characterIndex = fieldText.indexOf(' ↔')) >= 0 || (characterIndex = fieldText.indexOf('↔ ')) >= 0) { // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNotice({ priority: 157, message: "Unexpected space(s) beside ↔ divider character", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + addNotice({ priority: 157, message: "Unexpected space(s) beside ↔ divider character", characterIndex, excerpt, location: ourLocation }); } } else if (fieldText.indexOf('...') >= 0) { // Yes, we still actually allow this quoteBits = fieldText.split('...'); if ((characterIndex = fieldText.indexOf(' ...')) >= 0 || (characterIndex = fieldText.indexOf('... ')) >= 0) { // debugLog(`Unexpected space(s) beside ellipse characters in '${fieldText}'`); - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNotice({ priority: 156, message: "Unexpected space(s) beside ellipse characters", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + addNotice({ priority: 156, message: "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation }); } } // debugLog(`Got quoteBits=${quoteBits}`); @@ -295,7 +295,7 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT if (quoteBits) { // it had an ellipsis // parameterAssert(occurrence === 1, `Oh -- can get '${fieldText}' with occurrence=${occurrence} in ${bookID} ${C}:${V}`); if (occurrence !== 1) { - addNotice({ priority: 50, message: "Is this quote/occurrence correct???", details: `Occurrence=${occurrence}`, extract: fieldText, location: ourLocation }); + addNotice({ priority: 50, message: "Is this quote/occurrence correct???", details: `Occurrence=${occurrence}`, excerpt: fieldText, location: ourLocation }); } const numQuoteBits = quoteBits.length; if (numQuoteBits >= 2) { @@ -309,14 +309,14 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT else if (bitIndex === 0) partDescription = 'beginning'; else if (bitIndex === numQuoteBits - 1) partDescription = 'end'; else partDescription = `middle${numQuoteBits > 3 ? bitIndex : ''}`; - const extract = `${partDescription ? '(' + partDescription + ' quote portion)' : ''} '${quoteBits[bitIndex]}'`; + const excerpt = `${partDescription ? '(' + partDescription + ' quote portion)' : ''} '${quoteBits[bitIndex]}'`; if (verseText.indexOf(quoteBits[bitIndex]) >= 0) { console.assert(bitIndex > 0, "This shouldn't happen for bitIndex of zero!"); // debugLog(`914, Unable to find '${fieldText}' ${numQuoteBits === 1 ? '' : `'${quoteBits[bitIndex]}' `}${partDescription ? '(' + partDescription + ') ' : ''}in '${verseText}'`); - addNotice({ priority: 914, message: "Unable to find original language quote portion in the right place in the verse text", details: `passage ►${verseText}◄`, extract, location: ourLocation }); + addNotice({ priority: 914, message: "Unable to find original language quote portion in the right place in the verse text", details: `passage ►${verseText}◄`, excerpt, location: ourLocation }); } else { // debugLog(`915, Unable to find '${fieldText}' ${numQuoteBits === 1 ? '' : `'${quoteBits[bitIndex]}' `}${partDescription ? '(' + partDescription + ') ' : ''}in '${verseText}'`); - addNotice({ priority: 915, message: "Unable to find original language quote portion in verse text", details: `passage ►${verseText}◄`, extract, location: ourLocation }); + addNotice({ priority: 915, message: "Unable to find original language quote portion in verse text", details: `passage ►${verseText}◄`, excerpt, location: ourLocation }); } } // else debugLog(`Found quote ${bitIndex} at ${quoteIndex} (num text chars = ${verseText.length})`); @@ -328,8 +328,8 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT if (occurrence > 1) { // functionLog(`checkOriginalLanguageQuote is checking for ${occurrence} occurrences of ${fieldText}`); if (verseText.split(fieldText).length <= occurrence) { // There's not enough of them - const extract = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? '…' : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); - addNotice({ priority: 917, message: "Unable to find duplicate original language quote in verse text", details: `occurrence=${occurrenceString}, passage ►${verseText}◄`, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? '…' : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); + addNotice({ priority: 917, message: "Unable to find duplicate original language quote in verse text", details: `occurrence=${occurrenceString}, passage ►${verseText}◄`, excerpt, location: ourLocation }); } } else { // We only need to check for one occurrence // Double check that it doesn’t start/stop in the middle of a word @@ -350,8 +350,8 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT if (offendingChar === '\u2060') precederDescription = 'WordJoiner'; else if (offendingChar === '\u200D') precederDescription = 'ZeroWidth-WordJoiner'; else precederDescription = `${offendingChar}=D${offendingChar.charCodeAt()}/H${offendingChar.charCodeAt().toString(16)}`; - const extract = `(${precederDescription})` + fieldText.substring(0, extractLength - 3) + (fieldText.length > extractLength - 3 ? '…' : ''); - addNotice({ priority: 909, message: "Seems original language quote might not start at the beginning of a word", details: `passage ►${verseText}◄`, characterIndex: 0, extract, location: ourLocation }); + const excerpt = `(${precederDescription})` + fieldText.substring(0, excerptLength - 3) + (fieldText.length > excerptLength - 3 ? '…' : ''); + addNotice({ priority: 909, message: "Seems original language quote might not start at the beginning of a word", details: `passage ►${verseText}◄`, characterIndex: 0, excerpt, location: ourLocation }); } // Note: There's some Hebrew (RTL) characters at the beginning of the following regex if (fieldText.slice(-1) !== ' ' && remainingBits[1] && remainingBits[1][0].search(/[^׃־A-Za-z\s.,:;?!–)]…/) !== -1) { @@ -359,8 +359,8 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // const offendingChar = remainingBits[1][0]; // const badCharString = ` by '${offendingChar}' {unicodedata.name(offendingChar)}={hex(ord(offendingChar))}`; // debugLog(`Seems '${fieldText}' might not finish at the end of a word—it’s followed ${badCharString} in '${verseText}'`); - const extract = (fieldText.length > extractLength - 3 ? '…' : '') + fieldText.substring(fieldText.length - extractLength + 3, fieldText.length) + `(${remainingBits[1][0]}=D${remainingBits[1].charCodeAt(0)}/H${remainingBits[1].charCodeAt(0).toString(16)})`; - addNotice({ priority: 908, message: "Seems original language quote might not finish at the end of a word", details: `passage ►${verseText}◄`, characterIndex: fieldText.length, extract, location: ourLocation }); + const excerpt = (fieldText.length > excerptLength - 3 ? '…' : '') + fieldText.substring(fieldText.length - excerptLength + 3, fieldText.length) + `(${remainingBits[1][0]}=D${remainingBits[1].charCodeAt(0)}/H${remainingBits[1].charCodeAt(0).toString(16)})`; + addNotice({ priority: 908, message: "Seems original language quote might not finish at the end of a word", details: `passage ►${verseText}◄`, characterIndex: fieldText.length, excerpt, location: ourLocation }); } } } else { // can’t find the given text @@ -370,32 +370,32 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // debugLog(`722 fieldText='${fieldText}'${extraText}`); // debugLog(`722 verseText='${verseText}'`); if (fieldText[0] === ' ') { - const extract = fieldText.substring(0, extractLength) + fieldText.length > extractLength ? '…' : ''; - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith(' ')) { - const extract = fieldText.length > extractLength ? '…' : '' + fieldText.substring(fieldText.length - extractLength, fieldText.length); - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u2060') { // Word joiner - const extract = fieldText.substring(0, extractLength) + fieldText.length > extractLength ? '…' : ''; - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u2060')) { // Word joiner - const extract = fieldText.length > extractLength ? '…' : '' + fieldText.substring(fieldText.length - extractLength, fieldText.length); - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u200B') { // Zero-width space - const extract = fieldText.substring(0, extractLength) + fieldText.length > extractLength ? '…' : ''; - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u200B')) { // Zero-width space - const extract = fieldText.length > extractLength ? '…' : '' + fieldText.substring(fieldText.length - extractLength, fieldText.length); - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u200D') { // Zero-width joiner - const extract = fieldText.substring(0, extractLength) + fieldText.length > extractLength ? '…' : ''; - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u200D')) { // Zero-width joiner - const extract = fieldText.length > extractLength ? '…' : '' + fieldText.substring(fieldText.length - extractLength, fieldText.length); - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), extract, location: ourLocation }); + const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else { - const extract = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? '…' : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); - addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►${verseText}◄`, extract, location: ourLocation }); + const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? '…' : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); + addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►${verseText}◄`, excerpt, location: ourLocation }); } } } diff --git a/src/core/plain-text-check.js b/src/core/plain-text-check.js index 41f66805c..891635d4a 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, OPEN_CLOSE_PUNCTUATION_PAIRS, PAIRED_PUNCTUATION_OPENERS, PAIRED_PUNCTUATION_CLOSERS, isWhitespace, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, OPEN_CLOSE_PUNCTUATION_PAIRS, PAIRED_PUNCTUATION_OPENERS, PAIRED_PUNCTUATION_CLOSERS, isWhitespace, countOccurrences } from './text-handling-functions' import { checkTextField } from './field-text-check'; import { removeDisabledNotices } from './disabled-notices'; import { parameterAssert } from './utilities'; @@ -39,18 +39,18 @@ export function checkPlainText(languageCode, textType, textName, plainText, give let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (ptcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const cptResult = { successList: [], noticeList: [] }; @@ -61,14 +61,14 @@ export function checkPlainText(languageCode, textType, textName, plainText, give } function addNotice(noticeObject) { // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. - // functionLog(`checkPlainText notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkPlainText notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cPT addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cPT addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cPT addNotice: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cPT addNotice: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cPT addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract!==undefined, "cPT addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cPT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt!==undefined, "cPT addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cPT addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cPT addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cPT addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -131,33 +131,33 @@ export function checkPlainText(languageCode, textType, textName, plainText, give let characterIndex; if ((characterIndex = plainText.indexOf('<<<<<<<')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') - addNotice({ priority: 993, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') + addNotice({ priority: 993, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else if ((characterIndex = plainText.indexOf('=======')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') - addNotice({ priority: 992, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') + addNotice({ priority: 992, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else if ((characterIndex = plainText.indexOf('>>>>>>>>')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') - addNotice({ priority: 991, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') + addNotice({ priority: 991, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } if (plainText[0] === '\n') { characterIndex = 0; - const extract = (plainText.length > extractLength ? '…' : '') + plainText.slice(-extractLength).replace(/ /g, '␣').replace(/\n/g, '\\n') - addNotice({ priority: 539, message: "File starts with empty line", characterIndex, extract, location: ourLocation }); + const excerpt = (plainText.length > excerptLength ? '…' : '') + plainText.slice(-excerptLength).replace(/ /g, '␣').replace(/\n/g, '\\n') + addNotice({ priority: 539, message: "File starts with empty line", characterIndex, excerpt, location: ourLocation }); } if (!plainText.endsWith('\n') && !textName.endsWith('title.md')) { characterIndex = plainText.length - 1; - const extract = (plainText.length > extractLength ? '…' : '') + plainText.slice(-extractLength).replace(/ /g, '␣').replace(/\n/g, '\\n') - addNotice({ priority: 538, message: "File ends without newline character", characterIndex, extract, location: ourLocation }); + const excerpt = (plainText.length > excerptLength ? '…' : '') + plainText.slice(-excerptLength).replace(/ /g, '␣').replace(/\n/g, '\\n') + addNotice({ priority: 538, message: "File ends without newline character", characterIndex, excerpt, location: ourLocation }); } else if (plainText.endsWith('\n\n')) { characterIndex = plainText.length - 2; - const extract = (plainText.length > extractLength ? '…' : '') + plainText.slice(-extractLength).replace(/ /g, '␣').replace(/\n/g, '\\n') - addNotice({ priority: 138, message: "File ends with additional blank line(s)", characterIndex, extract, location: ourLocation }); + const excerpt = (plainText.length > excerptLength ? '…' : '') + plainText.slice(-excerptLength).replace(/ /g, '␣').replace(/\n/g, '\\n') + addNotice({ priority: 138, message: "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation }); } const lines = plainText.split('\n'); @@ -195,16 +195,16 @@ export function checkPlainText(languageCode, textType, textName, plainText, give } else // something is still open and this isn’t a match -- might just be consequential error if (char !== '’' // Closing single quote is also used as apostrophe in English && (textType !== 'markdown' || char !== '>' || characterIndex > 4)) { // Markdown uses > or >> or > > or > > > for block indents so ignore these -- might just be consequential error - const extract = (characterIndex > halfLength ? '…' : '') + line.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < line.length ? '…' : '') + const excerpt = (characterIndex > halfLength ? '…' : '') + line.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < line.length ? '…' : '') const details = `'${lastEntry.char}' opened on line ${lastEntry.n} character ${lastEntry.x + 1}`; - addNotice({ priority: 777, message: `Bad punctuation nesting: ${char} closing character doesn’t match`, details, lineNumber: n, characterIndex, extract, location: ourLocation }); + addNotice({ priority: 777, message: `Bad punctuation nesting: ${char} closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation }); // debugLog(` ERROR 777: mismatched characters: ${details}`); } } else // Closed something unexpectedly without an opener if (char !== '’' // Closing single quote is also used as apostrophe in English && (textType !== 'markdown' || char !== '>')) { // Markdown uses > for block indents so ignore these - const extract = (characterIndex > halfLength ? '…' : '') + line.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < line.length ? '…' : '') - addNotice({ priority: 774, message: `Unexpected ${char} closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + line.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < line.length ? '…' : '') + addNotice({ priority: 774, message: `Unexpected ${char} closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation }); // debugLog(` ERROR 774: closed with nothing open: ${char}`); } } @@ -220,9 +220,9 @@ export function checkPlainText(languageCode, textType, textName, plainText, give if (openMarkers.length) { const [{ char, n, x }] = openMarkers.slice(-1); const line = lines[n - 1]; - const extract = (x > halfLength ? '…' : '') + line.substring(x - halfLength, x + halfLengthPlus).replace(/ /g, '␣') + (x + halfLengthPlus < line.length ? '…' : '') + const excerpt = (x > halfLength ? '…' : '') + line.substring(x - halfLength, x + halfLengthPlus).replace(/ /g, '␣') + (x + halfLengthPlus < line.length ? '…' : '') const details = openMarkers.length > 1 ? `${openMarkers.length} unclosed set${openMarkers.length === 1 ? '' : 's'}` : null; - addNotice({ priority: 768, message: `At end of text with unclosed ${char} opening character`, details, lineNumber: n, characterIndex: x, extract, location: ourLocation }); + addNotice({ priority: 768, message: `At end of text with unclosed ${char} opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation }); } // TODO: Is this a duplicate of the above section about nesting? diff --git a/src/core/questions-tsv5-row-check.js b/src/core/questions-tsv5-row-check.js index 13c3633de..5e5e14965 100644 --- a/src/core/questions-tsv5-row-check.js +++ b/src/core/questions-tsv5-row-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' import * as books from './books/books'; // import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; @@ -30,7 +30,7 @@ const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz012345678 * @param {string} givenC - chapter number or (for OBS) story number string * @param {string} givenV - verse number or (for OBS) frame number string * @param {string} givenRowLocation - description of where the line is located - * @param {Object} checkingOptions - may contain extractLength parameter + * @param {Object} checkingOptions - may contain excerptLength parameter * @return {Object} - containing noticeList */ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { @@ -82,10 +82,10 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo * @param {string} rowID - 4-character row ID field * @param {Number} lineNumber - one-based line number * @param {Number} characterIndex - zero-based index of where the issue occurs in the line - * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkQuestionsTSV5DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + // functionLog(`checkQuestionsTSV5DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'message' parameter should be defined"); @@ -94,8 +94,8 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // parameterAssert(typeof lineNumber === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); // parameterAssert(characterIndex !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -313,18 +313,18 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo if (line === EXPECTED_QUESTIONS_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (tlcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -354,17 +354,17 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo let numVersesThisChapter, haveGoodChapterNumber; if (C.length) { if (C !== givenC) - addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation }); + addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation }); if (C === 'front') { } else if (/^\d+$/.test(C)) { let intC = Number(C); if (intC === 0) { - addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } // TODO: Does this next section need rewriting (see verse check below)??? else if (intC > numChaptersThisBook) { - addNoticePartial({ priority: 823, message: `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 823, message: `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } if (lowercaseBookID === 'obs') @@ -377,29 +377,29 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo if (!haveGoodBookID) // addNoticePartial({priority:500, "Invalid chapter number", rowLocation); // else - addNoticePartial({ priority: 822, message: "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 822, message: "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } } } else - addNoticePartial({ priority: 821, message: "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 821, message: "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); } else addNoticePartial({ priority: 820, message: "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:${V}${ourRowLocation}` }); if (V.length) { if (V !== givenV) - addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); if (bookID === 'OBS' || V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d as verse zero - addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); else { if (haveGoodChapterNumber) { if (intV > numVersesThisChapter) - addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); } else addNoticePartial({ priority: 812, message: "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation }); } @@ -414,20 +414,20 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo addNoticePartial({ priority: 779, message: "Missing row ID field", fieldName: 'Reference', location: ourRowLocation }); else { if (rowID.length !== 4) { - addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); if (rowID.length > 4) RIDSuggestion = rowID.substring(0, 5); else { // must be < 4 RIDSuggestion = rowID; while (RIDSuggestion.length < 4) RIDSuggestion += LC_ALPHABET_PLUS_DIGITS[Math.floor(Math.random() * LC_ALPHABET_PLUS_DIGITS.length)];; } } else if (LC_ALPHABET.indexOf(rowID[0]) < 0) - addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS.indexOf(rowID[3]) < 0) - addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[1]) < 0) - addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[2]) < 0) - addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation }); } if (tags.length) @@ -449,7 +449,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) // if (supportReference !== adjustedLink && V !== 'intro') { // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', excerpt: adjustedLink, location: ourRowLocation }); // } // } } @@ -474,7 +474,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) // if (supportReference !== adjustedLink && V !== 'intro') { // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', excerpt: adjustedLink, location: ourRowLocation }); // } // } } diff --git a/src/core/questions-tsv5-table-check.js b/src/core/questions-tsv5-table-check.js index 4abb03bfe..48707af47 100644 --- a/src/core/questions-tsv5-table-check.js +++ b/src/core/questions-tsv5-table-check.js @@ -1,5 +1,5 @@ import * as books from './books/books'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkQuestionsTSV5DataRow } from './questions-tsv5-row-check'; import { removeDisabledNotices } from './disabled-notices'; import { functionLog, parameterAssert } from './utilities'; @@ -52,7 +52,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi carResult.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkQuestionsTSV5Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkQuestionsTSV5Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); @@ -63,8 +63,8 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `TSV addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); // parameterAssert(characterIndex !== undefined, "ATSV addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `TSV addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "ATSV addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "ATSV addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `TSV addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -73,18 +73,18 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi } - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (ttcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); @@ -98,7 +98,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${ourLocation}` }); } } @@ -178,9 +178,9 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi else numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (intC > numChaptersThisBook) - addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) @@ -200,13 +200,13 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d titles - addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (intV > numVersesThisChapter) - addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (C === lastC && intV < lastintV) - addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); // else if (intV > lastintV + 1) // addNoticePartial({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } @@ -237,7 +237,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/ta-reference-check.js b/src/core/ta-reference-check.js index 0afd73e4b..871516661 100644 --- a/src/core/ta-reference-check.js +++ b/src/core/ta-reference-check.js @@ -36,15 +36,15 @@ export async function checkSupportReferenceInTA(fieldName, fieldText, givenLocat const ctarResult = { noticeList: [] }; function addNoticePartial(noticeObject) { - // functionLog(`checkSupportReferenceInTA Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkSupportReferenceInTA Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cTAref addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cTAref addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cTAref addNoticePartial: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cTAref addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cTAref addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cTAref addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cTAref addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cTAref addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cTAref addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cTAref addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cTAref addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cTAref addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); ctarResult.noticeList.push({ ...noticeObject, fieldName }); @@ -53,18 +53,18 @@ export async function checkSupportReferenceInTA(fieldName, fieldText, givenLocat // Main code for checkSupportReferenceInTA /* - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (trcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, "cf. default="+DEFAULT_EXTRACT_LENGTH); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, "cf. default="+DEFAULT_EXCERPT_LENGTH); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, "halfLengthPlus="+halfLengthPlus); */ @@ -93,7 +93,7 @@ export async function checkSupportReferenceInTA(fieldName, fieldText, givenLocat if (checkingOptions?.expectFullLink) { // debugLog("checkSupportReferenceInTA expect full link") if (!fieldText.startsWith('rc://*/')) - addNoticePartial({ priority: 879, message: `Badly formatted Resource Container link`, extract: fieldText, location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 879, message: `Badly formatted Resource Container link`, excerpt: fieldText, location: `${ourLocation} ${filepath}` }); filepath = `${fieldText.replace('rc://*/ta/man/', '')}/01.md`; // Other files are title.md, sub-title.md } else filepath = `${taRepoSectionName}/${fieldText}/01.md`; // Other files are title.md, sub-title.md @@ -106,12 +106,12 @@ export async function checkSupportReferenceInTA(fieldName, fieldText, givenLocat taFileContent = await getFile_({ username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }); // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); if (!taFileContent) - addNoticePartial({ priority: 889, message: `Unable to find TA link`, extract: fieldText, location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 889, message: `Unable to find TA link`, excerpt: fieldText, location: `${ourLocation} ${filepath}` }); else if (taFileContent.length < 10) - addNoticePartial({ priority: 887, message: `Linked TA article seems empty`, extract: fieldText, location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 887, message: `Linked TA article seems empty`, excerpt: fieldText, location: `${ourLocation} ${filepath}` }); } catch (trcGCerror) { // console.error("checkSupportReferenceInTA() failed to load", taRepoUsername, taRepoName, filepath, taRepoBranch, trcGCerror.message); - addNoticePartial({ priority: 888, message: `Error loading TA link`, extract: fieldText, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + addNoticePartial({ priority: 888, message: `Error loading TA link`, excerpt: fieldText, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); } // functionLog(`checkSupportReferenceInTA is returning ${JSON.stringify(ctarResult)}`); diff --git a/src/core/text-handling-functions.js b/src/core/text-handling-functions.js index 6c6c062e8..34f030f6e 100644 --- a/src/core/text-handling-functions.js +++ b/src/core/text-handling-functions.js @@ -1,4 +1,4 @@ -export const DEFAULT_EXTRACT_LENGTH = 15; +export const DEFAULT_EXCERPT_LENGTH = 15; // See http://xahlee.info/comp/unicode_matching_brackets.html for a more complete list diff --git a/src/core/tn-links-check.js b/src/core/tn-links-check.js index cabed4627..42702727b 100644 --- a/src/core/tn-links-check.js +++ b/src/core/tn-links-check.js @@ -1,7 +1,7 @@ import localforage from 'localforage'; import Path from 'path'; import * as books from '../core/books/books'; -import { DEFAULT_EXTRACT_LENGTH, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, countOccurrences } from './text-handling-functions' import { cachedGetFile, checkMarkdownText } from '../core'; import { userLog, debugLog, parameterAssert, logicAssert, ourParseInt } from './utilities'; // import { consoleLogObject } from '../core/utilities'; @@ -131,15 +131,15 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const ctarResult = { noticeList: [], checkedFileCount: 0, checkedFilenames: [], checkedRepoNames: [] }; function addNoticePartial(noticeObject) { - // functionLog(`checkTNLinksToOutside Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkTNLinksToOutside Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cTNlnk addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cTNlnk addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cTNlnk addNoticePartial: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cTNlnk addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex !== undefined, "cTNlnk addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cTNlnk addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cTNlnk addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cTNlnk addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cTNlnk addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cTNlnk addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cTNlnk addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cTNlnk addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); // noticeObject.debugChain = noticeObject.debugChain ? `checkTNLinksToOutside ${noticeObject.debugChain}` : `checkTNLinksToOutside(${fieldName})`; @@ -149,18 +149,18 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Main code for checkTNLinksToOutside // Get any options that were suppplied, or else set default values - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (trcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const getFile_ = (checkingOptions && checkingOptions?.getFile) ? checkingOptions?.getFile : cachedGetFile; @@ -218,12 +218,12 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f let languageCode = regexResultArray[1]; if (languageCode !== '*') { const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); } else { // At the moment, tC can’t handle these links with * so we have to ensure that they're not there const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, extract, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); } if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; const taRepoName = `${languageCode}_ta`; @@ -240,14 +240,14 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); } catch (trcGCerror) { // console.error(`checkTNLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); - addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, extract: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); alreadyGaveError = true; } if (!alreadyGaveError) { if (!taFileContent) - addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, extract: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else if (taFileContent.length < 10) - addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, extract: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else if (checkingOptions?.checkLinkedTAArticleFlag === true) { // functionLog(`checkTNLinksToOutside got ${checkingOptions?.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); if (await alreadyChecked(taPathParameters) !== true) { @@ -291,13 +291,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // debugLog("Fetched fileContent for", twRepoName, filepath, typeof fileContent, fileContent.length); } catch (trcGCerror) { console.error(`checkTNLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); - addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, extract: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); } if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, extract: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else { // we got the content of the TW article if (twFileContent.length < 10) - addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, extract: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else if (checkingOptions?.checkLinkedTWArticleFlag === true) { // functionLog(`checkTNLinksToOutside got ${checkingOptions?.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); if (await alreadyChecked(twPathParameters) !== true) { @@ -334,7 +334,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const checkResult = books.isGoodEnglishBookName(optionalB1); // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation }); + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } @@ -344,19 +344,19 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (C1 === undefined) { if (!books.isOneChapterBook(linkBookCode)) { // debugLog(` checkTNLinksToOutside C1 missing in THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); } C1 = '0'; // Try to avoid consequential errors } try { if (ourParseInt(C1) !== givenCint) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${givenCint}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${givenCint}`, excerpt: totalLink, location: ourLocation }); } catch (ccError) { console.error(`TN Link Check1 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); } try { if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check1 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); } @@ -372,9 +372,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenCint); } catch (tlcNVerror) { } if (!givenCint || givenCint < 1 || givenCint > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${givenCint} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${givenCint} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenCint}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenCint}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -393,7 +393,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f linkChapterInt = ourParseInt(C2); linkVerseInt = ourParseInt(V2); if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${V2}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${V2}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check1b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1} with ${C2}:${V2} from '${fieldText}': ${vvError}`); } @@ -409,9 +409,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); } catch (tlcNVerror) { } if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -432,12 +432,12 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f linkChapterInt = ourParseInt(C2); linkVerseInt = ourParseInt(V2); if (verseInt1a !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${V2}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${V2}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check1c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1a} with ${C2}:${V2} from '${fieldText}': ${vvError}`); } if (verseInt1b <= verseInt1a) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers @@ -450,9 +450,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); } catch (tlcNVerror) { } if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -471,7 +471,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const checkResult = books.isGoodEnglishBookName(optionalB1); // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation }); + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } @@ -480,13 +480,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); } catch (ccError) { console.error(`TN Link Check2 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); } try { if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check2 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); } @@ -502,9 +502,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); } catch (tlcNVerror) { } if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -523,7 +523,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const checkResult = books.isGoodEnglishBookName(optionalB1); // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation }); + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } @@ -532,19 +532,19 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); } catch (ccError) { console.error(`TN Link Check2b couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); } try { if (ourParseInt(V1a) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check2b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); } try { if (ourParseInt(V1b) <= ourParseInt(V1a)) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check2c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); } @@ -560,9 +560,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); } catch (tlcNVerror) { } if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -581,7 +581,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const checkResult = books.isGoodEnglishBookName(optionalB1); // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation }); + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } @@ -590,13 +590,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const linkVerseInt = ourParseInt(V2); try { if (ourParseInt(V1a) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check2d couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); } try { if (ourParseInt(V1b) <= ourParseInt(V1a)) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check2e couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); } @@ -612,7 +612,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenC); } catch (tlcNVerror) { } if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenC}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenC}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -631,7 +631,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const checkResult = books.isGoodEnglishBookName(optionalB1); // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation }); + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } @@ -640,13 +640,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); } catch (ccError) { console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); } try { if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); } @@ -662,9 +662,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); } catch (tlcNVerror) { } if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } @@ -684,7 +684,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const checkResult = books.isGoodEnglishBookName(optionalB1); // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 144, message: "Unknown Bible book name in TN link", details: totalLink, extract: optionalB1, location: ourLocation }); + addNoticePartial({ priority: 144, message: "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } @@ -693,13 +693,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown TN link don’t match", details: `${C1} vs ${linkChapterInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown TN link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); } catch (ccError) { console.error(`TN Link Check3b couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); } try { if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 752, message: "Verse numbers of markdown TN link don’t match", details: `${V1} vs ${linkVerseInt}`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 752, message: "Verse numbers of markdown TN link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); } catch (vvError) { console.error(`TN Link Check3b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); } @@ -715,9 +715,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); } catch (tlcNVerror) { } if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 656, message: "Bad chapter number in markdown TN link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 656, message: "Bad chapter number in markdown TN link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 654, message: "Bad verse number in markdown TN link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, extract: totalLink, location: ourLocation }); + addNoticePartial({ priority: 654, message: "Bad verse number in markdown TN link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } // TODO: We should see if we can find the correct note diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index 8156908b6..fc6e830e2 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; @@ -30,7 +30,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * @param {string} givenC - chapter number or (for OBS) story number string * @param {string} givenV - verse number or (for OBS) frame number string * @param {string} givenRowLocation - description of where the line is located - * @param {Object} checkingOptions - may contain extractLength, twRepoUsername, twRepoBranch (or tag), checkLinkedTWArticleFlag parameters + * @param {Object} checkingOptions - may contain excerptLength, twRepoUsername, twRepoBranch (or tag), checkLinkedTWArticleFlag parameters * @return {Object} - containing noticeList */ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { @@ -73,11 +73,11 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv * @param {string} rowID - 4-character row ID field * @param {Number} lineNumber - one-based line number * @param {Number} characterIndex - zero-based index of where the issue occurs in the line - * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ function addNoticePartial(noticeObject) { - // functionLog(`checkTN_TSVDataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + // functionLog(`checkTN_TSVDataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "checkTN_TSVDataRow addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `checkTN_TSVDataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "checkTN_TSVDataRow addNoticePartial: 'message' parameter should be defined"); @@ -86,8 +86,8 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // parameterAssert(typeof lineNumber === 'number', `checkTN_TSVDataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); // parameterAssert(characterIndex !== undefined, "checkTN_TSVDataRow addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkTN_TSVDataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "checkTN_TSVDataRow addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkTN_TSVDataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "checkTN_TSVDataRow addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkTN_TSVDataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "checkTN_TSVDataRow addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `checkTN_TSVDataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); // noticeObject.debugChain = noticeObject.debugChain ? `checkTN_TSVDataRow ${noticeObject.debugChain}` : 'checkTN_TSVDataRow'; @@ -334,18 +334,18 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv if (line === EXPECTED_TN_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (tlcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -369,7 +369,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // Check the fields one-by-one if (B.length) { if (B !== bookID) - addNoticePartial({ priority: 978, message: "Wrong book identifier", details: `expected '${bookID}'`, fieldName: 'Book', rowID, extract: B, location: ourRowLocation }); + addNoticePartial({ priority: 978, message: "Wrong book identifier", details: `expected '${bookID}'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation }); } else addNoticePartial({ priority: 977, message: "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation }); @@ -377,17 +377,17 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv let numVersesThisChapter, haveGoodChapterNumber; if (C.length) { if (C !== givenC) - addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Chapter', rowID, extract: C, location: ourRowLocation }); + addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation }); if (C === 'front') { } else if (/^\d+$/.test(C)) { let intC = Number(C); if (intC === 0) { - addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); + addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); haveGoodChapterNumber = false; } // TODO: Does this next section need rewriting (see verse check below)??? else if (intC > numChaptersThisBook) { - addNoticePartial({ priority: 823, message: `Invalid large chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); + addNoticePartial({ priority: 823, message: `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); haveGoodChapterNumber = false; } try { @@ -397,28 +397,28 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv if (!haveGoodBookID) // addNoticePartial({priority:500, "Invalid chapter number", rowLocation); // else - addNoticePartial({ priority: 822, message: "Unable to check chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); + addNoticePartial({ priority: 822, message: "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); haveGoodChapterNumber = false; } } else - addNoticePartial({ priority: 821, message: "Bad chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); + addNoticePartial({ priority: 821, message: "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation }); } else addNoticePartial({ priority: 820, message: "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:${V}${ourRowLocation}` }); if (V.length) { if (V !== givenV) - addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Verse', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation }); if (bookID === 'OBS' || V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d as verse zero - addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation }); else { if (haveGoodChapterNumber) { if (intV > numVersesThisChapter) - addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation }); } else addNoticePartial({ priority: 812, message: "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation }); } @@ -433,20 +433,20 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv addNoticePartial({ priority: 779, message: "Missing row ID field", fieldName: 'Verse', location: ourRowLocation }); else { if (rowID.length !== 4) { - addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); if (rowID.length > 4) RIDSuggestion = rowID.substring(0, 5); else { // must be < 4 RIDSuggestion = rowID; while (RIDSuggestion.length < 4) RIDSuggestion += LC_ALPHABET_PLUS_DIGITS[Math.floor(Math.random() * LC_ALPHABET_PLUS_DIGITS.length)];; } } else if (LC_ALPHABET.indexOf(rowID[0]) < 0) - addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS.indexOf(rowID[3]) < 0) - addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[1]) < 0) - addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[2]) < 0) - addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation }); } if (supportReference.length) { // need to check TN2 against TA @@ -458,12 +458,12 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv && !supportReference.startsWith('translate-') && !supportReference.startsWith('writing-') && supportReference !== 'guidelines-sonofgodprinciples') - addNoticePartial({ priority: 788, message: "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); + addNoticePartial({ priority: 788, message: "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation }); SRSuggestion = ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, checkingOptions); if (!checkingOptions?.disableAllLinkFetchingFlag) await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, checkingOptions); if (occurrenceNote.indexOf(supportReference) < 0) // The full link is NOT in the note! - addNoticePartial({ priority: 787, message: "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); + addNoticePartial({ priority: 787, message: "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation }); } if (supportReference.indexOf('\u200B') >= 0) { const charCount = countOccurrences(supportReference, '\u200B'); @@ -488,7 +488,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn’t occur if (origQuote.length) { - addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } // if (V !== 'intro') @@ -497,7 +497,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv else if (occurrence === '-1') // TODO check the special conditions when this can occur??? ; else if ('1234567'.indexOf(occurrence) < 0) { // it’s not one of these integers - addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } } @@ -536,7 +536,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // debugLog("Got TA Regex in OccurrenceNote", JSON.stringify(regexResultArray)); if (supportReference !== regexResultArray[1] && V !== 'intro') { const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', extract: regexResultArray[1], location: ourRowLocation }); + addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation }); } } } diff --git a/src/core/tn-tsv9-table-check.js b/src/core/tn-tsv9-table-check.js index a21f1db38..5a86071c6 100644 --- a/src/core/tn-tsv9-table-check.js +++ b/src/core/tn-tsv9-table-check.js @@ -1,5 +1,5 @@ import * as books from './books/books'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTN_TSVDataRow } from './tn-tsv9-row-check'; import { removeDisabledNotices } from './disabled-notices'; import { debugLog, parameterAssert } from './utilities'; @@ -59,7 +59,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex * @param {Object} noticeObject */ function addNoticePartial(noticeObject) { - // functionLog(`checkTN_TSV9Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkTN_TSV9Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "TSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "TSV addNoticePartial: 'message' parameter should be defined"); @@ -70,8 +70,8 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `TSV addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); // parameterAssert(characterIndex !== undefined, "TSV addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `TSV addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "TSV addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "TSV addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `TSV addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "TSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); if (noticeObject.debugChain) noticeObject.debugChain = `checkTN_TSV9Table ${noticeObject.debugChain}`; @@ -82,18 +82,18 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex } - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (ttcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); @@ -104,7 +104,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${ourLocation}` }); } let lines = tableText.split('\n'); @@ -186,9 +186,9 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex if (C !== lastC) numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (intC > numChaptersThisBook) - addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) @@ -208,13 +208,13 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d titles - addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (intV > numVersesThisChapter) - addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (C === lastC && intV < lastintV) - addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); // else if (intV > lastintV + 1) // addNoticePartial({priority:556, "Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } @@ -245,7 +245,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex try { C = fields[1]; } catch { } try { V = fields[2]; } catch { } try { rowID = fields[3]; } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index 8a0204dde..7992ef50b 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; @@ -28,7 +28,7 @@ const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz012345678 * @param {string} givenC - chapter number or (for OBS) story number string * @param {string} givenV - verse number or (for OBS) frame number string * @param {string} givenRowLocation - description of where the line is located - * @param {Object} checkingOptions - may contain extractLength parameter + * @param {Object} checkingOptions - may contain excerptLength parameter * @return {Object} - containing noticeList */ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { @@ -80,10 +80,10 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, * @param {string} rowID - 4-character row ID field * @param {Number} lineNumber - one-based line number * @param {Number} characterIndex - zero-based index of where the issue occurs in the line - * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkTWL_TSV6DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.extract}, ${noticeObject.location}`); + // functionLog(`checkTWL_TSV6DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `checkTWL_TSV6DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'message' parameter should be defined"); @@ -92,8 +92,8 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, // parameterAssert(typeof lineNumber === 'number', `checkTWL_TSV6DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); // parameterAssert(characterIndex !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkTWL_TSV6DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `checkTWL_TSV6DataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkTWL_TSV6DataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "checkTWL_TSV6DataRow addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `checkTWL_TSV6DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -313,18 +313,18 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (line === EXPECTED_TWL_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (tlcELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -354,17 +354,17 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, let numVersesThisChapter, haveGoodChapterNumber; if (C.length) { if (C !== givenC) - addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation }); + addNoticePartial({ priority: 976, message: "Wrong chapter number", details: `expected '${givenC}'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation }); if (C === 'front') { } else if (/^\d+$/.test(C)) { let intC = Number(C); if (intC === 0) { - addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 824, message: `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } // TODO: Does this next section need rewriting (see verse check below)??? else if (intC > numChaptersThisBook) { - addNoticePartial({ priority: 823, message: `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 823, message: `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } if (lowercaseBookID === 'obs') @@ -377,29 +377,29 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (!haveGoodBookID) // addNoticePartial({priority:500, "Invalid chapter number", rowLocation); // else - addNoticePartial({ priority: 822, message: "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 822, message: "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); haveGoodChapterNumber = false; } } } else - addNoticePartial({ priority: 821, message: "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation }); + addNoticePartial({ priority: 821, message: "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation }); } else addNoticePartial({ priority: 820, message: "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:${V}${ourRowLocation}` }); if (V.length) { if (V !== givenV) - addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 975, message: "Wrong verse number", details: `expected '${givenV}'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); if (bookID === 'OBS' || V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d as verse zero - addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 814, message: "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); else { if (haveGoodChapterNumber) { if (intV > numVersesThisChapter) - addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation }); + addNoticePartial({ priority: 813, message: "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation }); } else addNoticePartial({ priority: 812, message: "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation }); } @@ -414,20 +414,20 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, addNoticePartial({ priority: 779, message: "Missing row ID field", fieldName: 'Reference', location: ourRowLocation }); else { if (rowID.length !== 4) { - addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 778, message: "Row ID should be exactly 4 characters", details: `not ${rowID.length}`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); if (rowID.length > 4) RIDSuggestion = rowID.substring(0, 5); else { // must be < 4 RIDSuggestion = rowID; while (RIDSuggestion.length < 4) RIDSuggestion += LC_ALPHABET_PLUS_DIGITS[Math.floor(Math.random() * LC_ALPHABET_PLUS_DIGITS.length)];; } } else if (LC_ALPHABET.indexOf(rowID[0]) < 0) - addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS.indexOf(rowID[3]) < 0) - addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 175, message: "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[1]) < 0) - addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 174, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation }); else if (LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN.indexOf(rowID[2]) < 0) - addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, extract: rowID, location: ourRowLocation }); + addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation }); } if (tags.length) @@ -447,7 +447,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn’t occur if (quote.length) { - addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } // if (V !== 'intro') @@ -456,7 +456,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, else if (occurrence === '-1') // TODO check the special conditions when this can occur??? ; else if ('1234567'.indexOf(occurrence) < 0) { // it’s not one of these integers - addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation }); + addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } } @@ -481,7 +481,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, // // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) // // if (supportReference !== adjustedLink && V !== 'intro') { // // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - // // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation }); + // // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', excerpt: adjustedLink, location: ourRowLocation }); // // } // } } diff --git a/src/core/twl-tsv6-table-check.js b/src/core/twl-tsv6-table-check.js index d8b75faed..b6c33d561 100644 --- a/src/core/twl-tsv6-table-check.js +++ b/src/core/twl-tsv6-table-check.js @@ -1,5 +1,5 @@ import * as books from './books/books'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTWL_TSV6DataRow } from './twl-tsv6-row-check'; import { removeDisabledNotices } from './disabled-notices'; import { functionLog, parameterAssert } from './utilities'; @@ -52,7 +52,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam carResult.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkTWL_TSV6Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkTWL_TSV6Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); @@ -63,8 +63,8 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `TSV addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); // parameterAssert(characterIndex !== undefined, "ATSV addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `TSV addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "ATSV addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "ATSV addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `TSV addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -73,18 +73,18 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam } - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (ttcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); @@ -98,7 +98,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + addNoticePartial({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${ourLocation}` }); } } @@ -178,9 +178,9 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam else numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 551, C, V, message: `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (intC > numChaptersThisBook) - addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation }); + addNoticePartial({ priority: 737, C, V, message: "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) @@ -200,13 +200,13 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0 && bookID !== 'PSA') // Psalms have \d titles - addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 552, C, V, message: "Invalid zero verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (intV > numVersesThisChapter) - addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 734, C, V, message: "Invalid large verse number", details: `for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (C === lastC && intV < lastintV) - addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, extract: V, location: ourLocation }); + addNoticePartial({ priority: 733, C, V, message: "Receding verse number", details: `'${V}' after '${lastV} for chapter ${C}`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation }); // else if (intV > lastintV + 1) // addNoticePartial({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } @@ -237,7 +237,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TWL_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TWL_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/usfm-js-check.js b/src/core/usfm-js-check.js index ecaec7810..b7002d6f3 100644 --- a/src/core/usfm-js-check.js +++ b/src/core/usfm-js-check.js @@ -54,27 +54,27 @@ export function checkUSFMToJSON(bookID, filename, givenText, givenLocation, chec // functionLog(`checkUSFMToJSON success: ${successString}`); result.successList.push(successString); } - function addNotice6to7({ priority, message, lineNumber, characterIndex, extract, location }) { + function addNotice6to7({ priority, message, lineNumber, characterIndex, excerpt, location }) { /** * @description - adds a new notice entry, adding bookID,C,V to the given fields * @param {Number} priority - notice priority from 1 (lowest) to 999 (highest) * @param {string} message - the text of the notice message * @param {Number} characterIndex - where the issue occurs in the line - * @param {string} extract - short extract from the line centred on the problem (if available) + * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkUSFMToJSON notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkUSFMToJSON notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(priority !== undefined, "cUSFMjs addNotice6to7: 'priority' parameter should be defined"); parameterAssert(typeof priority === 'number', `cUSFMjs addNotice6to7: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); parameterAssert(message !== undefined, "cUSFMjs addNotice6to7: 'message' parameter should be defined"); parameterAssert(typeof message === 'string', `cUSFMjs addNotice6to7: 'message' parameter should be a string not a '${typeof message}': ${message}`); // parameterAssert(characterIndex !== undefined, "cUSFMjs addNotice6to7: 'characterIndex' parameter should be defined"); if (characterIndex) parameterAssert(typeof characterIndex === 'number', `cUSFMjs addNotice6to7: 'characterIndex' parameter should be a number not a '${typeof characterIndex}': ${characterIndex}`); - // parameterAssert(extract !== undefined, "cUSFMjs addNotice6to7: 'extract' parameter should be defined"); - if (extract) parameterAssert(typeof extract === 'string', `cUSFMjs addNotice6to7: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); + // parameterAssert(excerpt !== undefined, "cUSFMjs addNotice6to7: 'excerpt' parameter should be defined"); + if (excerpt) parameterAssert(typeof excerpt === 'string', `cUSFMjs addNotice6to7: 'excerpt' parameter should be a string not a '${typeof excerpt}': ${excerpt}`); parameterAssert(location !== undefined, "cUSFMjs addNotice6to7: 'location' parameter should be defined"); parameterAssert(typeof location === 'string', `cUSFMjs addNotice6to7: 'location' parameter should be a string not a '${typeof location}': ${location}`); - result.noticeList.push({ priority, message, bookID, lineNumber, characterIndex, extract, location }); + result.noticeList.push({ priority, message, bookID, lineNumber, characterIndex, excerpt, location }); } diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index b4c80d91a..5238b4a4a 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH, isWhitespace, countOccurrences, ourDeleteAll } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences, ourDeleteAll } from './text-handling-functions' import * as books from '../core/books/books'; import { checkTextField } from './field-text-check'; import { checkTextfileContents } from './file-text-check'; @@ -164,18 +164,18 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (usfmELerror) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength} cf. default=${DEFAULT_EXTRACT_LENGTH}`); - const halfLength = Math.floor(extractLength / 2); // rounded down - const halfLengthPlus = Math.floor((extractLength + 1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength} cf. default=${DEFAULT_EXCERPT_LENGTH}`); + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -191,7 +191,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } function addNoticePartial(noticeObject) { // debugLog("checkUSFMText addNoticePartial:", JSON.stringify(noticeObject)); - // functionLog(`checkUSFMText addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.C}:${noticeObject.V} ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? ` ${noticeObject.extract}` : ""}${noticeObject.location}`); + // functionLog(`checkUSFMText addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.C}:${noticeObject.V} ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? ` ${noticeObject.excerpt}` : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cUSFM addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cUSFM addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cUSFM addNoticePartial: 'message' parameter should be defined"); @@ -202,8 +202,8 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `cUSFM addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); // parameterAssert(characterIndex !== undefined, "cUSFM addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex !== undefined) parameterAssert(typeof noticeObject.characterIndex === 'number', `cUSFM addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cUSFM addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cUSFM addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cUSFM addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cUSFM addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cUSFM addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cUSFM addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); @@ -231,9 +231,9 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // We only get one error if it fails if (grammarCheckResult.error && grammarCheckResult.error.priority) // Prevent these false alarms (from Ohm schema issues, esp. empty lemma="" fields) - if (!grammarCheckResult.error.extract - // Note: checking the extract might not always be reliable if they choose a length < 10 - || (grammarCheckResult.error.extract.indexOf('mma="" ') < 0 // see https://github.com/Bridgeconn/usfm-grammar/issues/87 + if (!grammarCheckResult.error.excerpt + // Note: checking the excerpt might not always be reliable if they choose a length < 10 + || (grammarCheckResult.error.excerpt.indexOf('mma="" ') < 0 // see https://github.com/Bridgeconn/usfm-grammar/issues/87 && grammarCheckResult.error.message.indexOf('Expected "c", "v", ') < 0 // forgotten what this prevents ??? && grammarCheckResult.error.message.indexOf('Expected "f*", "+", ') < 0 // see https://github.com/Bridgeconn/usfm-grammar/issues/86 )) @@ -414,7 +414,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex userLog(`CVCheck couldn’t convert ${bookID} chapter '${chapterNumberString}': ${usfmCIerror}`); } if (chapterInt < 1 || chapterInt > expectedVersesPerChapterList.length) - addNoticePartial({ priority: 869, message: "Chapter number out of range", C: chapterNumberString, extract: `${bookID} ${chapterNumberString}`, location: CVlocation }); + addNoticePartial({ priority: 869, message: "Chapter number out of range", C: chapterNumberString, excerpt: `${bookID} ${chapterNumberString}`, location: CVlocation }); else { let discoveredVerseList = [], discoveredVerseWithTextList = []; // debugLog(`Chapter ${chapterNumberString} verses ${Object.keys(result1.returnedJSON.chapters[chapterNumberString])}`); @@ -441,7 +441,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex discoveredVerseWithTextList.push(v); } } catch (usfmVIerror) { - addNoticePartial({ priority: 762, message: "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, extract: verseNumberString, location: `${CVlocation} with ${usfmVIerror}` }); + addNoticePartial({ priority: 762, message: "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `${CVlocation} with ${usfmVIerror}` }); } } else { // It’s NOT a verse bridge let verseInt; @@ -453,7 +453,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } if (verseInt < 1 || verseInt > expectedVersesPerChapterList[chapterInt - 1]) - addNoticePartial({ priority: 868, message: "Verse number out of range", C: chapterNumberString, V: verseNumberString, extract: `${bookID} ${chapterNumberString}:${verseNumberString}`, location: CVlocation }); + addNoticePartial({ priority: 868, message: "Verse number out of range", C: chapterNumberString, V: verseNumberString, excerpt: `${bookID} ${chapterNumberString}:${verseNumberString}`, location: CVlocation }); if (verseHasText) discoveredVerseWithTextList.push(verseInt); @@ -564,7 +564,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const lCount = countOccurrences(fileText, opener); const rCount = countOccurrences(fileText, closer); if (lCount !== rCount) - addNoticePartial({ priority: 873, message: `Mismatched ${opener}${closer} fields`, extract: `(left=${lCount.toLocaleString()}, right=${rCount.toLocaleString()})`, location: fileLocation }); + addNoticePartial({ priority: 873, message: `Mismatched ${opener}${closer} fields`, excerpt: `(left=${lCount.toLocaleString()}, right=${rCount.toLocaleString()})`, location: fileLocation }); } } // end of checkUSFMCharacterFields function @@ -594,22 +594,22 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex for (const compulsoryMarker of COMPULSORY_MARKERS) if (!markerSet.has(compulsoryMarker)) - addNoticePartial({ priority: 819, message: "Missing compulsory USFM line", extract: `missing \\${compulsoryMarker}`, location: fileLocation }); + addNoticePartial({ priority: 819, message: "Missing compulsory USFM line", excerpt: `missing \\${compulsoryMarker}`, location: fileLocation }); for (const expectedMarker of EXPECTED_MARKERS) if (!markerSet.has(expectedMarker) && (!expectedMarker.endsWith('1') || !markerSet.has(expectedMarker.substring(0, expectedMarker.length - 1)))) - addNoticePartial({ priority: 519, message: "Missing expected USFM line", extract: `missing \\${expectedMarker}`, location: fileLocation }); + addNoticePartial({ priority: 519, message: "Missing expected USFM line", excerpt: `missing \\${expectedMarker}`, location: fileLocation }); if (books.isExtraBookID(bookID)) for (const expectedMarker of EXPECTED_PERIPHERAL_BOOK_MARKERS) if (!markerSet.has(expectedMarker)) - addNoticePartial({ priority: 517, message: "Missing expected USFM line", extract: `missing \\${expectedMarker}`, location: fileLocation }); + addNoticePartial({ priority: 517, message: "Missing expected USFM line", excerpt: `missing \\${expectedMarker}`, location: fileLocation }); else for (const expectedMarker of EXPECTED_BIBLE_BOOK_MARKERS) if (!markerSet.has(expectedMarker)) - addNoticePartial({ priority: 518, message: "Missing expected USFM line", extract: `missing \\${expectedMarker}`, location: fileLocation }); + addNoticePartial({ priority: 518, message: "Missing expected USFM line", excerpt: `missing \\${expectedMarker}`, location: fileLocation }); for (const deprecatedMarker of DEPRECATED_MARKERS) if (markerSet.has(deprecatedMarker)) - addNoticePartial({ priority: 218, message: "Using deprecated USFM marker", extract: `\\${deprecatedMarker}`, location: fileLocation }); + addNoticePartial({ priority: 218, message: "Using deprecated USFM marker", excerpt: `\\${deprecatedMarker}`, location: fileLocation }); } // end of checkUSFMFileContents function @@ -656,8 +656,8 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const ixWordEnd = adjustedRest.indexOf('|'); if (ixWordEnd < 0 && adjustedRest.indexOf('lemma="') >= 0) { const characterIndex = 5; // Presumably, a little bit into the word - const extract = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') - addNoticePartial({ priority: 912, message: 'Missing | character in \\w line', lineNumber, C, V, characterIndex, extract, location: lineLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + addNoticePartial({ priority: 912, message: 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); } parameterAssert(ixWordEnd >= 1, `Why1 is w| = ${ixWordEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); ixEnd = adjustedRest.indexOf('\\w*'); @@ -712,8 +712,8 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const ixWordEnd = adjustedRest.indexOf('|'); if (ixWordEnd < 0 && adjustedRest.indexOf('lemma="') >= 0) { const characterIndex = nextWIndex + 5; // Presumably, a little bit into the word - const extract = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') - addNoticePartial({ priority: 911, message: 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, extract, location: lineLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + addNoticePartial({ priority: 911, message: 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); adjustedRest = ''; // Avoid follow-on errors break; } @@ -746,21 +746,21 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (adjustedRest) { let characterIndex; if ((characterIndex = adjustedRest.indexOf('"')) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') - addNoticePartial({ priority: 776, message: 'Unexpected " straight quote character', details, lineNumber, C, V, extract, location: lineLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + addNoticePartial({ priority: 776, message: 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation }); // debugLog(`ERROR 776: in ${marker} '${adjustedRest}' from '${rest}'`); } if ((characterIndex = adjustedRest.indexOf("'")) >= 0) { - const extract = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') - addNoticePartial({ priority: 775, message: "Unexpected ' straight quote character", details, lineNumber, C, V, extract, location: lineLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + addNoticePartial({ priority: 775, message: "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation }); // debugLog(`ERROR 775: in ${marker} '${adjustedRest}' from '${rest}'`); } if (adjustedRest.indexOf('\\') >= 0 || adjustedRest.indexOf('|') >= 0) { // functionLog(`checkUSFMLineText ${languageCode} ${filename} ${lineNumber} ${C}:${V} somehow ended up with ${marker}='${adjustedRest}'`); characterIndex = adjustedRest.indexOf('\\'); if (characterIndex === -1) characterIndex = adjustedRest.indexOf('|'); - const extract = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') - addNoticePartial({ priority: 875, message: "Unexpected USFM field", details, lineNumber, C, V, extract, location: lineLocation }); + const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + addNoticePartial({ priority: 875, message: "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation }); } if (adjustedRest !== rest) // Only re-check if line has changed (because original is checked in checkUSFMLineInternals()) // Note: false (below) is for allowedLinks flag @@ -805,44 +805,44 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (repoCode === 'UHB' || repoCode === 'UGNT') { if (attributeCounter === 1) { if (attributeName !== 'lemma') - addNoticePartial({ priority: 857, message: "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 857, message: "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 2) { if (attributeName !== 'strong') - addNoticePartial({ priority: 856, message: "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 856, message: "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 3) { if (attributeName !== 'x-morph') - addNoticePartial({ priority: 855, message: "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 855, message: "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 4) { if (attributeName !== 'x-tw') // we can have TWO of these -- THREE EVEN in EXO 15:23 and 1KI 21:9!!! - addNoticePartial({ priority: 854, message: "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 854, message: "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 5) { if (attributeName !== 'x-tw') - addNoticePartial({ priority: 854, message: "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 854, message: "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 6) { if (attributeName !== 'x-tw') - addNoticePartial({ priority: 854, message: "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 854, message: "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else // #7 or more - addNoticePartial({ priority: 853, message: "Unexpected extra original \\w attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 853, message: "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); if (attributeName === 'x-morph' && ((repoCode === 'UHB' && !attributeValue.startsWith('He,') && !attributeValue.startsWith('Ar,')) || (repoCode === 'UGNT' && !attributeValue.startsWith('Gr,')))) - addNoticePartial({ priority: 852, message: "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 852, message: "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else { // a translation -- not UHB or UGNT if (attributeCounter === 1) { if (attributeName !== 'x-occurrence') - addNoticePartial({ priority: 848, message: "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 848, message: "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 2) { if (attributeName !== 'x-occurrences') - addNoticePartial({ priority: 847, message: "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 847, message: "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else // #3 or more - addNoticePartial({ priority: 846, message: "Unexpected extra translation \\w attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 846, message: "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } } if (repoCode === 'UHB' || repoCode === 'UGNT') { if (attributeCounter < 3) - addNoticePartial({ priority: 837, message: "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found ${attributeCounter}`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation }); + addNoticePartial({ priority: 837, message: "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found ${attributeCounter}`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation }); } else if (attributeCounter < 2) - addNoticePartial({ priority: 836, message: "Seems too few translation \\w attributes", details: `Expected two attributes but only found ${attributeCounter}`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation }); + addNoticePartial({ priority: 836, message: "Seems too few translation \\w attributes", details: `Expected two attributes but only found ${attributeCounter}`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation }); } while ((regexResultArray1 = KS_REGEX.exec(adjustedRest))) { // debugLog(`Got ${repoCode} \\k-s Regex in ${C}:${V} line: '${JSON.stringify(regexResultArray1)}`); @@ -854,12 +854,12 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const attributeName = regexResultArray2[1]; //, attributeValue = regexResultArray2[2]; if (attributeCounter === 1) { if (attributeName !== 'x-tw') - addNoticePartial({ priority: 839, message: "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 839, message: "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else // #2 or more - addNoticePartial({ priority: 838, message: "Unexpected extra \\k-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 838, message: "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } if (attributeCounter < 1) - addNoticePartial({ priority: 835, message: "Seems too few original \\k-s attributes", details: `Expected one attribute but only found ${attributeCounter}`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation }); + addNoticePartial({ priority: 835, message: "Seems too few original \\k-s attributes", details: `Expected one attribute but only found ${attributeCounter}`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation }); } while ((regexResultArray1 = ZALNS_REGEX.exec(adjustedRest))) { // debugLog(`Got ${repoCode} \\zaln-s Regex in ${C}:${V} line: '${JSON.stringify(regexResultArray1)}`); @@ -871,27 +871,27 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const attributeName = regexResultArray2[1]; //, attributeValue = regexResultArray2[2]; if (attributeCounter === 1) { if (attributeName !== 'x-strong') - addNoticePartial({ priority: 830, message: "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 830, message: "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 2) { if (attributeName !== 'x-lemma') - addNoticePartial({ priority: 829, message: "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 829, message: "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 3) { if (attributeName !== 'x-morph') - addNoticePartial({ priority: 828, message: "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 828, message: "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 4) { if (attributeName !== 'x-occurrence') - addNoticePartial({ priority: 827, message: "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 827, message: "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 5) { if (attributeName !== 'x-occurrences') - addNoticePartial({ priority: 826, message: "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 826, message: "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else if (attributeCounter === 6) { if (attributeName !== 'x-content') - addNoticePartial({ priority: 825, message: "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 825, message: "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } else // #7 or more - addNoticePartial({ priority: 833, message: "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, extract: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 833, message: "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); } if (attributeCounter < 6) - addNoticePartial({ priority: 834, message: "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found ${attributeCounter}`, lineNumber, C, V, extract: regexResultArray1[0], location: lineLocation }); + addNoticePartial({ priority: 834, message: "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found ${attributeCounter}`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation }); } } // end of checkUSFMLineAttributes function @@ -916,15 +916,15 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // functionLog(`checkUSFMLineInternals(${lineNumber}, ${C}:${V}, ${marker}='${rest}', ${lineLocation}, ${JSON.stringify(checkingOptions)})…`); if (marker === 'c' && isNaN(rest)) - addNoticePartial({ priority: 822, message: "Expected field to contain an integer", lineNumber, characterIndex: 3, extract: `\\c ${rest}`, C, V, location: lineLocation }); + addNoticePartial({ priority: 822, message: "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c ${rest}`, C, V, location: lineLocation }); if (marker === 'v') { let Vstr = (rest) ? rest.split(' ', 1)[0] : '?'; if (isNaN(Vstr) && Vstr.indexOf('-') < 0) - addNoticePartial({ priority: 822, message: "Expected field to contain an integer", characterIndex: 3, extract: `\\v ${rest}`, C, V, location: lineLocation }); + addNoticePartial({ priority: 822, message: "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v ${rest}`, C, V, location: lineLocation }); } else if (marker === 'h' || marker === 'toc1' || marker === 'toc2' || marker === 'toc3') if (rest.toLowerCase() === rest || rest.toUpperCase() === rest) - addNoticePartial({ priority: languageCode === 'en' || languageCode === 'fr' ? 490 : 190, message: "Expected header field to contain a mixed-case string", fieldName: `\\${marker}`, extract: rest, C, V, location: lineLocation }); + addNoticePartial({ priority: languageCode === 'en' || languageCode === 'fr' ? 490 : 190, message: "Expected header field to contain a mixed-case string", fieldName: `\\${marker}`, excerpt: rest, C, V, location: lineLocation }); if (rest) { checkUSFMLineText(lineNumber, C, V, marker, rest, lineLocation, checkingOptions); @@ -945,9 +945,9 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (ALLOWED_LINE_START_MARKERS.indexOf(marker) >= 0 || marker === 'SPECIAL1') { if (rest && MARKERS_WITHOUT_CONTENT.indexOf(marker) >= 0) if (isWhitespace(rest)) - addNoticePartial({ priority: 301, message: `Unexpected whitespace after \\${marker} marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation }); + addNoticePartial({ priority: 301, message: `Unexpected whitespace after \\${marker} marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation }); else if (rest !== 'ס' && rest !== 'פ') // in UHB NEH 3:20 or EZR 3:18 - addNoticePartial({ priority: 401, message: `Unexpected content after \\${marker} marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation }); + addNoticePartial({ priority: 401, message: `Unexpected content after \\${marker} marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation }); else if (MARKERS_WITH_COMPULSORY_CONTENT.indexOf(marker) >= 0 && !rest) addNoticePartial({ priority: 711, message: "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\${marker} marker${lineLocation}` }); } else // it’s not a recognised line marker @@ -973,7 +973,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticePartial({ priority: 903, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); + addNoticePartial({ priority: 903, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${ourLocation}` }); } function findStartMarker(C, V, lineNumber, USFMline) { @@ -986,8 +986,8 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (char === ' ') break; // Cope with self-closing milestones like \k-s\* if (char === '\\' && (characterIndex === USFMline.length - 1 || USFMline[characterIndex + 1] !== '*')) { - const extract = USFMline.substring(0, extractLength) + (USFMline.length > extractLength ? '…' : ''); - addNoticePartial({ priority: 603, message: "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, extract, location: ourLocation }); + const excerpt = USFMline.substring(0, excerptLength) + (USFMline.length > excerptLength ? '…' : ''); + addNoticePartial({ priority: 603, message: "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation }); break; } foundMarker += char; @@ -1015,9 +1015,9 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } let characterIndex; if ((characterIndex = line.indexOf('\r')) >= 0) { - const iy = characterIndex + halfLength; // Want extract to focus more on what follows - const extract = (iy > halfLength ? '…' : '') + line.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < line.length ? '…' : '') - addNoticePartial({ priority: 703, C, V, message: "Unexpected CarriageReturn character", lineNumber: n, characterIndex, extract, location: ourLocation }); + const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > halfLength ? '…' : '') + line.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < line.length ? '…' : '') + addNoticePartial({ priority: 703, C, V, message: "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation }); } let marker, rest; @@ -1031,7 +1031,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex rest = line; if (validLineStartCharacters.indexOf(line[0]) < 0) { // These are the often expected characters // Drop the priority if it’s a "half-likely" character - addNoticePartial({ priority: `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, message: "Expected line to start with backslash", lineNumber: n, characterIndex: 0, extract: line[0], location: ourLocation }); + addNoticePartial({ priority: `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, message: "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation }); if (line[1] === '\\') { // Let’s drop the leading punctuation and try to check the rest of the line marker = line.substring(2).split(' ', 1)[0]; rest = line.substring(marker.length + 2 + 1); // Skip leading character, backslash, marker, and space after marker @@ -1053,11 +1053,11 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex try { intC = ourParseInt(C); } catch (usfmICerror) { - addNoticePartial({ priority: 724, C, V, message: "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 724, C, V, message: "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location: ourLocation }); intC = -999; // Used to prevent consequential errors } if (C === lastC || (intC > 0 && intC !== lastIntC + 1)) - addNoticePartial({ priority: 764, C, V, message: "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''} (${lastC ? lastC : '0'} → ${C})`, location: ourLocation }); + addNoticePartial({ priority: 764, C, V, message: "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''} (${lastC ? lastC : '0'} → ${C})`, location: ourLocation }); lastC = C; lastV = '0'; lastIntC = intC; lastIntV = 0; } else if (marker === 'v') { @@ -1066,11 +1066,11 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex try { intV = ourParseInt(V); } catch (usfmIVerror) { - addNoticePartial({ priority: 723, C, V, message: "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 723, C, V, message: "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location: ourLocation }); intV = -999; // Used to prevent consequential errors } if (V === lastV || (intV > 0 && intV !== lastIntV + 1)) - addNoticePartial({ priority: 763, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); + addNoticePartial({ priority: 763, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); lastV = V; lastIntV = intV; } else { // handle verse bridge const bits = V.split('-'); @@ -1080,13 +1080,13 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex intFirstV = ourParseInt(firstV); intSecondV = ourParseInt(secondV); } catch (usfmV12error) { - addNoticePartial({ priority: 762, C, V, message: "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, Math.max(9, extractLength))}${rest.length > extractLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 762, C, V, message: "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, Math.max(9, excerptLength))}${rest.length > excerptLength ? '…' : ''}`, location: ourLocation }); intFirstV = -999; intSecondV = -998; // Used to prevent consequential errors } if (intSecondV <= intFirstV) - addNoticePartial({ priority: 769, C, V, message: "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, Math.max(9, extractLength))}${rest.length > extractLength ? '…' : ''} (${firstV} → ${secondV})`, location: ourLocation }); + addNoticePartial({ priority: 769, C, V, message: "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, Math.max(9, excerptLength))}${rest.length > excerptLength ? '…' : ''} (${firstV} → ${secondV})`, location: ourLocation }); else if (firstV === lastV || (intFirstV > 0 && intFirstV !== lastIntV + 1)) - addNoticePartial({ priority: 766, C, V, message: "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `${rest.substring(0, Math.max(9, extractLength))}${rest.length > extractLength ? '…' : ''} (${lastV} → ${firstV})`, location: ourLocation }); + addNoticePartial({ priority: 766, C, V, message: "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, Math.max(9, excerptLength))}${rest.length > excerptLength ? '…' : ''} (${lastV} → ${firstV})`, location: ourLocation }); lastV = secondV; lastIntV = intSecondV; } } else if ((vIndex = rest.indexOf('\\v ')) >= 0) { @@ -1097,18 +1097,18 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex intV = parseInt(restRest); // debugLog("Got", intV); } catch (usfmIIVerror) { - addNoticePartial({ priority: 720, C, V, message: "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, extract: `${restRest.substring(0, halfLength)}${restRest.length > halfLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 720, C, V, message: "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `${restRest.substring(0, halfLength)}${restRest.length > halfLength ? '…' : ''}`, location: ourLocation }); intV = -999; // Used to prevent consequential errors } if (intV > 0 && intV !== lastIntV + 1) - addNoticePartial({ priority: 761, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, extract: `${restRest.substring(0, halfLength)}${restRest.length > halfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); + addNoticePartial({ priority: 761, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${restRest.substring(0, halfLength)}${restRest.length > halfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); lastV = intV.toString(); lastIntV = intV; } if (marker === 'id' && !rest.startsWith(bookID)) { - const thisLength = Math.max(4, extractLength); - const extract = `${rest.substring(0, thisLength)}${rest.length > thisLength ? '…' : ''}`; - addNoticePartial({ priority: 987, C, V, message: "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, extract, location: ourLocation }); + const thisLength = Math.max(4, excerptLength); + const excerpt = `${rest.substring(0, thisLength)}${rest.length > thisLength ? '…' : ''}`; + addNoticePartial({ priority: 987, C, V, message: "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation }); } // Check the order of markers diff --git a/src/core/yaml-text-check.js b/src/core/yaml-text-check.js index c4cd753f4..32354f80f 100644 --- a/src/core/yaml-text-check.js +++ b/src/core/yaml-text-check.js @@ -1,4 +1,4 @@ -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import yaml from 'yaml'; import { checkTextField } from './field-text-check'; import { checkTextfileContents } from './file-text-check'; @@ -34,18 +34,18 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; // if (textName) ourLocation = ` in ${textName}${ourLocation}`; - let extractLength; + let excerptLength; try { - extractLength = checkingOptions?.extractLength; + excerptLength = checkingOptions?.excerptLength; } catch (ytcError) { } - if (typeof extractLength !== 'number' || isNaN(extractLength)) { - extractLength = DEFAULT_EXTRACT_LENGTH; - // debugLog(`Using default extractLength=${extractLength}`); + if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { + excerptLength = DEFAULT_EXCERPT_LENGTH; + // debugLog(`Using default excerptLength=${excerptLength}`); } // else - // debugLog(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); - // const halfLength = Math.floor(extractLength / 2); // rounded down - // const halfLengthPlus = Math.floor((extractLength+1) / 2); // rounded up + // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); + // const halfLength = Math.floor(excerptLength / 2); // rounded down + // const halfLengthPlus = Math.floor((excerptLength+1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const cytResult = { successList: [], noticeList: [] }; @@ -55,15 +55,15 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c cytResult.successList.push(successString); } function addNotice(noticeObject) { - // functionLog(`checkYAMLText Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkYAMLText Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cYt addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cManT addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cYt addNotice: 'message' parameter should be defined"); parameterAssert(typeof noticeObject.message === 'string', `cManT addNotice: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); // parameterAssert(characterIndex!==undefined, "cYt addNotice: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cManT addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract!==undefined, "cYt addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cManT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt!==undefined, "cYt addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cManT addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cYt addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cYt addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); if (noticeObject.debugChain) noticeObject.debugChain = `checkYAMLText ${noticeObject.debugChain}`; diff --git a/src/core/yaml-text-check.md b/src/core/yaml-text-check.md index 76ce0b02c..fa14c2d5e 100644 --- a/src/core/yaml-text-check.md +++ b/src/core/yaml-text-check.md @@ -183,7 +183,7 @@ projects: path: './67-REV.usfm' categories: [ 'bible-nt' ] `; -// This is an extract from a media.yaml file: +// This is an excerpt from a media.yaml file: const textG2 = `resource: version: '{latest}' media: diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index 6ac2bdb6b..b28f9c68b 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -186,7 +186,7 @@ export function RenderRawResults({ results }) { if (allPropertiesSet.has('fieldName')) headerData = headerData.concat([{ title: 'Field', field: 'fieldName' }]); if (allPropertiesSet.has('lineNumber')) headerData = headerData.concat([{ title: 'Line', field: 'lineNumber' }]); if (allPropertiesSet.has('characterIndex')) headerData = headerData.concat([{ title: 'CharIndex', field: 'characterIndex' }]); - if (allPropertiesSet.has('extract')) headerData = headerData.concat([{ title: 'Extract', field: 'extract' }]); + if (allPropertiesSet.has('excerpt')) headerData = headerData.concat([{ title: 'Excerpt', field: 'excerpt' }]); if (allPropertiesSet.has('location')) headerData = headerData.concat([{ title: 'Location', field: 'location' }]); if (allPropertiesSet.has('extra')) headerData = headerData.concat([{ title: 'Extra', field: 'extra' }]); // debugLog("headerData", headerData.length, JSON.stringify(headerData)); @@ -324,7 +324,7 @@ function RenderProcessedArray({ arrayType, results }) { // priority (integer), message (string) // plus optional fields: // bookID, C, V, repoName, filename, lineNumber - // characterIindex (integer), extract (string), location (string) + // characterIindex (integer), excerpt (string), location (string) // // debugLog("In RenderProcessedArray with ", arrayType); // consoleLogObject('RenderProcessedArray results', results); @@ -342,7 +342,7 @@ function RenderProcessedArray({ arrayType, results }) { <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex > 0 ? " (at character " + (listEntry.characterIndex + 1) + ")" : ""} - <span style={{ color: 'DimGray' }}>{listEntry.extract ? ` around ►${listEntry.extract}◄` : ""}</span> + <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> {listEntry.location} <RenderPriority entry={listEntry} /> </li>; @@ -358,7 +358,7 @@ function RenderGivenArray({ array, color }) { // plus possible optional fields: // bookID, C, V, // repoName, filename, lineNumber, - // characterIndex (integer), extract (string), location (descriptive string) + // characterIndex (integer), excerpt (string), location (descriptive string) // // debugLog("In RenderGivenArray with ", arrayType); // consoleLogObject('RenderGivenArray results', results); @@ -370,7 +370,7 @@ function RenderGivenArray({ array, color }) { <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} - <span style={{ color: 'DimGray' }}>{listEntry.extract ? ` around ►${listEntry.extract}◄` : ""}</span> + <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> {listEntry.location} <RenderPriority entry={listEntry} /> </li>; @@ -393,7 +393,7 @@ function getGradientcolor(priorityValue) { function RenderWarningsGradient({ results }) { // Display our array of 8-part lists in a nicer format // 1/ priority number, 2/ bookID, 3/ C, 4/ V, 5/ message, - // 6/ index (integer), 7/ extract (optional), 8/ location + // 6/ index (integer), 7/ excerpt (optional), 8/ location // // Expects results to contain: // 1/ warningList @@ -408,7 +408,7 @@ function RenderWarningsGradient({ results }) { <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} - <span style={{ color: 'DimGray' }}>{listEntry.extract ? ` around ►${listEntry.extract}◄` : ""}</span> + <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> {listEntry.location} <RenderPriority entry={listEntry} /> </li>; diff --git a/src/demos/all-book-packages-check/AllBookPackagesCheck.js b/src/demos/all-book-packages-check/AllBookPackagesCheck.js index 4459d3d58..0f5b29a21 100644 --- a/src/demos/all-book-packages-check/AllBookPackagesCheck.js +++ b/src/demos/all-book-packages-check/AllBookPackagesCheck.js @@ -64,11 +64,11 @@ function AllBookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { userLog(`AllBookPackagesCheck bookIDList (${bookIDList.length}) = ${bookIDList.join(', ')}`); const checkingOptions = { // Uncomment any of these to test them - // extractLength: 25, + // excerptLength: 25, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // Or this allows the parameters to be specified as a BookPackagesCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); useEffect(() => { diff --git a/src/demos/all-book-packages-check/README.md b/src/demos/all-book-packages-check/README.md index 0666ccdbc..4da73c968 100644 --- a/src/demos/all-book-packages-check/README.md +++ b/src/demos/all-book-packages-check/README.md @@ -31,10 +31,10 @@ import AllBookPackagesCheck from './AllBookPackagesCheck'; displayType='SingleList' // Lines starting with // are ignored -- you can add or remove // as desired - // Specifying maximumSimilarMessages and extractLength is just to show off options + // Specifying maximumSimilarMessages and excerptLength is just to show off options // —those fields are not necessary (or normal) here maximumSimilarMessages='4' // Default is 3 (0 means don’t suppress any) - // extractLength='20' // Default is 15 + // excerptLength='20' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings /> ``` diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 8c883fa53..3f26f281b 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -35,14 +35,14 @@ function BookPackageCheck(/*username, languageCode, bookID,*/ props) { const checkingOptions = { // Uncomment any of these to test them dataSet: dataSet, // Can be 'OLD' (Markdown, etc.), 'NEW' (TSV only), or 'BOTH', or 'DEFAULT' - // extractLength: 25, // default is 15 + // excerptLength: 25, // default is 15 checkManifestFlag: true, checkReadmeFlag: true, checkLicenseFlag: true, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // Or this allows the parameters to be specified as a BookPackageCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); if (props.disableAllLinkFetchingFlag) checkingOptions.disableAllLinkFetchingFlag = props.disableAllLinkFetchingFlag.toLowerCase() === 'true'; if (props.checkLinkedTAArticleFlag) checkingOptions.checkLinkedTAArticleFlag = props.checkLinkedTAArticleFlag.toLowerCase() === 'true'; diff --git a/src/demos/book-package-check/README.md b/src/demos/book-package-check/README.md index 8ee322165..142591253 100644 --- a/src/demos/book-package-check/README.md +++ b/src/demos/book-package-check/README.md @@ -45,9 +45,9 @@ import BookPackageCheck from './BookPackageCheck'; checkLinkedTWArticleFlag='true' // 'true' or 'false' // Lines starting with // are ignored -- you can add or remove // as desired - // Specifying extractLength and maximumSimilarMessages is just to show off options + // Specifying excerptLength and maximumSimilarMessages is just to show off options // —those fields are not necessary (or normal) here - extractLength='20' // Default is 15 + excerptLength='20' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings maximumSimilarMessages='5' // Default is 3 (0 means don’t suppress any) // ignorePriorityNumberList='[]' diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index 889477a0f..cb3c25518 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -71,7 +71,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult function addNoticePartial(noticeObject) { // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. - // functionLog(`checkBookPackage addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.bookID} ${noticeObject.C}:${noticeObject.V} ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${extract ? ` ${extract}` : ""}${location}`); + // functionLog(`checkBookPackage addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.bookID} ${noticeObject.C}:${noticeObject.V} ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cBP addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cBP addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cBP addNoticePartial: 'message' parameter should be defined"); @@ -88,8 +88,8 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `cBP addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}': ${noticeObject.V}`); // parameterAssert(characterIndex !== undefined, "cBP addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cBP addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(extract !== undefined, "cBP addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cBP addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + // parameterAssert(excerpt !== undefined, "cBP addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cBP addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cBP addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cBP addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); parameterAssert(noticeObject.extra !== undefined, "cBP addNoticePartial: 'extra' parameter should be defined"); @@ -290,7 +290,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (books.isValidBookID(bookID)) // must be in FRT, BAK, etc. whichTestament = 'other' else { - addNoticePartial({ priority: 902, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${generalLocation}` }); return checkBookPackageResult; + addNoticePartial({ priority: 902, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${generalLocation}` }); return checkBookPackageResult; } } // functionLog(`checkBookPackage: bookNumberAndName='${bookNumberAndName}' (${whichTestament} testament)`); @@ -498,7 +498,7 @@ async function checkTQMarkdownBook(username, languageCode, repoName, branch, boo function addNoticePartial(noticeObject) { // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. - // functionLog(`checkTQMarkdownBook addNoticePartial: ${noticeObject.priority}:${noticeObject.message} ${noticeObject.bookID} ${noticeObject.C}:${noticeObject.V} ${noticeObject.filename}:${noticeObject.lineNumber} ${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? ` ${noticeObject.extract}` : ""}${noticeObject.location}`); + // functionLog(`checkTQMarkdownBook addNoticePartial: ${noticeObject.priority}:${noticeObject.message} ${noticeObject.bookID} ${noticeObject.C}:${noticeObject.V} ${noticeObject.filename}:${noticeObject.lineNumber} ${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? ` ${noticeObject.excerpt}` : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cTQ addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cTQ addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}'`); parameterAssert(noticeObject.message !== undefined, "cTQ addNoticePartial: 'message' parameter should be defined"); @@ -513,8 +513,8 @@ async function checkTQMarkdownBook(username, languageCode, repoName, branch, boo if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `cTQ addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}'`); // parameterAssert(characterIndex !== undefined, "cTQ addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cTQ addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}'`); - // parameterAssert(extract !== undefined, "cTQ addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cTQ addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}'`); + // parameterAssert(excerpt !== undefined, "cTQ addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cTQ addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}'`); parameterAssert(noticeObject.location !== undefined, "cTQ addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cTQ addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); parameterAssert(noticeObject.extra !== undefined, "cTQ addNoticePartial: 'extra' parameter should be defined"); @@ -554,7 +554,7 @@ async function checkTQMarkdownBook(username, languageCode, repoName, branch, boo // Process noticeList line by line, appending the repoCode as an extra field as we go for (const noticeEntry of cfResultObject.noticeList) { - // noticeEntry is an array of eight fields: 1=priority, 2=bookID, 3=C, 4=V, 5=msg, 6=characterIndex, 7=extract, 8=location + // noticeEntry is an array of eight fields: 1=priority, 2=bookID, 3=C, 4=V, 5=msg, 6=characterIndex, 7=excerpt, 8=location // parameterAssert(Object.keys(noticeEntry).length === 5, `cTQ ourCheckTQFileContents notice length=${Object.keys(noticeEntry).length}`); // We add the repoCode as an extra value addNoticePartial({ ...noticeEntry, bookID, C, V, extra: repoCode }); diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index a6b6e54bf..4b03b8ef0 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -50,11 +50,11 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { // debugLog(`bookIDList (${bookIDList.length}) = ${bookIDList.join(', ')}`); const checkingOptions = { // Uncomment any of these to test them - // extractLength: 25, + // excerptLength: 25, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // Or this allows the parameters to be specified as a BookPackagesCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); useEffect(() => { diff --git a/src/demos/book-packages-check/README.md b/src/demos/book-packages-check/README.md index e07898a39..455514a23 100644 --- a/src/demos/book-packages-check/README.md +++ b/src/demos/book-packages-check/README.md @@ -38,10 +38,10 @@ import BookPackagesCheck from './BookPackagesCheck'; displayType='SingleList' // Lines starting with // are ignored -- you can add or remove // as desired - // Specifying maximumSimilarMessages and extractLength is just to show off options + // Specifying maximumSimilarMessages and excerptLength is just to show off options // —those fields are not necessary (or normal) here maximumSimilarMessages='4' // Default is 3 (0 means don’t suppress any) - // extractLength='20' // Default is 15 + // excerptLength='20' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings // sortBy='ByRepo' // Default is 'ByPriority'; also have 'ByRepo' and 'AsFound' // showDisabledNoticesFlag='false' // Display known specific non-issues: 'true' or 'false' diff --git a/src/demos/book-packages-check/checkBookPackages.js b/src/demos/book-packages-check/checkBookPackages.js index 3dbd9d5a2..aa741583e 100644 --- a/src/demos/book-packages-check/checkBookPackages.js +++ b/src/demos/book-packages-check/checkBookPackages.js @@ -21,7 +21,7 @@ export async function checkBookPackages(username, languageCode, bookIDList, setR function addNotice(noticeObject) { // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. - userLog(`cBPs addNotice: (priority=${noticeObject.priority}) ${noticeObject.extra} ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? ` ${noticeObject.extract}` : ""}${noticeObject.location}`); + userLog(`cBPs addNotice: (priority=${noticeObject.priority}) ${noticeObject.extra} ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? ` ${noticeObject.excerpt}` : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cBPs addNotice: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cBPs addNotice: 'priority' parameter should be a number not a '${typeof noticeObject.priority}'`); parameterAssert(noticeObject.message !== undefined, "cBPs addNotice: 'message' parameter should be defined"); @@ -38,8 +38,8 @@ export async function checkBookPackages(username, languageCode, bookIDList, setR if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `cBPs addNotice: 'V' parameter should be a string not a '${typeof noticeObject.V}'`); // parameterAssert(characterIndex !== undefined, "cBPs addNotice: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cBPs addNotice: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}'`); - // parameterAssert(extract !== undefined, "cBPs addNotice: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cBPs addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}'`); + // parameterAssert(excerpt !== undefined, "cBPs addNotice: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cBPs addNotice: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}'`); parameterAssert(noticeObject.location !== undefined, "cBPs addNotice: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cBPs addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); parameterAssert(noticeObject.extra !== undefined, "cBPs addNotice: 'extra' parameter should be defined"); @@ -63,7 +63,7 @@ export async function checkBookPackages(username, languageCode, bookIDList, setR bookNumberAndName = books.usfmNumberName(bookID); // whichTestament = books.testament(bookID); // returns 'old' or 'new' } catch (CBPsError) { - addNotice({ priority: 900, message: "Bad parameter: should be given a valid book abbreviation", extract: bookIDList, location: ` (not '${bookIDList}')` }); + addNotice({ priority: 900, message: "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '${bookIDList}')` }); return checkBookPackagesResult; } // debugLog(`bookNumberAndName='${bookNumberAndName}' (${whichTestament} testament)`); @@ -98,7 +98,7 @@ export async function checkBookPackages(username, languageCode, bookIDList, setR // Concat is faster if we don’t need to process each notice individually checkBookPackagesResult.noticeList = checkBookPackagesResult.noticeList.concat(cbpResultObject.noticeList); // for (const noticeEntry of cbpResultObject.noticeList) - // // noticeEntry is an array of eight fields: 1=priority, 2=bookID, 3=C, 4=V, 5=msg, 6=characterIndex, 7=extract, 8=location + // // noticeEntry is an array of eight fields: 1=priority, 2=bookID, 3=C, 4=V, 5=msg, 6=characterIndex, 7=excerpt, 8=location // // The extra value from checkBookPackage is the repo name // addNotice({noticeEntry.priority, noticeEntry[1], noticeEntry[2], noticeEntry[3], noticeEntry[4], noticeEntry[5], noticeEntry[6], noticeEntry[7], noticeEntry[5]); diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 9f0cec2f9..782330e8b 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -199,11 +199,11 @@ function FileCheck(props) { if (givenLocation && givenLocation[0] !== ' ') givenLocation = ` ${givenLocation}`; const checkingOptions = { // Uncomment any of these to test them - // extractLength: 25, + // excerptLength: 25, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // Or this allows the parameters to be specified as a FileCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); if (props.disableAllLinkFetchingFlag) checkingOptions.disableAllLinkFetchingFlag = props.disableAllLinkFetchingFlag.toLowerCase() === 'true'; if (props.checkLinkedTAArticleFlag) checkingOptions.checkLinkedTAArticleFlag = props.checkLinkedTAArticleFlag.toLowerCase() === 'true'; diff --git a/src/demos/file-check/README.md b/src/demos/file-check/README.md index 0247fef6b..d711e06d3 100644 --- a/src/demos/file-check/README.md +++ b/src/demos/file-check/README.md @@ -52,9 +52,9 @@ and then validates the content of one file selected from the repo. // The location field appears in check messages to help the user locate the issue location="as specified in FileCheck demo" - // Specifying extractLength and cutoffPriorityLevel is just to show off options + // Specifying excerptLength and cutoffPriorityLevel is just to show off options // —those fields are not necessary (or normal) here - extractLength='12' // Default is 15 + excerptLength='12' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings // Normally links in files are downloaded to check that they really exist diff --git a/src/demos/gl-book-package-check/GlBookPackageCheck.js b/src/demos/gl-book-package-check/GlBookPackageCheck.js index f5abf63a0..1ff53b6d1 100644 --- a/src/demos/gl-book-package-check/GlBookPackageCheck.js +++ b/src/demos/gl-book-package-check/GlBookPackageCheck.js @@ -35,14 +35,14 @@ function GlBookPackageCheck(/*username, languageCode, bookIDs,*/ props) { // autoClearCache(bookIDs); // This technique avoids the complications of needing a button const checkingOptions = { // Uncomment any of these to test them - // extractLength: 25, + // excerptLength: 25, checkManifestFlag: true, checkReadmeFlag: true, checkLicenseFlag: true, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // Or this allows the parameters to be specified as a GlBookPackageCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); useEffect(() => { diff --git a/src/demos/gl-book-package-check/README.md b/src/demos/gl-book-package-check/README.md index 7cf9fb17e..d6feb2c5f 100644 --- a/src/demos/gl-book-package-check/README.md +++ b/src/demos/gl-book-package-check/README.md @@ -46,10 +46,10 @@ clearCheckedArticleCache(); displayType='SingleList' // Lines starting with // are ignored -- you can add or remove // as desired - // Specifying maximumSimilarMessages and extractLength is just to show off options + // Specifying maximumSimilarMessages and excerptLength is just to show off options // —those fields are not necessary (or normal) here maximumSimilarMessages='4' // Default is 3 (0 means don’t suppress any) - // extractLength='20' // Default is 15 + // excerptLength='20' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings /> ``` diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index 0c1877c9f..e4d1a1e6c 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -51,7 +51,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { fieldName: string (if relevant) characterIndex: A zero-based integer index which indicates the position of the error on the line or in the text field as appropriate. - extract: An extract of the checked text which indicates the area + excerpt: An excerpt of the checked text which indicates the area containing the problem. Where helpful, some character substitutions have already been made, for example, if the notice is about spaces, @@ -121,7 +121,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { && (thisUniqueNotice.rowID === item.rowID || thisUniqueNotice.rowID === undefined || item.rowID === undefined) && (thisUniqueNotice.lineNumber === item.lineNumber || thisUniqueNotice.lineNumber === undefined || item.lineNumber === undefined) && (thisUniqueNotice.characterIndex === item.characterIndex || thisUniqueNotice.characterIndex === undefined || item.characterIndex === undefined) - && (thisUniqueNotice.extract === item.extract || thisUniqueNotice.extract === undefined || item.extract === undefined) + && (thisUniqueNotice.excerpt === item.excerpt || thisUniqueNotice.excerpt === undefined || item.excerpt === undefined) && (thisUniqueNotice.extra === item.extra || thisUniqueNotice.extra === undefined || item.extra === undefined) ) return ix; @@ -261,7 +261,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { } else userLog(`Using supplied cutoffPriorityLevel=${cutoffPriorityLevel} cf. default=${DEFAULT_CUTOFF_PRIORITY_LEVEL}`); // if (cutoffPriorityLevel > errorPriorityLevel) - // resultObject.errorList.push({999, "Cutoff level must not be higher than error level", extract:`(${cutoffPriorityLevel} vs ${errorPriorityLevel})`, " in processNoticesCommon options"]); + // resultObject.errorList.push({999, "Cutoff level must not be higher than error level", excerpt:`(${cutoffPriorityLevel} vs ${errorPriorityLevel})`, " in processNoticesCommon options"]); let showDisabledNoticesFlag = optionalProcessingOptions.showDisabledNoticesFlag === true; if (showDisabledNoticesFlag) userLog(`showDisabledNoticesFlag=${showDisabledNoticesFlag}`); @@ -406,7 +406,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { const thisNewNotice = { ...thisParticularNotice, priority: 701, message: "\\s5 fields should be coded as \\ts\\* milestones", location: ` in ${givenNoticeObject.checkType}`, // I think we need to delete these fields below as they were probably set in thisParticularNotice - C: undefined, V: undefined, characterIndex: undefined, extract: undefined + C: undefined, V: undefined, characterIndex: undefined, excerpt: undefined }; // if (thisParticularNotice.filename && thisParticularNotice.filename.length) // thisNewNotice.filename = thisParticularNotice.filename; // Sometimes we have an additional file identifier @@ -449,7 +449,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { remainingNoticeList = newNoticeList; } // if (cutoffPriorityLevel > errorPriorityLevel) - // resultObject.errorList.push({999, "Cutoff level must not be higher than error level", extract:`(${cutoffPriorityLevel} vs ${errorPriorityLevel})`, " in processNoticesCommon options"]); + // resultObject.errorList.push({999, "Cutoff level must not be higher than error level", excerpt:`(${cutoffPriorityLevel} vs ${errorPriorityLevel})`, " in processNoticesCommon options"]); // Sort the remainingNoticeList as required const SORT_LIST = ['TN', 'TN2', 'LT', 'ST', 'UHB', 'UGNT', 'TWL', 'TW', 'TQ', 'TQ2', 'SN', 'SQ', 'TA', undefined, 'README', 'LICENSE']; diff --git a/src/demos/notice-processing1.md b/src/demos/notice-processing1.md index 8db7e0241..3a427cc3b 100644 --- a/src/demos/notice-processing1.md +++ b/src/demos/notice-processing1.md @@ -12,7 +12,7 @@ It should be noted that although the success messages are simple strings, the no 4. The verse number (if relevant, string or empty string, can be a range, e.g., '22-24') 5. The main error/warning message (string) 6. The (zero-based) index of where the error was found on the line. -1 indicates that this field is not helpful/relevant. -7. A text extract (typically 10 characters) centred about the error. An empty string indicates that this field is not helpful/relevant. +7. A text excerpt (typically 10 characters) centred about the error. An empty string indicates that this field is not helpful/relevant. 8. The location of the error, e.g., "line 2 in file GEN.usfm in unfoldingWord/en_ult repo". Note below that the optional `processOptions` object allows the user to adjust things like the division point between error and warning priorities, and allows low priority or certain notices to simply be dropped, etc. The system defaults to suppressing multiple cases of similar errors, but this can also be fine-tuned through these parameters. diff --git a/src/demos/notice-processing2.md b/src/demos/notice-processing2.md index e3d199b01..316178e02 100644 --- a/src/demos/notice-processing2.md +++ b/src/demos/notice-processing2.md @@ -12,7 +12,7 @@ It should be noted that although the success messages are simple strings, the no 4. The verse number (if relevant, string or empty string, can be a range, e.g., '22-24') 5. The main error/warning message (string) 6. The (zero-based) index of where the error was found on the line. -1 indicates that this field is not helpful/relevant. -7. A text extract (typically 10 characters) centred about the error. An empty string indicates that this field is not helpful/relevant. +7. A text excerpt (typically 10 characters) centred about the error. An empty string indicates that this field is not helpful/relevant. 8. The location of the error, e.g., "line 2 in file GEN.usfm in unfoldingWord/en_ult repo". Note below that the optional `processOptions` object allows the user to adjust things like the division point between error and warning priorities, and allows low priority or certain notices to simply be dropped, etc. The system defaults to suppressing multiple cases of similar errors, but this can also be fine-tuned through these parameters. diff --git a/src/demos/notice-processing3.md b/src/demos/notice-processing3.md index 918fe11f5..7a2b8012a 100644 --- a/src/demos/notice-processing3.md +++ b/src/demos/notice-processing3.md @@ -12,7 +12,7 @@ It should be noted that although the success messages are simple strings, the no 4. The verse number (if relevant, string or empty string, can be a range, e.g., '22-24') 5. The main error/warning message (string) 6. The (zero-based) index of where the error was found on the line. -1 indicates that this field is not helpful/relevant. -7. A text extract (typically 10 characters) centred about the error. An empty string indicates that this field is not helpful/relevant. +7. A text excerpt (typically 10 characters) centred about the error. An empty string indicates that this field is not helpful/relevant. 8. The location of the error, e.g., "line 2 in file GEN.usfm in unfoldingWord/en_ult repo". Note below that the optional `processOptions` object allows the user to adjust things like the division point between error and warning priorities, and allows low priority or certain notices to simply be dropped, etc. The system defaults to suppressing multiple cases of similar errors, but this can also be fine-tuned through these parameters. diff --git a/src/demos/repo-check/README.md b/src/demos/repo-check/README.md index cc596e207..612078b7f 100644 --- a/src/demos/repo-check/README.md +++ b/src/demos/repo-check/README.md @@ -45,10 +45,10 @@ import RepoCheck from './RepoCheck'; // Alternatives are `SevereMediumLow', 'SingleList' displayType='SingleList' - // Specifying maximumSimilarMessages and extractLength is just to show off options + // Specifying maximumSimilarMessages and excerptLength is just to show off options // —those fields are not necessary (or normal) here maximumSimilarMessages='4' // Default is 3 (0 means don’t suppress any) - // extractLength='20' // Default is 15 + // excerptLength='20' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings showDisabledNoticesFlag='false' // Display known specific non-issues: 'true' or 'false' /> diff --git a/src/demos/repo-check/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index 69658a6d2..d3c3b60e8 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -31,7 +31,7 @@ function RepoCheck(/*username, languageCode,*/ props) { if (branch === undefined) branch = 'master'; const checkingOptions = { // Uncomment any of these to test them - // extractLength: 25, + // excerptLength: 25, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // NOTE: I removed this again as it didn’t really seem to make sense to enable it here @@ -42,7 +42,7 @@ function RepoCheck(/*username, languageCode,*/ props) { // checkingOptions.checkLinkedTWArticleFlag = true; // } // Or this allows the parameters to be specified as a RepoCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); @@ -104,7 +104,7 @@ function RepoCheck(/*username, languageCode,*/ props) { rawCRResults = await checkRepo(username, repoName, branch, "", setResultValue, checkingOptions); } catch (checkRepoError) { rawCRResults = { successList: [], noticeList: [] }; - rawCRResults.noticeList.push({ priority: 999, message: "checkRepo function FAILED", repoName, extract: checkRepoError, location: repoName }); + rawCRResults.noticeList.push({ priority: 999, message: "checkRepo function FAILED", repoName, excerpt: checkRepoError, location: repoName }); // debugLog("RepoCheck trace is", checkRepoError.trace); } // debugLog("checkRepo() returned", typeof rawCRResults); //, JSON.stringify(rawCRResults)); diff --git a/src/demos/repo-check/checkRepo.js b/src/demos/repo-check/checkRepo.js index 1db18bc59..31b805558 100644 --- a/src/demos/repo-check/checkRepo.js +++ b/src/demos/repo-check/checkRepo.js @@ -58,7 +58,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe // Adds the notices to the result that we will later return // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. // Note that bookID,C,V might all be empty strings (as some repos don’t have BCV) - // functionLog(`checkRepo addNoticePartial: ${noticeObject.priority}:${noticeObject.message} bookID=${noticeObject.bookID} ${noticeObject.C}:${noticeObject.V} ${noticeObject.filename}:${noticeObject.lineNumber} ${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? ` ${noticeObject.extract}` : ""}${noticeObject.location}`); + // functionLog(`checkRepo addNoticePartial: ${noticeObject.priority}:${noticeObject.message} bookID=${noticeObject.bookID} ${noticeObject.C}:${noticeObject.V} ${noticeObject.filename}:${noticeObject.lineNumber} ${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? ` ${noticeObject.excerpt}` : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cR addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cR addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}'`); parameterAssert(noticeObject.message !== undefined, "cR addNoticePartial: 'message' parameter should be defined"); @@ -75,8 +75,8 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe if (noticeObject.V) parameterAssert(typeof noticeObject.V === 'string', `cR addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}'`); // parameterAssert(characterIndex !== undefined, "cR addNoticePartial: 'characterIndex' parameter should be defined"); if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `cR addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}'`); - // parameterAssert(extract !== undefined, "cR addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) parameterAssert(typeof noticeObject.extract === 'string', `cR addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}'`); + // parameterAssert(excerpt !== undefined, "cR addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cR addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}'`); parameterAssert(noticeObject.location !== undefined, "cR addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cR addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); // parameterAssert(noticeObject.extra !== undefined, "cR addNoticePartial: 'extra' parameter should be defined"); From 76eb3a15b00f1c5e4a814aa19ed46b29dc204ecf Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Fri, 12 Feb 2021 15:35:26 +1300 Subject: [PATCH 04/16] Update and fix tests --- noticeList.txt | 2 +- .../book-package-check.test.js.snap | 1966 ++++++++--------- .../tn-table-row-check.test.js.snap | 212 +- src/__tests__/tn-table-row-check.test.js | 96 +- src/core/README.md | 2 +- src/core/manifest-text-check.md | 2 +- src/core/markdown-text-check.md | 2 +- src/core/tn-tsv9-row-check.js | 170 +- src/core/tn-tsv9-row-check.md | 6 +- src/core/tn-tsv9-table-check.js | 4 +- 10 files changed, 1231 insertions(+), 1231 deletions(-) diff --git a/noticeList.txt b/noticeList.txt index 50ce8db55..ca9be97de 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -57,7 +57,7 @@ Got 445 notices: 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 533 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 339 979, "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv5-row-check.js line 339 - 979, "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 357 + 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 357 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 339 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 372 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 375 diff --git a/src/__tests__/__snapshots__/book-package-check.test.js.snap b/src/__tests__/__snapshots__/book-package-check.test.js.snap index 0453daec2..ede570f79 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -73,8 +73,8 @@ Object { "V": "1", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 23, @@ -90,8 +90,8 @@ Object { "V": "2", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 47, @@ -107,8 +107,8 @@ Object { "V": "6", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 105, @@ -124,8 +124,8 @@ Object { "V": "19", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 295, @@ -141,8 +141,8 @@ Object { "V": "19", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 300, @@ -158,8 +158,8 @@ Object { "V": "22", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 354, @@ -175,8 +175,8 @@ Object { "V": "4", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 414, @@ -192,8 +192,8 @@ Object { "V": "11", "bookID": "RUT", "details": "Expected 3-4 attributes but only found 2", + "excerpt": "\\\\w שֵׁ֖ם|lemma=\\"שֵׁם\\" strong=\\"H8034\\"\\\\w*", "extra": "UHB", - "extract": "\\\\w שֵׁ֖ם|lemma=\\"שֵׁם\\" strong=\\"H8034\\"\\\\w*", "filename": "08-RUT.usfm", "lineNumber": 1195, "location": " in en RUT book package from unfoldingWord master branch", @@ -208,8 +208,8 @@ Object { "V": "11", "bookID": "RUT", "characterIndex": 0, + "excerpt": "| x-tw=\\"…", "extra": "UHB", - "extract": "| x-tw=\\"…", "fieldName": "\\\\k-s", "filename": "08-RUT.usfm", "lineNumber": 1196, @@ -224,8 +224,8 @@ Object { "C": "2", "V": "1", "bookID": "RUT", + "excerpt": "…ew␣Ketiv)␣", "extra": "LT", - "extract": "…ew␣Ketiv)␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 754, @@ -240,8 +240,8 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "excerpt": "…uncertain␣", "extra": "LT", - "extract": "…uncertain␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 944, @@ -256,8 +256,8 @@ Object { "C": "3", "V": "3", "bookID": "RUT", + "excerpt": "…rew␣Qere)␣", "extra": "LT", - "extract": "…rew␣Qere)␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 1651, @@ -272,8 +272,8 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "excerpt": "…uscripts)␣", "extra": "LT", - "extract": "…uscripts)␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 2024, @@ -289,8 +289,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "it,'", "extra": "LT", - "extract": "it,'", "filename": "08-RUT.usfm", "lineNumber": 2218, "location": " in en RUT book package from unfoldingWord master branch", @@ -304,8 +304,8 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "excerpt": "…uscripts)␣", "extra": "LT", - "extract": "…uscripts)␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 2283, @@ -320,8 +320,8 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "excerpt": "…rew␣Qere)␣", "extra": "LT", - "extract": "…rew␣Qere)␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 2284, @@ -336,8 +336,8 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "excerpt": "…ew␣Ketiv)␣", "extra": "LT", - "extract": "…ew␣Ketiv)␣", "fieldName": "from \\\\f", "filename": "08-RUT.usfm", "lineNumber": 2329, @@ -351,8 +351,8 @@ Object { Object { "bookID": "RUT", "characterIndex": 311926, + "excerpt": "…n-e\\\\*\\\\zaln-e\\\\*.", "extra": "LT", - "extract": "…n-e\\\\*\\\\zaln-e\\\\*.", "filename": "08-RUT.usfm", "location": " in en RUT book package from unfoldingWord master branch", "message": "File ends without newline character", @@ -365,8 +365,8 @@ Object { "bookID": "RUT", "characterIndex": 54, "details": "'‘' opened on line 2217 character 179", + "excerpt": "…ln-e\\\\*.”", "extra": "LT", - "extract": "…ln-e\\\\*.”", "filename": "08-RUT.usfm", "lineNumber": 2274, "location": " in en RUT book package from unfoldingWord master branch", @@ -380,8 +380,8 @@ Object { "bookID": "RUT", "characterIndex": 178, "details": "2 unclosed sets", + "excerpt": "…n-e\\\\*,␣‘\\\\zaln-s…", "extra": "LT", - "extract": "…n-e\\\\*,␣‘\\\\zaln-s…", "filename": "08-RUT.usfm", "lineNumber": 2217, "location": " in en RUT book package from unfoldingWord master branch", @@ -408,8 +408,8 @@ Object { "V": "3", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Naomi's", "extra": "ST", - "extract": "Naomi's", "filename": "08-RUT.usfm", "lineNumber": 110, "location": " in en RUT book package from unfoldingWord master branch", @@ -424,8 +424,8 @@ Object { "V": "8", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…n-law,␣\\"Each", "extra": "ST", - "extract": "…n-law,␣\\"Each", "filename": "08-RUT.usfm", "lineNumber": 244, "location": " in en RUT book package from unfoldingWord master branch", @@ -439,8 +439,8 @@ Object { "C": "1", "V": "8", "bookID": "RUT", + "excerpt": "…in-law, \\"Each", "extra": "ST", - "extract": "…in-law, \\"Each", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 244, @@ -456,8 +456,8 @@ Object { "V": "8", "bookID": "RUT", "characterIndex": 271, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 244, @@ -473,8 +473,8 @@ Object { "V": "8", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "mother's", "extra": "ST", - "extract": "mother's", "filename": "08-RUT.usfm", "lineNumber": 255, "location": " in en RUT book package from unfoldingWord master branch", @@ -489,8 +489,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "home.\\"", "extra": "ST", - "extract": "home.\\"", "filename": "08-RUT.usfm", "lineNumber": 298, "location": " in en RUT book package from unfoldingWord master branch", @@ -505,8 +505,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "said,␣\\"No!", "extra": "ST", - "extract": "said,␣\\"No!", "filename": "08-RUT.usfm", "lineNumber": 311, "location": " in en RUT book package from unfoldingWord master branch", @@ -520,8 +520,8 @@ Object { "C": "1", "V": "10", "bookID": "RUT", + "excerpt": "said, \\"No!", "extra": "ST", - "extract": "said, \\"No!", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 311, @@ -537,8 +537,8 @@ Object { "V": "10", "bookID": "RUT", "characterIndex": 61, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 311, @@ -554,8 +554,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…atives.\\"", "extra": "ST", - "extract": "…atives.\\"", "filename": "08-RUT.usfm", "lineNumber": 319, "location": " in en RUT book package from unfoldingWord master branch", @@ -570,8 +570,8 @@ Object { "V": "11", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "said,␣\\"No,", "extra": "ST", - "extract": "said,␣\\"No,", "filename": "08-RUT.usfm", "lineNumber": 325, "location": " in en RUT book package from unfoldingWord master branch", @@ -585,8 +585,8 @@ Object { "C": "1", "V": "11", "bookID": "RUT", + "excerpt": "said, \\"No,", "extra": "ST", - "extract": "said, \\"No,", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 325, @@ -602,8 +602,8 @@ Object { "V": "11", "bookID": "RUT", "characterIndex": 173, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 325, @@ -619,8 +619,8 @@ Object { "V": "13", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "mine.\\"", "extra": "ST", - "extract": "mine.\\"", "filename": "08-RUT.usfm", "lineNumber": 430, "location": " in en RUT book package from unfoldingWord master branch", @@ -635,8 +635,8 @@ Object { "V": "15", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "her,␣\\"Look!", "extra": "ST", - "extract": "her,␣\\"Look!", "filename": "08-RUT.usfm", "lineNumber": 456, "location": " in en RUT book package from unfoldingWord master branch", @@ -650,8 +650,8 @@ Object { "C": "1", "V": "15", "bookID": "RUT", + "excerpt": "her, \\"Look!", "extra": "ST", - "extract": "her, \\"Look!", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 456, @@ -667,8 +667,8 @@ Object { "V": "15", "bookID": "RUT", "characterIndex": 51, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 456, @@ -684,8 +684,8 @@ Object { "V": "15", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "her!\\"", "extra": "ST", - "extract": "her!\\"", "filename": "08-RUT.usfm", "lineNumber": 472, "location": " in en RUT book package from unfoldingWord master branch", @@ -700,8 +700,8 @@ Object { "V": "16", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…plied,␣\\"No!", "extra": "ST", - "extract": "…plied,␣\\"No!", "filename": "08-RUT.usfm", "lineNumber": 477, "location": " in en RUT book package from unfoldingWord master branch", @@ -715,8 +715,8 @@ Object { "C": "1", "V": "16", "bookID": "RUT", + "excerpt": "…eplied, \\"No!", "extra": "ST", - "extract": "…eplied, \\"No!", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 477, @@ -732,8 +732,8 @@ Object { "V": "16", "bookID": "RUT", "characterIndex": 176, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 477, @@ -749,8 +749,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "die.\\"", "extra": "ST", - "extract": "die.\\"", "filename": "08-RUT.usfm", "lineNumber": 546, "location": " in en RUT book package from unfoldingWord master branch", @@ -765,8 +765,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…aimed,␣\\"It", "extra": "ST", - "extract": "…aimed,␣\\"It", "filename": "08-RUT.usfm", "lineNumber": 601, "location": " in en RUT book package from unfoldingWord master branch", @@ -780,8 +780,8 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "excerpt": "…laimed, \\"It", "extra": "ST", - "extract": "…laimed, \\"It", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 601, @@ -797,8 +797,8 @@ Object { "V": "19", "bookID": "RUT", "characterIndex": 57, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 601, @@ -814,8 +814,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Naomi!\\"", "extra": "ST", - "extract": "Naomi!\\"", "filename": "08-RUT.usfm", "lineNumber": 609, "location": " in en RUT book package from unfoldingWord master branch", @@ -830,8 +830,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "them,␣\\"You", "extra": "ST", - "extract": "them,␣\\"You", "filename": "08-RUT.usfm", "lineNumber": 613, "location": " in en RUT book package from unfoldingWord master branch", @@ -845,8 +845,8 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "excerpt": "them, \\"You", "extra": "ST", - "extract": "them, \\"You", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 613, @@ -862,8 +862,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 613, @@ -879,8 +879,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "means␣'pleasan…", "extra": "ST", - "extract": "means␣'pleasan…", "filename": "08-RUT.usfm", "lineNumber": 623, "location": " in en RUT book package from unfoldingWord master branch", @@ -894,8 +894,8 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "excerpt": "means 'pleasa…", "extra": "ST", - "extract": "means 'pleasa…", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 623, @@ -911,8 +911,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…aln-e\\\\* '\\\\zaln-…", "extra": "ST", - "extract": "…aln-e\\\\* '\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 623, @@ -928,8 +928,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "means␣'bitter.…", "extra": "ST", - "extract": "means␣'bitter.…", "filename": "08-RUT.usfm", "lineNumber": 630, "location": " in en RUT book package from unfoldingWord master branch", @@ -943,8 +943,8 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "excerpt": "means 'bitter…", "extra": "ST", - "extract": "means 'bitter…", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 630, @@ -960,8 +960,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…aln-e\\\\* '\\\\zaln-…", "extra": "ST", - "extract": "…aln-e\\\\* '\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 630, @@ -977,8 +977,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "badly.\\"", "extra": "ST", - "extract": "badly.\\"", "filename": "08-RUT.usfm", "lineNumber": 670, "location": " in en RUT book package from unfoldingWord master branch", @@ -993,8 +993,8 @@ Object { "V": "1", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Naomi's", "extra": "ST", - "extract": "Naomi's", "filename": "08-RUT.usfm", "lineNumber": 717, "location": " in en RUT book package from unfoldingWord master branch", @@ -1009,8 +1009,8 @@ Object { "V": "1", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…limelek's", "extra": "ST", - "extract": "…limelek's", "filename": "08-RUT.usfm", "lineNumber": 729, "location": " in en RUT book package from unfoldingWord master branch", @@ -1025,8 +1025,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Naomi,␣\\"Let", "extra": "ST", - "extract": "Naomi,␣\\"Let", "filename": "08-RUT.usfm", "lineNumber": 741, "location": " in en RUT book package from unfoldingWord master branch", @@ -1040,8 +1040,8 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "excerpt": "Naomi, \\"Let", "extra": "ST", - "extract": "Naomi, \\"Let", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 741, @@ -1057,8 +1057,8 @@ Object { "V": "2", "bookID": "RUT", "characterIndex": 165, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 741, @@ -1074,8 +1074,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…ission.\\"", "extra": "ST", - "extract": "…ission.\\"", "filename": "08-RUT.usfm", "lineNumber": 766, "location": " in en RUT book package from unfoldingWord master branch", @@ -1090,8 +1090,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"Go", "extra": "ST", - "extract": "…plied,␣\\"Go", "filename": "08-RUT.usfm", "lineNumber": 768, "location": " in en RUT book package from unfoldingWord master branch", @@ -1105,8 +1105,8 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "excerpt": "…eplied, \\"Go", "extra": "ST", - "extract": "…eplied, \\"Go", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 768, @@ -1122,8 +1122,8 @@ Object { "V": "2", "bookID": "RUT", "characterIndex": 64, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 768, @@ -1139,8 +1139,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…ughter.\\"", "extra": "ST", - "extract": "…ughter.\\"", "filename": "08-RUT.usfm", "lineNumber": 771, "location": " in en RUT book package from unfoldingWord master branch", @@ -1155,8 +1155,8 @@ Object { "V": "3", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…limelek's", "extra": "ST", - "extract": "…limelek's", "filename": "08-RUT.usfm", "lineNumber": 802, "location": " in en RUT book package from unfoldingWord master branch", @@ -1171,8 +1171,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…aying,␣\\"May", "extra": "ST", - "extract": "…aying,␣\\"May", "filename": "08-RUT.usfm", "lineNumber": 814, "location": " in en RUT book package from unfoldingWord master branch", @@ -1186,8 +1186,8 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "excerpt": "saying, \\"May", "extra": "ST", - "extract": "saying, \\"May", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 814, @@ -1203,8 +1203,8 @@ Object { "V": "4", "bookID": "RUT", "characterIndex": 175, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 814, @@ -1220,8 +1220,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "you!\\"", "extra": "ST", - "extract": "you!\\"", "filename": "08-RUT.usfm", "lineNumber": 818, "location": " in en RUT book package from unfoldingWord master branch", @@ -1236,8 +1236,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"May", "extra": "ST", - "extract": "…plied,␣\\"May", "filename": "08-RUT.usfm", "lineNumber": 820, "location": " in en RUT book package from unfoldingWord master branch", @@ -1251,8 +1251,8 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "excerpt": "…eplied, \\"May", "extra": "ST", - "extract": "…eplied, \\"May", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 820, @@ -1268,8 +1268,8 @@ Object { "V": "4", "bookID": "RUT", "characterIndex": 55, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 820, @@ -1285,8 +1285,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "you!\\"", "extra": "ST", - "extract": "you!\\"", "filename": "08-RUT.usfm", "lineNumber": 823, "location": " in en RUT book package from unfoldingWord master branch", @@ -1301,8 +1301,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…reman,␣\\"Who", "extra": "ST", - "extract": "…reman,␣\\"Who", "filename": "08-RUT.usfm", "lineNumber": 834, "location": " in en RUT book package from unfoldingWord master branch", @@ -1316,8 +1316,8 @@ Object { "C": "2", "V": "5", "bookID": "RUT", + "excerpt": "…oreman, \\"Who", "extra": "ST", - "extract": "…oreman, \\"Who", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 834, @@ -1333,8 +1333,8 @@ Object { "V": "5", "bookID": "RUT", "characterIndex": 82, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 834, @@ -1350,8 +1350,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "to?\\"", "extra": "ST", - "extract": "to?\\"", "filename": "08-RUT.usfm", "lineNumber": 840, "location": " in en RUT book package from unfoldingWord master branch", @@ -1366,8 +1366,8 @@ Object { "V": "6", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"She", "extra": "ST", - "extract": "…plied,␣\\"She", "filename": "08-RUT.usfm", "lineNumber": 843, "location": " in en RUT book package from unfoldingWord master branch", @@ -1381,8 +1381,8 @@ Object { "C": "2", "V": "6", "bookID": "RUT", + "excerpt": "…eplied, \\"She", "extra": "ST", - "extract": "…eplied, \\"She", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 843, @@ -1398,8 +1398,8 @@ Object { "V": "6", "bookID": "RUT", "characterIndex": 100, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 843, @@ -1415,8 +1415,8 @@ Object { "V": "7", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "me,␣'Please", "extra": "ST", - "extract": "me,␣'Please", "filename": "08-RUT.usfm", "lineNumber": 859, "location": " in en RUT book package from unfoldingWord master branch", @@ -1430,8 +1430,8 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "excerpt": "me, 'Please", "extra": "ST", - "extract": "me, 'Please", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 859, @@ -1447,8 +1447,8 @@ Object { "V": "7", "bookID": "RUT", "characterIndex": 50, + "excerpt": "…ln-e\\\\*, '\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, '\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 859, @@ -1464,8 +1464,8 @@ Object { "V": "7", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "behind.'", "extra": "ST", - "extract": "behind.'", "filename": "08-RUT.usfm", "lineNumber": 873, "location": " in en RUT book package from unfoldingWord master branch", @@ -1480,8 +1480,8 @@ Object { "V": "7", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…helter.\\"", "extra": "ST", - "extract": "…helter.\\"", "filename": "08-RUT.usfm", "lineNumber": 893, "location": " in en RUT book package from unfoldingWord master branch", @@ -1496,8 +1496,8 @@ Object { "V": "8", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Ruth,␣\\"Young", "extra": "ST", - "extract": "Ruth,␣\\"Young", "filename": "08-RUT.usfm", "lineNumber": 898, "location": " in en RUT book package from unfoldingWord master branch", @@ -1511,8 +1511,8 @@ Object { "C": "2", "V": "8", "bookID": "RUT", + "excerpt": "Ruth, \\"Young", "extra": "ST", - "extract": "Ruth, \\"Young", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 898, @@ -1528,8 +1528,8 @@ Object { "V": "8", "bookID": "RUT", "characterIndex": 158, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 898, @@ -1545,8 +1545,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "filled.\\"", "extra": "ST", - "extract": "filled.\\"", "filename": "08-RUT.usfm", "lineNumber": 972, "location": " in en RUT book package from unfoldingWord master branch", @@ -1561,8 +1561,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…aimed,␣\\"Why", "extra": "ST", - "extract": "…aimed,␣\\"Why", "filename": "08-RUT.usfm", "lineNumber": 988, "location": " in en RUT book package from unfoldingWord master branch", @@ -1576,8 +1576,8 @@ Object { "C": "2", "V": "10", "bookID": "RUT", + "excerpt": "…laimed, \\"Why", "extra": "ST", - "extract": "…laimed, \\"Why", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 988, @@ -1593,8 +1593,8 @@ Object { "V": "10", "bookID": "RUT", "characterIndex": 57, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 988, @@ -1610,8 +1610,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…eigner!\\"", "extra": "ST", - "extract": "…eigner!\\"", "filename": "08-RUT.usfm", "lineNumber": 1011, "location": " in en RUT book package from unfoldingWord master branch", @@ -1626,8 +1626,8 @@ Object { "V": "11", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"People", "extra": "ST", - "extract": "…plied,␣\\"People", "filename": "08-RUT.usfm", "lineNumber": 1013, "location": " in en RUT book package from unfoldingWord master branch", @@ -1641,8 +1641,8 @@ Object { "C": "2", "V": "11", "bookID": "RUT", + "excerpt": "…eplied, \\"People", "extra": "ST", - "extract": "…eplied, \\"People", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1013, @@ -1658,8 +1658,8 @@ Object { "V": "11", "bookID": "RUT", "characterIndex": 82, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1013, @@ -1675,8 +1675,8 @@ Object { "V": "12", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "full.\\"", "extra": "ST", - "extract": "full.\\"", "filename": "08-RUT.usfm", "lineNumber": 1086, "location": " in en RUT book package from unfoldingWord master branch", @@ -1691,8 +1691,8 @@ Object { "V": "13", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"Sir,", "extra": "ST", - "extract": "…plied,␣\\"Sir,", "filename": "08-RUT.usfm", "lineNumber": 1091, "location": " in en RUT book package from unfoldingWord master branch", @@ -1706,8 +1706,8 @@ Object { "C": "2", "V": "13", "bookID": "RUT", + "excerpt": "…eplied, \\"Sir,", "extra": "ST", - "extract": "…eplied, \\"Sir,", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1091, @@ -1723,8 +1723,8 @@ Object { "V": "13", "bookID": "RUT", "characterIndex": 55, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1091, @@ -1740,8 +1740,8 @@ Object { "V": "13", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "girls!\\"", "extra": "ST", - "extract": "girls!\\"", "filename": "08-RUT.usfm", "lineNumber": 1122, "location": " in en RUT book package from unfoldingWord master branch", @@ -1756,8 +1756,8 @@ Object { "V": "14", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "her,␣\\"Come", "extra": "ST", - "extract": "her,␣\\"Come", "filename": "08-RUT.usfm", "lineNumber": 1135, "location": " in en RUT book package from unfoldingWord master branch", @@ -1771,8 +1771,8 @@ Object { "C": "2", "V": "14", "bookID": "RUT", + "excerpt": "her, \\"Come", "extra": "ST", - "extract": "her, \\"Come", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1135, @@ -1788,8 +1788,8 @@ Object { "V": "14", "bookID": "RUT", "characterIndex": 51, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1135, @@ -1805,8 +1805,8 @@ Object { "V": "14", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "it.\\"", "extra": "ST", - "extract": "it.\\"", "filename": "08-RUT.usfm", "lineNumber": 1153, "location": " in en RUT book package from unfoldingWord master branch", @@ -1821,8 +1821,8 @@ Object { "V": "15", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…rkers,␣\\"Even", "extra": "ST", - "extract": "…rkers,␣\\"Even", "filename": "08-RUT.usfm", "lineNumber": 1193, "location": " in en RUT book package from unfoldingWord master branch", @@ -1836,8 +1836,8 @@ Object { "C": "2", "V": "15", "bookID": "RUT", + "excerpt": "…orkers, \\"Even", "extra": "ST", - "extract": "…orkers, \\"Even", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1193, @@ -1853,8 +1853,8 @@ Object { "V": "15", "bookID": "RUT", "characterIndex": 64, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1193, @@ -1870,8 +1870,8 @@ Object { "V": "16", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "her.\\"", "extra": "ST", - "extract": "her.\\"", "filename": "08-RUT.usfm", "lineNumber": 1246, "location": " in en RUT book package from unfoldingWord master branch", @@ -1886,8 +1886,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "her,␣\\"Where", "extra": "ST", - "extract": "her,␣\\"Where", "filename": "08-RUT.usfm", "lineNumber": 1320, "location": " in en RUT book package from unfoldingWord master branch", @@ -1901,8 +1901,8 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "excerpt": "her, \\"Where", "extra": "ST", - "extract": "her, \\"Where", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1320, @@ -1918,8 +1918,8 @@ Object { "V": "19", "bookID": "RUT", "characterIndex": 155, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1320, @@ -1935,8 +1935,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "you.\\"", "extra": "ST", - "extract": "you.\\"", "filename": "08-RUT.usfm", "lineNumber": 1347, "location": " in en RUT book package from unfoldingWord master branch", @@ -1951,8 +1951,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "said,␣\\"The", "extra": "ST", - "extract": "said,␣\\"The", "filename": "08-RUT.usfm", "lineNumber": 1360, "location": " in en RUT book package from unfoldingWord master branch", @@ -1966,8 +1966,8 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "excerpt": "said, \\"The", "extra": "ST", - "extract": "said, \\"The", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1360, @@ -1983,8 +1983,8 @@ Object { "V": "19", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1360, @@ -2000,8 +2000,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Boaz.\\"", "extra": "ST", - "extract": "Boaz.\\"", "filename": "08-RUT.usfm", "lineNumber": 1374, "location": " in en RUT book package from unfoldingWord master branch", @@ -2016,8 +2016,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…n-law,␣\\"May", "extra": "ST", - "extract": "…n-law,␣\\"May", "filename": "08-RUT.usfm", "lineNumber": 1379, "location": " in en RUT book package from unfoldingWord master branch", @@ -2031,8 +2031,8 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "excerpt": "…in-law, \\"May", "extra": "ST", - "extract": "…in-law, \\"May", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1379, @@ -2048,8 +2048,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 145, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1379, @@ -2065,8 +2065,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "died.\\"", "extra": "ST", - "extract": "died.\\"", "filename": "08-RUT.usfm", "lineNumber": 1401, "location": " in en RUT book package from unfoldingWord master branch", @@ -2081,8 +2081,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "added,␣\\"That", "extra": "ST", - "extract": "added,␣\\"That", "filename": "08-RUT.usfm", "lineNumber": 1404, "location": " in en RUT book package from unfoldingWord master branch", @@ -2096,8 +2096,8 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "excerpt": "added, \\"That", "extra": "ST", - "extract": "added, \\"That", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1404, @@ -2113,8 +2113,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 292, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1404, @@ -2130,8 +2130,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "family.\\"", "extra": "ST", - "extract": "family.\\"", "filename": "08-RUT.usfm", "lineNumber": 1425, "location": " in en RUT book package from unfoldingWord master branch", @@ -2146,8 +2146,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "said,␣\\"He", "extra": "ST", - "extract": "said,␣\\"He", "filename": "08-RUT.usfm", "lineNumber": 1435, "location": " in en RUT book package from unfoldingWord master branch", @@ -2161,8 +2161,8 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "excerpt": "said, \\"He", "extra": "ST", - "extract": "said, \\"He", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1435, @@ -2178,8 +2178,8 @@ Object { "V": "21", "bookID": "RUT", "characterIndex": 173, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1435, @@ -2195,8 +2195,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "me,␣'Stay", "extra": "ST", - "extract": "me,␣'Stay", "filename": "08-RUT.usfm", "lineNumber": 1438, "location": " in en RUT book package from unfoldingWord master branch", @@ -2210,8 +2210,8 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "excerpt": "me, 'Stay", "extra": "ST", - "extract": "me, 'Stay", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1438, @@ -2227,8 +2227,8 @@ Object { "V": "21", "bookID": "RUT", "characterIndex": 162, + "excerpt": "…ln-e\\\\*, '\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, '\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1438, @@ -2244,8 +2244,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "field.'\\"", "extra": "ST", - "extract": "field.'\\"", "filename": "08-RUT.usfm", "lineNumber": 1453, "location": " in en RUT book package from unfoldingWord master branch", @@ -2260,8 +2260,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "field.'\\"", "extra": "ST", - "extract": "field.'\\"", "filename": "08-RUT.usfm", "lineNumber": 1453, "location": " in en RUT book package from unfoldingWord master branch", @@ -2276,8 +2276,8 @@ Object { "V": "22", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Ruth,␣\\"My", "extra": "ST", - "extract": "Ruth,␣\\"My", "filename": "08-RUT.usfm", "lineNumber": 1460, "location": " in en RUT book package from unfoldingWord master branch", @@ -2291,8 +2291,8 @@ Object { "C": "2", "V": "22", "bookID": "RUT", + "excerpt": "Ruth, \\"My", "extra": "ST", - "extract": "Ruth, \\"My", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1460, @@ -2308,8 +2308,8 @@ Object { "V": "22", "bookID": "RUT", "characterIndex": 158, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 1460, @@ -2325,8 +2325,8 @@ Object { "V": "22", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "else's", "extra": "ST", - "extract": "else's", "filename": "08-RUT.usfm", "lineNumber": 1483, "location": " in en RUT book package from unfoldingWord master branch", @@ -2341,8 +2341,8 @@ Object { "V": "22", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "you.\\"", "extra": "ST", - "extract": "you.\\"", "filename": "08-RUT.usfm", "lineNumber": 1488, "location": " in en RUT book package from unfoldingWord master branch", @@ -2357,8 +2357,8 @@ Object { "V": "23", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Boaz's", "extra": "ST", - "extract": "Boaz's", "filename": "08-RUT.usfm", "lineNumber": 1497, "location": " in en RUT book package from unfoldingWord master branch", @@ -2373,8 +2373,8 @@ Object { "V": "1", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Ruth,␣\\"My", "extra": "ST", - "extract": "Ruth,␣\\"My", "filename": "08-RUT.usfm", "lineNumber": 1537, "location": " in en RUT book package from unfoldingWord master branch", @@ -2388,8 +2388,8 @@ Object { "C": "3", "V": "1", "bookID": "RUT", + "excerpt": "Ruth, \\"My", "extra": "ST", - "extract": "Ruth, \\"My", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1537, @@ -2405,8 +2405,8 @@ Object { "V": "1", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1537, @@ -2422,8 +2422,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Boaz's", "extra": "ST", - "extract": "Boaz's", "filename": "08-RUT.usfm", "lineNumber": 1560, "location": " in en RUT book package from unfoldingWord master branch", @@ -2438,8 +2438,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "do.\\"", "extra": "ST", - "extract": "do.\\"", "filename": "08-RUT.usfm", "lineNumber": 1675, "location": " in en RUT book package from unfoldingWord master branch", @@ -2454,8 +2454,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"I", "extra": "ST", - "extract": "…plied,␣\\"I", "filename": "08-RUT.usfm", "lineNumber": 1678, "location": " in en RUT book package from unfoldingWord master branch", @@ -2469,8 +2469,8 @@ Object { "C": "3", "V": "5", "bookID": "RUT", + "excerpt": "…eplied, \\"I", "extra": "ST", - "extract": "…eplied, \\"I", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1678, @@ -2486,8 +2486,8 @@ Object { "V": "5", "bookID": "RUT", "characterIndex": 64, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1678, @@ -2503,8 +2503,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "do.\\"", "extra": "ST", - "extract": "do.\\"", "filename": "08-RUT.usfm", "lineNumber": 1688, "location": " in en RUT book package from unfoldingWord master branch", @@ -2519,8 +2519,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "her,␣\\"Who", "extra": "ST", - "extract": "her,␣\\"Who", "filename": "08-RUT.usfm", "lineNumber": 1787, "location": " in en RUT book package from unfoldingWord master branch", @@ -2534,8 +2534,8 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "excerpt": "her, \\"Who", "extra": "ST", - "extract": "her, \\"Who", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1787, @@ -2551,8 +2551,8 @@ Object { "V": "9", "bookID": "RUT", "characterIndex": 51, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1787, @@ -2568,8 +2568,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "you?\\"", "extra": "ST", - "extract": "you?\\"", "filename": "08-RUT.usfm", "lineNumber": 1789, "location": " in en RUT book package from unfoldingWord master branch", @@ -2584,8 +2584,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"I", "extra": "ST", - "extract": "…plied,␣\\"I", "filename": "08-RUT.usfm", "lineNumber": 1791, "location": " in en RUT book package from unfoldingWord master branch", @@ -2599,8 +2599,8 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "excerpt": "…eplied, \\"I", "extra": "ST", - "extract": "…eplied, \\"I", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1791, @@ -2616,8 +2616,8 @@ Object { "V": "9", "bookID": "RUT", "characterIndex": 55, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1791, @@ -2633,8 +2633,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "husband's", "extra": "ST", - "extract": "husband's", "filename": "08-RUT.usfm", "lineNumber": 1805, "location": " in en RUT book package from unfoldingWord master branch", @@ -2649,8 +2649,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "me.\\"", "extra": "ST", - "extract": "me.\\"", "filename": "08-RUT.usfm", "lineNumber": 1813, "location": " in en RUT book package from unfoldingWord master branch", @@ -2665,8 +2665,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"May", "extra": "ST", - "extract": "…plied,␣\\"May", "filename": "08-RUT.usfm", "lineNumber": 1818, "location": " in en RUT book package from unfoldingWord master branch", @@ -2680,8 +2680,8 @@ Object { "C": "3", "V": "10", "bookID": "RUT", + "excerpt": "…eplied, \\"May", "extra": "ST", - "extract": "…eplied, \\"May", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1818, @@ -2697,8 +2697,8 @@ Object { "V": "10", "bookID": "RUT", "characterIndex": 55, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1818, @@ -2714,8 +2714,8 @@ Object { "V": "12", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Naomi's", "extra": "ST", - "extract": "Naomi's", "filename": "08-RUT.usfm", "lineNumber": 1889, "location": " in en RUT book package from unfoldingWord master branch", @@ -2730,8 +2730,8 @@ Object { "V": "13", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…orning.\\"", "extra": "ST", - "extract": "…orning.\\"", "filename": "08-RUT.usfm", "lineNumber": 1988, "location": " in en RUT book package from unfoldingWord master branch", @@ -2746,8 +2746,8 @@ Object { "V": "14", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "added,␣\\"It", "extra": "ST", - "extract": "added,␣\\"It", "filename": "08-RUT.usfm", "lineNumber": 1994, "location": " in en RUT book package from unfoldingWord master branch", @@ -2761,8 +2761,8 @@ Object { "C": "3", "V": "14", "bookID": "RUT", + "excerpt": "added, \\"It", "extra": "ST", - "extract": "added, \\"It", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 1994, @@ -2778,8 +2778,8 @@ Object { "V": "14", "bookID": "RUT", "characterIndex": 53, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 1994, @@ -2795,8 +2795,8 @@ Object { "V": "14", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "here.\\"", "extra": "ST", - "extract": "here.\\"", "filename": "08-RUT.usfm", "lineNumber": 2006, "location": " in en RUT book package from unfoldingWord master branch", @@ -2811,8 +2811,8 @@ Object { "V": "15", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "her,␣\\"Bring", "extra": "ST", - "extract": "her,␣\\"Bring", "filename": "08-RUT.usfm", "lineNumber": 2038, "location": " in en RUT book package from unfoldingWord master branch", @@ -2826,8 +2826,8 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "excerpt": "her, \\"Bring", "extra": "ST", - "extract": "her, \\"Bring", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2038, @@ -2843,8 +2843,8 @@ Object { "V": "15", "bookID": "RUT", "characterIndex": 51, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2038, @@ -2860,8 +2860,8 @@ Object { "V": "15", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "out.\\"", "extra": "ST", - "extract": "out.\\"", "filename": "08-RUT.usfm", "lineNumber": 2046, "location": " in en RUT book package from unfoldingWord master branch", @@ -2876,8 +2876,8 @@ Object { "V": "16", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "her,␣\\"Is", "extra": "ST", - "extract": "her,␣\\"Is", "filename": "08-RUT.usfm", "lineNumber": 2081, "location": " in en RUT book package from unfoldingWord master branch", @@ -2891,8 +2891,8 @@ Object { "C": "3", "V": "16", "bookID": "RUT", + "excerpt": "her, \\"Is", "extra": "ST", - "extract": "her, \\"Is", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2081, @@ -2908,8 +2908,8 @@ Object { "V": "16", "bookID": "RUT", "characterIndex": 51, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2081, @@ -2925,8 +2925,8 @@ Object { "V": "16", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…ughter?\\"", "extra": "ST", - "extract": "…ughter?\\"", "filename": "08-RUT.usfm", "lineNumber": 2085, "location": " in en RUT book package from unfoldingWord master branch", @@ -2941,8 +2941,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Naomi,␣\\"He", "extra": "ST", - "extract": "Naomi,␣\\"He", "filename": "08-RUT.usfm", "lineNumber": 2103, "location": " in en RUT book package from unfoldingWord master branch", @@ -2956,8 +2956,8 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "excerpt": "Naomi, \\"He", "extra": "ST", - "extract": "Naomi, \\"He", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2103, @@ -2973,8 +2973,8 @@ Object { "V": "17", "bookID": "RUT", "characterIndex": 53, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2103, @@ -2990,8 +2990,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…aying,␣'I", "extra": "ST", - "extract": "…aying,␣'I", "filename": "08-RUT.usfm", "lineNumber": 2109, "location": " in en RUT book package from unfoldingWord master branch", @@ -3005,8 +3005,8 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "excerpt": "saying, 'I", "extra": "ST", - "extract": "saying, 'I", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2109, @@ -3022,8 +3022,8 @@ Object { "V": "17", "bookID": "RUT", "characterIndex": 286, + "excerpt": "…ln-e\\\\*, '\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, '\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2109, @@ -3039,8 +3039,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…thing.'\\"", "extra": "ST", - "extract": "…thing.'\\"", "filename": "08-RUT.usfm", "lineNumber": 2120, "location": " in en RUT book package from unfoldingWord master branch", @@ -3055,8 +3055,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…othing.'\\"", "extra": "ST", - "extract": "…othing.'\\"", "filename": "08-RUT.usfm", "lineNumber": 2120, "location": " in en RUT book package from unfoldingWord master branch", @@ -3071,8 +3071,8 @@ Object { "V": "18", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "said,␣\\"My", "extra": "ST", - "extract": "said,␣\\"My", "filename": "08-RUT.usfm", "lineNumber": 2123, "location": " in en RUT book package from unfoldingWord master branch", @@ -3086,8 +3086,8 @@ Object { "C": "3", "V": "18", "bookID": "RUT", + "excerpt": "said, \\"My", "extra": "ST", - "extract": "said, \\"My", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2123, @@ -3103,8 +3103,8 @@ Object { "V": "18", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2123, @@ -3120,8 +3120,8 @@ Object { "V": "18", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "today.\\"", "extra": "ST", - "extract": "today.\\"", "filename": "08-RUT.usfm", "lineNumber": 2141, "location": " in en RUT book package from unfoldingWord master branch", @@ -3136,8 +3136,8 @@ Object { "V": "1", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "said,␣\\"Come", "extra": "ST", - "extract": "said,␣\\"Come", "filename": "08-RUT.usfm", "lineNumber": 2188, "location": " in en RUT book package from unfoldingWord master branch", @@ -3151,8 +3151,8 @@ Object { "C": "4", "V": "1", "bookID": "RUT", + "excerpt": "said, \\"Come", "extra": "ST", - "extract": "said, \\"Come", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2188, @@ -3168,8 +3168,8 @@ Object { "V": "1", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2188, @@ -3185,8 +3185,8 @@ Object { "V": "1", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "down.\\"", "extra": "ST", - "extract": "down.\\"", "filename": "08-RUT.usfm", "lineNumber": 2193, "location": " in en RUT book package from unfoldingWord master branch", @@ -3201,8 +3201,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "them,␣\\"Please", "extra": "ST", - "extract": "them,␣\\"Please", "filename": "08-RUT.usfm", "lineNumber": 2217, "location": " in en RUT book package from unfoldingWord master branch", @@ -3216,8 +3216,8 @@ Object { "C": "4", "V": "2", "bookID": "RUT", + "excerpt": "them, \\"Please", "extra": "ST", - "extract": "them, \\"Please", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2217, @@ -3233,8 +3233,8 @@ Object { "V": "2", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2217, @@ -3250,8 +3250,8 @@ Object { "V": "2", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…siness.\\"", "extra": "ST", - "extract": "…siness.\\"", "filename": "08-RUT.usfm", "lineNumber": 2225, "location": " in en RUT book package from unfoldingWord master branch", @@ -3266,8 +3266,8 @@ Object { "V": "3", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…ative,␣\\"Did", "extra": "ST", - "extract": "…ative,␣\\"Did", "filename": "08-RUT.usfm", "lineNumber": 2237, "location": " in en RUT book package from unfoldingWord master branch", @@ -3281,8 +3281,8 @@ Object { "C": "4", "V": "3", "bookID": "RUT", + "excerpt": "…lative, \\"Did", "extra": "ST", - "extract": "…lative, \\"Did", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2237, @@ -3298,8 +3298,8 @@ Object { "V": "3", "bookID": "RUT", "characterIndex": 56, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2237, @@ -3315,8 +3315,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "you.\\"", "extra": "ST", - "extract": "you.\\"", "filename": "08-RUT.usfm", "lineNumber": 2328, "location": " in en RUT book package from unfoldingWord master branch", @@ -3331,8 +3331,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…plied,␣\\"I", "extra": "ST", - "extract": "…plied,␣\\"I", "filename": "08-RUT.usfm", "lineNumber": 2332, "location": " in en RUT book package from unfoldingWord master branch", @@ -3346,8 +3346,8 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "excerpt": "…eplied, \\"I", "extra": "ST", - "extract": "…eplied, \\"I", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2332, @@ -3363,8 +3363,8 @@ Object { "V": "4", "bookID": "RUT", "characterIndex": 55, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2332, @@ -3380,8 +3380,8 @@ Object { "V": "4", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "it!\\"", "extra": "ST", - "extract": "it!\\"", "filename": "08-RUT.usfm", "lineNumber": 2335, "location": " in en RUT book package from unfoldingWord master branch", @@ -3396,8 +3396,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "him,␣\\"When", "extra": "ST", - "extract": "him,␣\\"When", "filename": "08-RUT.usfm", "lineNumber": 2341, "location": " in en RUT book package from unfoldingWord master branch", @@ -3411,8 +3411,8 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "excerpt": "him, \\"When", "extra": "ST", - "extract": "him, \\"When", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2341, @@ -3428,8 +3428,8 @@ Object { "V": "5", "bookID": "RUT", "characterIndex": 51, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2341, @@ -3445,8 +3445,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…elative's", "extra": "ST", - "extract": "…elative's", "filename": "08-RUT.usfm", "lineNumber": 2356, "location": " in en RUT book package from unfoldingWord master branch", @@ -3461,8 +3461,8 @@ Object { "V": "5", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "…usband.\\"", "extra": "ST", - "extract": "…usband.\\"", "filename": "08-RUT.usfm", "lineNumber": 2380, "location": " in en RUT book package from unfoldingWord master branch", @@ -3477,8 +3477,8 @@ Object { "V": "6", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "said,␣\\"Then", "extra": "ST", - "extract": "said,␣\\"Then", "filename": "08-RUT.usfm", "lineNumber": 2385, "location": " in en RUT book package from unfoldingWord master branch", @@ -3492,8 +3492,8 @@ Object { "C": "4", "V": "6", "bookID": "RUT", + "excerpt": "said, \\"Then", "extra": "ST", - "extract": "said, \\"Then", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2385, @@ -3509,8 +3509,8 @@ Object { "V": "6", "bookID": "RUT", "characterIndex": 173, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2385, @@ -3526,8 +3526,8 @@ Object { "V": "6", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "son's", "extra": "ST", - "extract": "son's", "filename": "08-RUT.usfm", "lineNumber": 2401, "location": " in en RUT book package from unfoldingWord master branch", @@ -3542,8 +3542,8 @@ Object { "V": "6", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "it.\\"", "extra": "ST", - "extract": "it.\\"", "filename": "08-RUT.usfm", "lineNumber": 2419, "location": " in en RUT book package from unfoldingWord master branch", @@ -3558,8 +3558,8 @@ Object { "V": "8", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Boaz,␣\\"You", "extra": "ST", - "extract": "Boaz,␣\\"You", "filename": "08-RUT.usfm", "lineNumber": 2474, "location": " in en RUT book package from unfoldingWord master branch", @@ -3573,8 +3573,8 @@ Object { "C": "4", "V": "8", "bookID": "RUT", + "excerpt": "Boaz, \\"You", "extra": "ST", - "extract": "Boaz, \\"You", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2474, @@ -3590,8 +3590,8 @@ Object { "V": "8", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2474, @@ -3607,8 +3607,8 @@ Object { "V": "8", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "…urself!\\"", "extra": "ST", - "extract": "…urself!\\"", "filename": "08-RUT.usfm", "lineNumber": 2478, "location": " in en RUT book package from unfoldingWord master branch", @@ -3623,8 +3623,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "there,␣\\"Today", "extra": "ST", - "extract": "there,␣\\"Today", "filename": "08-RUT.usfm", "lineNumber": 2510, "location": " in en RUT book package from unfoldingWord master branch", @@ -3638,8 +3638,8 @@ Object { "C": "4", "V": "9", "bookID": "RUT", + "excerpt": "there, \\"Today", "extra": "ST", - "extract": "there, \\"Today", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2510, @@ -3655,8 +3655,8 @@ Object { "V": "9", "bookID": "RUT", "characterIndex": 53, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2510, @@ -3672,8 +3672,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Mahlon's", "extra": "ST", - "extract": "Mahlon's", "filename": "08-RUT.usfm", "lineNumber": 2536, "location": " in en RUT book package from unfoldingWord master branch", @@ -3688,8 +3688,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "Mahlon's", "extra": "ST", - "extract": "Mahlon's", "filename": "08-RUT.usfm", "lineNumber": 2560, "location": " in en RUT book package from unfoldingWord master branch", @@ -3704,8 +3704,8 @@ Object { "V": "10", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "them.\\"", "extra": "ST", - "extract": "them.\\"", "filename": "08-RUT.usfm", "lineNumber": 2599, "location": " in en RUT book package from unfoldingWord master branch", @@ -3720,8 +3720,8 @@ Object { "V": "11", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "said,␣\\"Yes,", "extra": "ST", - "extract": "said,␣\\"Yes,", "filename": "08-RUT.usfm", "lineNumber": 2619, "location": " in en RUT book package from unfoldingWord master branch", @@ -3735,8 +3735,8 @@ Object { "C": "4", "V": "11", "bookID": "RUT", + "excerpt": "said, \\"Yes,", "extra": "ST", - "extract": "said, \\"Yes,", "fieldName": "from \\\\w", "filename": "08-RUT.usfm", "lineNumber": 2619, @@ -3752,8 +3752,8 @@ Object { "V": "11", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\w", "filename": "08-RUT.usfm", "lineNumber": 2619, @@ -3769,8 +3769,8 @@ Object { "V": "12", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "woman.\\"", "extra": "ST", - "extract": "woman.\\"", "filename": "08-RUT.usfm", "lineNumber": 2706, "location": " in en RUT book package from unfoldingWord master branch", @@ -3785,8 +3785,8 @@ Object { "V": "14", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Naomi,␣\\"Praise", "extra": "ST", - "extract": "Naomi,␣\\"Praise", "filename": "08-RUT.usfm", "lineNumber": 2742, "location": " in en RUT book package from unfoldingWord master branch", @@ -3800,8 +3800,8 @@ Object { "C": "4", "V": "14", "bookID": "RUT", + "excerpt": "Naomi, \\"Praise", "extra": "ST", - "extract": "Naomi, \\"Praise", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2742, @@ -3817,8 +3817,8 @@ Object { "V": "14", "bookID": "RUT", "characterIndex": 165, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2742, @@ -3834,8 +3834,8 @@ Object { "V": "15", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "old.\\"", "extra": "ST", - "extract": "old.\\"", "filename": "08-RUT.usfm", "lineNumber": 2805, "location": " in en RUT book package from unfoldingWord master branch", @@ -3850,8 +3850,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "said,␣\\"It", "extra": "ST", - "extract": "said,␣\\"It", "filename": "08-RUT.usfm", "lineNumber": 2832, "location": " in en RUT book package from unfoldingWord master branch", @@ -3865,8 +3865,8 @@ Object { "C": "4", "V": "17", "bookID": "RUT", + "excerpt": "said, \\"It", "extra": "ST", - "extract": "said, \\"It", "fieldName": "from \\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2832, @@ -3882,8 +3882,8 @@ Object { "V": "17", "bookID": "RUT", "characterIndex": 167, + "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", "fieldName": "\\\\zaln-s", "filename": "08-RUT.usfm", "lineNumber": 2832, @@ -3899,8 +3899,8 @@ Object { "V": "17", "bookID": "RUT", "details": "(line marker=\\\\w)", + "excerpt": "son!\\"", "extra": "ST", - "extract": "son!\\"", "filename": "08-RUT.usfm", "lineNumber": 2840, "location": " in en RUT book package from unfoldingWord master branch", @@ -3915,8 +3915,8 @@ Object { "V": "18", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Perez's", "extra": "ST", - "extract": "Perez's", "filename": "08-RUT.usfm", "lineNumber": 2867, "location": " in en RUT book package from unfoldingWord master branch", @@ -3931,8 +3931,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\v)", + "excerpt": "…␣Hezron's", "extra": "ST", - "extract": "…␣Hezron's", "filename": "08-RUT.usfm", "lineNumber": 2871, "location": " in en RUT book package from unfoldingWord master branch", @@ -3947,8 +3947,8 @@ Object { "V": "19", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Ram's", "extra": "ST", - "extract": "Ram's", "filename": "08-RUT.usfm", "lineNumber": 2875, "location": " in en RUT book package from unfoldingWord master branch", @@ -3963,8 +3963,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\v)", + "excerpt": "…minadab's", "extra": "ST", - "extract": "…minadab's", "filename": "08-RUT.usfm", "lineNumber": 2879, "location": " in en RUT book package from unfoldingWord master branch", @@ -3979,8 +3979,8 @@ Object { "V": "20", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Nahshon's", "extra": "ST", - "extract": "Nahshon's", "filename": "08-RUT.usfm", "lineNumber": 2883, "location": " in en RUT book package from unfoldingWord master branch", @@ -3995,8 +3995,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\v)", + "excerpt": "…␣Salmon's", "extra": "ST", - "extract": "…␣Salmon's", "filename": "08-RUT.usfm", "lineNumber": 2887, "location": " in en RUT book package from unfoldingWord master branch", @@ -4011,8 +4011,8 @@ Object { "V": "21", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Boaz's", "extra": "ST", - "extract": "Boaz's", "filename": "08-RUT.usfm", "lineNumber": 2891, "location": " in en RUT book package from unfoldingWord master branch", @@ -4027,8 +4027,8 @@ Object { "V": "22", "bookID": "RUT", "details": "(line marker=\\\\v)", + "excerpt": "22␣Obed's", "extra": "ST", - "extract": "22␣Obed's", "filename": "08-RUT.usfm", "lineNumber": 2895, "location": " in en RUT book package from unfoldingWord master branch", @@ -4043,8 +4043,8 @@ Object { "V": "22", "bookID": "RUT", "details": "(line marker=\\\\zaln-s)", + "excerpt": "Jesse's", "extra": "ST", - "extract": "Jesse's", "filename": "08-RUT.usfm", "lineNumber": 2899, "location": " in en RUT book package from unfoldingWord master branch", @@ -4057,8 +4057,8 @@ Object { Object { "bookID": "RUT", "characterIndex": 324394, + "excerpt": "…n-e\\\\*\\\\zaln-e\\\\*.", "extra": "ST", - "extract": "…n-e\\\\*\\\\zaln-e\\\\*.", "filename": "08-RUT.usfm", "location": " in en RUT book package from unfoldingWord master branch", "message": "File ends without newline character", @@ -4071,8 +4071,8 @@ Object { "C": "1", "V": "6", "bookID": "RUT", + "excerpt": "figs-idiom", "extra": "TN", - "extract": "figs-idiom", "fieldName": "SupportReference", "filename": "en_tn_08-RUT.tsv", "lineNumber": 19, @@ -4089,8 +4089,8 @@ Object { "V": "6", "bookID": "RUT", "details": "(SR='figs-idiom')", + "excerpt": "figs-synecdoche", "extra": "TN", - "extract": "figs-synecdoche", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 19, @@ -4106,8 +4106,8 @@ Object { "C": "1", "V": "7", "bookID": "RUT", + "excerpt": "figs-idiom", "extra": "TN", - "extract": "figs-idiom", "fieldName": "SupportReference", "filename": "en_tn_08-RUT.tsv", "lineNumber": 20, @@ -4124,8 +4124,8 @@ Object { "V": "9", "bookID": "RUT", "characterIndex": 52, + "excerpt": "…itality - that …", "extra": "TN", - "extract": "…itality - that …", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 92, @@ -4142,8 +4142,8 @@ Object { "V": "9", "bookID": "RUT", "details": "(empty SR field)", + "excerpt": "figs-euphemism", "extra": "TN", - "extract": "figs-euphemism", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 94, @@ -4159,8 +4159,8 @@ Object { "C": "2", "V": "11", "bookID": "RUT", + "excerpt": "figs-idiom", "extra": "TN", - "extract": "figs-idiom", "fieldName": "SupportReference", "filename": "en_tn_08-RUT.tsv", "lineNumber": 107, @@ -4194,8 +4194,8 @@ Object { "V": "12", "bookID": "RUT", "details": "(empty SR field)", + "excerpt": "grammar-connect-logic-contrast", "extra": "TN", - "extract": "grammar-connect-logic-contrast", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 184, @@ -4212,8 +4212,8 @@ Object { "V": "intro", "bookID": "RUT", "characterIndex": 407, + "excerpt": "…in␣him.␣<br><br…", "extra": "TN", - "extract": "…in␣him.␣<br><br…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 205, @@ -4230,8 +4230,8 @@ Object { "V": "7", "bookID": "RUT", "details": "(empty SR field)", + "excerpt": "figs-idiom", "extra": "TN", - "extract": "figs-idiom", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 230, @@ -4248,8 +4248,8 @@ Object { "V": "14", "bookID": "RUT", "characterIndex": 155, + "excerpt": "…se” or “ we giv…", "extra": "TN", - "extract": "…se” or “ we giv…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 255, @@ -4265,8 +4265,8 @@ Object { "C": "4", "V": "15", "bookID": "RUT", + "excerpt": "grammar-connect-logic-result", "extra": "TN", - "extract": "grammar-connect-logic-result", "fieldName": "SupportReference", "filename": "en_tn_08-RUT.tsv", "lineNumber": 260, @@ -4283,8 +4283,8 @@ Object { "V": "3", "bookID": "RUT", "characterIndex": 69, + "excerpt": "…aomi␣a␣widow.\\\\n\\\\n", "extra": "TQ", - "extract": "…aomi␣a␣widow.\\\\n\\\\n", "filename": "rut/01/03.md", "location": " in unfoldingWord (master)", "message": "File ends with additional blank line(s)", @@ -4298,8 +4298,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 166, + "excerpt": "…erly␣with␣her.␣", "extra": "TQ", - "extract": "…erly␣with␣her.␣", "filename": "rut/01/20.md", "location": " in unfoldingWord (master)", "message": "File ends without newline character", @@ -4313,8 +4313,8 @@ Object { "V": "20", "bookID": "RUT", "characterIndex": 122, + "excerpt": "…ed␣by␣Yahweh”\\\\n\\\\n", "extra": "TQ", - "extract": "…ed␣by␣Yahweh”\\\\n\\\\n", "filename": "rut/02/20.md", "location": " in unfoldingWord (master)", "message": "File ends with additional blank line(s)", @@ -4328,8 +4328,8 @@ Object { "V": "9", "bookID": "RUT", "characterIndex": 75, + "excerpt": "…deemer.”", "extra": "TQ", - "extract": "…deemer.”", "filename": "rut/03/09.md", "lineNumber": 3, "location": " in unfoldingWord (master)", @@ -4358,8 +4358,8 @@ Object { "V": "5", "bookID": "RUT", "characterIndex": 188, + "excerpt": "…␣inheritance.\\\\n\\\\n", "extra": "TQ", - "extract": "…␣inheritance.\\\\n\\\\n", "filename": "rut/04/05.md", "location": " in unfoldingWord (master)", "message": "File ends with additional blank line(s)", @@ -4373,8 +4373,8 @@ Object { "V": "12", "bookID": "RUT", "characterIndex": 147, + "excerpt": "…son␣to␣Judah.\\\\n\\\\n", "extra": "TQ", - "extract": "…son␣to␣Judah.\\\\n\\\\n", "filename": "rut/04/12.md", "location": " in unfoldingWord (master)", "message": "File ends with additional blank line(s)", @@ -4388,8 +4388,8 @@ Object { "V": "15", "bookID": "RUT", "characterIndex": 179, + "excerpt": "…on␣for␣Naomi.\\\\n\\\\n", "extra": "TQ", - "extract": "…on␣for␣Naomi.\\\\n\\\\n", "filename": "rut/04/15.md", "location": " in unfoldingWord (master)", "message": "File ends with additional blank line(s)", @@ -4403,8 +4403,8 @@ Object { "V": "17", "bookID": "RUT", "characterIndex": 157, + "excerpt": "…her␣of␣David.\\\\n\\\\n", "extra": "TQ", - "extract": "…her␣of␣David.\\\\n\\\\n", "filename": "rut/04/17.md", "location": " in unfoldingWord (master)", "message": "File ends with additional blank line(s)", @@ -4588,8 +4588,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 13, @@ -4605,8 +4605,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 14, @@ -4622,8 +4622,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 16, @@ -4639,8 +4639,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 18, @@ -4656,8 +4656,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 19, @@ -4673,8 +4673,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 21, @@ -4690,8 +4690,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 23, @@ -4707,8 +4707,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 24, @@ -4724,8 +4724,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 25, @@ -4741,8 +4741,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 27, @@ -4758,8 +4758,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 31, @@ -4775,8 +4775,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 33, @@ -4792,8 +4792,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 34, @@ -4809,8 +4809,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 36, @@ -4826,8 +4826,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 39, @@ -4843,8 +4843,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 40, @@ -4859,8 +4859,8 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "excerpt": "odliness,␣", "extra": "LT", - "extract": "odliness,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 42, @@ -4876,8 +4876,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 181, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 42, @@ -4893,8 +4893,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 42, @@ -4910,8 +4910,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 43, @@ -4927,8 +4927,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 44, @@ -4944,8 +4944,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 47, @@ -4961,8 +4961,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 48, @@ -4978,8 +4978,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 49, @@ -4995,8 +4995,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 50, @@ -5012,8 +5012,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 51, @@ -5029,8 +5029,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 52, @@ -5046,8 +5046,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 53, @@ -5063,8 +5063,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 56, @@ -5080,8 +5080,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 57, @@ -5097,8 +5097,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 58, @@ -5114,8 +5114,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 61, @@ -5130,8 +5130,8 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "excerpt": "time.␣", "extra": "LT", - "extract": "time.␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 62, @@ -5147,8 +5147,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 52, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 62, @@ -5164,8 +5164,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 63, @@ -5181,8 +5181,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 64, @@ -5198,8 +5198,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 66, @@ -5215,8 +5215,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 67, @@ -5232,8 +5232,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 68, @@ -5249,8 +5249,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 70, @@ -5266,8 +5266,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 71, @@ -5283,8 +5283,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 72, @@ -5300,8 +5300,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 73, @@ -5317,8 +5317,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 75, @@ -5334,8 +5334,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 76, @@ -5351,8 +5351,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 77, @@ -5368,8 +5368,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 80, @@ -5385,8 +5385,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 81, @@ -5402,8 +5402,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 83, @@ -5419,8 +5419,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 84, @@ -5436,8 +5436,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 85, @@ -5453,8 +5453,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 86, @@ -5470,8 +5470,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 89, @@ -5487,8 +5487,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 91, @@ -5504,8 +5504,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 92, @@ -5521,8 +5521,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 93, @@ -5538,8 +5538,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 94, @@ -5555,8 +5555,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 95, @@ -5572,8 +5572,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 97, @@ -5589,8 +5589,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 98, @@ -5606,8 +5606,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 99, @@ -5623,8 +5623,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 100, @@ -5640,8 +5640,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 101, @@ -5657,8 +5657,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 102, @@ -5674,8 +5674,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 103, @@ -5691,8 +5691,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 105, @@ -5708,8 +5708,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 106, @@ -5725,8 +5725,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 107, @@ -5742,8 +5742,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 108, @@ -5759,8 +5759,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 109, @@ -5776,8 +5776,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 111, @@ -5793,8 +5793,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 113, @@ -5810,8 +5810,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 114, @@ -5827,8 +5827,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 116, @@ -5844,8 +5844,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 117, @@ -5861,8 +5861,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 118, @@ -5878,8 +5878,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 119, @@ -5895,8 +5895,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 120, @@ -5912,8 +5912,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 125, @@ -5929,8 +5929,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 126, @@ -5946,8 +5946,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 129, @@ -5963,8 +5963,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 130, @@ -5980,8 +5980,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 131, @@ -5997,8 +5997,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 132, @@ -6014,8 +6014,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 134, @@ -6031,8 +6031,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 135, @@ -6048,8 +6048,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 136, @@ -6065,8 +6065,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 137, @@ -6082,8 +6082,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 138, @@ -6099,8 +6099,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 141, @@ -6116,8 +6116,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 142, @@ -6133,8 +6133,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 143, @@ -6150,8 +6150,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 144, @@ -6167,8 +6167,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 145, @@ -6184,8 +6184,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 147, @@ -6201,8 +6201,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 148, @@ -6218,8 +6218,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 149, @@ -6235,8 +6235,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 150, @@ -6252,8 +6252,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 151, @@ -6269,8 +6269,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 152, @@ -6286,8 +6286,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 153, @@ -6303,8 +6303,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 154, @@ -6320,8 +6320,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 155, @@ -6337,8 +6337,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 158, @@ -6353,8 +6353,8 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "excerpt": "ebellion.␣", "extra": "LT", - "extract": "ebellion.␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 159, @@ -6370,8 +6370,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 185, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 159, @@ -6387,8 +6387,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 159, @@ -6404,8 +6404,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 160, @@ -6421,8 +6421,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 161, @@ -6438,8 +6438,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 162, @@ -6455,8 +6455,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 163, @@ -6472,8 +6472,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 164, @@ -6489,8 +6489,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 165, @@ -6506,8 +6506,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 166, @@ -6523,8 +6523,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 167, @@ -6540,8 +6540,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 170, @@ -6557,8 +6557,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 172, @@ -6574,8 +6574,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 173, @@ -6591,8 +6591,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 174, @@ -6608,8 +6608,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 175, @@ -6625,8 +6625,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 177, @@ -6642,8 +6642,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 178, @@ -6659,8 +6659,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 181, @@ -6676,8 +6676,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 182, @@ -6693,8 +6693,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 184, @@ -6710,8 +6710,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 186, @@ -6727,8 +6727,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 191, @@ -6744,8 +6744,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 192, @@ -6761,8 +6761,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 196, @@ -6778,8 +6778,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 202, @@ -6795,8 +6795,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 203, @@ -6812,8 +6812,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 204, @@ -6829,8 +6829,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 205, @@ -6845,8 +6845,8 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "excerpt": "…ntrolled.␣", "extra": "LT", - "extract": "…ntrolled.␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 206, @@ -6862,8 +6862,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 104, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 206, @@ -6879,8 +6879,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 207, @@ -6896,8 +6896,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 212, @@ -6913,8 +6913,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 213, @@ -6930,8 +6930,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 214, @@ -6947,8 +6947,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 215, @@ -6964,8 +6964,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 220, @@ -6981,8 +6981,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 221, @@ -6998,8 +6998,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 222, @@ -7015,8 +7015,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 224, @@ -7032,8 +7032,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 227, @@ -7049,8 +7049,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 228, @@ -7066,8 +7066,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 229, @@ -7083,8 +7083,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 232, @@ -7100,8 +7100,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 233, @@ -7117,8 +7117,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 234, @@ -7134,8 +7134,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 235, @@ -7151,8 +7151,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 236, @@ -7168,8 +7168,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 237, @@ -7185,8 +7185,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 239, @@ -7202,8 +7202,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 244, @@ -7219,8 +7219,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 245, @@ -7236,8 +7236,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 247, @@ -7253,8 +7253,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 248, @@ -7270,8 +7270,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 250, @@ -7287,8 +7287,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 252, @@ -7304,8 +7304,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 253, @@ -7321,8 +7321,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 254, @@ -7338,8 +7338,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 255, @@ -7355,8 +7355,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 256, @@ -7372,8 +7372,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 257, @@ -7388,8 +7388,8 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "excerpt": "umcision.␣", "extra": "LT", - "extract": "umcision.␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 258, @@ -7405,8 +7405,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 184, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 258, @@ -7422,8 +7422,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 258, @@ -7439,8 +7439,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 259, @@ -7456,8 +7456,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 262, @@ -7473,8 +7473,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 264, @@ -7490,8 +7490,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 265, @@ -7507,8 +7507,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 266, @@ -7524,8 +7524,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 268, @@ -7541,8 +7541,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 269, @@ -7558,8 +7558,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 270, @@ -7575,8 +7575,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 271, @@ -7592,8 +7592,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 272, @@ -7609,8 +7609,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 274, @@ -7626,8 +7626,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 275, @@ -7643,8 +7643,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 279, @@ -7660,8 +7660,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 280, @@ -7677,8 +7677,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 283, @@ -7694,8 +7694,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 284, @@ -7711,8 +7711,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 285, @@ -7728,8 +7728,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 286, @@ -7745,8 +7745,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 288, @@ -7762,8 +7762,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 289, @@ -7779,8 +7779,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 290, @@ -7796,8 +7796,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 62, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 291, @@ -7813,8 +7813,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 292, @@ -7830,8 +7830,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 293, @@ -7847,8 +7847,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 294, @@ -7864,8 +7864,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 295, @@ -7881,8 +7881,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 296, @@ -7898,8 +7898,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 297, @@ -7914,8 +7914,8 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "excerpt": "bellies.”␣", "extra": "LT", - "extract": "bellies.”␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 298, @@ -7931,8 +7931,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 177, + "excerpt": "…aln-e\\\\*.”␣", "extra": "LT", - "extract": "…aln-e\\\\*.”␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 298, @@ -7948,8 +7948,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 298, @@ -7965,8 +7965,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 299, @@ -7982,8 +7982,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 300, @@ -7999,8 +7999,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 301, @@ -8016,8 +8016,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 302, @@ -8033,8 +8033,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 303, @@ -8050,8 +8050,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 304, @@ -8067,8 +8067,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 305, @@ -8084,8 +8084,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 306, @@ -8101,8 +8101,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 307, @@ -8118,8 +8118,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 308, @@ -8135,8 +8135,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 309, @@ -8152,8 +8152,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 311, @@ -8169,8 +8169,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 315, @@ -8186,8 +8186,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 316, @@ -8202,8 +8202,8 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "excerpt": "faith,␣", "extra": "LT", - "extract": "faith,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 317, @@ -8219,8 +8219,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 172, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 317, @@ -8236,8 +8236,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 317, @@ -8253,8 +8253,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 318, @@ -8270,8 +8270,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 319, @@ -8287,8 +8287,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 322, @@ -8304,8 +8304,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 323, @@ -8321,8 +8321,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 324, @@ -8338,8 +8338,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 325, @@ -8355,8 +8355,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 326, @@ -8372,8 +8372,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 329, @@ -8389,8 +8389,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 331, @@ -8406,8 +8406,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 335, @@ -8423,8 +8423,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 336, @@ -8440,8 +8440,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 339, @@ -8457,8 +8457,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 341, @@ -8474,8 +8474,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 343, @@ -8491,8 +8491,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 346, @@ -8508,8 +8508,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 348, @@ -8525,8 +8525,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 349, @@ -8542,8 +8542,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 352, @@ -8559,8 +8559,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 354, @@ -8576,8 +8576,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 355, @@ -8593,8 +8593,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 356, @@ -8610,8 +8610,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 357, @@ -8627,8 +8627,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 359, @@ -8644,8 +8644,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 360, @@ -8661,8 +8661,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 361, @@ -8678,8 +8678,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 362, @@ -8695,8 +8695,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 363, @@ -8712,8 +8712,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 364, @@ -8729,8 +8729,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 365, @@ -8746,8 +8746,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 366, @@ -8762,8 +8762,8 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "excerpt": "orrupted.␣", "extra": "LT", - "extract": "orrupted.␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 368, @@ -8779,8 +8779,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 57, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 368, @@ -8796,8 +8796,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 369, @@ -8813,8 +8813,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 371, @@ -8830,8 +8830,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 373, @@ -8847,8 +8847,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 374, @@ -8864,8 +8864,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 375, @@ -8881,8 +8881,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 378, @@ -8898,8 +8898,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 379, @@ -8915,8 +8915,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 380, @@ -8932,8 +8932,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 381, @@ -8949,8 +8949,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 383, @@ -8966,8 +8966,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 384, @@ -8983,8 +8983,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 385, @@ -9000,8 +9000,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 386, @@ -9017,8 +9017,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 387, @@ -9034,8 +9034,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 388, @@ -9051,8 +9051,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 389, @@ -9068,8 +9068,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 390, @@ -9085,8 +9085,8 @@ Object { "V": "16", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 391, @@ -9102,8 +9102,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 396, @@ -9119,8 +9119,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 397, @@ -9136,8 +9136,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 398, @@ -9153,8 +9153,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 399, @@ -9170,8 +9170,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 400, @@ -9187,8 +9187,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 401, @@ -9204,8 +9204,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 402, @@ -9220,8 +9220,8 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "excerpt": "teaching.␣", "extra": "LT", - "extract": "teaching.␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 403, @@ -9237,8 +9237,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 183, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 403, @@ -9254,8 +9254,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 403, @@ -9271,8 +9271,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 404, @@ -9288,8 +9288,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 406, @@ -9305,8 +9305,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 409, @@ -9322,8 +9322,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 410, @@ -9339,8 +9339,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 411, @@ -9356,8 +9356,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 412, @@ -9373,8 +9373,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 413, @@ -9390,8 +9390,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 414, @@ -9407,8 +9407,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 415, @@ -9424,8 +9424,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 416, @@ -9441,8 +9441,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 417, @@ -9458,8 +9458,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 419, @@ -9475,8 +9475,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 422, @@ -9492,8 +9492,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 424, @@ -9509,8 +9509,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 428, @@ -9526,8 +9526,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 429, @@ -9543,8 +9543,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 430, @@ -9560,8 +9560,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 431, @@ -9577,8 +9577,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 432, @@ -9594,8 +9594,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 433, @@ -9611,8 +9611,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 434, @@ -9628,8 +9628,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 436, @@ -9645,8 +9645,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 437, @@ -9662,8 +9662,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 438, @@ -9679,8 +9679,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 439, @@ -9695,8 +9695,8 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "excerpt": "good.␣", "extra": "LT", - "extract": "good.␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 446, @@ -9712,8 +9712,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 52, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 446, @@ -9729,8 +9729,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 447, @@ -9746,8 +9746,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 450, @@ -9763,8 +9763,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 453, @@ -9780,8 +9780,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 454, @@ -9797,8 +9797,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 456, @@ -9814,8 +9814,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 458, @@ -9831,8 +9831,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 462, @@ -9847,8 +9847,8 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "excerpt": "children,␣", "extra": "LT", - "extract": "children,␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 466, @@ -9864,8 +9864,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 56, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 466, @@ -9881,8 +9881,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 467, @@ -9898,8 +9898,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 470, @@ -9915,8 +9915,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 471, @@ -9932,8 +9932,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 472, @@ -9949,8 +9949,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 473, @@ -9966,8 +9966,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 475, @@ -9983,8 +9983,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 476, @@ -10000,8 +10000,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 477, @@ -10017,8 +10017,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 478, @@ -10034,8 +10034,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 479, @@ -10051,8 +10051,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 481, @@ -10068,8 +10068,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 482, @@ -10085,8 +10085,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 483, @@ -10102,8 +10102,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 484, @@ -10119,8 +10119,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 485, @@ -10136,8 +10136,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 486, @@ -10153,8 +10153,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 487, @@ -10170,8 +10170,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 491, @@ -10187,8 +10187,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 495, @@ -10204,8 +10204,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 496, @@ -10221,8 +10221,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 497, @@ -10238,8 +10238,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 499, @@ -10254,8 +10254,8 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "excerpt": "sensible.␣", "extra": "LT", - "extract": "sensible.␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 501, @@ -10271,8 +10271,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 56, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 501, @@ -10288,8 +10288,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 502, @@ -10305,8 +10305,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 503, @@ -10322,8 +10322,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 505, @@ -10339,8 +10339,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 506, @@ -10356,8 +10356,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 507, @@ -10373,8 +10373,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 510, @@ -10390,8 +10390,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 511, @@ -10407,8 +10407,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 512, @@ -10424,8 +10424,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 513, @@ -10441,8 +10441,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 514, @@ -10458,8 +10458,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 515, @@ -10475,8 +10475,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 516, @@ -10492,8 +10492,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 518, @@ -10508,8 +10508,8 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "excerpt": "dignity,␣", "extra": "LT", - "extract": "dignity,␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 519, @@ -10525,8 +10525,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 55, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 519, @@ -10542,8 +10542,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 520, @@ -10559,8 +10559,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 522, @@ -10576,8 +10576,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 523, @@ -10593,8 +10593,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 524, @@ -10610,8 +10610,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 528, @@ -10627,8 +10627,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 530, @@ -10644,8 +10644,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 531, @@ -10661,8 +10661,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 532, @@ -10678,8 +10678,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 535, @@ -10695,8 +10695,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 536, @@ -10712,8 +10712,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 537, @@ -10729,8 +10729,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 538, @@ -10746,8 +10746,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 540, @@ -10763,8 +10763,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 541, @@ -10780,8 +10780,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 544, @@ -10797,8 +10797,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 545, @@ -10814,8 +10814,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 549, @@ -10831,8 +10831,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 550, @@ -10848,8 +10848,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 552, @@ -10865,8 +10865,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 553, @@ -10882,8 +10882,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 554, @@ -10899,8 +10899,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 555, @@ -10916,8 +10916,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 557, @@ -10933,8 +10933,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 558, @@ -10950,8 +10950,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 560, @@ -10966,8 +10966,8 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "excerpt": "argue,␣", "extra": "LT", - "extract": "argue,␣", "fieldName": "from \\\\w", "filename": "57-TIT.usfm", "lineNumber": 561, @@ -10983,8 +10983,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 53, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\w", "filename": "57-TIT.usfm", "lineNumber": 561, @@ -11000,8 +11000,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 562, @@ -11017,8 +11017,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 563, @@ -11034,8 +11034,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 565, @@ -11051,8 +11051,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 567, @@ -11068,8 +11068,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 569, @@ -11085,8 +11085,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 570, @@ -11102,8 +11102,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 571, @@ -11119,8 +11119,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 572, @@ -11136,8 +11136,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 574, @@ -11153,8 +11153,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 575, @@ -11170,8 +11170,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 577, @@ -11187,8 +11187,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 582, @@ -11204,8 +11204,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 583, @@ -11221,8 +11221,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 584, @@ -11238,8 +11238,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 586, @@ -11255,8 +11255,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 587, @@ -11272,8 +11272,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 588, @@ -11289,8 +11289,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 589, @@ -11306,8 +11306,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 592, @@ -11323,8 +11323,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 593, @@ -11340,8 +11340,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 594, @@ -11357,8 +11357,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 595, @@ -11374,8 +11374,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 596, @@ -11391,8 +11391,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 597, @@ -11408,8 +11408,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 599, @@ -11425,8 +11425,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 601, @@ -11442,8 +11442,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 602, @@ -11458,8 +11458,8 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "excerpt": "people,␣", "extra": "LT", - "extract": "people,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 603, @@ -11475,8 +11475,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 178, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 603, @@ -11492,8 +11492,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 603, @@ -11509,8 +11509,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 604, @@ -11526,8 +11526,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 605, @@ -11543,8 +11543,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 606, @@ -11560,8 +11560,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 608, @@ -11577,8 +11577,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 609, @@ -11594,8 +11594,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 610, @@ -11611,8 +11611,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 611, @@ -11628,8 +11628,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 612, @@ -11645,8 +11645,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 613, @@ -11662,8 +11662,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 616, @@ -11679,8 +11679,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 619, @@ -11696,8 +11696,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 620, @@ -11713,8 +11713,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 621, @@ -11730,8 +11730,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 622, @@ -11747,8 +11747,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 624, @@ -11764,8 +11764,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 625, @@ -11781,8 +11781,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 626, @@ -11797,8 +11797,8 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "excerpt": "age,␣", "extra": "LT", - "extract": "age,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 627, @@ -11814,8 +11814,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 167, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 627, @@ -11831,8 +11831,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 627, @@ -11848,8 +11848,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 628, @@ -11865,8 +11865,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 634, @@ -11882,8 +11882,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 635, @@ -11899,8 +11899,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 636, @@ -11916,8 +11916,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 637, @@ -11933,8 +11933,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 638, @@ -11950,8 +11950,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 639, @@ -11967,8 +11967,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 640, @@ -11984,8 +11984,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 641, @@ -12001,8 +12001,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 642, @@ -12018,8 +12018,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 643, @@ -12035,8 +12035,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 644, @@ -12052,8 +12052,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 645, @@ -12069,8 +12069,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 646, @@ -12086,8 +12086,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 647, @@ -12103,8 +12103,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 648, @@ -12120,8 +12120,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 649, @@ -12137,8 +12137,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 652, @@ -12154,8 +12154,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 653, @@ -12171,8 +12171,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 654, @@ -12188,8 +12188,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 655, @@ -12205,8 +12205,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 656, @@ -12222,8 +12222,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 657, @@ -12239,8 +12239,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 659, @@ -12256,8 +12256,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 661, @@ -12273,8 +12273,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 662, @@ -12290,8 +12290,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 663, @@ -12307,8 +12307,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 664, @@ -12324,8 +12324,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 665, @@ -12341,8 +12341,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 666, @@ -12358,8 +12358,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 668, @@ -12375,8 +12375,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 670, @@ -12392,8 +12392,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 671, @@ -12409,8 +12409,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 672, @@ -12426,8 +12426,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 673, @@ -12443,8 +12443,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 674, @@ -12460,8 +12460,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 675, @@ -12477,8 +12477,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 676, @@ -12494,8 +12494,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 680, @@ -12511,8 +12511,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 681, @@ -12528,8 +12528,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 684, @@ -12545,8 +12545,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 685, @@ -12562,8 +12562,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 686, @@ -12579,8 +12579,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 687, @@ -12596,8 +12596,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 688, @@ -12613,8 +12613,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 689, @@ -12630,8 +12630,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 690, @@ -12647,8 +12647,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 691, @@ -12664,8 +12664,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 692, @@ -12681,8 +12681,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 694, @@ -12698,8 +12698,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 695, @@ -12715,8 +12715,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 700, @@ -12732,8 +12732,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 701, @@ -12749,8 +12749,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 702, @@ -12766,8 +12766,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 704, @@ -12783,8 +12783,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 706, @@ -12800,8 +12800,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 708, @@ -12817,8 +12817,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 711, @@ -12834,8 +12834,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 713, @@ -12851,8 +12851,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 714, @@ -12868,8 +12868,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 715, @@ -12885,8 +12885,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 716, @@ -12901,8 +12901,8 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "excerpt": "work,␣", "extra": "LT", - "extract": "work,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 717, @@ -12918,8 +12918,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 169, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 717, @@ -12935,8 +12935,8 @@ Object { "V": "1", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 717, @@ -12952,8 +12952,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 718, @@ -12969,8 +12969,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 720, @@ -12986,8 +12986,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 722, @@ -13003,8 +13003,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 724, @@ -13020,8 +13020,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 725, @@ -13037,8 +13037,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 726, @@ -13054,8 +13054,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 727, @@ -13071,8 +13071,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 728, @@ -13088,8 +13088,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 729, @@ -13105,8 +13105,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 730, @@ -13122,8 +13122,8 @@ Object { "V": "2", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 731, @@ -13139,8 +13139,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 734, @@ -13156,8 +13156,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 735, @@ -13173,8 +13173,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 736, @@ -13190,8 +13190,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 737, @@ -13207,8 +13207,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 738, @@ -13224,8 +13224,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 739, @@ -13241,8 +13241,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 740, @@ -13258,8 +13258,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 742, @@ -13275,8 +13275,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 746, @@ -13292,8 +13292,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 748, @@ -13309,8 +13309,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 749, @@ -13326,8 +13326,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 750, @@ -13343,8 +13343,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 751, @@ -13360,8 +13360,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 752, @@ -13377,8 +13377,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 753, @@ -13394,8 +13394,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 755, @@ -13411,8 +13411,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 756, @@ -13428,8 +13428,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 757, @@ -13445,8 +13445,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 758, @@ -13462,8 +13462,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 759, @@ -13479,8 +13479,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 760, @@ -13496,8 +13496,8 @@ Object { "V": "3", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 762, @@ -13513,8 +13513,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 766, @@ -13530,8 +13530,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 767, @@ -13547,8 +13547,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 768, @@ -13564,8 +13564,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 769, @@ -13581,8 +13581,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 770, @@ -13598,8 +13598,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 771, @@ -13615,8 +13615,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 772, @@ -13632,8 +13632,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 773, @@ -13649,8 +13649,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 774, @@ -13666,8 +13666,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 775, @@ -13683,8 +13683,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 776, @@ -13699,8 +13699,8 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "excerpt": "appeared,␣", "extra": "LT", - "extract": "appeared,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 779, @@ -13716,8 +13716,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 178, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 779, @@ -13733,8 +13733,8 @@ Object { "V": "4", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 779, @@ -13750,8 +13750,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 780, @@ -13767,8 +13767,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 783, @@ -13784,8 +13784,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 784, @@ -13801,8 +13801,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 785, @@ -13818,8 +13818,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 786, @@ -13835,8 +13835,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 787, @@ -13852,8 +13852,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 788, @@ -13869,8 +13869,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 789, @@ -13886,8 +13886,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 790, @@ -13903,8 +13903,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 791, @@ -13920,8 +13920,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 792, @@ -13937,8 +13937,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 793, @@ -13954,8 +13954,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 794, @@ -13971,8 +13971,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 797, @@ -13988,8 +13988,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 798, @@ -14005,8 +14005,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 799, @@ -14022,8 +14022,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 801, @@ -14039,8 +14039,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 804, @@ -14056,8 +14056,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 805, @@ -14073,8 +14073,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 806, @@ -14090,8 +14090,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 808, @@ -14107,8 +14107,8 @@ Object { "V": "5", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 809, @@ -14124,8 +14124,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 812, @@ -14141,8 +14141,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 813, @@ -14158,8 +14158,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 814, @@ -14175,8 +14175,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 815, @@ -14192,8 +14192,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 816, @@ -14209,8 +14209,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 817, @@ -14226,8 +14226,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 818, @@ -14243,8 +14243,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 819, @@ -14260,8 +14260,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 820, @@ -14277,8 +14277,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 821, @@ -14293,8 +14293,8 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "excerpt": "Christ,␣", "extra": "LT", - "extract": "Christ,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 822, @@ -14310,8 +14310,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 175, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 822, @@ -14327,8 +14327,8 @@ Object { "V": "6", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 822, @@ -14344,8 +14344,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 823, @@ -14361,8 +14361,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 825, @@ -14378,8 +14378,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 828, @@ -14395,8 +14395,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 829, @@ -14412,8 +14412,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 830, @@ -14429,8 +14429,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 831, @@ -14446,8 +14446,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 834, @@ -14463,8 +14463,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 835, @@ -14480,8 +14480,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 837, @@ -14497,8 +14497,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 840, @@ -14514,8 +14514,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 841, @@ -14531,8 +14531,8 @@ Object { "V": "7", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 842, @@ -14548,8 +14548,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 845, @@ -14565,8 +14565,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 846, @@ -14582,8 +14582,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 847, @@ -14599,8 +14599,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 849, @@ -14616,8 +14616,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 850, @@ -14633,8 +14633,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 852, @@ -14650,8 +14650,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 853, @@ -14667,8 +14667,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 855, @@ -14684,8 +14684,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 856, @@ -14701,8 +14701,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 858, @@ -14718,8 +14718,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 860, @@ -14735,8 +14735,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 862, @@ -14752,8 +14752,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 864, @@ -14769,8 +14769,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 865, @@ -14786,8 +14786,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 868, @@ -14803,8 +14803,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 871, @@ -14820,8 +14820,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 872, @@ -14837,8 +14837,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 873, @@ -14854,8 +14854,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 874, @@ -14871,8 +14871,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 876, @@ -14888,8 +14888,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 877, @@ -14905,8 +14905,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 878, @@ -14922,8 +14922,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 879, @@ -14939,8 +14939,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 880, @@ -14956,8 +14956,8 @@ Object { "V": "8", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 881, @@ -14973,8 +14973,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 10, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 884, @@ -14990,8 +14990,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 885, @@ -15007,8 +15007,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 886, @@ -15024,8 +15024,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 887, @@ -15041,8 +15041,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 888, @@ -15058,8 +15058,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 889, @@ -15075,8 +15075,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 890, @@ -15092,8 +15092,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 891, @@ -15109,8 +15109,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 892, @@ -15126,8 +15126,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 893, @@ -15143,8 +15143,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 894, @@ -15160,8 +15160,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 897, @@ -15177,8 +15177,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 898, @@ -15194,8 +15194,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 900, @@ -15211,8 +15211,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 901, @@ -15227,8 +15227,8 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "excerpt": "orthless.␣", "extra": "LT", - "extract": "orthless.␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 902, @@ -15244,8 +15244,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 178, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 902, @@ -15261,8 +15261,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 902, @@ -15278,8 +15278,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 903, @@ -15295,8 +15295,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 904, @@ -15312,8 +15312,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 905, @@ -15329,8 +15329,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 906, @@ -15346,8 +15346,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 907, @@ -15363,8 +15363,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 908, @@ -15380,8 +15380,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 909, @@ -15397,8 +15397,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 910, @@ -15413,8 +15413,8 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "excerpt": "warnings,␣", "extra": "LT", - "extract": "warnings,␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 911, @@ -15430,8 +15430,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 180, + "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", - "extract": "…zaln-e\\\\*,␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 911, @@ -15447,8 +15447,8 @@ Object { "V": "10", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 911, @@ -15464,8 +15464,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 912, @@ -15481,8 +15481,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 913, @@ -15498,8 +15498,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 914, @@ -15515,8 +15515,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 917, @@ -15532,8 +15532,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 923, @@ -15549,8 +15549,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 924, @@ -15566,8 +15566,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 926, @@ -15583,8 +15583,8 @@ Object { "V": "11", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 927, @@ -15600,8 +15600,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 931, @@ -15617,8 +15617,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 932, @@ -15634,8 +15634,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 934, @@ -15651,8 +15651,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 935, @@ -15668,8 +15668,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 936, @@ -15685,8 +15685,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 937, @@ -15702,8 +15702,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 938, @@ -15719,8 +15719,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 939, @@ -15736,8 +15736,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 940, @@ -15753,8 +15753,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 942, @@ -15770,8 +15770,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 943, @@ -15787,8 +15787,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 944, @@ -15804,8 +15804,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 945, @@ -15821,8 +15821,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 946, @@ -15838,8 +15838,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 947, @@ -15855,8 +15855,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 950, @@ -15871,8 +15871,8 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "excerpt": "there.␣", "extra": "LT", - "extract": "there.␣", "fieldName": "from \\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 954, @@ -15888,8 +15888,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 168, + "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", - "extract": "…zaln-e\\\\*.␣", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 954, @@ -15905,8 +15905,8 @@ Object { "V": "12", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 954, @@ -15922,8 +15922,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 955, @@ -15939,8 +15939,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 956, @@ -15956,8 +15956,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 960, @@ -15973,8 +15973,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 961, @@ -15990,8 +15990,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 962, @@ -16007,8 +16007,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 963, @@ -16024,8 +16024,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 964, @@ -16041,8 +16041,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 965, @@ -16058,8 +16058,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 967, @@ -16075,8 +16075,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 968, @@ -16092,8 +16092,8 @@ Object { "V": "13", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 969, @@ -16109,8 +16109,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 972, @@ -16126,8 +16126,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 973, @@ -16143,8 +16143,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 974, @@ -16160,8 +16160,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 975, @@ -16177,8 +16177,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 977, @@ -16194,8 +16194,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 980, @@ -16211,8 +16211,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 981, @@ -16228,8 +16228,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 982, @@ -16245,8 +16245,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 983, @@ -16262,8 +16262,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 984, @@ -16279,8 +16279,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 985, @@ -16296,8 +16296,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 986, @@ -16313,8 +16313,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 988, @@ -16330,8 +16330,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 989, @@ -16347,8 +16347,8 @@ Object { "V": "14", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 991, @@ -16364,8 +16364,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 11, + "excerpt": "…zaln-s | x-stro…", "extra": "LT", - "extract": "…zaln-s | x-stro…", "fieldName": "\\\\v", "filename": "57-TIT.usfm", "lineNumber": 995, @@ -16381,8 +16381,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 996, @@ -16398,8 +16398,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 999, @@ -16415,8 +16415,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1000, @@ -16432,8 +16432,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1001, @@ -16449,8 +16449,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1002, @@ -16466,8 +16466,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1003, @@ -16483,8 +16483,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1004, @@ -16500,8 +16500,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1006, @@ -16517,8 +16517,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1007, @@ -16534,8 +16534,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1008, @@ -16551,8 +16551,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1009, @@ -16568,8 +16568,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1010, @@ -16585,8 +16585,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1011, @@ -16602,8 +16602,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1013, @@ -16619,8 +16619,8 @@ Object { "V": "15", "bookID": "TIT", "characterIndex": 0, + "excerpt": "| x-stro…", "extra": "LT", - "extract": "| x-stro…", "fieldName": "\\\\zaln-s", "filename": "57-TIT.usfm", "lineNumber": 1014, @@ -16634,8 +16634,8 @@ Object { Object { "bookID": "TIT", "characterIndex": 134985, + "excerpt": "…2\\"\\\\w*\\\\zaln-e\\\\*.", "extra": "LT", - "extract": "…2\\"\\\\w*\\\\zaln-e\\\\*.", "filename": "57-TIT.usfm", "location": " in en TIT book package from unfoldingWord master branch", "message": "File ends without newline character", @@ -16647,8 +16647,8 @@ Object { Object { "bookID": "TIT", "characterIndex": 176298, + "excerpt": "…2\\"\\\\w*\\\\zaln-e\\\\*.", "extra": "ST", - "extract": "…2\\"\\\\w*\\\\zaln-e\\\\*.", "filename": "57-TIT.usfm", "location": " in en TIT book package from unfoldingWord master branch", "message": "File ends without newline character", @@ -16662,8 +16662,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 304, + "excerpt": "… (See: \\\\[\\\\[rc:/…", "extra": "TN", - "extract": "… (See: \\\\[\\\\[rc:/…", "fieldName": "OccurrenceNote", "filename": "en_tn_57-TIT.tsv", "lineNumber": 41, @@ -16680,8 +16680,8 @@ Object { "V": "9", "bookID": "TIT", "characterIndex": 359, + "excerpt": "…ic-goal\\\\]\\\\])", "extra": "TN", - "extract": "…ic-goal\\\\]\\\\])", "fieldName": "OccurrenceNote", "filename": "en_tn_57-TIT.tsv", "lineNumber": 41, @@ -16698,8 +16698,8 @@ Object { "V": "10", "bookID": "TIT", "details": "(empty SR field)", + "excerpt": "figs-metaphor", "extra": "TN", - "extract": "figs-metaphor", "fieldName": "OccurrenceNote", "filename": "en_tn_57-TIT.tsv", "lineNumber": 44, @@ -16716,8 +16716,8 @@ Object { "V": "5", "bookID": "TIT", "details": "(SR='figs-activepassive')", + "excerpt": "figs-metonymy", "extra": "TN", - "extract": "figs-metonymy", "fieldName": "OccurrenceNote", "filename": "en_tn_57-TIT.tsv", "lineNumber": 91, @@ -16733,8 +16733,8 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "excerpt": "figs-inclusive", "extra": "TN", - "extract": "figs-inclusive", "fieldName": "SupportReference", "filename": "en_tn_57-TIT.tsv", "lineNumber": 189, @@ -16750,8 +16750,8 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "excerpt": "figs-inclusive", "extra": "TN", - "extract": "figs-inclusive", "fieldName": "SupportReference", "filename": "en_tn_57-TIT.tsv", "lineNumber": 197, diff --git a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap index 007b03962..a6546a87d 100644 --- a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap +++ b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`checkTN_TSVDataRow() - BookID tests - should find wrong book ID 1`] = ` +exports[`checkTN_TSV9DataRow() - BookID tests - should find wrong book ID 1`] = ` Object { "noticeList": Array [ Object { @@ -8,7 +8,7 @@ Object { "V": "2", "bookID": "GEN", "details": "expected 'GEN'", - "extract": "RUT", + "excerpt": "RUT", "fieldName": "Book", "location": " that was supplied", "message": "Wrong book identifier", @@ -20,7 +20,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -31,7 +31,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - GL Note tests - should find bad ellipse 1`] = ` +exports[`checkTN_TSV9DataRow() - GL Note tests - should find bad ellipse 1`] = ` Object { "noticeList": Array [ Object { @@ -49,7 +49,7 @@ Object { "V": "3", "bookID": "GEN", "characterIndex": 11, - "extract": "…ellipse...", + "excerpt": "…ellipse...", "fieldName": "GLQuote", "location": " that was supplied", "message": "Unexpected doubled . characters", @@ -60,14 +60,14 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Occurrence Note tests - should find empty note 1`] = ` +exports[`checkTN_TSV9DataRow() - Occurrence Note tests - should find empty note 1`] = ` Object { "noticeList": Array [ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "figs-imperative", + "excerpt": "figs-imperative", "fieldName": "SupportReference", "location": " that was supplied", "message": "Link to TA should also be in OccurrenceNote", @@ -88,14 +88,14 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Occurrence Note tests - should find white space 1`] = ` +exports[`checkTN_TSV9DataRow() - Occurrence Note tests - should find white space 1`] = ` Object { "noticeList": Array [ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "figs-imperative", + "excerpt": "figs-imperative", "fieldName": "SupportReference", "location": " that was supplied", "message": "Link to TA should also be in OccurrenceNote", @@ -116,7 +116,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - invalid Original Language 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - invalid Original Language 1`] = ` Object { "noticeList": Array [ Object { @@ -144,7 +144,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail to find OrigLang Quote 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail to find OrigLang Quote 1`] = ` Object { "noticeList": Array [ Object { @@ -152,7 +152,7 @@ Object { "V": "2", "bookID": "GEN", "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "extract": "וְחֹ֖שחֹ֖שֶךְ", + "excerpt": "וְחֹ֖שחֹ֖שֶךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -164,7 +164,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -175,7 +175,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with leading space 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with leading space 1`] = ` Object { "noticeList": Array [ Object { @@ -183,7 +183,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 0, - "extract": "␣וְחֹ֖שֶׁךְ", + "excerpt": "␣וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unexpected leading space", @@ -196,7 +196,7 @@ Object { "bookID": "GEN", "characterIndex": 0, "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "extract": "(ּ=D1468/H5bc) וְחֹ֖שֶׁךְ", + "excerpt": "(ּ=D1468/H5bc) וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Seems original language quote might not start at the beginning of a word", @@ -208,7 +208,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -220,7 +220,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with leading word joiner 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with leading word joiner 1`] = ` Object { "noticeList": Array [ Object { @@ -228,7 +228,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 0, - "extract": "‼וְ‼חֹ֖שֶׁךְ", + "excerpt": "‼וְ‼חֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unexpected leading word-joiner", @@ -240,7 +240,7 @@ Object { "V": "2", "bookID": "GEN", "details": "quote which starts with 'word joiner'", - "extract": "", + "excerpt": "", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -252,7 +252,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -264,7 +264,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with leading zero width joiner 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with leading zero width joiner 1`] = ` Object { "noticeList": Array [ Object { @@ -272,7 +272,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 0, - "extract": "‼וְחֹ֖שֶׁךְ", + "excerpt": "‼וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unexpected leading zero-width joiner", @@ -284,7 +284,7 @@ Object { "V": "2", "bookID": "GEN", "details": "quote which starts with 'zero-width joiner'", - "extract": "", + "excerpt": "", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -296,7 +296,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -308,7 +308,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with leading zero width non-joiner 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with leading zero width non-joiner 1`] = ` Object { "noticeList": Array [ Object { @@ -316,7 +316,7 @@ Object { "V": "2", "bookID": "GEN", "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "extract": "וְחֹֹ֖֖שֶׁךְ", + "excerpt": "וְחֹֹ֖֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -328,7 +328,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -339,7 +339,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with trailing space 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with trailing space 1`] = ` Object { "noticeList": Array [ Object { @@ -347,7 +347,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 11, - "extract": "חֹ֖שֶׁךְ␣", + "excerpt": "חֹ֖שֶׁךְ␣", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unexpected trailing space(s)", @@ -359,7 +359,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -371,7 +371,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with trailing word joiner 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with trailing word joiner 1`] = ` Object { "noticeList": Array [ Object { @@ -379,7 +379,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 0, - "extract": "וְ‼חֹ֖שֶׁךְ‼", + "excerpt": "וְ‼חֹ֖שֶׁךְ‼", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unexpected trailing word-joiner", @@ -391,7 +391,7 @@ Object { "V": "2", "bookID": "GEN", "details": "quote which ends with 'word joiner'", - "extract": "וְחֹ֖שֶׁךְ", + "excerpt": "וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -403,7 +403,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -415,7 +415,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with trailing zero width joiner 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with trailing zero width joiner 1`] = ` Object { "noticeList": Array [ Object { @@ -423,7 +423,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 0, - "extract": "וְחֹ֖שֶׁךְ‼", + "excerpt": "וְחֹ֖שֶׁךְ‼", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unexpected trailing zero-width joiner", @@ -435,7 +435,7 @@ Object { "V": "2", "bookID": "GEN", "details": "quote which ends with 'zero-width joiner'", - "extract": "וְחֹ֖שֶׁךְ", + "excerpt": "וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -447,7 +447,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -459,7 +459,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should fail with trailing zero width non-joiner 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should fail with trailing zero width non-joiner 1`] = ` Object { "noticeList": Array [ Object { @@ -467,7 +467,7 @@ Object { "V": "2", "bookID": "GEN", "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "extract": "וְחֹ֖ש֖שֶׁךְ", + "excerpt": "וְחֹ֖ש֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -479,7 +479,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -490,7 +490,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - Original Quote tests - should find missing Original Quote 1`] = ` +exports[`checkTN_TSV9DataRow() - Original Quote tests - should find missing Original Quote 1`] = ` Object { "noticeList": Array [ Object { @@ -508,7 +508,7 @@ Object { "V": "3", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -519,7 +519,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - SupportReference tests - should find long SupportReference 1`] = ` +exports[`checkTN_TSV9DataRow() - SupportReference tests - should find long SupportReference 1`] = ` Object { "noticeList": Array [ Object { @@ -527,7 +527,7 @@ Object { "V": "2", "bookID": "GEN", "details": "not 5", - "extract": "r7q33", + "excerpt": "r7q33", "fieldName": "ID", "location": " that was supplied", "message": "Row ID should be exactly 4 characters", @@ -539,7 +539,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -550,7 +550,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - SupportReference tests - should find missing SupportReference 1`] = ` +exports[`checkTN_TSV9DataRow() - SupportReference tests - should find missing SupportReference 1`] = ` Object { "noticeList": Array [ Object { @@ -567,7 +567,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -578,7 +578,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - SupportReference tests - should find short SupportReference 1`] = ` +exports[`checkTN_TSV9DataRow() - SupportReference tests - should find short SupportReference 1`] = ` Object { "noticeList": Array [ Object { @@ -586,7 +586,7 @@ Object { "V": "2", "bookID": "GEN", "details": "not 3", - "extract": "q7q", + "excerpt": "q7q", "fieldName": "ID", "location": " that was supplied", "message": "Row ID should be exactly 4 characters", @@ -598,7 +598,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -610,7 +610,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - TSV format tests - empty line should fail 1`] = ` +exports[`checkTN_TSV9DataRow() - TSV format tests - empty line should fail 1`] = ` Object { "noticeList": Array [ Object { @@ -627,7 +627,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - TSV format tests - should fail not TSV 1`] = ` +exports[`checkTN_TSV9DataRow() - TSV format tests - should fail not TSV 1`] = ` Object { "noticeList": Array [ Object { @@ -644,7 +644,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - TSV format tests - should find wrong row count 1`] = ` +exports[`checkTN_TSV9DataRow() - TSV format tests - should find wrong row count 1`] = ` Object { "noticeList": Array [ Object { @@ -661,7 +661,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail broken link end 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail broken link end 1`] = ` Object { "noticeList": Array [ Object { @@ -703,7 +703,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail broken link start 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail broken link start 1`] = ` Object { "noticeList": Array [ Object { @@ -745,7 +745,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail double broken link end 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail double broken link end 1`] = ` Object { "noticeList": Array [ Object { @@ -775,7 +775,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail double broken link start 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail double broken link start 1`] = ` Object { "noticeList": Array [ Object { @@ -805,14 +805,14 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail if SupportReference link differs from link in OccurrenceNote 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail if SupportReference link differs from link in OccurrenceNote 1`] = ` Object { "noticeList": Array [ Object { "C": "1", "V": "6", "bookID": "GEN", - "extract": "figs-imperative", + "excerpt": "figs-imperative", "fieldName": "SupportReference", "location": " that was supplied", "message": "Link to TA should also be in OccurrenceNote", @@ -834,7 +834,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid doublet link 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid doublet link 1`] = ` Object { "noticeList": Array [ Object { @@ -842,7 +842,7 @@ Object { "V": "12", "bookID": "RUT", "characterIndex": 170, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -864,7 +864,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid first link 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid first link 1`] = ` Object { "noticeList": Array [ Object { @@ -872,7 +872,7 @@ Object { "V": "9", "bookID": "GEN", "characterIndex": 235, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -883,7 +883,7 @@ Object { "C": "1", "V": "9", "bookID": "GEN", - "extract": "[[rc://*/ta/man/translate/figs-activepassivez]]", + "excerpt": "[[rc://*/ta/man/translate/figs-activepassivez]]", "fieldName": "OccurrenceNote", "location": " that was supplied translate/figs-activepassivez/01.md: tn-table-row-check.test getFile(): Could not find src/__tests__/fixtures/unfoldingWord/en_ta/translate/figs-activepassivez/01.md", "message": "Error loading OccurrenceNote TA link", @@ -895,7 +895,7 @@ Object { "V": "9", "bookID": "GEN", "characterIndex": 287, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -907,7 +907,7 @@ Object { "V": "9", "bookID": "GEN", "details": "(SR='figs-activepassive')", - "extract": "figs-activepassivez", + "excerpt": "figs-activepassivez", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "Should have a SupportReference when OccurrenceNote has a TA link", @@ -919,7 +919,7 @@ Object { "V": "9", "bookID": "GEN", "details": "(SR='figs-activepassive')", - "extract": "figs-imperative", + "excerpt": "figs-imperative", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "Should have a SupportReference when OccurrenceNote has a TA link", @@ -930,7 +930,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid link path 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid link path 1`] = ` Object { "noticeList": Array [ Object { @@ -948,7 +948,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid second link 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid second link 1`] = ` Object { "noticeList": Array [ Object { @@ -956,7 +956,7 @@ Object { "V": "9", "bookID": "GEN", "characterIndex": 235, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -968,7 +968,7 @@ Object { "V": "9", "bookID": "GEN", "characterIndex": 286, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -979,7 +979,7 @@ Object { "C": "1", "V": "9", "bookID": "GEN", - "extract": "[[rc://*/ta/man/translate/figs-imperativez]]", + "excerpt": "[[rc://*/ta/man/translate/figs-imperativez]]", "fieldName": "OccurrenceNote", "location": " that was supplied translate/figs-imperativez/01.md: tn-table-row-check.test getFile(): Could not find src/__tests__/fixtures/unfoldingWord/en_ta/translate/figs-imperativez/01.md", "message": "Error loading OccurrenceNote TA link", @@ -991,7 +991,7 @@ Object { "V": "9", "bookID": "GEN", "details": "(SR='figs-activepassive')", - "extract": "figs-imperativez", + "excerpt": "figs-imperativez", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "Should have a SupportReference when OccurrenceNote has a TA link", @@ -1002,7 +1002,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid verse link 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid verse link 1`] = ` Object { "noticeList": Array [ Object { @@ -1020,7 +1020,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid verse link end 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid verse link end 1`] = ` Object { "noticeList": Array [ Object { @@ -1050,7 +1050,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - link tests - should fail invalid verse link start 1`] = ` +exports[`checkTN_TSV9DataRow() - link tests - should fail invalid verse link start 1`] = ` Object { "noticeList": Array [ Object { @@ -1080,7 +1080,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - should find invalid Book ID, chapter number, ID, SupportReference, quotes, OccurrenceNote 1`] = ` +exports[`checkTN_TSV9DataRow() - should find invalid Book ID, chapter number, ID, SupportReference, quotes, OccurrenceNote 1`] = ` Object { "noticeList": Array [ Object { @@ -1088,7 +1088,7 @@ Object { "V": "2", "bookID": "GEN", "details": "expected 'GEN'", - "extract": "GIN", + "excerpt": "GIN", "fieldName": "Book", "location": " that was supplied", "message": "Wrong book identifier", @@ -1100,7 +1100,7 @@ Object { "V": "2", "bookID": "GEN", "details": "expected '1'", - "extract": "200", + "excerpt": "200", "fieldName": "Chapter", "location": " that was supplied", "message": "Wrong chapter number", @@ -1111,7 +1111,7 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "200", + "excerpt": "200", "fieldName": "Chapter", "location": " that was supplied", "message": "Invalid large chapter number", @@ -1123,7 +1123,7 @@ Object { "V": "2", "bookID": "GEN", "details": "expected '2'", - "extract": "9", + "excerpt": "9", "fieldName": "Verse", "location": " that was supplied", "message": "Wrong verse number", @@ -1145,7 +1145,7 @@ Object { "V": "2", "bookID": "GEN", "details": "not 5", - "extract": "W-3r5", + "excerpt": "W-3r5", "fieldName": "ID", "location": " that was supplied", "message": "Row ID should be exactly 4 characters", @@ -1156,7 +1156,7 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "Laugh", + "excerpt": "Laugh", "fieldName": "SupportReference", "location": " that was supplied", "message": "Only 'Just-In-Time Training' TA articles allowed here", @@ -1167,7 +1167,7 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "Laugh", + "excerpt": "Laugh", "fieldName": "SupportReference", "location": " that was supplied translate/Laugh/01.md: tn-table-row-check.test getFile(): Could not find src/__tests__/fixtures/unfoldingWord/en_ta/translate/Laugh/01.md", "message": "Error loading TA link", @@ -1178,7 +1178,7 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "Laugh", + "excerpt": "Laugh", "fieldName": "SupportReference", "location": " that was supplied", "message": "Link to TA should also be in OccurrenceNote", @@ -1199,7 +1199,7 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "extract": "17", + "excerpt": "17", "fieldName": "Occurrence", "location": " that was supplied", "message": "Invalid occurrence field", @@ -1211,7 +1211,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 11, - "extract": "…ellipse...", + "excerpt": "…ellipse...", "fieldName": "GLQuote", "location": " that was supplied", "message": "Unexpected doubled . characters", @@ -1223,7 +1223,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 13, - "extract": "…o␣hoo,,<br>␣los…", + "excerpt": "…o␣hoo,,<br>␣los…", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", @@ -1236,7 +1236,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 0, - "extract": "<br>Boo hoo,,<b…", + "excerpt": "<br>Boo hoo,,<b…", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", @@ -1249,7 +1249,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 11, - "extract": "…Boo hoo,,<br> l…", + "excerpt": "…Boo hoo,,<br> l…", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", @@ -1262,7 +1262,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 30, - "extract": "…my shoe !", + "excerpt": "…my shoe !", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", @@ -1275,14 +1275,14 @@ Object { } `; -exports[`checkTN_TSVDataRow() - should find invalid SupportReference and missing quotes 1`] = ` +exports[`checkTN_TSV9DataRow() - should find invalid SupportReference and missing quotes 1`] = ` Object { "noticeList": Array [ Object { "C": "2", "V": "3", "bookID": "GEN", - "extract": "Laugh", + "excerpt": "Laugh", "fieldName": "SupportReference", "location": " that was supplied", "message": "Only 'Just-In-Time Training' TA articles allowed here", @@ -1293,7 +1293,7 @@ Object { "C": "2", "V": "3", "bookID": "GEN", - "extract": "Laugh", + "excerpt": "Laugh", "fieldName": "SupportReference", "location": " that was supplied translate/Laugh/01.md: tn-table-row-check.test getFile(): Could not find src/__tests__/fixtures/unfoldingWord/en_ta/translate/Laugh/01.md", "message": "Error loading TA link", @@ -1304,7 +1304,7 @@ Object { "C": "2", "V": "3", "bookID": "GEN", - "extract": "Laugh", + "excerpt": "Laugh", "fieldName": "SupportReference", "location": " that was supplied", "message": "Link to TA should also be in OccurrenceNote", @@ -1325,7 +1325,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - should find language code instead of asterisk 1`] = ` +exports[`checkTN_TSV9DataRow() - should find language code instead of asterisk 1`] = ` Object { "noticeList": Array [ Object { @@ -1334,7 +1334,7 @@ Object { "bookID": "EXO", "characterIndex": 90, "details": "not 'en'", - "extract": "…[[rc://en/ta/ma…", + "excerpt": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "Resource container link should have '*' language code", @@ -1345,7 +1345,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - should find mismatched bookId 1`] = ` +exports[`checkTN_TSV9DataRow() - should find mismatched bookId 1`] = ` Object { "noticeList": Array [ Object { @@ -1353,7 +1353,7 @@ Object { "V": "2", "bookID": "GEN", "details": "expected 'GEN'", - "extract": "EXO", + "excerpt": "EXO", "fieldName": "Book", "location": " that was supplied", "message": "Wrong book identifier", @@ -1365,7 +1365,7 @@ Object { "V": "2", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", @@ -1376,7 +1376,7 @@ Object { } `; -exports[`checkTN_TSVDataRow() - should find mismatched chapter verse 1`] = ` +exports[`checkTN_TSV9DataRow() - should find mismatched chapter verse 1`] = ` Object { "noticeList": Array [ Object { @@ -1384,7 +1384,7 @@ Object { "V": "33", "bookID": "GEN", "details": "expected '22'", - "extract": "2", + "excerpt": "2", "fieldName": "Chapter", "location": " that was supplied", "message": "Wrong chapter number", @@ -1396,7 +1396,7 @@ Object { "V": "33", "bookID": "GEN", "details": "expected '33'", - "extract": "3", + "excerpt": "3", "fieldName": "Verse", "location": " that was supplied", "message": "Wrong verse number", @@ -1408,7 +1408,7 @@ Object { "V": "33", "bookID": "GEN", "characterIndex": 90, - "extract": "…[[rc://*/ta/man…", + "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "tC cannot yet process '*' language code", diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index 7d465f537..555ca33c0 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -1,6 +1,6 @@ /* eslint-env jest */ -import {checkTN_TSVDataRow} from '../core/tn-table-row-check'; +import {checkTN_TSV9DataRow} from '../core/tn-tsv9-row-check'; import Path from "path"; import fs from 'fs-extra'; @@ -21,108 +21,108 @@ const optionalCheckingOptions = { } } -describe('checkTN_TSVDataRow() - ', () => { +describe('checkTN_TSV9DataRow() - ', () => { const languageCode = 'en'; describe('link tests - ', () => { it('should fail invalid doublet link', async() => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [[rc://*/ta/man/translate/figs-parallelism]], [Doublet](../figs-doublet/01.md))"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail broken link start', async() => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [rc://*/ta/man/translate/figs-parallelism]]"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should fail broken link end', async() => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [[rc://*/ta/man/translate/figs-parallelism]"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should fail double broken link start', async() => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: rc://*/ta/man/translate/figs-parallelism]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail double broken link end', async() => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [[rc://*/ta/man/translate/figs-parallelism)"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail if SupportReference link differs from link in OccurrenceNote', async() => { const chosenLine = "GEN\t1\t6\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://*/ta/man/figs-parallelism]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','6', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','6', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail invalid link path', async() => { const chosenLine = "GEN\t1\t7\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://*/ta/woman/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','7', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','7', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); it('should succeed with mixed link types', async() => { const chosenLine = "GEN\t1\t8\tss9r\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://*/ta/man/translate/figs-merism]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','8', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','8', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); }); it('should succeed with dual links', async() => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassive]] and [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); }); it('should fail invalid first link', async() => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassivez]] and [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(5); expect(rawResults).toMatchSnapshot(); }); it('should fail invalid second link', async() => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassive]] and [[rc://*/ta/man/translate/figs-imperativez]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(4); expect(rawResults).toMatchSnapshot(); }); it('should pass valid verse link', async() => { const chosenLine = "GEN\t1\t19\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md)."; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','19', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','19', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); it('should fail invalid verse link', async() => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/zzz.md)."; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); it('should fail invalid verse link start', async() => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in Genesis 1:7](../01/07.md)."; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail invalid verse link end', async() => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md."; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -132,83 +132,83 @@ describe('checkTN_TSVDataRow() - ', () => { describe('Original Quote tests - ', () => { it('invalid Original Language', async() => { const chosenLine = "GEN\t1\t1\tf2mg\t\t0\t\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story."; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','1', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','1', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should find missing Original Quote', async() => { const chosenLine = "GEN\t1\t3\ta7qw\tfigs-imperative\t\t1\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','3', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','3', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail to find OrigLang Quote', async() => { const chosenLine = "GEN\t1\t2\tb7qw\tfigs-imperative\tוְחֹ֖שֶךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail to find 2nd instance/occurrence', async() => { const chosenLine = "GEN\t1\t2\tc7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t2\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); }); it('should fail with leading space', async() => { const chosenLine = "GEN\t1\t2\te7qw\tfigs-imperative\t וְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should fail with trailing space', async() => { const chosenLine = "GEN\t1\t2\tf7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ \t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail with leading word joiner', async() => { const chosenLine = "GEN\t1\t2\tg7qw\tfigs-imperative\t\u2060וְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should fail with trailing word joiner', async() => { const chosenLine = "GEN\t1\t2\th7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\u2060\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should fail with leading zero width non-joiner', async() => { const chosenLine = "GEN\t1\t2\ti7qw\tfigs-imperative\t\u200cוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail with trailing zero width non-joiner', async() => { const chosenLine = "GEN\t1\t2\tj7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\u200c\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should fail with leading zero width joiner', async() => { const chosenLine = "GEN\t1\t2\tk7qw\tfigs-imperative\t\u200dוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should fail with trailing zero width joiner', async() => { const chosenLine = "GEN\t1\t2\tl7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\u200d\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); @@ -219,14 +219,14 @@ describe('checkTN_TSVDataRow() - ', () => { it('should find white space', async() => { const chosenLine = "GEN\t1\t2\tm7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\t "; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should find empty note', async() => { const chosenLine = "GEN\t1\t2\tn7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\t"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -237,7 +237,7 @@ describe('checkTN_TSVDataRow() - ', () => { it('should find bad ellipse', async() => { const chosenLine = "GEN\t2\t3\tw3r5\t\t\t1\tBad ellipse...\tNote8"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','2','3', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','2','3', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -248,7 +248,7 @@ describe('checkTN_TSVDataRow() - ', () => { it('should find wrong book ID', async() => { const chosenLine = "RUT\t1\t2\to7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -257,7 +257,7 @@ describe('checkTN_TSVDataRow() - ', () => { const chosenLine = "GIN\t1\t2\tp7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; let error = false; try { - await checkTN_TSVDataRow(languageCode, chosenLine, 'GIN', '1', '2', 'that was supplied', optionalCheckingOptions); + await checkTN_TSV9DataRow(languageCode, chosenLine, 'GIN', '1', '2', 'that was supplied', optionalCheckingOptions); error = false; } catch(e) { error = true; @@ -270,27 +270,27 @@ describe('checkTN_TSVDataRow() - ', () => { describe('TSV format tests - ', () => { it('empty line should fail', async() => { const chosenLine = ""; //lineG; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); it('header should succeed', async() => { const chosenLine = "Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); it('should find wrong row count', async() => { const chosenLine = "EXO\t2\t3\tw3r5\t\t1\t\t<br>Boo"; // only 8 fields - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); it('should fail not TSV', async() => { const chosenLine = "Peace on Earth, good will to all men/people!"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); @@ -300,7 +300,7 @@ describe('checkTN_TSVDataRow() - ', () => { describe('SupportReference tests - ', () => { it('should find short SupportReference', async() => { const chosenLine = "GEN\t1\t2\tq7q\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); rawResults.suggestion = undefined; // We need to get rid of random characters in suggestion expect(rawResults).toMatchSnapshot(); @@ -308,14 +308,14 @@ describe('checkTN_TSVDataRow() - ', () => { it('should find long SupportReference', async() => { const chosenLine = "GEN\t1\t2\tr7q33\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should find missing SupportReference', async() => { const chosenLine = "GEN\t1\t2\t\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -324,48 +324,48 @@ describe('checkTN_TSVDataRow() - ', () => { it('should find invalid SupportReference and missing quotes', async() => { const chosenLine = "GEN\t2\t3\tw3r5\tLaugh\t\t1\t\tNote5"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','2','3', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','2','3', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(4); expect(rawResults).toMatchSnapshot(); }); it('should skip front matter', async() => { const chosenLine = "GEN\t1\tintro\tzb6f\t\t\t0\t\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist."; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','intro', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','intro', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); it('should find invalid Book ID, chapter number, ID, SupportReference, quotes, OccurrenceNote', async() => { const chosenLine = "GIN\t200\t9\tW-3r5\tLaugh\t\t17\tBad ellipse...\t<br>Boo hoo,,<br> lost my shoe !"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(16); expect(rawResults).toMatchSnapshot(); }); it('should find mismatched chapter verse', async() => { const chosenLine = "GEN\t2\t3\ts7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','22','33', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','22','33', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); it('should find mismatched bookId', async() => { const chosenLine = "EXO\t1\t2\tt7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); it('should find language code instead of asterisk', async() => { const chosenLine = "EXO\t1\t2\tu7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'EXO','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'EXO','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); it('should be valid', async() => { const chosenLine = "GEN\t1\t2\tv7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); }); diff --git a/src/core/README.md b/src/core/README.md index c9259da36..d11ad1668 100644 --- a/src/core/README.md +++ b/src/core/README.md @@ -7,7 +7,7 @@ This non-component function can have playgrounds to test them out. `checkFieldLinks()` checks text fields that might either be a link or contain one or more links. -`checkTN_TSVDataRow()` checks a line of tab-separated fields. +`checkTN_TSV9DataRow()` checks a line of tab-separated fields. Each of the above return a list of error messages and a list of warning messages. diff --git a/src/core/manifest-text-check.md b/src/core/manifest-text-check.md index 92ae7cbf3..2fd74b040 100644 --- a/src/core/manifest-text-check.md +++ b/src/core/manifest-text-check.md @@ -228,7 +228,7 @@ function CheckManifestText(props) { const [results, setResults] = useState(null); - // We need the following construction because checkTN_TSVDataRow is an ASYNC function + // We need the following construction because checkTN_TSV9DataRow is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 diff --git a/src/core/markdown-text-check.md b/src/core/markdown-text-check.md index ce1c6886c..088b6de9b 100644 --- a/src/core/markdown-text-check.md +++ b/src/core/markdown-text-check.md @@ -52,7 +52,7 @@ function CheckMarkdownText(props) { const [results, setResults] = useState(null); - // We need the following construction because checkTN_TSVDataRow is an ASYNC function + // We need the following construction because checkTN_TSV9DataRow is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index fc6e830e2..752265aa7 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -33,7 +33,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * @param {Object} checkingOptions - may contain excerptLength, twRepoUsername, twRepoBranch (or tag), checkLinkedTWArticleFlag parameters * @return {Object} - containing noticeList */ -export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { +export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { /* This function is only for checking one data row and the function doesn’t assume that it has any previous context. @@ -41,22 +41,22 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv Returns an object containing the noticeList. */ - // functionLog(`checkTN_TSVDataRow(${languageCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); - parameterAssert(languageCode !== undefined, "checkTN_TSVDataRow: 'languageCode' parameter should be defined"); - parameterAssert(typeof languageCode === 'string', `checkTN_TSVDataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(line !== undefined, "checkTN_TSVDataRow: 'line' parameter should be defined"); - parameterAssert(typeof line === 'string', `checkTN_TSVDataRow: 'line' parameter should be a string not a '${typeof line}'`); - parameterAssert(bookID !== undefined, "checkTN_TSVDataRow: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkTN_TSVDataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkTN_TSVDataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkTN_TSVDataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(books.isValidBookID(bookID), `checkTN_TSVDataRow: '${bookID}' is not a valid USFM book identifier`); - // parameterAssert(givenC !== undefined, "checkTN_TSVDataRow: 'givenC' parameter should be defined"); - if (givenC) parameterAssert(typeof givenC === 'string', `checkTN_TSVDataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); - // parameterAssert(givenV !== undefined, "checkTN_TSVDataRow: 'givenV' parameter should be defined"); - if (givenV) parameterAssert(typeof givenV === 'string', `checkTN_TSVDataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); - parameterAssert(givenRowLocation !== undefined, "checkTN_TSVDataRow: 'givenRowLocation' parameter should be defined"); - parameterAssert(typeof givenRowLocation === 'string', `checkTN_TSVDataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); + // functionLog(`checkTN_TSV9DataRow(${languageCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkTN_TSV9DataRow: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkTN_TSV9DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(line !== undefined, "checkTN_TSV9DataRow: 'line' parameter should be defined"); + parameterAssert(typeof line === 'string', `checkTN_TSV9DataRow: 'line' parameter should be a string not a '${typeof line}'`); + parameterAssert(bookID !== undefined, "checkTN_TSV9DataRow: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkTN_TSV9DataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkTN_TSV9DataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkTN_TSV9DataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(books.isValidBookID(bookID), `checkTN_TSV9DataRow: '${bookID}' is not a valid USFM book identifier`); + // parameterAssert(givenC !== undefined, "checkTN_TSV9DataRow: 'givenC' parameter should be defined"); + if (givenC) parameterAssert(typeof givenC === 'string', `checkTN_TSV9DataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); + // parameterAssert(givenV !== undefined, "checkTN_TSV9DataRow: 'givenV' parameter should be defined"); + if (givenV) parameterAssert(typeof givenV === 'string', `checkTN_TSV9DataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); + parameterAssert(givenRowLocation !== undefined, "checkTN_TSV9DataRow: 'givenRowLocation' parameter should be defined"); + parameterAssert(typeof givenRowLocation === 'string', `checkTN_TSV9DataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); let ourRowLocation = givenRowLocation; if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; @@ -77,20 +77,20 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv * @param {string} location - description of where the issue is located */ function addNoticePartial(noticeObject) { - // functionLog(`checkTN_TSVDataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); - parameterAssert(noticeObject.priority !== undefined, "checkTN_TSVDataRow addNoticePartial: 'priority' parameter should be defined"); - parameterAssert(typeof noticeObject.priority === 'number', `checkTN_TSVDataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); - parameterAssert(noticeObject.message !== undefined, "checkTN_TSVDataRow addNoticePartial: 'message' parameter should be defined"); - parameterAssert(typeof noticeObject.message === 'string', `checkTN_TSVDataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); - // parameterAssert(lineNumber !== undefined, "checkTN_TSVDataRow addNoticePartial: 'lineNumber' parameter should be defined"); - // parameterAssert(typeof lineNumber === 'number', `checkTN_TSVDataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); - // parameterAssert(characterIndex !== undefined, "checkTN_TSVDataRow addNoticePartial: 'characterIndex' parameter should be defined"); - if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkTN_TSVDataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(excerpt !== undefined, "checkTN_TSVDataRow addNoticePartial: 'excerpt' parameter should be defined"); - if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkTN_TSVDataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); - parameterAssert(noticeObject.location !== undefined, "checkTN_TSVDataRow addNoticePartial: 'location' parameter should be defined"); - parameterAssert(typeof noticeObject.location === 'string', `checkTN_TSVDataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - // noticeObject.debugChain = noticeObject.debugChain ? `checkTN_TSVDataRow ${noticeObject.debugChain}` : 'checkTN_TSVDataRow'; + // functionLog(`checkTN_TSV9DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); + parameterAssert(noticeObject.priority !== undefined, "checkTN_TSV9DataRow addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `checkTN_TSV9DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "checkTN_TSV9DataRow addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `checkTN_TSV9DataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(lineNumber !== undefined, "checkTN_TSV9DataRow addNoticePartial: 'lineNumber' parameter should be defined"); + // parameterAssert(typeof lineNumber === 'number', `checkTN_TSV9DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); + // parameterAssert(characterIndex !== undefined, "checkTN_TSV9DataRow addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkTN_TSV9DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(excerpt !== undefined, "checkTN_TSV9DataRow addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkTN_TSV9DataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); + parameterAssert(noticeObject.location !== undefined, "checkTN_TSV9DataRow addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `checkTN_TSV9DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + // noticeObject.debugChain = noticeObject.debugChain ? `checkTN_TSV9DataRow ${noticeObject.debugChain}` : 'checkTN_TSV9DataRow'; // Also uses the given bookID,C,V, parameters from the main function call drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); } @@ -113,18 +113,18 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // We don’t currently use the allowedLinks parameter - // functionLog(`checkTN_TSVDataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote', "checkTN_TSVDataRow ourMarkdownTextChecks: Only run this check on OccurrenceNotes") - parameterAssert(fieldText !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(allowedLinks === true || allowedLinks === false, "checkTN_TSVDataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); - parameterAssert(rowLocation !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); - parameterAssert(typeof rowLocation === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkTN_TSV9DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'OccurrenceNote', "checkTN_TSV9DataRow ourMarkdownTextChecks: Only run this check on OccurrenceNotes") + parameterAssert(fieldText !== undefined, "checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkTN_TSV9DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); @@ -162,17 +162,17 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // Updates the global list of notices - // functionLog(`checkTN_TSVDataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSVDataRow ourCheckTextField: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSVDataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSVDataRow ourCheckTextField: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSVDataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldText !== undefined, "checkTN_TSVDataRow ourCheckTextField: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkTN_TSVDataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(allowedLinks === true || allowedLinks === false, "checkTN_TSVDataRow ourCheckTextField: allowedLinks parameter must be either true or false"); - parameterAssert(rowLocation !== undefined, "checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be defined"); - parameterAssert(typeof rowLocation === 'string', `checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkTN_TSV9DataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckTextField: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckTextField: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkTN_TSV9DataRow ourCheckTextField: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkTN_TSV9DataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkTN_TSV9DataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkTN_TSV9DataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkTN_TSV9DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'OccurrenceNote' ? 'markdown' : 'raw'; const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); @@ -203,14 +203,14 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // Updates the global list of notices - // functionLog(`checkTN_TSVDataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkTN_TSV9DataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const coqResultObject = await checkSupportReferenceInTA(fieldName, taLinkText, rowLocation, { ...checkingOptions, taRepoLanguageCode: languageCode }); @@ -243,16 +243,16 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // Updates the global list of notices - // functionLog(`checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldText !== undefined, "checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(occurrence !== undefined, "checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); - parameterAssert(typeof occurrence === 'string', `checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(occurrence !== undefined, "checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); + parameterAssert(typeof occurrence === 'string', `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); @@ -287,14 +287,14 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // Updates the global list of notices - // functionLog(`checkTN_TSVDataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSVDataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSVDataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSVDataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSVDataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSVDataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTN_TSVDataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTN_TSVDataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkTN_TSV9DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); @@ -330,7 +330,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // end of ourCheckTNLinksToOutside function - // Main code for checkTN_TSVDataRow function + // Main code for checkTN_TSV9DataRow function if (line === EXPECTED_TN_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place @@ -354,7 +354,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in tn_table-row-check"); numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } catch (tlcNCerror) { - addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); + addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); } const haveGoodBookID = numChaptersThisBook !== undefined; @@ -559,8 +559,8 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv addNoticePartial({ priority: 984, message: `Found wrong number of TSV fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, details: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, rowID, location: ourRowLocation }); } - // debugLog(` checkTN_TSVDataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); - // debugLog("checkTN_TSVDataRow result is", JSON.stringify(drResult)); + // debugLog(` checkTN_TSV9DataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkTN_TSV9DataRow result is", JSON.stringify(drResult)); return drResult; // object with noticeList and possibly suggestion only } -// end of checkTN_TSVDataRow function +// end of checkTN_TSV9DataRow function diff --git a/src/core/tn-tsv9-row-check.md b/src/core/tn-tsv9-row-check.md index 822991129..682b727bb 100644 --- a/src/core/tn-tsv9-row-check.md +++ b/src/core/tn-tsv9-row-check.md @@ -11,7 +11,7 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkTN_TSVDataRow } from './tn-tsv9-row-check'; +import { checkTN_TSV9DataRow } from './tn-tsv9-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples @@ -54,7 +54,7 @@ function CheckTNTSVRow(props) { const [results, setResults] = useState(null); - // We need the following construction because checkTN_TSVDataRow is an ASYNC function + // We need the following construction because checkTN_TSV9DataRow is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -62,7 +62,7 @@ function CheckTNTSVRow(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {tableLineName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkTN_TSVDataRow(languageCode, tableLine, bookID, C, V, givenLocation, checkingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, tableLine, bookID, C, V, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableLineName}: "{tableLine.substr(0,256)}…"<br/><br/> diff --git a/src/core/tn-tsv9-table-check.js b/src/core/tn-tsv9-table-check.js index 5a86071c6..dd2c363bd 100644 --- a/src/core/tn-tsv9-table-check.js +++ b/src/core/tn-tsv9-table-check.js @@ -1,6 +1,6 @@ import * as books from './books/books'; import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' -import { checkTN_TSVDataRow } from './tn-tsv9-row-check'; +import { checkTN_TSV9DataRow } from './tn-tsv9-row-check'; import { removeDisabledNotices } from './disabled-notices'; import { debugLog, parameterAssert } from './utilities'; @@ -129,7 +129,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex const [B, C, V, rowID, supportReference, origQuote, occurrence, _GLQuote, _occurrenceNote] = fields; // Use the row check to do most basic checks - const drResultObject = await checkTN_TSVDataRow(languageCode, lines[n], bookID, C, V, ourLocation, checkingOptions); + const drResultObject = await checkTN_TSV9DataRow(languageCode, lines[n], bookID, C, V, ourLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); From 504d544692f383c2c86b89d1b28294b6d1643fae Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Mon, 15 Feb 2021 20:54:30 +1300 Subject: [PATCH 05/16] Next round of restructuring for new formats --- README.md | 4 +- noticeList.txt | 186 ++++++++--------- package.json | 2 +- src/__tests__/tn-table-row-check.test.js | 189 +++++++++--------- src/core/getApi.js | 2 +- src/core/index.js | 2 +- src/core/markdown-text-check.js | 39 +++- ...tn-links-check.js => notes-links-check.js} | 133 ++++++------ src/core/notes-tsv7-row-check.js | 46 ++--- src/core/notes-tsv7-row-check.md | 2 +- src/core/notes-tsv7-table-check.js | 6 +- src/core/notes-tsv7-table-check.md | 10 +- src/core/orig-quote-check.js | 74 +++---- src/core/questions-tsv5-row-check.js | 138 ++++++------- src/core/questions-tsv5-row-check.md | 2 +- src/core/questions-tsv5-table-check.js | 8 +- src/core/questions-tsv5-table-check.md | 16 +- src/core/tn-tsv9-row-check.js | 36 ++-- src/core/tn-tsv9-row-check.md | 2 +- src/core/tn-tsv9-table-check.js | 9 +- src/core/twl-tsv6-row-check.js | 189 +++++------------- src/core/twl-tsv6-row-check.md | 4 +- src/core/twl-tsv6-table-check.js | 11 +- src/core/twl-tsv6-table-check.md | 20 +- .../book-package-check/BookPackageCheck.js | 11 +- .../book-package-check/checkBookPackage.js | 10 +- .../book-packages-check/BookPackagesCheck.js | 8 +- src/demos/book-packages-check/README.md | 3 + .../book-packages-check/checkBookPackages.js | 14 +- src/demos/file-check/checkFileContents.js | 19 +- src/demos/notice-processing-functions.js | 17 +- src/demos/repo-check/checkRepo.js | 14 +- yarn.lock | 49 +++-- 33 files changed, 632 insertions(+), 643 deletions(-) rename src/core/{tn-links-check.js => notes-links-check.js} (86%) diff --git a/README.md b/README.md index b39d1d105..be2fba27c 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ In addition, there are Styleguidist pages viewable at [[https://unfoldingword.gi This code is designed to thoroughly check various types of Bible-related content data files. This includes: 1. [Unified Standard Format Marker](ubsicap.github.io/usfm/) (USFM) Bible content files, including original language Bibles and Bible translations aligned by word/phrase to the original words/phrases -1. Translation Notes (TN) tables in Tab-Separated Values (9-column TSV) files -1. General annotation tables in Tab-Separated Values (7-column TSV) files (uses TN2 and TQ2) +1. Legacy Translation Notes (TN) tables in Tab-Separated Values (9-column TSV) files +1. New tables in Tab-Separated Values (TSV) files (uses TWL, TN2 and TQ2, SN and SQ) 1. Markdown files (and markdown fields in TSV files) 1. Plain-text files 1. Metadata (manifest) YAML files diff --git a/noticeList.txt b/noticeList.txt index ca9be97de..b6623c1d4 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,6 +1,6 @@ -Last updated 2021-02-12 15:28:05.179431 by makeNoticeList.py +Last updated 2021-02-15 11:01:29.507046 by makeNoticeList.py Got 445 notices: - checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 264 + checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 256 languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 927 marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 955 `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,034 @@ -34,7 +34,7 @@ Got 445 notices: 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 386 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 577 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 605 - 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 268 + 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 260 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 94 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 117 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 136 @@ -51,29 +51,29 @@ Got 445 notices: 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,111 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 676 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 505 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 452 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 498 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 559 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 533 - 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 339 + 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 288 979, "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv5-row-check.js line 339 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 357 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 339 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 372 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 375 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 357 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 306 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv5-row-check.js line 357 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 380 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 357 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 393 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 342 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 393 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 412 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 393 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 199 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 269 - 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from tn-links-check.js line 226 - 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 293 - 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 291 + 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 226 + 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 285 + 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 283 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 943, `USFM3 toJSON Check doesn’t pass`, location: ourLocation from usfm-js-check.js line 91 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,161 @@ -84,7 +84,7 @@ Got 445 notices: 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 641 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 639 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 163 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 445 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 394 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 486 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 473 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 332 @@ -105,17 +105,17 @@ Got 445 notices: 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 363 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 293 - 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 66 + 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 76 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 102 889, `Unable to find TA link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 888, `Error loading TA link`, excerpt: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 887, `Linked TA article seems empty`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 - 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 248 - 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 243 - 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 250 - 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 297 - 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 294 - 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 300 + 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 248 + 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 243 + 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 250 + 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 297 + 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 294 + 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 300 879, `Badly formatted Resource Container link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 763 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 567 @@ -136,9 +136,9 @@ Got 445 notices: 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 - 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from tn-links-check.js line 745 - 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from tn-links-check.js line 749 - 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from tn-links-check.js line 756 + 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 745 + 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 749 + 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 756 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 857 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 859 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 843 @@ -152,53 +152,53 @@ Got 445 notices: 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 883 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 362 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 311 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 362 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 385 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 362 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 367 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 316 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 367 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 390 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 367 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 380 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 329 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 380 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 400 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 380 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 386 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 335 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 386 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 405 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 386 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 389 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 338 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv5-row-check.js line 389 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 408 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 389 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 398 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 347 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 398 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 417 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 398 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 351 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 402 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 421 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 404 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 353 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 404 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 423 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 404 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 408 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 357 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv5-row-check.js line 408 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 427 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 408 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 411 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 360 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv5-row-check.js line 411 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 430 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 411 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 459 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 408 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 500 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 487 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 464 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 413 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 505 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 492 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 227 @@ -208,14 +208,14 @@ Got 445 notices: 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 461 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 447 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 466 - 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 + 787, "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 539 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 512 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 414 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 363 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 414 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 433 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 414 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 417 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 366 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 417 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 436 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 417 @@ -236,11 +236,11 @@ Got 445 notices: 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 - 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 702 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 450 + 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 702 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 399 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 491 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 478 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 441 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 390 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 482 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 469 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 140 @@ -255,21 +255,21 @@ Got 445 notices: 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 117 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 177 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 180 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 353 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 483 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 535 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 643 - 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 696 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 359 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 396 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 435 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 489 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 541 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 593 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 649 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 440 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 547 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 599 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 353 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 483 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 535 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 643 + 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 696 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 359 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 396 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 435 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 489 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 541 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 593 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 649 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 440 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 547 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 599 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 204 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 196 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv5-table-check.js line 196 @@ -316,23 +316,23 @@ Got 445 notices: 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 422 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 952 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,020 - 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 718 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 375 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 412 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 453 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 505 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 563 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 665 - 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 720 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 377 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 414 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 455 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 507 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 565 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 615 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from tn-links-check.js line 667 - 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"'+leftoverLinksList2[0]+'"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from tn-links-check.js line 737 - 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"'+leftoverLinksList1[0]+'"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from tn-links-check.js line 731 + 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 718 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 375 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 412 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 453 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 505 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 563 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 665 + 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 720 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 377 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 414 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 455 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 507 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 565 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 615 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 667 + 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"'+leftoverLinksList2[0]+'"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 737 + 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"'+leftoverLinksList1[0]+'"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 731 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 254 638, "Only found whitespace", location: ourLocation from field-text-check.js line 108 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 128 @@ -344,7 +344,7 @@ Got 445 notices: 583, "Unexpected newLine character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 236 582, "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 242 581, "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 248 - 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from tn-links-check.js line 347 + 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 347 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 211 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 203 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 203 @@ -358,7 +358,7 @@ Got 445 notices: 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 - 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from tn-links-check.js line 222 + 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 222 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 135 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 106 @@ -366,17 +366,17 @@ Got 445 notices: 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,124 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 247 375, "Ellipsis without surrounding snippet", location: ourLocation from orig-quote-check.js line 325 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 471 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 439 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 464 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 420 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 439 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 464 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 470 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 512 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 527 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 457 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 499 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 474 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 442 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 467 + 373, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 423 + 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 442 + 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 467 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 454 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 515 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 530 @@ -386,29 +386,29 @@ Got 445 notices: 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 948 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 149 282, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 215 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 491 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 459 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 484 + 274, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 440 + 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 459 + 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 484 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 545 - 274, "Missing Annotation field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 + 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 256, "Possibly missing current copyright year", details: fullYearString, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 262 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 319 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 264 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 270 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 373 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 424 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 443 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 424 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 426 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 375 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 426 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 428 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 377 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 428 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 430 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 379 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 430 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 @@ -418,12 +418,12 @@ Got 445 notices: 157, "Unexpected space(s) beside ↔ divider character", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 265 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 272 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 643 - 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 687 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 337 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 474 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 526 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 584 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from tn-links-check.js line 634 + 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 687 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 337 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 474 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 526 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 584 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 634 138, "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 160 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 117 110, `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 137 diff --git a/package.json b/package.json index 8a5fc1b76..0cac689f7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha1", + "version": "2.0.0_alpha2", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index 555ca33c0..540f5511b 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -1,6 +1,6 @@ /* eslint-env jest */ -import {checkTN_TSV9DataRow} from '../core/tn-tsv9-row-check'; +import { checkTN_TSV9DataRow } from '../core/tn-tsv9-row-check'; import Path from "path"; import fs from 'fs-extra'; @@ -23,106 +23,107 @@ const optionalCheckingOptions = { describe('checkTN_TSV9DataRow() - ', () => { const languageCode = 'en'; + const repoCode = 'TN'; describe('link tests - ', () => { - it('should fail invalid doublet link', async() => { + it('should fail invalid doublet link', async () => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [[rc://*/ta/man/translate/figs-parallelism]], [Doublet](../figs-doublet/01.md))"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'RUT', '2', '12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail broken link start', async() => { + it('should fail broken link start', async () => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [rc://*/ta/man/translate/figs-parallelism]]"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'RUT', '2', '12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should fail broken link end', async() => { + it('should fail broken link end', async () => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [[rc://*/ta/man/translate/figs-parallelism]"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'RUT', '2', '12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should fail double broken link start', async() => { + it('should fail double broken link start', async () => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: rc://*/ta/man/translate/figs-parallelism]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'RUT', '2', '12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail double broken link end', async() => { + it('should fail double broken link end', async () => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: [[rc://*/ta/man/translate/figs-parallelism)"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'RUT','2','12', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'RUT', '2', '12', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail if SupportReference link differs from link in OccurrenceNote', async() => { + it('should fail if SupportReference link differs from link in OccurrenceNote', async () => { const chosenLine = "GEN\t1\t6\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://*/ta/man/figs-parallelism]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','6', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '6', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail invalid link path', async() => { + it('should fail invalid link path', async () => { const chosenLine = "GEN\t1\t7\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://*/ta/woman/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','7', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '7', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); - it('should succeed with mixed link types', async() => { + it('should succeed with mixed link types', async () => { const chosenLine = "GEN\t1\t8\tss9r\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://*/ta/man/translate/figs-merism]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','8', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '8', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); }); - it('should succeed with dual links', async() => { + it('should succeed with dual links', async () => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassive]] and [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); }); - it('should fail invalid first link', async() => { + it('should fail invalid first link', async () => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassivez]] and [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(5); expect(rawResults).toMatchSnapshot(); }); - it('should fail invalid second link', async() => { + it('should fail invalid second link', async () => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassive]] and [[rc://*/ta/man/translate/figs-imperativez]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(4); expect(rawResults).toMatchSnapshot(); }); - it('should pass valid verse link', async() => { + it('should pass valid verse link', async () => { const chosenLine = "GEN\t1\t19\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md)."; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','19', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '19', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); - it('should fail invalid verse link', async() => { + it('should fail invalid verse link', async () => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/zzz.md)."; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); - it('should fail invalid verse link start', async() => { + it('should fail invalid verse link start', async () => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in Genesis 1:7](../01/07.md)."; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail invalid verse link end', async() => { + it('should fail invalid verse link end', async () => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md."; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','9', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -130,85 +131,85 @@ describe('checkTN_TSV9DataRow() - ', () => { }); describe('Original Quote tests - ', () => { - it('invalid Original Language', async() => { + it('invalid Original Language', async () => { const chosenLine = "GEN\t1\t1\tf2mg\t\t0\t\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story."; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','1', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '1', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should find missing Original Quote', async() => { + it('should find missing Original Quote', async () => { const chosenLine = "GEN\t1\t3\ta7qw\tfigs-imperative\t\t1\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','3', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '3', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail to find OrigLang Quote', async() => { + it('should fail to find OrigLang Quote', async () => { const chosenLine = "GEN\t1\t2\tb7qw\tfigs-imperative\tוְחֹ֖שֶךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail to find 2nd instance/occurrence', async() => { + it('should fail to find 2nd instance/occurrence', async () => { const chosenLine = "GEN\t1\t2\tc7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t2\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); }); - it('should fail with leading space', async() => { + it('should fail with leading space', async () => { const chosenLine = "GEN\t1\t2\te7qw\tfigs-imperative\t וְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should fail with trailing space', async() => { + it('should fail with trailing space', async () => { const chosenLine = "GEN\t1\t2\tf7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ \t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail with leading word joiner', async() => { + it('should fail with leading word joiner', async () => { const chosenLine = "GEN\t1\t2\tg7qw\tfigs-imperative\t\u2060וְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should fail with trailing word joiner', async() => { + it('should fail with trailing word joiner', async () => { const chosenLine = "GEN\t1\t2\th7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\u2060\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should fail with leading zero width non-joiner', async() => { + it('should fail with leading zero width non-joiner', async () => { const chosenLine = "GEN\t1\t2\ti7qw\tfigs-imperative\t\u200cוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail with trailing zero width non-joiner', async() => { + it('should fail with trailing zero width non-joiner', async () => { const chosenLine = "GEN\t1\t2\tj7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\u200c\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should fail with leading zero width joiner', async() => { + it('should fail with leading zero width joiner', async () => { const chosenLine = "GEN\t1\t2\tk7qw\tfigs-imperative\t\u200dוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should fail with trailing zero width joiner', async() => { + it('should fail with trailing zero width joiner', async () => { const chosenLine = "GEN\t1\t2\tl7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\u200d\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); @@ -217,16 +218,16 @@ describe('checkTN_TSV9DataRow() - ', () => { describe('Occurrence Note tests - ', () => { - it('should find white space', async() => { + it('should find white space', async () => { const chosenLine = "GEN\t1\t2\tm7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\t "; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should find empty note', async() => { + it('should find empty note', async () => { const chosenLine = "GEN\t1\t2\tn7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\t"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -235,9 +236,9 @@ describe('checkTN_TSV9DataRow() - ', () => { describe('GL Note tests - ', () => { - it('should find bad ellipse', async() => { + it('should find bad ellipse', async () => { const chosenLine = "GEN\t2\t3\tw3r5\t\t\t1\tBad ellipse...\tNote8"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','2','3', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '2', '3', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -246,20 +247,20 @@ describe('checkTN_TSV9DataRow() - ', () => { describe('BookID tests - ', () => { - it('should find wrong book ID', async() => { + it('should find wrong book ID', async () => { const chosenLine = "RUT\t1\t2\to7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it.skip('should find invalid book ID', async() => { + it.skip('should find invalid book ID', async () => { const chosenLine = "GIN\t1\t2\tp7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; let error = false; try { - await checkTN_TSV9DataRow(languageCode, chosenLine, 'GIN', '1', '2', 'that was supplied', optionalCheckingOptions); + await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GIN', '1', '2', 'that was supplied', optionalCheckingOptions); error = false; - } catch(e) { + } catch (e) { error = true; } expect(error).toBeTruthy(); @@ -268,29 +269,29 @@ describe('checkTN_TSV9DataRow() - ', () => { }); describe('TSV format tests - ', () => { - it('empty line should fail', async() => { + it('empty line should fail', async () => { const chosenLine = ""; //lineG; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); - it('header should succeed', async() => { + it('header should succeed', async () => { const chosenLine = "Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); - it('should find wrong row count', async() => { + it('should find wrong row count', async () => { const chosenLine = "EXO\t2\t3\tw3r5\t\t1\t\t<br>Boo"; // only 8 fields - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); - it('should fail not TSV', async() => { + it('should fail not TSV', async () => { const chosenLine = "Peace on Earth, good will to all men/people!"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); @@ -298,74 +299,74 @@ describe('checkTN_TSV9DataRow() - ', () => { }); describe('SupportReference tests - ', () => { - it('should find short SupportReference', async() => { + it('should find short SupportReference', async () => { const chosenLine = "GEN\t1\t2\tq7q\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); rawResults.suggestion = undefined; // We need to get rid of random characters in suggestion expect(rawResults).toMatchSnapshot(); }); - it('should find long SupportReference', async() => { + it('should find long SupportReference', async () => { const chosenLine = "GEN\t1\t2\tr7q33\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should find missing SupportReference', async() => { + it('should find missing SupportReference', async () => { const chosenLine = "GEN\t1\t2\t\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); }); - it('should find invalid SupportReference and missing quotes', async() => { + it('should find invalid SupportReference and missing quotes', async () => { const chosenLine = "GEN\t2\t3\tw3r5\tLaugh\t\t1\t\tNote5"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','2','3', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '2', '3', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(4); expect(rawResults).toMatchSnapshot(); }); - it('should skip front matter', async() => { + it('should skip front matter', async () => { const chosenLine = "GEN\t1\tintro\tzb6f\t\t\t0\t\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist."; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','intro', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', 'intro', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); - it('should find invalid Book ID, chapter number, ID, SupportReference, quotes, OccurrenceNote', async() => { + it('should find invalid Book ID, chapter number, ID, SupportReference, quotes, OccurrenceNote', async () => { const chosenLine = "GIN\t200\t9\tW-3r5\tLaugh\t\t17\tBad ellipse...\t<br>Boo hoo,,<br> lost my shoe !"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(16); expect(rawResults).toMatchSnapshot(); }); - it('should find mismatched chapter verse', async() => { + it('should find mismatched chapter verse', async () => { const chosenLine = "GEN\t2\t3\ts7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','22','33', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '22', '33', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(3); expect(rawResults).toMatchSnapshot(); }); - it('should find mismatched bookId', async() => { + it('should find mismatched bookId', async () => { const chosenLine = "EXO\t1\t2\tt7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); - it('should find language code instead of asterisk', async() => { + it('should find language code instead of asterisk', async () => { const chosenLine = "EXO\t1\t2\tu7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'EXO','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'EXO', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); - it('should be valid', async() => { + it('should be valid', async () => { const chosenLine = "GEN\t1\t2\tv7qw\tfigs-imperative\tוְחֹ֖שֶׁךְ\t1\tDarkness\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://*/ta/man/translate/figs-imperative]])"; - const rawResults = await checkTN_TSV9DataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(1); }); diff --git a/src/core/getApi.js b/src/core/getApi.js index 527c3250f..f94e619f4 100644 --- a/src/core/getApi.js +++ b/src/core/getApi.js @@ -4,7 +4,7 @@ import localforage from 'localforage'; import { setup } from 'axios-cache-adapter'; import JSZip from 'jszip'; import * as books from './books'; -import { clearCheckedArticleCache } from './tn-links-check'; +import { clearCheckedArticleCache } from './notes-links-check'; import { functionLog, userLog, parameterAssert } from './utilities'; diff --git a/src/core/index.js b/src/core/index.js index 80d7efb03..254f3580e 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -13,7 +13,7 @@ export * from './notes-tsv7-table-check'; export * from './plain-text-check'; export * from './questions-tsv5-row-check'; export * from './questions-tsv5-table-check'; -export * from './tn-links-check'; +export * from './notes-links-check'; export * from './tn-tsv9-row-check'; export * from './tn-tsv9-table-check'; export * from './twl-tsv6-row-check'; diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 8e8ffd5fe..0e8822201 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -5,7 +5,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { userLog, parameterAssert } from './utilities'; -const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.4.6'; +const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.5.0'; const IMAGE_REGEX = new RegExp('!\\[([^\\]]+?)\\]\\(([^ \\]]+?)\\)', 'g'); @@ -97,7 +97,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe // We assume that checking for compulsory fields is done elsewhere // Updates the global list of notices - // debugLog(`cMdT ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${optionalFieldLocation}, …)`); + // functionLog(`cMdT ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${optionalFieldLocation}, …)`); parameterAssert(fieldName !== undefined, "cMdT ourCheckTextField: 'fieldName' parameter should be defined"); parameterAssert(typeof fieldName === 'string', `cMdT ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); parameterAssert(lineNumber !== undefined, "cMdT ourCheckTextField: 'lineNumber' parameter should be defined"); @@ -192,8 +192,9 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe // debugLog(` '${location}' has ${lines.length.toLocaleString()} total lines`); let headerLevel = 0; - let lastNumLeadingSpaces = 0; + // let lastNumLeadingSpaces = 0; // let lastLineContents; + let indentLevels = []; const suggestedLines = []; for (let n = 1; n <= lines.length; n++) { @@ -206,13 +207,35 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe if (thisHeaderLevel > headerLevel + 1 && !textOrFileName.startsWith('TA ')) // Suppress this notice for translationAcademy subsections addNotice({ priority: 172, message: "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation }); - if (thisHeaderLevel > 0) + if (thisHeaderLevel > 0) { headerLevel = thisHeaderLevel; + indentLevels = []; // reset + } numLeadingSpaces = line.match(/^ */)[0].length; - // debugLog(`Got numLeadingSpaces=${numLeadingSpaces} for ${line}${atString}`); - if (numLeadingSpaces && lastNumLeadingSpaces && numLeadingSpaces !== lastNumLeadingSpaces) - addNotice({ priority: 282, message: "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation }); + // debugLog(`Got numLeadingSpaces=${numLeadingSpaces} with indentLevels=${JSON.stringify(indentLevels)} for ${line}${ourLocation}`); + const previousIndentLevel = (indentLevels.length > 0) ? indentLevels[indentLevels.length - 1] : 0; + if ((numLeadingSpaces > previousIndentLevel) // We have an indent level increase + || (numLeadingSpaces===0 && line.length > 0 && indentLevels.length===0)) // we have our first zero-level indent + indentLevels.push(numLeadingSpaces); + else if (numLeadingSpaces < previousIndentLevel) { // We have an indent level decrease + if (indentLevels.length > 1 && indentLevels[indentLevels.length - 2] === numLeadingSpaces) + // We went back to the previous level + indentLevels.pop(); + else { // seems we didn't go back to the previous level ??? + let foundPreviousLevel = false; + for (let z = indentLevels.length-1; z>= 0; z--) { + if (indentLevels[z] === numLeadingSpaces) { + // debugLog(`After finding ${numLeadingSpaces} spaces, reducing length of ${JSON.stringify(indentLevels)} to ${z+1}`); + indentLevels.length = z+1; + foundPreviousLevel = true; + break; + } + } + if (!foundPreviousLevel) + addNotice({ priority: 282, message: "Nesting of header levels seems confused", details: `recent indent levels=${JSON.stringify(indentLevels)} but now ${numLeadingSpaces}`, lineNumber: n, characterIndex: 0, location: ourLocation }); + } + } const suggestedLine = await checkMarkdownLineContents(n, line, ourLocation); suggestedLines.push(suggestedLine === undefined ? line : suggestedLine); @@ -223,7 +246,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe } // lastLineContents = line; - lastNumLeadingSpaces = numLeadingSpaces; + // lastNumLeadingSpaces = numLeadingSpaces; } // Check for an uneven number of sets of symmetrical (i.e., opener == closer) multicharacter markdown formatting sequences diff --git a/src/core/tn-links-check.js b/src/core/notes-links-check.js similarity index 86% rename from src/core/tn-links-check.js rename to src/core/notes-links-check.js index 42702727b..5376df579 100644 --- a/src/core/tn-links-check.js +++ b/src/core/notes-links-check.js @@ -7,7 +7,7 @@ import { userLog, debugLog, parameterAssert, logicAssert, ourParseInt } from './ // import { consoleLogObject } from '../core/utilities'; -// const TN_LINKS_VALIDATOR_VERSION_STRING = '0.7.5'; +// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.7'; const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; @@ -15,8 +15,9 @@ const DEFAULT_BRANCH = 'master'; const GENERAL_LINK1_REGEX = new RegExp('\\[[^\\]]+?\\]\\([^\\)]+?\\)', 'g'); // [displayLink](URL) const GENERAL_LINK2_REGEX = new RegExp('\\[\\[[^\\]]+?\\]\\]', 'g'); // [[combinedDisplayLink]] -const TA_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); -const TW_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); +const TA_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TW_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TWL_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g'); // Just a raw link // TODO: Do we need to normalise Bible links, i.e., make sure that the link itself // (we don't care about the displayed text) doesn't specify superfluous levels/information @@ -74,14 +75,15 @@ async function alreadyChecked({ username, repository, path, branch }) { /** * + * @param {string} repoCode, e.g., 'TN', 'SN', 'TN2', or even 'TWL' * @param {string} bookID - * @param {string} fieldName + * @param {string} fieldName, e.g., 'OccurrenceNote' or 'Note' or 'TWLink' * @param {string} fieldText * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, fieldText, givenLocation, checkingOptions) { - /* This is for the case of the OccurrenceNote field containing markdown links +export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, fieldText, givenLocation, checkingOptions) { + /* This is for the case of the OccurrenceNote or Note field containing markdown links bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. @@ -108,22 +110,23 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // checkingOptions.checkLinkedTWArticleFlag */ - // functionLog(`checkTNLinksToOutside v${TN_LINKS_VALIDATOR_VERSION_STRING} ${bookID} (${fieldName}, (${fieldText.length}) '${fieldText}', ${givenLocation}, …)…`); - parameterAssert(bookID !== undefined, "checkTNLinksToOutside: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkTNLinksToOutside: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkTNLinksToOutside: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkTNLinksToOutside: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkTNLinksToOutside: '${bookID}' is not a valid USFM book identifier`); - parameterAssert(typeof givenC === 'string', `checkTNLinksToOutside: 'givenC' parameter should be a string not a '${typeof givenC}'`); - parameterAssert(typeof givenV === 'string', `checkTNLinksToOutside: 'givenV' parameter should be a string not a '${typeof givenV}'`); - parameterAssert(fieldName !== undefined, "checkTNLinksToOutside: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTNLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Annotation', `checkTNLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' or 'Annotation' not '${fieldName}'`); - parameterAssert(fieldText !== undefined, "checkTNLinksToOutside: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkTNLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(givenLocation !== undefined, "checkTNLinksToOutside: 'fieldText' parameter should be defined"); - parameterAssert(typeof givenLocation === 'string', `checkTNLinksToOutside: 'fieldText' parameter should be a string not a '${typeof givenLocation}'`); - parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Annotation', `Unexpected checkTNLinksToOutside fieldName='${fieldName}'`); + // functionLog(`checkNotesLinksToOutside v${NOTES_LINKS_VALIDATOR_VERSION_STRING} ${repoCode} ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, …)…`); + parameterAssert(repoCode !== undefined, "checkNotesLinksToOutside: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkNotesLinksToOutside: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + parameterAssert(bookID !== undefined, "checkNotesLinksToOutside: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkNotesLinksToOutside: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkNotesLinksToOutside: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkNotesLinksToOutside: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesLinksToOutside: '${bookID}' is not a valid USFM book identifier`); + parameterAssert(typeof givenC === 'string', `checkNotesLinksToOutside: 'givenC' parameter should be a string not a '${typeof givenC}'`); + parameterAssert(typeof givenV === 'string', `checkNotesLinksToOutside: 'givenV' parameter should be a string not a '${typeof givenV}'`); + parameterAssert(fieldName !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Note' || fieldName === 'TWLink', `checkNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' or 'Note' or 'TWLink' not '${fieldName}'`); + parameterAssert(fieldText !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(givenLocation !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); + parameterAssert(typeof givenLocation === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof givenLocation}'`); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -131,7 +134,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const ctarResult = { noticeList: [], checkedFileCount: 0, checkedFilenames: [], checkedRepoNames: [] }; function addNoticePartial(noticeObject) { - // functionLog(`checkTNLinksToOutside Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); + // functionLog(`checkNotesLinksToOutside Notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "cTNlnk addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cTNlnk addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cTNlnk addNoticePartial: 'message' parameter should be defined"); @@ -142,12 +145,12 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `cTNlnk addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); parameterAssert(noticeObject.location !== undefined, "cTNlnk addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cTNlnk addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - // noticeObject.debugChain = noticeObject.debugChain ? `checkTNLinksToOutside ${noticeObject.debugChain}` : `checkTNLinksToOutside(${fieldName})`; + // noticeObject.debugChain = noticeObject.debugChain ? `checkNotesLinksToOutside ${noticeObject.debugChain}` : `checkNotesLinksToOutside(${fieldName})`; ctarResult.noticeList.push({ ...noticeObject, bookID, fieldName }); } - // Main code for checkTNLinksToOutside + // Main code for checkNotesLinksToOutside // Get any options that were suppplied, or else set default values let excerptLength; try { @@ -167,7 +170,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f let defaultLanguageCode; try { defaultLanguageCode = checkingOptions?.defaultLanguageCode; } catch (trcLCerror) { } if (!defaultLanguageCode) defaultLanguageCode = DEFAULT_LANGUAGE_CODE; - // debugLog("checkTNLinksToOutside defaultLanguageCode", defaultLanguageCode); + // debugLog("checkNotesLinksToOutside defaultLanguageCode", defaultLanguageCode); let taRepoUsername; try { taRepoUsername = checkingOptions?.taRepoUsername; } catch (trcUNerror) { } @@ -209,9 +212,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f let processedLinkList = []; // Check for TA links like [[rc://en/ta/man/translate/figs-metaphor]] - // debugLog("checkTNLinksToOutside: Search for TA links") + // debugLog("checkNotesLinksToOutside: Search for TA links") while ((regexResultArray = TA_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside TA resultArray=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside TA resultArray=${JSON.stringify(regexResultArray)}`); taLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 4, `TA_REGEX expected 4 fields (not ${regexResultArray.length})`) @@ -220,7 +223,8 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); - } else { // At the moment, tC can’t handle these links with * so we have to ensure that they're not there + } else if (repoCode === 'TN') { // but not TN2 + // At the moment, tC can’t handle these links with * so we have to ensure that they're not there const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); @@ -232,14 +236,14 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // debugLog(`Got tA filepath=${filepath}`); if (!checkingOptions?.disableAllLinkFetchingFlag) { - // functionLog(`checkTNLinksToOutside: need to check against ${taRepoName}`); + // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; let taFileContent, alreadyGaveError = false; try { taFileContent = await getFile_(taPathParameters); // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); } catch (trcGCerror) { - // console.error(`checkTNLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); + // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); alreadyGaveError = true; } @@ -249,9 +253,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f else if (taFileContent.length < 10) addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else if (checkingOptions?.checkLinkedTAArticleFlag === true) { - // functionLog(`checkTNLinksToOutside got ${checkingOptions?.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); if (await alreadyChecked(taPathParameters) !== true) { - // functionLog(`checkTNLinksToOutside needs to check TA article: ${filepath}`); + // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); const checkTAFileResult = await checkMarkdownText(languageCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); for (const noticeObject of checkTAFileResult.noticeList) ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); @@ -267,11 +271,12 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f } } - // Check for TW links like [[rc://en/tw/dict/bible/other/death]] + // Check for TW links like [[rc://en/tw/dict/bible/other/death]] in TN or rc://en/tw/dict/bible/other/death in TWLinks // (These are not nearly as many as TA links.) - // debugLog("checkTNLinksToOutside: Search for TW links") - while ((regexResultArray = TW_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside TW resultArray=${JSON.stringify(regexResultArray)}`); + // debugLog("checkNotesLinksToOutside: Search for TW links") + const ourTWRegex = (fieldName === 'TWLink') ? TWL_REGEX : TW_REGEX + while ((regexResultArray = ourTWRegex.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside TW resultArray=${JSON.stringify(regexResultArray)}`); twLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 4, `TW_REGEX expected 4 fields (not ${regexResultArray.length})`) @@ -283,14 +288,14 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // debugLog(`Got tW filepath=${filepath}`); if (!checkingOptions?.disableAllLinkFetchingFlag) { - // debugLog(`Need to check against ${twRepoName}`); + // debugLog(`Need to check TW link against ${twRepoName}`); const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; let twFileContent; try { twFileContent = await getFile_(twPathParameters); - // debugLog("Fetched fileContent for", twRepoName, filepath, typeof fileContent, fileContent.length); + // debugLog(`Fetched fileContent for ${twRepoName} ${filepath} ${typeof fileContent} ${twFileContent.length}`); } catch (trcGCerror) { - console.error(`checkTNLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); + console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); } if (!twFileContent) @@ -299,9 +304,9 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (twFileContent.length < 10) addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else if (checkingOptions?.checkLinkedTWArticleFlag === true) { - // functionLog(`checkTNLinksToOutside got ${checkingOptions?.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); if (await alreadyChecked(twPathParameters) !== true) { - // functionLog(`checkTNLinksToOutside needs to check TW article: ${filepath}`); + // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); const checkTWFileResult = await checkMarkdownText(languageCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); for (const noticeObject of checkTWFileResult.noticeList) ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); @@ -317,11 +322,11 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f } } - // debugLog("checkTNLinksToOutside: Search for Bible links") + // debugLog("checkNotesLinksToOutside: Search for Bible links") // Check for this-chapter Bible links like [Revelation 3:11](./11.md) while ((regexResultArray = THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisChapterBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 6, `THIS_CHAPTER_BIBLE_REGEX expected 6 fields (not ${regexResultArray.length})`); @@ -343,7 +348,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const linkVerseInt = ourParseInt(V2); if (C1 === undefined) { if (!books.isOneChapterBook(linkBookCode)) { - // debugLog(` checkTNLinksToOutside C1 missing in THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside C1 missing in THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); } C1 = '0'; // Try to avoid consequential errors @@ -364,7 +369,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -380,7 +385,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for this-verse Bible links like [11](../03/11.md) while ((regexResultArray = THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside THIS_VERSE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside THIS_VERSE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisVerseBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 4, `THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX expected 4 fields (not ${regexResultArray.length})`); @@ -401,7 +406,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -417,7 +422,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for this-verse Bible links like [11](../03/11.md) while ((regexResultArray = THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside THIS_VERSE_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside THIS_VERSE_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisVerseBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 5, `THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX expected 5 fields (not ${regexResultArray.length})`); @@ -442,7 +447,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -458,7 +463,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for this-book Bible links like [Revelation 3:11](../03/11.md) while ((regexResultArray = THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside THIS_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside THIS_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisBookBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 8, `THIS_BOOK_BIBLE_REGEX expected 8 fields (not ${regexResultArray.length})`); @@ -494,7 +499,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -510,7 +515,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) while ((regexResultArray = BCV_V_TO_THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside THIS_BOOK_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside THIS_BOOK_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisBookBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 9, `BCV_V_TO_THIS_BOOK_BIBLE_REGEX expected 9 fields (not ${regexResultArray.length})`); @@ -552,7 +557,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -568,7 +573,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) while ((regexResultArray = BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisChapterBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 7, `BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX expected 7 fields (not ${regexResultArray.length})`); @@ -604,7 +609,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); // try { // numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; // } catch (tlcNCerror) { } @@ -618,7 +623,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for other book Bible links like [Revelation 3:11](../03/11.md) while ((regexResultArray = OTHER_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside OTHER_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside OTHER_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); otherBookBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 8, `OTHER_BOOK_BIBLE_REGEX expected 8 fields (not ${regexResultArray.length})`); @@ -654,7 +659,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -670,7 +675,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f // Check for TN links like [Titus 3:11](../03/11/zd2d) while ((regexResultArray = TN_REGEX.exec(fieldText))) { - // debugLog(` checkTNLinksToOutside TN_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside TN_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); TNLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 9, `TN_REGEX expected 9 fields (not ${regexResultArray.length})`); @@ -707,7 +712,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in tn-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -728,13 +733,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (totalLinks1 > BibleLinkCount) { const leftoverLinksList1 = linksList1.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above // if (leftoverLinksList1.length > 0) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); - addNoticePartial({ priority: 648, message: "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check ${leftoverLinksList1.length === 1 ? '"'+leftoverLinksList1[0]+'"' : JSON.stringify(leftoverLinksList1)}`, location: ourLocation }); + addNoticePartial({ priority: 648, message: "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check ${leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)}`, location: ourLocation }); } const twaLinkCount = twLinkCount + taLinkCount; if (totalLinks2 > twaLinkCount) { const leftoverLinksList2 = linksList2.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above // if (leftoverLinksList2.length > 0) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); - addNoticePartial({ priority: 649, message: "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check ${leftoverLinksList2.length === 1 ? '"'+leftoverLinksList2[0]+'"' : JSON.stringify(leftoverLinksList2)}`, location: ourLocation }); + addNoticePartial({ priority: 649, message: "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check ${leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)}`, location: ourLocation }); } // Check for badly formed links (not processed by the above code) @@ -756,7 +761,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f addNoticePartial({ priority: 843, message: `Mismatched [ ]( ) link characters`, details: `left=${leftCount.toLocaleString()}, middle=${middleCount.toLocaleString()}, right=${rightCount.toLocaleString()}`, location: ourLocation }); - // functionLog(`checkTNLinksToOutside is returning ${JSON.stringify(ctarResult)}`); + // functionLog(`checkNotesLinksToOutside is returning ${JSON.stringify(ctarResult)}`); return ctarResult; } -// end of checkTNLinksToOutside function +// end of checkNotesLinksToOutside function diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index 3b7d4b0cc..190060894 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -3,12 +3,12 @@ import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; import { checkSupportReferenceInTA } from './ta-reference-check'; -import { checkTNLinksToOutside } from './tn-links-check'; +import { checkNotesLinksToOutside } from './notes-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.7'; +// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.8'; const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_NOTES_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; @@ -127,7 +127,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); // parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); // parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Note', "checkNotesTSV7DataRow ourMarkdownTextChecks: Only run this check on Notes") + parameterAssert(fieldName === 'Note', `checkNotesTSV7DataRow ourMarkdownTextChecks: Only run this check on Notes not '${fieldName}'`); parameterAssert(fieldText !== undefined, "checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldText === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); parameterAssert(allowedLinks === true || allowedLinks === false, "checkNotesTSV7DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); @@ -144,7 +144,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // process results line by line for (const noticeEntry of omtcResultObject.noticeList) { // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - // NOTE: Ellipses in Annotation have the normal meaning + // NOTE: Ellipses in Note have the normal meaning // not like the specialised meaning in the Quote snippet fields if (noticeEntry.priority !== 178 && noticeEntry.priority !== 179 // unexpected space after ellipse, ellipse after space && !noticeEntry.message.startsWith("Unexpected … character after space") // 191 @@ -246,7 +246,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID parameterAssert(typeof occurrence === 'string', `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + const coqResultObject = await checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -261,21 +261,21 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // end of ourCheckTNOriginalLanguageQuote function - async function ourCheckTNLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Updates the global list of notices - // functionLog(`checkNotesTSV7DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Note', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Note' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkNotesTSV7DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Note', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'Note' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coqResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); // Choose only ONE of the following @@ -306,7 +306,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } - // end of ourCheckTNLinksToOutside function + // end of ourcheckNotesLinksToOutside function // Main code for checkNotesTSV7DataRow function @@ -332,7 +332,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID if (bookID === 'OBS') numChaptersThisBook = 50; // There's 50 Open Bible Stories else { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-row-check"); + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkNotesTSV7DataRow"); try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } catch (tlcNCerror) { @@ -449,7 +449,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID if (checkingOptions?.disableAllLinkFetchingFlag !== true) await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, checkingOptions); if (note.indexOf(supportReference) < 0) - addNoticePartial({ priority: 787, message: "Link to TA should also be in Annotation", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation }); + addNoticePartial({ priority: 787, message: "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation }); } let characterIndex; if ((characterIndex = supportReference.indexOf('\u200B') !== -1)) { @@ -502,10 +502,10 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation }); else { // More than just whitespace ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', note, true, ourRowLocation, checkingOptions); - await ourCheckTNLinksToOutside(rowID, 'Note', note, ourRowLocation, linkCheckingOptions); + await ourcheckNotesLinksToOutside(rowID, 'Note', note, ourRowLocation, linkCheckingOptions); let regexResultArray; while ((regexResultArray = TA_REGEX.exec(note))) { - // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); + // debugLog("Got TA Regex in Note", JSON.stringify(regexResultArray)); const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) if (supportReference !== adjustedLink && V !== 'intro') { const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" @@ -516,13 +516,13 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (repoCode === 'TN2') - addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Note', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 274, message: "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation }); // 7 [reference, rowID, tags, supportReference, quote, occurrence, note] const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${SRSuggestion === undefined ? supportReference : SRSuggestion}\t${QSuggestion === undefined ? quote : QSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${ASuggestion === undefined ? note : ASuggestion}`; if (suggestion !== line) { - // debugLog(`Had annotation ${line}`); - // debugLog(`Sug annotation ${suggestion}`); + // debugLog(`Had note ${line}`); + // debugLog(`Sug note ${suggestion}`); drResult.suggestion = suggestion; } diff --git a/src/core/notes-tsv7-row-check.md b/src/core/notes-tsv7-row-check.md index a89b1ba6d..6148f9f7b 100644 --- a/src/core/notes-tsv7-row-check.md +++ b/src/core/notes-tsv7-row-check.md @@ -1,4 +1,4 @@ -## Annotation (TSV) Row Check Sandbox +## Notes (TSV) Row Check Sandbox This function checks one tab-separated line for typical formatting errors. diff --git a/src/core/notes-tsv7-table-check.js b/src/core/notes-tsv7-table-check.js index 1d0b18627..fd803f8ce 100644 --- a/src/core/notes-tsv7-table-check.js +++ b/src/core/notes-tsv7-table-check.js @@ -5,7 +5,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { functionLog, parameterAssert } from './utilities'; -const NOTES_TABLE_VALIDATOR_VERSION_STRING = '0.3.1'; +const NOTES_TABLE_VALIDATOR_VERSION_STRING = '0.3.2'; const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; @@ -69,7 +69,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); if (noticeObject.debugChain) noticeObject.debugChain = `checkNotesTSV7Table ${noticeObject.debugChain}`; - carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: repoCode }); + carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode }); } @@ -92,7 +92,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena if (bookID === 'OBS') numChaptersThisBook = 50; // There's 50 Open Bible Stories else { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-table-check"); + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkNotesTSV7Table"); try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } diff --git a/src/core/notes-tsv7-table-check.md b/src/core/notes-tsv7-table-check.md index fa96612be..d97ee5ce0 100644 --- a/src/core/notes-tsv7-table-check.md +++ b/src/core/notes-tsv7-table-check.md @@ -1,6 +1,6 @@ -## Annotation (TSV) Table Text Check Sandbox +## Notes (TSV) Table Text Check Sandbox -This function checks the given block of annotation (TSV) table lines for typical formatting errors. +This function checks the given block of note (TSV) table lines for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) @@ -48,7 +48,7 @@ const data = { givenLocation : 'that was supplied', } -function checkNotesTSV7Table(props) { +function CheckNotesTSV7Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -72,7 +72,7 @@ function checkNotesTSV7Table(props) { }, []); // end of useEffect part return results; -} // end of checkNotesTSV7Table function +} // end of CheckNotesTSV7Table function -<checkNotesTSV7Table data={data}/> +<CheckNotesTSV7Table data={data}/> ``` diff --git a/src/core/orig-quote-check.js b/src/core/orig-quote-check.js index dfae5cfe4..9e936bf81 100644 --- a/src/core/orig-quote-check.js +++ b/src/core/orig-quote-check.js @@ -4,12 +4,13 @@ import { cachedGetFile } from '../core/getApi'; import { debugLog, parameterAssert, ourParseInt } from './utilities'; -// const QUOTE_VALIDATOR_VERSION_STRING = '0.8.1'; +// const QUOTE_VALIDATOR_VERSION_STRING = '0.9.0'; /** * * @param {string} languageCode + * @param {string} repoCode * @param {string} fieldName * @param {string} fieldText * @param {string} occurrenceString @@ -19,7 +20,7 @@ import { debugLog, parameterAssert, ourParseInt } from './utilities'; * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrenceString, bookID, C, V, givenLocation, checkingOptions) { +export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrenceString, bookID, C, V, givenLocation, checkingOptions) { // Checks that the Hebrew/Greek quote can be found in the original texts // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. @@ -31,9 +32,11 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // (UHB or UGNT will be used for the repo name) // checkingOptions?.originalLanguageRepoBranch (or tag) - // functionLog(`checkOriginalLanguageQuote v${QUOTE_VALIDATOR_VERSION_STRING} (${fieldName}, (${fieldText.length}) '${fieldText}', ${occurrenceString}, ${bookID} ${C}:${V} ${givenLocation}, …)…`); + // functionLog(`checkOriginalLanguageQuote v${QUOTE_VALIDATOR_VERSION_STRING} ${languageCode}, ${repoCode}, ${fieldName}, (${fieldText.length}) '${fieldText}', ${occurrenceString}, ${bookID} ${C}:${V} ${givenLocation}, …)…`); parameterAssert(languageCode !== undefined, "checkOriginalLanguageQuote: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkOriginalLanguageQuote: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode !== undefined, "checkOriginalLanguageQuote: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkOriginalLanguageQuote: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); parameterAssert(fieldName !== undefined, "checkOriginalLanguageQuote: 'fieldName' parameter should be defined"); parameterAssert(typeof fieldName === 'string', `checkOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); parameterAssert(fieldText !== undefined, "checkOriginalLanguageQuote: 'fieldText' parameter should be defined"); @@ -53,6 +56,9 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT parameterAssert(givenLocation !== undefined, "checkOriginalLanguageQuote: 'givenLocation' parameter should be defined"); parameterAssert(typeof givenLocation === 'string', `checkOriginalLanguageQuote: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); + const discontiguousDivider = (repoCode === 'TN') ? '…' : ' & '; + // debugLog(`Got discontiguousDivider='${discontiguousDivider}' for ${repoCode}`); + let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -243,28 +249,28 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // fieldText = fieldText.strip() # so we don’t get consequential errors let characterIndex; - if ((characterIndex = fieldText.indexOf('...')) >= 0) { + if (discontiguousDivider==='…' && (characterIndex = fieldText.indexOf('...')) >= 0) { // debugLog(`Bad ellipse characters in '${fieldText}'`); const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); addNotice({ priority: 159, message: "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation }); } let quoteBits; - if (fieldText.indexOf('…') >= 0) { - quoteBits = fieldText.split('…'); - if ((characterIndex = fieldText.indexOf(' …')) >= 0 || (characterIndex = fieldText.indexOf('… ')) >= 0) { + if (fieldText.indexOf(discontiguousDivider) >= 0) { + quoteBits = fieldText.split(discontiguousDivider); + if ((characterIndex = fieldText.indexOf(` ${discontiguousDivider}`)) >= 0 || (characterIndex = fieldText.indexOf(`${discontiguousDivider} `)) >= 0) { // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNotice({ priority: 158, message: "Unexpected space(s) beside ellipse character", characterIndex, excerpt, location: ourLocation }); - } - } else if (fieldText.indexOf('↔') >= 0) { - quoteBits = fieldText.split('↔'); - if ((characterIndex = fieldText.indexOf(' ↔')) >= 0 || (characterIndex = fieldText.indexOf('↔ ')) >= 0) { - // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - addNotice({ priority: 157, message: "Unexpected space(s) beside ↔ divider character", characterIndex, excerpt, location: ourLocation }); + const excerpt = (characterIndex > halfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? discontiguousDivider : ''); + addNotice({ priority: 158, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); } - } else if (fieldText.indexOf('...') >= 0) { // Yes, we still actually allow this + // } else if (fieldText.indexOf('↔') >= 0) { + // quoteBits = fieldText.split('↔'); + // if ((characterIndex = fieldText.indexOf(' ↔')) >= 0 || (characterIndex = fieldText.indexOf('↔ ')) >= 0) { + // // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); + // const excerpt = (characterIndex > halfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + // addNotice({ priority: 157, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); + // } + } else if (discontiguousDivider==='…' && fieldText.indexOf('...') >= 0) { // Yes, we still actually allow this quoteBits = fieldText.split('...'); if ((characterIndex = fieldText.indexOf(' ...')) >= 0 || (characterIndex = fieldText.indexOf('... ')) >= 0) { // debugLog(`Unexpected space(s) beside ellipse characters in '${fieldText}'`); @@ -322,13 +328,13 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // else debugLog(`Found quote ${bitIndex} at ${quoteIndex} (num text chars = ${verseText.length})`); } } else // < 2 - addNotice({ priority: 375, message: "Ellipsis without surrounding snippet", location: ourLocation }); - } else { // Only a single quote (no ellipsis) + addNotice({ priority: 375, message: "Divider without surrounding snippet", location: ourLocation }); + } else { // Only a single quote (no discontiguousDivider) if (verseText.indexOf(fieldText) >= 0) { if (occurrence > 1) { // functionLog(`checkOriginalLanguageQuote is checking for ${occurrence} occurrences of ${fieldText}`); if (verseText.split(fieldText).length <= occurrence) { // There's not enough of them - const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? '…' : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); + const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? discontiguousDivider : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); addNotice({ priority: 917, message: "Unable to find duplicate original language quote in verse text", details: `occurrence=${occurrenceString}, passage ►${verseText}◄`, excerpt, location: ourLocation }); } } else { // We only need to check for one occurrence @@ -337,7 +343,7 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT let remainingBits = verseText.split(fieldText); // debugLog(`remaingBits=${JSON.stringify(remainingBits)}`); if (remainingBits.length > 2) // Join the extra bits back up - remainingBits = [remainingBits[0], remainingBits.slice(1).join('…')]; + remainingBits = [remainingBits[0], remainingBits.slice(1).join(discontiguousDivider)]; parameterAssert(remainingBits.length === 2, `remaining bits are ${remainingBits.length}`); // Note: There's some Hebrew (RTL) characters at the beginning of the following regex // Note: Straight quotes are included here (even though unwanted) as other code warns about them @@ -347,10 +353,10 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // const badCharString = ` by '{offendingChar}' {unicodedata.name(offendingChar)}={hex(ord(offendingChar))}`; // debugLog(`Seems '${fieldText}' might not start at the beginning of a word—it’s preceded ${badCharString} in '${verseText}'`); let precederDescription; - if (offendingChar === '\u2060') precederDescription = 'WordJoiner'; - else if (offendingChar === '\u200D') precederDescription = 'ZeroWidth-WordJoiner'; + if (offendingChar === '\u2060') precederDescription = 'WordJoiner'; + else if (offendingChar === '\u200D') precederDescription = 'ZeroWidth-WordJoiner'; else precederDescription = `${offendingChar}=D${offendingChar.charCodeAt()}/H${offendingChar.charCodeAt().toString(16)}`; - const excerpt = `(${precederDescription})` + fieldText.substring(0, excerptLength - 3) + (fieldText.length > excerptLength - 3 ? '…' : ''); + const excerpt = `(${precederDescription})` + fieldText.substring(0, excerptLength - 3) + (fieldText.length > excerptLength - 3 ? discontiguousDivider : ''); addNotice({ priority: 909, message: "Seems original language quote might not start at the beginning of a word", details: `passage ►${verseText}◄`, characterIndex: 0, excerpt, location: ourLocation }); } // Note: There's some Hebrew (RTL) characters at the beginning of the following regex @@ -359,7 +365,7 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // const offendingChar = remainingBits[1][0]; // const badCharString = ` by '${offendingChar}' {unicodedata.name(offendingChar)}={hex(ord(offendingChar))}`; // debugLog(`Seems '${fieldText}' might not finish at the end of a word—it’s followed ${badCharString} in '${verseText}'`); - const excerpt = (fieldText.length > excerptLength - 3 ? '…' : '') + fieldText.substring(fieldText.length - excerptLength + 3, fieldText.length) + `(${remainingBits[1][0]}=D${remainingBits[1].charCodeAt(0)}/H${remainingBits[1].charCodeAt(0).toString(16)})`; + const excerpt = (fieldText.length > excerptLength - 3 ? discontiguousDivider : '') + fieldText.substring(fieldText.length - excerptLength + 3, fieldText.length) + `(${remainingBits[1][0]}=D${remainingBits[1].charCodeAt(0)}/H${remainingBits[1].charCodeAt(0).toString(16)})`; addNotice({ priority: 908, message: "Seems original language quote might not finish at the end of a word", details: `passage ►${verseText}◄`, characterIndex: fieldText.length, excerpt, location: ourLocation }); } } @@ -370,31 +376,31 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT // debugLog(`722 fieldText='${fieldText}'${extraText}`); // debugLog(`722 verseText='${verseText}'`); if (fieldText[0] === ' ') { - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith(' ')) { - const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u2060') { // Word joiner - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u2060')) { // Word joiner - const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u200B') { // Zero-width space - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u200B')) { // Zero-width space - const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u200D') { // Zero-width joiner - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? '…' : ''; + const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u200D')) { // Zero-width joiner - const excerpt = fieldText.length > excerptLength ? '…' : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else { - const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? '…' : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); + const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? discontiguousDivider : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►${verseText}◄`, excerpt, location: ourLocation }); } } diff --git a/src/core/questions-tsv5-row-check.js b/src/core/questions-tsv5-row-check.js index 5e5e14965..2ea8ac35f 100644 --- a/src/core/questions-tsv5-row-check.js +++ b/src/core/questions-tsv5-row-check.js @@ -3,12 +3,12 @@ import * as books from './books/books'; // import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; // import { checkSupportReferenceInTA } from './ta-reference-check'; -import { checkTNLinksToOutside } from './tn-links-check'; +// import { checkNotesLinksToOutside } from './notes-links-check'; // import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const QUESTIONS_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.0'; +// const QUESTIONS_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.1'; const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 5; // so expects 4 tabs per line const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse'; @@ -127,7 +127,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Annotation', "checkQuestionsTSV5DataRow ourMarkdownTextChecks: Only run this check on Annotations") + parameterAssert(fieldName === 'Question' || fieldName === 'Response', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: Only run this check on Questions and Responses not '${fieldName}'`); parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); @@ -144,7 +144,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // process results line by line for (const noticeEntry of omtcResultObject.noticeList) { // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - // NOTE: Ellipses in Annotation have the normal meaning + // NOTE: Ellipses in Question and Answer have the normal meaning // not like the specialised meaning in the Quote snippet fields if (noticeEntry.priority !== 178 && noticeEntry.priority !== 179 // unexpected space after ellipse, ellipse after space && !noticeEntry.message.startsWith("Unexpected … character after space") // 191 @@ -183,7 +183,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - // const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; + // const fieldType = fieldName === 'Question' ? 'markdown' : 'raw'; // const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // // Choose only ONE of the following @@ -246,7 +246,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // parameterAssert(typeof occurrence === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - // const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + // const coqResultObject = await checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); // // Choose only ONE of the following // // This is the fast way of append the results from this field @@ -261,52 +261,52 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // // end of ourCheckTNOriginalLanguageQuote function - async function ourCheckTNLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { - // Checks that the TA/TW/Bible reference can be found + // async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // // Checks that the TA/TW/Bible reference can be found - // Updates the global list of notices + // // Updates the global list of notices - // functionLog(`checkQuestionsTSV5DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Annotation', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Annotation' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV5DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // // functionLog(`checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(fieldName === 'Question', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'Question' not '${fieldName}'`); + // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); - // debugLog("coqResultObject", JSON.stringify(coqResultObject)); + // const coqResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + // // debugLog("coqResultObject", JSON.stringify(coqResultObject)); - // Choose only ONE of the following - // This is the fast way of append the results from this field - // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); - // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // process results line by line - for (const coqNoticeEntry of coqResultObject.noticeList) { - if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check - drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is - else // For our direct checks, we add the repoCode as an extra value - addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); - } - // The following is needed coz we might be checking the linked TA and/or TW articles - if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) - if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; - else drResult.checkedFileCount = coqResultObject.checkedFileCount; - if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) - if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; - else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; - if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) - for (const checkedRepoName of coqResultObject.checkedRepoNames) - try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } - catch { drResult.checkedRepoNames = [checkedRepoName]; } - if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) - for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) - try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } - catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } - // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); - } - // end of ourCheckTNLinksToOutside function + // // Choose only ONE of the following + // // This is the fast way of append the results from this field + // // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // // process results line by line + // for (const coqNoticeEntry of coqResultObject.noticeList) { + // if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + // drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is + // else // For our direct checks, we add the repoCode as an extra value + // addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); + // } + // // The following is needed coz we might be checking the linked TA and/or TW articles + // if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) + // if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; + // else drResult.checkedFileCount = coqResultObject.checkedFileCount; + // if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) + // if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; + // else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; + // if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) + // for (const checkedRepoName of coqResultObject.checkedRepoNames) + // try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } + // catch { drResult.checkedRepoNames = [checkedRepoName]; } + // if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) + // for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) + // try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } + // catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } + // // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); + // } + // // end of ourcheckNotesLinksToOutside function // Main code for checkQuestionsTSV5DataRow function @@ -342,9 +342,9 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo const haveGoodBookID = numChaptersThisBook !== undefined; let fields = line.split('\t'); - let RIDSuggestion, QSuggestion, ASuggestion; + let RIDSuggestion, QSuggestion, RSuggestion; if (fields.length === NUM_EXPECTED_QUESTIONS_TSV_FIELDS) { - const [reference, rowID, tags, question, answer] = fields; + const [reference, rowID, tags, question, response] = fields; // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; @@ -436,55 +436,55 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo if (question.length) { if (question.indexOf('\u200B') >= 0) { const charCount = countOccurrences(question, '\u200B'); - addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Question', rowID, location: ourRowLocation }); } if (isWhitespace(question)) - addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation }); else { // More than just whitespace - ASuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', question, true, ourRowLocation, checkingOptions); - await ourCheckTNLinksToOutside(rowID, 'Annotation', question, ourRowLocation, linkCheckingOptions); + RSuggestion = await ourMarkdownTextChecks(rowID, 'Question', question, true, ourRowLocation, checkingOptions); + // await ourcheckNotesLinksToOutside(rowID, 'Question', question, ourRowLocation, linkCheckingOptions); // let regexResultArray; // while ((regexResultArray = TA_REGEX.exec(question))) { - // // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); + // // debugLog("Got TA Regex in Question", JSON.stringify(regexResultArray)); // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) // if (supportReference !== adjustedLink && V !== 'intro') { // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', excerpt: adjustedLink, location: ourRowLocation }); + // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Question', excerpt: adjustedLink, location: ourRowLocation }); // } // } } } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (repoCode === 'TN2') - addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 274, message: "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation }); - if (answer.length) { - if (answer.indexOf('\u200B') >= 0) { - const charCount = countOccurrences(answer, '\u200B'); - addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + if (response.length) { + if (response.indexOf('\u200B') >= 0) { + const charCount = countOccurrences(response, '\u200B'); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Response', rowID, location: ourRowLocation }); } - if (isWhitespace(answer)) - addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + if (isWhitespace(response)) + addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation }); else { // More than just whitespace - ASuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', answer, true, ourRowLocation, checkingOptions); - await ourCheckTNLinksToOutside(rowID, 'Annotation', answer, ourRowLocation, linkCheckingOptions); + RSuggestion = await ourMarkdownTextChecks(rowID, 'Response', response, true, ourRowLocation, checkingOptions); + // await ourcheckNotesLinksToOutside(rowID, 'Response', response, ourRowLocation, linkCheckingOptions); // let regexResultArray; // while ((regexResultArray = TA_REGEX.exec(answer))) { - // // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); + // // debugLog("Got TA Regex in Response", JSON.stringify(regexResultArray)); // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) // if (supportReference !== adjustedLink && V !== 'intro') { // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', excerpt: adjustedLink, location: ourRowLocation }); + // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Response', excerpt: adjustedLink, location: ourRowLocation }); // } // } } } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (repoCode === 'TN2') - addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 274, message: "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation }); // 7 [reference, rowID, tags, question, answer] - const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${QSuggestion === undefined ? question : QSuggestion}\t${ASuggestion === undefined ? answer : ASuggestion}`; + const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${QSuggestion === undefined ? question : QSuggestion}\t${RSuggestion === undefined ? response : RSuggestion}`; if (suggestion !== line) { // debugLog(`Had question ${line}`); // debugLog(`Sug question ${suggestion}`); diff --git a/src/core/questions-tsv5-row-check.md b/src/core/questions-tsv5-row-check.md index cd5a336f1..3d584982d 100644 --- a/src/core/questions-tsv5-row-check.md +++ b/src/core/questions-tsv5-row-check.md @@ -1,4 +1,4 @@ -## Annotation (TSV) Row Check Sandbox +## Questions (TSV) Row Check Sandbox This function checks one tab-separated line for typical formatting errors. diff --git a/src/core/questions-tsv5-table-check.js b/src/core/questions-tsv5-table-check.js index 48707af47..5c1515e56 100644 --- a/src/core/questions-tsv5-table-check.js +++ b/src/core/questions-tsv5-table-check.js @@ -5,7 +5,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { functionLog, parameterAssert } from './utilities'; -const QUESTIONS_TABLE_VALIDATOR_VERSION_STRING = '0.1.0'; +const QUESTIONS_TABLE_VALIDATOR_VERSION_STRING = '0.1.1'; const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 5; // so expects 4 tabs per line const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse'; @@ -30,7 +30,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi Returns a result object containing a successList and a noticeList */ - functionLog(`checkQuestionsTSV5Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + functionLog(`checkQuestionsTSV5Table(${languageCode}, ${repoCode}, ${bookID}, ${filename}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkQuestionsTSV5Table: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV5Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode === 'TQ' || repoCode === 'SQ', `checkTWL_TSV6Table: repoCode expected 'TQ' or 'SQ' not '${repoCode}'`); @@ -69,7 +69,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); if (noticeObject.debugChain) noticeObject.debugChain = `checkQuestionsTSV5Table ${noticeObject.debugChain}`; - carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: repoCode }); + carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode }); } @@ -92,7 +92,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi if (bookID === 'OBS') numChaptersThisBook = 50; // There's 50 Open Bible Stories else { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-table-check"); + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkQuestionsTSV5Table"); try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } diff --git a/src/core/questions-tsv5-table-check.md b/src/core/questions-tsv5-table-check.md index 1f84f41f7..4b79caaf3 100644 --- a/src/core/questions-tsv5-table-check.md +++ b/src/core/questions-tsv5-table-check.md @@ -1,6 +1,6 @@ -## Annotation (TSV) Table Text Check Sandbox +## Questions (TSV) Table Text Check Sandbox -This function checks the given block of annotation (TSV) table lines for typical formatting errors. +This function checks the given block of question/response (TSV) table lines for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) @@ -11,7 +11,7 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkNotesTSV7Table } from './questions-tsv5-table-check'; +import { checkQuestionsTSV5Table } from './questions-tsv5-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Text samples @@ -48,12 +48,12 @@ const data = { givenLocation : 'that was supplied', } -function checkNotesTSV7Table(props) { +function CheckQuestionsTSV5Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkNotesTSV7Table is an ASYNC function + // We need the following construction because checkQuestionsTSV5Table is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -61,7 +61,7 @@ function checkNotesTSV7Table(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {repoCode} for {tableTextName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkNotesTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); + const rawResults = await checkQuestionsTSV5Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> @@ -72,7 +72,7 @@ function checkNotesTSV7Table(props) { }, []); // end of useEffect part return results; -} // end of checkNotesTSV7Table function +} // end of CheckQuestionsTSV5Table function -<checkNotesTSV7Table data={data}/> +<CheckQuestionsTSV5Table data={data}/> ``` diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index 752265aa7..45c4326c8 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -3,7 +3,7 @@ import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; import { checkSupportReferenceInTA } from './ta-reference-check'; -import { checkTNLinksToOutside } from './tn-links-check'; +import { checkNotesLinksToOutside } from './notes-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; @@ -33,7 +33,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * @param {Object} checkingOptions - may contain excerptLength, twRepoUsername, twRepoBranch (or tag), checkLinkedTWArticleFlag parameters * @return {Object} - containing noticeList */ -export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { +export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { /* This function is only for checking one data row and the function doesn’t assume that it has any previous context. @@ -41,9 +41,11 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi Returns an object containing the noticeList. */ - // functionLog(`checkTN_TSV9DataRow(${languageCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkTN_TSV9DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkTN_TSV9DataRow: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkTN_TSV9DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode !== undefined, "checkTN_TSV9DataRow: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkTN_TSV9DataRow: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); parameterAssert(line !== undefined, "checkTN_TSV9DataRow: 'line' parameter should be defined"); parameterAssert(typeof line === 'string', `checkTN_TSV9DataRow: 'line' parameter should be a string not a '${typeof line}'`); parameterAssert(bookID !== undefined, "checkTN_TSV9DataRow: 'bookID' parameter should be defined"); @@ -118,7 +120,7 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); // parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); // parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote', "checkTN_TSV9DataRow ourMarkdownTextChecks: Only run this check on OccurrenceNotes") + parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourMarkdownTextChecks: Only run this check on OccurrenceNotes not '${fieldName}'`); parameterAssert(fieldText !== undefined, "checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldText === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); parameterAssert(allowedLinks === true || allowedLinks === false, "checkTN_TSV9DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); @@ -254,7 +256,7 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi parameterAssert(typeof occurrence === 'string', `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + const coqResultObject = await checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -277,7 +279,7 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi * @param {string} rowLocation * @param {Object} checkingOptions */ - async function ourCheckTNLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Uses @@ -287,16 +289,16 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi // Updates the global list of notices - // functionLog(`checkTN_TSV9DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkTN_TSV9DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coqResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); // Choose only ONE of the following @@ -327,7 +329,7 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } - // end of ourCheckTNLinksToOutside function + // end of ourcheckNotesLinksToOutside function // Main code for checkTN_TSV9DataRow function @@ -530,7 +532,7 @@ export async function checkTN_TSV9DataRow(languageCode, line, bookID, givenC, gi addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation }); else { // More than just whitespace ONSuggestion = await ourMarkdownTextChecks(rowID, 'OccurrenceNote', occurrenceNote, true, ourRowLocation, checkingOptions); - await ourCheckTNLinksToOutside(rowID, 'OccurrenceNote', occurrenceNote, ourRowLocation, linkCheckingOptions); + await ourcheckNotesLinksToOutside(rowID, 'OccurrenceNote', occurrenceNote, ourRowLocation, linkCheckingOptions); let regexResultArray; while ((regexResultArray = TA_REGEX.exec(occurrenceNote))) { // debugLog("Got TA Regex in OccurrenceNote", JSON.stringify(regexResultArray)); diff --git a/src/core/tn-tsv9-row-check.md b/src/core/tn-tsv9-row-check.md index 682b727bb..e20e14158 100644 --- a/src/core/tn-tsv9-row-check.md +++ b/src/core/tn-tsv9-row-check.md @@ -62,7 +62,7 @@ function CheckTNTSVRow(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {tableLineName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkTN_TSV9DataRow(languageCode, tableLine, bookID, C, V, givenLocation, checkingOptions); + const rawResults = await checkTN_TSV9DataRow(languageCode, 'TN', tableLine, bookID, C, V, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableLineName}: "{tableLine.substr(0,256)}…"<br/><br/> diff --git a/src/core/tn-tsv9-table-check.js b/src/core/tn-tsv9-table-check.js index dd2c363bd..76fa909c8 100644 --- a/src/core/tn-tsv9-table-check.js +++ b/src/core/tn-tsv9-table-check.js @@ -21,7 +21,10 @@ const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOr * @param {Object} checkingOptions */ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableText, givenLocation, checkingOptions) { - /* This function is optimised for checking the entire file, i.e., all rows. + /* + repoCode is not passed through here, as can only be 'TN' + + This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -41,6 +44,8 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex parameterAssert(typeof givenLocation === 'string', `checkTN_TSV9Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); parameterAssert(checkingOptions !== undefined, "checkTN_TSV9Table: 'checkingOptions' parameter should be defined"); + const repoCode = 'TN'; + let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -129,7 +134,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex const [B, C, V, rowID, supportReference, origQuote, occurrence, _GLQuote, _occurrenceNote] = fields; // Use the row check to do most basic checks - const drResultObject = await checkTN_TSV9DataRow(languageCode, lines[n], bookID, C, V, ourLocation, checkingOptions); + const drResultObject = await checkTN_TSV9DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index 7992ef50b..fe888196f 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -1,17 +1,17 @@ import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' import * as books from './books/books'; import { checkTextField } from './field-text-check'; -import { checkMarkdownText } from './markdown-text-check'; +// import { checkMarkdownText } from './markdown-text-check'; // import { checkSupportReferenceInTA } from './ta-reference-check'; -import { checkTNLinksToOutside } from './tn-links-check'; +import { checkNotesLinksToOutside } from './notes-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const TWL_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.0'; +// const TWL_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.1'; const NUM_EXPECTED_TWL_TSV_FIELDS = 6; // so expects 5 tabs per line -const EXPECTED_TWL_HEADING_LINE = 'Reference\tID\tTags\tQuote\tOccurrence\tTWLink'; +const EXPECTED_TWL_HEADING_LINE = 'Reference\tID\tTags\tOrigWords\tOccurrence\tTWLink'; const LC_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'; const LC_ALPHABET_PLUS_DIGITS = 'abcdefghijklmnopqrstuvwxyz0123456789'; @@ -68,7 +68,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; const linkCheckingOptions = { ...checkingOptions }; - linkCheckingOptions.taRepoLanguageCode = languageCode; + linkCheckingOptions.twRepoLanguageCode = languageCode; let drResult = { noticeList: [] }; @@ -102,57 +102,6 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); } - async function ourMarkdownTextChecks(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { - /** - * @description - checks the given markdown field and processes the returned results - * @param {string} rowID - 4-character row ID field - * @param {string} fieldName - name of the field being checked - * @param {string} fieldText - the actual text of the field being checked - * @param {} allowedLinks - true if links are allowed in the field, otherwise false - * @param {string} rowLocation - description of where the line is located - * @param {Object} checkingOptions - parameters that might affect the check - */ - // Does markdown checks for small errors like leading/trailing spaces, etc. - - // We assume that checking for compulsory fields is done elsewhere - - // Updates the global list of notices - - // We don’t currently use the allowedLinks parameter - - // functionLog(`checkTWL_TSV6DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Annotation', "checkTWL_TSV6DataRow ourMarkdownTextChecks: Only run this check on Annotations") - parameterAssert(fieldText !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(allowedLinks === true || allowedLinks === false, "checkTWL_TSV6DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); - parameterAssert(rowLocation !== undefined, "checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); - parameterAssert(typeof rowLocation === 'string', `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - - const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); - - // Choose only ONE of the following - // This is the fast way of append the results from this field - // result.noticeList = result.noticeList.concat(cmtResultObject.noticeList); - // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // process results line by line - for (const noticeEntry of omtcResultObject.noticeList) { - // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - // NOTE: Ellipses in Annotation have the normal meaning - // not like the specialised meaning in the Quote snippet fields - if (noticeEntry.priority !== 178 && noticeEntry.priority !== 179 // unexpected space after ellipse, ellipse after space - && !noticeEntry.message.startsWith("Unexpected … character after space") // 191 - ) - addNoticePartial({ ...noticeEntry, rowID, fieldName }); - } - return omtcResultObject.suggestion; // There may or may not be one! - } - // end of ourMarkdownTextChecks function - function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { /** * @description - checks the given text field and processes the returned results @@ -181,7 +130,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, parameterAssert(typeof rowLocation === 'string', `checkTWL_TSV6DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; + const fieldType = 'raw'; const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following @@ -197,36 +146,6 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, } // end of ourCheckTextField function - /* - async function ourCheckSupportReferenceInTA(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { - // Checks that the TA reference can be found - - // Updates the global list of notices - - // functionLog(`checkTWL_TSV6DataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - - const coqResultObject = await checkSupportReferenceInTA(fieldName, taLinkText, rowLocation, { ...checkingOptions, taRepoLanguageCode: languageCode, expectFullLink: true }); - - // Choose only ONE of the following - // This is the fast way of append the results from this field - // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); - // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // process results line by line - for (const noticeEntry of coqResultObject.noticeList) { - // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckSupportReferenceInTA notice length=${Object.keys(noticeEntry).length}`); - addNoticePartial({ ...noticeEntry, rowID, fieldName }); - } - } - // end of ourCheckSupportReferenceInTA function - */ - async function ourCheckTNOriginalLanguageQuote(rowID, fieldName, fieldText, occurrence, rowLocation, checkingOptions) { // Checks that the Hebrew/Greek quote can be found in the original texts @@ -246,14 +165,14 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, parameterAssert(typeof occurrence === 'string', `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const coqResultObject = await checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + const colqResultObject = await checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field - // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // result.noticeList = result.noticeList.concat(colqResultObject.noticeList); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line - for (const noticeEntry of coqResultObject.noticeList) { + for (const noticeEntry of colqResultObject.noticeList) { // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); addNoticePartial({ ...noticeEntry, rowID, fieldName }); } @@ -261,52 +180,52 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, // end of ourCheckTNOriginalLanguageQuote function - async function ourCheckTNLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Updates the global list of notices - // functionLog(`checkTWL_TSV6DataRow ourCheckTNLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Annotation', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'fieldName' parameter should be 'Annotation' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourCheckTNLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkTWL_TSV6DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'TWLink', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'TWLink' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coqResultObject = await checkTNLinksToOutside(bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); - // debugLog("coqResultObject", JSON.stringify(coqResultObject)); + const coTNlResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); // Choose only ONE of the following // This is the fast way of append the results from this field - // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // result.noticeList = result.noticeList.concat(coTNlResultObject.noticeList); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line - for (const coqNoticeEntry of coqResultObject.noticeList) { + for (const coqNoticeEntry of coTNlResultObject.noticeList) { if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is else // For our direct checks, we add the repoCode as an extra value addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); } // The following is needed coz we might be checking the linked TA and/or TW articles - if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) - if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; - else drResult.checkedFileCount = coqResultObject.checkedFileCount; - if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) - if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; - else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; - if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) - for (const checkedRepoName of coqResultObject.checkedRepoNames) + if (coTNlResultObject.checkedFileCount && coTNlResultObject.checkedFileCount > 0) + if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coTNlResultObject.checkedFileCount; + else drResult.checkedFileCount = coTNlResultObject.checkedFileCount; + if (coTNlResultObject.checkedFilesizes && coTNlResultObject.checkedFilesizes > 0) + if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coTNlResultObject.checkedFilesizes; + else drResult.checkedFilesizes = coTNlResultObject.checkedFilesizes; + if (coTNlResultObject.checkedRepoNames && coTNlResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of coTNlResultObject.checkedRepoNames) try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } catch { drResult.checkedRepoNames = [checkedRepoName]; } - if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) - for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) + if (coTNlResultObject.checkedFilenameExtensions && coTNlResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of coTNlResultObject.checkedFilenameExtensions) try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } - // end of ourCheckTNLinksToOutside function + // end of ourcheckNotesLinksToOutside function // Main code for checkTWL_TSV6DataRow function @@ -323,8 +242,8 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + const halfLength = Math.floor(excerptLength / 2); // rounded down + const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -332,7 +251,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (bookID === 'OBS') numChaptersThisBook = 50; // There's 50 Open Bible Stories else { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-row-check"); + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkTWL_TSV6DataRow"); try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } catch (tlcNCerror) { @@ -468,33 +387,33 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (TWLink.length) { if (TWLink.indexOf('\u200B') >= 0) { const charCount = countOccurrences(TWLink, '\u200B'); - addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'Annotation', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'TWLink', rowID, location: ourRowLocation }); } if (isWhitespace(TWLink)) - addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 796, message: "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation }); else { // More than just whitespace - LSuggestion = await ourMarkdownTextChecks(rowID, 'Annotation', TWLink, true, ourRowLocation, checkingOptions); - await ourCheckTNLinksToOutside(rowID, 'Annotation', TWLink, ourRowLocation, linkCheckingOptions); - // let regexResultArray; - // while ((regexResultArray = TA_REGEX.exec(TWLink))) { - // debugLog("Got TA Regex in Annotation", JSON.stringify(regexResultArray)); - // // const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) - // // if (supportReference !== adjustedLink && V !== 'intro') { - // // const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - // // addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Annotation', excerpt: adjustedLink, location: ourRowLocation }); - // // } - // } + if (!TWLink.startsWith('rc://*/tw/dict/bible/')) + addNoticePartial({ priority: 798, message: "Field doesn't contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation }); + else { // it starts correctly + const bits = TWLink.substring('rc://*/tw/dict/bible/'.length).split('/'); + // debugLog(`checkTWL_TSV6DataRow checking ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); + if (bits[0] !== 'kt' && bits[0] !== 'name' && bits[0] !== 'other') { + const characterIndex = 'rc://*/tw/dict/bible/'.length; + const excerpt = (characterIndex > halfLength ? '…' : '') + TWLink.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < TWLink.length ? '…' : '') + addNoticePartial({ priority: 797, message: "Field doesn't contain proper TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); + } else { // all good so far + // debugLog(`checkTWL_TSV6DataRow looking up ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); + await ourcheckNotesLinksToOutside(rowID, 'TWLink', TWLink, ourRowLocation, linkCheckingOptions); + } + } } } - else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (repoCode === 'TN2') - addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation }); + else // TWLink is empty/missing + addNoticePartial({ priority: 799, message: "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation }); // 7 [reference, rowID, tags, quote, occurrence, TWLink] const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${QSuggestion === undefined ? quote : QSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${LSuggestion === undefined ? TWLink : LSuggestion}`; if (suggestion !== line) { - // debugLog(`Had annotation ${line}`); - // debugLog(`Sug annotation ${suggestion}`); drResult.suggestion = suggestion; } diff --git a/src/core/twl-tsv6-row-check.md b/src/core/twl-tsv6-row-check.md index 533a692c9..df50bb16b 100644 --- a/src/core/twl-tsv6-row-check.md +++ b/src/core/twl-tsv6-row-check.md @@ -1,4 +1,4 @@ -## Annotation (TSV) Row Check Sandbox +## TW Links (TSV) Row Check Sandbox This function checks one tab-separated line for typical formatting errors. @@ -16,7 +16,7 @@ import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples const lineE = ""; -const lineH = "Reference\tID\tTags\tQuote\tOccurrence\tTWLink"; +const lineH = "Reference\tID\tTags\tOrigWords\tOccurrence\tTWLink"; const lineN = "Peace on Earth, good will to all men/people!"; const lineG = "2:3\tw3r5\t\t1\t\tThis is an optional note"; const lineB1 = "2:3\tw3r5\t\t1\t\t<br>Boo"; diff --git a/src/core/twl-tsv6-table-check.js b/src/core/twl-tsv6-table-check.js index b6c33d561..4cd486349 100644 --- a/src/core/twl-tsv6-table-check.js +++ b/src/core/twl-tsv6-table-check.js @@ -2,13 +2,13 @@ import * as books from './books/books'; import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTWL_TSV6DataRow } from './twl-tsv6-row-check'; import { removeDisabledNotices } from './disabled-notices'; -import { functionLog, parameterAssert } from './utilities'; +import { parameterAssert } from './utilities'; const TWL_TABLE_VALIDATOR_VERSION_STRING = '0.1.0'; const NUM_EXPECTED_TWL_TSV_FIELDS = 6; // so expects 5 tabs per line -const EXPECTED_TWL_HEADING_LINE = 'Reference\tID\tTags\tQuote\tOccurrence\tTWLink'; +const EXPECTED_TWL_HEADING_LINE = 'Reference\tID\tTags\tOrigWords\tOccurrence\tTWLink'; /** @@ -30,7 +30,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam Returns a result object containing a successList and a noticeList */ - functionLog(`checkTWL_TSV6Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkTWL_TSV6Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkTWL_TSV6Table: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkTWL_TSV6Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode === 'TWL', `checkTWL_TSV6Table: repoCode expected 'TWL' not '${repoCode}'`); @@ -69,7 +69,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); if (noticeObject.debugChain) noticeObject.debugChain = `checkTWL_TSV6Table ${noticeObject.debugChain}`; - carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode: repoCode }); + carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode }); } @@ -92,7 +92,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam if (bookID === 'OBS') numChaptersThisBook = 50; // There's 50 Open Bible Stories else { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in annotation-table-check"); + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkTWL_TSV6Table"); try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } @@ -123,6 +123,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam // eslint-disable-next-line no-unused-vars const [reference, rowID, tags, quote, occurrence, TWLLink] = fields; const [C, V] = reference.split(':') + if (V === '3') break; // Use the row check to do most basic checks const drResultObject = await checkTWL_TSV6DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); diff --git a/src/core/twl-tsv6-table-check.md b/src/core/twl-tsv6-table-check.md index 10039d2c3..099fc00a8 100644 --- a/src/core/twl-tsv6-table-check.md +++ b/src/core/twl-tsv6-table-check.md @@ -1,6 +1,6 @@ -## Annotation (TSV) Table Text Check Sandbox +## TW Links (TSV) Table Text Check Sandbox -This function checks the given block of annotation (TSV) table lines for typical formatting errors. +This function checks the given block of TW Links (TSV) table lines for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) @@ -11,11 +11,11 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkNotesTSV7Table } from './twl-tsv6-table-check'; +import { checkTWL_TSV6Table } from './twl-tsv6-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Text samples -const textA = `Reference\tID\tTags\tQuote\tOccurrence\tTWLink +const textA = `Reference\tID\tTags\tOrigWords\tOccurrence\tTWLink 2:3\tw3r5\t\t\t\t1\t<br>Boo 99:3\tw3r5\t\t\t\t1\tBad chapter number 2:boo\tw3r5\t\t\t\t1\tBad verse number @@ -25,7 +25,7 @@ const textA = `Reference\tID\tTags\tQuote\tOccurrence\tTWLink 2:3\tw3r5\t\t\t\t17\tNote7 2:3\tw3r5\t\t\tBad ellipse...\t1\tNote8 2:3\tw3r5\t\t\t\t1\t<br>Boo hoo,, lost my shoe !`; -const textG = `Reference\tID\tTags\tQuote\tOccurrence\tTWLink +const textG = `Reference\tID\tTags\tOrigWords\tOccurrence\tTWLink front:intro\td9wn\t\t\t\t0\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; const lineA2 = "1:intro\tzb6f\t\t\t\t0\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist. 1:1\tf2mg\t\t\t0\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story. @@ -48,12 +48,12 @@ const data = { givenLocation : 'that was supplied', } -function checkNotesTSV7Table(props) { +function CheckTWL_TSV6Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkNotesTSV7Table is an ASYNC function + // We need the following construction because checkTWL_TSV6Table is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -61,7 +61,7 @@ function checkNotesTSV7Table(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {repoCode} for {tableTextName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkNotesTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); + const rawResults = await checkTWL_TSV6Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> @@ -72,7 +72,7 @@ function checkNotesTSV7Table(props) { }, []); // end of useEffect part return results; -} // end of checkNotesTSV7Table function +} // end of CheckTWL_TSV6Table function -<checkNotesTSV7Table data={data}/> +<CheckTWL_TSV6Table data={data}/> ``` diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 3f26f281b..799229d25 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -5,10 +5,10 @@ import { clearCaches, clearCheckedArticleCache, ourParseInt, preloadReposIfNeces import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccesses, RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderTotals } from '../RenderProcessedResults'; import { checkBookPackage } from './checkBookPackage'; -import { userLog, parameterAssert } from '../../core/utilities'; +import { userLog, debugLog, parameterAssert } from '../../core/utilities'; -// const BP_VALIDATOR_VERSION_STRING = '0.3.7'; +// const BP_VALIDATOR_VERSION_STRING = '0.3.8'; function BookPackageCheck(/*username, languageCode, bookID,*/ props) { @@ -94,7 +94,12 @@ function BookPackageCheck(/*username, languageCode, bookID,*/ props) { const origLangRepo = whichTestament === 'old' ? 'UHB' : 'UGNT'; repoPreloadList.unshift(origLangRepo); } - // debugLog(`BookPackageCheck got repoPreloadList=${repoPreloadList} for dataSet=${dataSet}`) + // TODO: Eventually we'll have all books here, so the repos can be included above + if (bookID === 'OBS' || bookID === 'TIT') { + repoPreloadList.push('SN'); + repoPreloadList.push('SQ'); + } + debugLog(`BookPackageCheck got repoPreloadList=${repoPreloadList} for dataSet=${dataSet}`) // if (bookID !== 'OBS') { // Preload the reference repos setResultValue(<p style={{ color: 'magenta' }}>Preloading {repoPreloadList.length} repos for <i>{username}</i> {languageCode} ready for <b>{bookID}</b> book package check…</p>); diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index cb3c25518..abf6fe08b 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -6,7 +6,7 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { checkRepo } from '../repo-check/checkRepo'; -// const BP_VALIDATOR_VERSION_STRING = '0.5.6'; +// const BP_VALIDATOR_VERSION_STRING = '0.5.7'; const MANIFEST_FILENAME = 'manifest.yaml'; @@ -259,7 +259,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // debugLog(`Year ${fullYearString} is ${typeof fullYearString}`); if (markdownFileContent.indexOf(fullYearString) === -1) // Can't find this year string in file // NOTE: We don’t use addNoticePartial, because it adds a misleading BookID - checkBookPackageResult.noticeList.push({ priority: 256, message: "Possibly missing current copyright year", details: fullYearString, repoName, filename, location: markdownLocation, extra: repoCode }); + checkBookPackageResult.noticeList.push({ priority: 256, message: "Possibly missing current copyright year", details: `possibly expecting '${fullYearString}'`, repoName, filename, location: markdownLocation, extra: repoCode }); } return markdownFileContent.length; @@ -274,7 +274,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // Main code for checkBookPackage() // NOTE: TN and TQ are used here for the old resource formats, e.g., 9-column TSV TN2 and markdown TQ2 - // The TN2, TQ2, SN, and SQ repoCodes refer to the new 7-column annotation TSV format. + // The TN2, TQ2, SN, and SQ repoCodes refer to the new 7-column notes TSV format. // debugLog("checkBookPackage() main code…"); let repoCodeList; let bookNumberAndName, whichTestament; @@ -298,7 +298,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // So now we want to work through checking this one specified Bible book in various repos const origLangRepoCode = whichTestament === 'old' ? 'UHB' : 'UGNT'; if (dataSet === 'DEFAULT') - repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ'] : [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ']; + repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ', 'SN', 'SQ'] : [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ']; else if (dataSet === 'OLD') repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ'] : [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ']; else if (dataSet === 'NEW') @@ -399,7 +399,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (!newCheckingOptions?.disableAllLinkFetchingFlag) { // We also check the manifest file for each repo if requested // because a faulty manifest might also stop a BP from working correctly in various programs - if (!checkedManifestDetails.includes(repoName)) { // Don’t want to check more than once, esp. for annotations repos + if (!checkedManifestDetails.includes(repoName)) { // Don’t want to check more than once checkedManifestDetails.push(repoName); // Remember that we checked this one // debugLog(`Maybe checking MANIFEST etc. for ${repoName}`); diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index 4b03b8ef0..938104f47 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -5,10 +5,10 @@ import { clearCaches, clearCheckedArticleCache, ourParseInt, preloadReposIfNeces import { checkBookPackages } from './checkBookPackages'; import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccesses, RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderTotals } from '../RenderProcessedResults'; -import { userLog } from '../../core/utilities'; +import { userLog, debugLog } from '../../core/utilities'; -// const BPS_VALIDATOR_VERSION_STRING = '0.2.1'; +// const BPS_VALIDATOR_VERSION_STRING = '0.2.2'; /** @@ -50,7 +50,8 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { // debugLog(`bookIDList (${bookIDList.length}) = ${bookIDList.join(', ')}`); const checkingOptions = { // Uncomment any of these to test them - // excerptLength: 25, + dataSet: dataSet, // Can be 'OLD' (Markdown, etc.), 'NEW' (TSV only), or 'BOTH', or 'DEFAULT' + // excerptLength: 25, suppressNoticeDisablingFlag: true, // Leave this one as true (otherwise demo checks are less efficient) }; // Or this allows the parameters to be specified as a BookPackagesCheck property @@ -89,6 +90,7 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { repoPreloadList = ['LT', 'ST', 'TN', 'TN2', 'TWL', 'TA', 'TW', 'TQ', 'TQ2']; if (haveNT) repoPreloadList.unshift('UGNT'); if (haveOT) repoPreloadList.unshift('UHB'); + debugLog(`BookPackagesCheck got repoPreloadList=${repoPreloadList} for dataSet=${dataSet}`) setResultValue(<p style={{ color: 'magenta' }}>Preloading {repoPreloadList.length} repos for <i>{username}</i> {languageCode} ready for book packages check…</p>); const successFlag = await preloadReposIfNecessary(username, languageCode, bookIDList, branch, repoPreloadList); diff --git a/src/demos/book-packages-check/README.md b/src/demos/book-packages-check/README.md index 455514a23..fb282e57e 100644 --- a/src/demos/book-packages-check/README.md +++ b/src/demos/book-packages-check/README.md @@ -33,6 +33,9 @@ import BookPackagesCheck from './BookPackagesCheck'; // bookIDs='LUK,ACT,EPH,1TI,2TI,TIT,2JN,3JN' // NT // The above English book packages should all be finished or well along the way + // We can choose the forthcoming new TSV formats or the existing formats + dataSet='OLD' // 'OLD' (Markdown TQ, TSV TN, etc.), 'NEW' (TSV TQ2, TN2, etc.), 'DEFAULT', or 'BOTH' + // Default displayType is 'ErrorsWarnings' // Alternatives are `SevereMediumLow', 'SingleList' displayType='SingleList' diff --git a/src/demos/book-packages-check/checkBookPackages.js b/src/demos/book-packages-check/checkBookPackages.js index aa741583e..edff0bea8 100644 --- a/src/demos/book-packages-check/checkBookPackages.js +++ b/src/demos/book-packages-check/checkBookPackages.js @@ -3,11 +3,21 @@ import { checkBookPackage } from '../book-package-check/checkBookPackage'; import { userLog, parameterAssert } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; -// const BPs_VALIDATOR_VERSION_STRING = '0.2.4'; +// const BPs_VALIDATOR_VERSION_STRING = '0.2.5'; +/** + * + * @param {string} username -- Door43 username/orgname + * @param {string} languageCode + * @param {*} bookIDList + * @param {Function} setResultValue + * @param {Object} checkingOptions + */ export async function checkBookPackages(username, languageCode, bookIDList, setResultValue, checkingOptions) { - // userLog(`I'm here in checkBookPackages v${VALIDATOR_VERSION_STRING} + // NOTE: dataSet is simply passed through here to checkBookPackage in checkingOptions + // + // userLog(`I'm here in checkBookPackages v${VALIDATOR_VERSION_STRING} // with ${username}, ${languageCode}, ${bookIDList}, ${JSON.stringify(checkingOptions)}`); let abortFlag = false; const startTime = new Date(); diff --git a/src/demos/file-check/checkFileContents.js b/src/demos/file-check/checkFileContents.js index aa82f963a..28b587638 100644 --- a/src/demos/file-check/checkFileContents.js +++ b/src/demos/file-check/checkFileContents.js @@ -1,20 +1,20 @@ import * as books from '../../core/books/books'; import { - userLog, functionLog, parameterAssert, + userLog, parameterAssert, logicAssert, formRepoName, checkUSFMText, checkMarkdownFileContents, checkPlainText, checkYAMLText, checkManifestText, checkTN_TSV9Table, checkNotesTSV7Table, checkQuestionsTSV5Table, checkTWL_TSV6Table, } from '../../core'; -// const CHECK_FILE_CONTENTS_VERSION_STRING = '0.4.0'; +// const CHECK_FILE_CONTENTS_VERSION_STRING = '0.4.1'; /** * * @param {string} username for Door43.org * @param {string} languageCode, e.g., 'en' - * @param {string} repoCode, e.g., 'TN' + * @param {string} repoCode, e.g., 'LT', 'TN', 'TN2', 'TQ', 'TWL', etc. * @param {string} branch, e.g., 'master' * @param {string} filename * @param {string} fileContent @@ -24,7 +24,7 @@ import { export async function checkFileContents(username, languageCode, repoCode, branch, filename, fileContent, givenLocation, checkingOptions) { // Determine the file type from the filename extension // and return the results of checking that kind of file text - functionLog(`checkFileContents(${username}, ${languageCode}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkFileContents(${username}, ${languageCode}, ${repoCode}, ${branch}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(username !== undefined, "checkFileContents: 'username' parameter should be defined"); parameterAssert(typeof username === 'string', `checkFileContents: 'username' parameter should be a string not a '${typeof username}': ${username}`); parameterAssert(languageCode !== undefined, "checkFileContents: 'languageCode' parameter should be defined"); @@ -55,13 +55,14 @@ export async function checkFileContents(username, languageCode, repoCode, branch const bookID = filenameMain.startsWith(`${languageCode}_`) || filenameMain.startsWith('en_') ? filenameMain.substring(filenameMain.length - 3) : filenameMain.substring(0, 3).toUpperCase(); // functionLog(`checkFileContents have TSV bookID=${bookID}`); parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); - if (filename.startsWith(`${languageCode}_`) || filenameMain.startsWith('en_')) + if (filename.startsWith(`${languageCode}_`) || filenameMain.startsWith('en_')) { + logicAssert(repoCode==='TN', `These filenames ${filenameMain} are only for TN ${repoCode}`); checkFileResult = await checkTN_TSV9Table(languageCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); - else { - const repoCode = filenameMain.substring(4).toUpperCase(); + } else { + logicAssert(repoCode!=='TN', `This code with ${filenameMain} is not for TN`); let checkFunction = { - TN: checkNotesTSV7Table, SN: checkNotesTSV7Table, - TQ: checkQuestionsTSV5Table, SQ: checkQuestionsTSV5Table, + TN2: checkNotesTSV7Table, SN: checkNotesTSV7Table, + TQ2: checkQuestionsTSV5Table, SQ: checkQuestionsTSV5Table, TWL: checkTWL_TSV6Table, }[repoCode]; checkFileResult = await checkFunction(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index e4d1a1e6c..1552961c6 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -2,7 +2,7 @@ import { userLog, parameterAssert } from '../core/utilities'; import { isDisabledNotice } from '../core/disabled-notices'; -// const NOTICE_PROCESSOR_VERSION_STRING = '0.9.9'; +// const NOTICE_PROCESSOR_VERSION_STRING = '0.9.10'; // All of the following can be overriden with optionalProcessingOptions const DEFAULT_MAXIMUM_SIMILAR_MESSAGES = 3; // Zero means no suppression of similar messages @@ -144,8 +144,10 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { if (givenNoticeObject.noticeList && givenNoticeObject.noticeList.length) { const ALL_TSV_FIELDNAMES = ['Book', 'Chapter', 'Verse', 'Reference', 'ID', 'Tags', 'SupportReference', + 'OrigWords', 'TWLink', 'OrigQuote', 'Quote', 'Occurrence', 'GLQuote', - 'OccurrenceNote', 'Annotation']; + 'Question', 'Response', + 'OccurrenceNote', 'Note']; const numberStore = {}, duplicatePriorityList = []; for (const thisGivenNotice of standardisedNoticeList) { const thisPriority = thisGivenNotice.priority, thisMsg = thisGivenNotice.message; @@ -178,8 +180,11 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { } // Check fields for bad values, and also across fields for unexpected combinations - const thisRepoName = thisGivenNotice.repoName, thisFilename = thisGivenNotice.filename, thisLineNumber = thisGivenNotice.lineNumber, - thisRowID = thisGivenNotice.rowID, thisFieldName = thisGivenNotice.fieldName, thisLocation = thisGivenNotice.location, thisExtra = thisGivenNotice.extra; + const thisRepoName = thisGivenNotice.repoName, + thisFilename = thisGivenNotice.filename, thisLineNumber = thisGivenNotice.lineNumber, + thisC = thisGivenNotice.C, thisV = thisGivenNotice.V, + thisRowID = thisGivenNotice.rowID, thisFieldName = thisGivenNotice.fieldName, + thisLocation = thisGivenNotice.location, thisExtra = thisGivenNotice.extra; if (thisRepoName) { parameterAssert(thisRepoName.indexOf(' ') < 0 && thisRepoName.indexOf('/') < 0 && thisRepoName.indexOf('\\') < 0, `repoName '${thisRepoName}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisLocation) @@ -194,6 +199,10 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { if (thisLocation) parameterAssert(thisLocation.indexOf(thisFilename) < 0, `filename is repeated in location in ${JSON.stringify(thisGivenNotice)}`); } + if (thisC) + parameterAssert(thisC === 'front' || !isNaN(thisC * 1), `C '${thisC}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); + if (thisV) // TODO: We'll need to remove this check once we start getting verse ranges, etc. + parameterAssert(thisV === 'intro' || !isNaN(thisV * 1), `V '${thisV}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisRowID) { parameterAssert(thisRowID.indexOf(' ') < 0 && thisRowID.indexOf('/') < 0 && thisRowID.indexOf('\\') < 0, `rowID '${thisRowID}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisLocation) diff --git a/src/demos/repo-check/checkRepo.js b/src/demos/repo-check/checkRepo.js index 31b805558..eefd5ab4d 100644 --- a/src/demos/repo-check/checkRepo.js +++ b/src/demos/repo-check/checkRepo.js @@ -4,7 +4,7 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { logicAssert, parameterAssert, repositoryExistsOnDoor43, getFileListFromZip, cachedGetFile, cachedGetRepositoryZipFile } from '../../core'; -// const REPO_VALIDATOR_VERSION_STRING = '0.4.5'; +// const REPO_VALIDATOR_VERSION_STRING = '0.4.6'; /** @@ -13,7 +13,7 @@ import { logicAssert, parameterAssert, repositoryExistsOnDoor43, getFileListFrom * @param {string} repoName * @param {string} branch * @param {string} givenLocation - * @param {*} setResultValue + * @param {Function} setResultValue * @param {Object} checkingOptions */ export async function checkRepo(username, repoName, branch, givenLocation, setResultValue, checkingOptions) { @@ -214,15 +214,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe // Default to the main filename without the extension let bookOrFileCode = thisFilename.substring(0, thisFilename.length - thisFilenameExtension.length - 1); let ourBookID = ''; - if (repoName === 'en_translation-annotations' && thisFilenameExtension === 'tsv') { - // functionLog(`checkRepo have en_translation-annotations bookOrFileCode=${bookOrFileCode}`); - const bookID = bookOrFileCode.substring(0, 3).toUpperCase(); - // functionLog(`checkRepo have bookID=${bookID}`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for Annotations)`); - bookOrFileCode = `${bookOrFileCode.substring(4).toUpperCase()} ${bookID}`; - ourBookID = bookID; - } - else if (thisFilenameExtension === 'usfm') { + if (thisFilenameExtension === 'usfm') { // const filenameMain = thisFilename.substring(0, thisFilename.length - 5); // drop .usfm // debugLog(`Have USFM filenameMain=${bookOrFileCode}`); const bookID = bookOrFileCode.substring(bookOrFileCode.length - 3).toUpperCase(); diff --git a/yarn.lock b/yarn.lock index ed4ada9e2..0d3a6b365 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1238,9 +1238,9 @@ resolve-from "^5.0.0" "@istanbuljs/schema@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" - integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== "@jest/console@^24.7.1", "@jest/console@^24.9.0": version "24.9.0" @@ -1901,9 +1901,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.14.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.26.tgz#e40df24c957568f350cca04e63bfb1e1556d1cbf" - integrity sha512-skWxepWOs+VArEBWd2S/VR3wUavioIIx9/HzW+UJiIjtwa6+kNXdsOeq7FfxDXf56hIcL0ieo2brwMgBJ1+lhw== + version "14.14.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b" + integrity sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1916,9 +1916,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.0.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.0.tgz#a4e8205a4955690eef712a6d0394a1d2e121e721" - integrity sha512-O3SQC6+6AySHwrspYn2UvC6tjo6jCTMMmylxZUFhE1CulVu5l3AxU6ca9lrJDTQDVllF62LIxVSx5fuYL6LiZg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.1.tgz#374e31645d58cb18a07b3ecd8e9dede4deb2cccd" + integrity sha512-DxZZbyMAM9GWEzXL+BMZROWz9oo6A9EilwwOMET2UVu2uZTqMWS5S69KVtuVKaRjCUpcrOXRalet86/OpG4kqw== "@types/prop-types@*": version "15.7.3" @@ -1943,9 +1943,9 @@ "@types/react" "*" "@types/react@*": - version "17.0.1" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.1.tgz#eb1f1407dea8da3bc741879c1192aa703ab9975b" - integrity sha512-w8t9f53B2ei4jeOqf/gxtc2Sswnc3LBK5s0DyJcg5xd10tMHXts2N31cKjWfH9IC/JvEPa/YF1U4YeP1t4R6HQ== + version "17.0.2" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8" + integrity sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -3497,9 +3497,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: - version "1.0.30001185" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001185.tgz#3482a407d261da04393e2f0d61eefbc53be43b95" - integrity sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg== + version "1.0.30001187" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001187.tgz#5706942631f83baa5a0218b7dfa6ced29f845438" + integrity sha512-w7/EP1JRZ9552CyrThUnay2RkZ1DXxKe/Q2swTC4+LElLh9RRYrL1Z+27LlakB8kzY0fSmHw9mc7XYDUKAKWMA== canvg@^3.0.6: version "3.0.7" @@ -4895,9 +4895,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.663" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.663.tgz#dd54adfd8d7f0e01b80d236c6e232efbaa0c686c" - integrity sha512-xkVkzHj6k3oRRGlmdgUCCLSLhtFYHDCTH7SeK+LJdJjnsLcrdbpr8EYmfMQhez3V/KPO5UScSpzQ0feYX6Qoyw== + version "1.3.664" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.664.tgz#8fb039e2fa8ef3ab2568308464a28425d4f6e2a3" + integrity sha512-yb8LrTQXQnh9yhnaIHLk6CYugF/An50T20+X0h++hjjhVfgSp1DGoMSYycF8/aD5eiqS4QwaNhiduFvK8rifRg== elliptic@^6.5.3: version "6.5.4" @@ -9032,11 +9032,16 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.45.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.45.0: version "1.45.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +"mime-db@>= 1.43.0 < 2": + version "1.46.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" + integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== + mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.28" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" @@ -9614,9 +9619,9 @@ open@^6.3.0: is-wsl "^1.1.0" open@^7.0.2: - version "7.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.0.tgz#ad95b98f871d9acb0ec8fecc557082cc9986626b" - integrity sha512-PGoBCX/lclIWlpS/R2PQuIR4NJoXh6X5AwVzE7WXnWRGvHg7+4TBCgsujUgiPpm0K1y4qvQeWnCWVTpTKZBtvA== + version "7.4.1" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.1.tgz#4ccedc11ca348d398378ffb39c71357df55fe6f7" + integrity sha512-Pxv+fKRsd/Ozflgn2Gjev1HZveJJeKR6hKKmdaImJMuEZ6htAvCTbcMABJo+qevlAelTLCrEK3YTKZ9fVTcSPw== dependencies: is-docker "^2.0.0" is-wsl "^2.1.1" From dcd7ba8fc267a36289ae5771d5f9dfe0aee9d181 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Tue, 16 Feb 2021 16:46:34 +1300 Subject: [PATCH 06/16] Update for latest TSV formats plus some general improvements --- README.md | 2 +- noticeList.txt | 486 +++++++++--------- package.json | 2 +- .../fixtures/unfoldingWord/en_tn/README.md | 10 +- src/__tests__/tn-table-row-check.test.js | 2 +- src/core/BCS-usfm-grammar-check.js | 8 +- src/core/field-link-check.js | 23 +- src/core/field-text-check.js | 67 +-- src/core/field-text-check.md | 2 +- src/core/file-text-check.js | 24 +- src/core/file-text-check.md | 2 +- src/core/index.js | 4 +- src/core/manifest-text-check.js | 25 +- src/core/markdown-file-contents-check.js | 17 +- src/core/markdown-text-check.js | 17 +- src/core/markdown-text-check.md | 5 +- src/core/notes-links-check.js | 19 +- src/core/notes-tsv7-row-check.js | 14 +- src/core/notes-tsv7-table-check.js | 20 +- src/core/orig-quote-check.js | 57 +- src/core/plain-text-check.js | 31 +- src/core/plain-text-check.md | 2 +- ...w-check.js => questions-tsv7-row-check.js} | 336 ++++++------ ...w-check.md => questions-tsv7-row-check.md} | 4 +- ...check.js => questions-tsv7-table-check.js} | 70 +-- ...check.md => questions-tsv7-table-check.md} | 16 +- src/core/ta-reference-check.js | 6 +- src/core/tn-tsv9-row-check.js | 37 +- src/core/tn-tsv9-row-check.md | 2 +- src/core/tn-tsv9-table-check.js | 22 +- src/core/tn-tsv9-table-check.md | 6 +- src/core/twl-tsv6-row-check.js | 16 +- src/core/twl-tsv6-table-check.js | 10 +- src/core/usfm-text-check.js | 38 +- src/core/yaml-text-check.js | 23 +- src/demos/RenderProcessedResults.js | 85 +-- .../book-package-check/BookPackageCheck.js | 37 +- .../book-package-check/checkBookPackage.js | 33 +- .../book-packages-check/BookPackagesCheck.js | 8 +- src/demos/file-check/checkFileContents.js | 20 +- src/demos/notice-processing-functions.js | 7 +- src/demos/notice-processing1.md | 2 +- src/demos/notice-processing2.md | 2 +- src/demos/notice-processing3.md | 2 +- styleguide.config.js | 16 +- yarn.lock | 6 +- 46 files changed, 876 insertions(+), 767 deletions(-) rename src/core/{questions-tsv5-row-check.js => questions-tsv7-row-check.js} (64%) rename src/core/{questions-tsv5-row-check.md => questions-tsv7-row-check.md} (99%) rename src/core/{questions-tsv5-table-check.js => questions-tsv7-table-check.js} (86%) rename src/core/{questions-tsv5-table-check.md => questions-tsv7-table-check.md} (97%) diff --git a/README.md b/README.md index be2fba27c..7de87e877 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ There is provision for checking to be altered and/or sped-up when the calling ap - `getFile`: a function which takes the four parameters ({username, repository, path, branch}) and returns the full text of the relevant Door43 file—default is to use our own function and associated caching - `fetchRepositoryZipFile`: a function which takes the three parameters ({username, repository, branch}) and returns the contents of the zip file containing all the Door43 files—default is to use our own function and associated caching - `getFileListFromZip`: takes the same three parameters and returns a list/array containing the filepaths of all the files in the zip file from Door43—default is to use our own function and associated caching -- `originalLanguageVerseText`: the Hebrew/Aramaic or Greek original language text for the book/chapter/verse of the TSV line being checked—this enables `OrigQuote` fields to be checked without needing to load and parse the actual USFM file +- `originalLanguageVerseText`: the Hebrew/Aramaic or Greek original language text for the book/chapter/verse of the TSV line being checked—this enables `Quote` fields to be checked without needing to load and parse the actual USFM file - `originalLanguageRepoUsername` and `originalLanguageRepoBranch`: these two fields can be used to specify the username/organisation and/or the branch/tag name for fetching the UHB and UGNT files for checking - `taRepoUsername`, `taRepoBranchName`: these two fields can be used to specify the username/organisation and/or the branch/tag name for fetching the TA files for checking - `taRepoLanguageCode`, and `taRepoSectionName`: can be used to specify how the `SupportReference` field is checked in TA—defaults are 'en' and 'translate' diff --git a/noticeList.txt b/noticeList.txt index b6623c1d4..00319cb95 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,5 +1,5 @@ -Last updated 2021-02-15 11:01:29.507046 by makeNoticeList.py -Got 445 notices: +Last updated 2021-02-16 12:00:30.263351 by makeNoticeList.py +Got 451 notices: checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 256 languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 927 marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 955 @@ -26,16 +26,16 @@ Got 445 notices: 999, "checkRepo function FAILED", repoName, excerpt: checkRepoError, location: repoName from RepoCheck.js line 107 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 174 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 235 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 382 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 575 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 601 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 389 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 582 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 608 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 178 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 239 - 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 386 - 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 577 - 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 605 + 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 393 + 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 584 + 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 612 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 260 - 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 94 + 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 95 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 117 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 136 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 123 @@ -44,34 +44,38 @@ Got 445 notices: 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 144 990, "Unable to load file", details: `username=$username`, repoName, filename ], elapsedSeconds: 0 ; from FileCheck.js line 63 989, "Unable to find/load repository", location: ourLocation from checkRepo.js line 186 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 248 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 240 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 240 - 988, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 240 + 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-tsv9-table-check.js line 127 + 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from twl-tsv6-table-check.js line 117 + 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 117 + 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from questions-tsv7-table-check.js line 117 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,111 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 676 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 452 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv5-row-check.js line 498 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 559 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 561 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv7-row-check.js line 500 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 533 - 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 288 - 979, "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv5-row-check.js line 339 - 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 357 + 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 253 + 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 241 + 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 240 + 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 240 + 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 258 + 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 359 + 979, "Invalid book identifier passed to checkQuestionsTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv7-row-check.js line 309 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 339 - 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 372 - 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 375 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 306 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv5-row-check.js line 357 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 380 + 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 374 + 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 377 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 276 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 382 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv7-row-check.js line 327 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 357 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 342 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 393 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 412 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 312 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 414 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 363 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 393 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 199 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 269 - 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 226 + 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 230 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 285 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 283 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 @@ -84,38 +88,39 @@ Got 445 notices: 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 641 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 639 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 163 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 394 - 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 486 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 364 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 488 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 415 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 473 - 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 332 - 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 374 - 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 377 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 380 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 383 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 386 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 389 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 392 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 395 - 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 398 - 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 319 - 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 316 + 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 338 + 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 380 + 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 383 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 386 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 389 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 392 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 395 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 398 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 401 + 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 404 + 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 325 + 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 322 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 660 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 716 - 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 354 - 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 363 + 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 360 + 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 369 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 - 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 293 + 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 300 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 76 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 102 889, `Unable to find TA link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 888, `Error loading TA link`, excerpt: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 887, `Linked TA article seems empty`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 - 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 248 - 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 243 - 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 250 - 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 297 - 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 294 - 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 300 + 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 252 + 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 247 + 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 254 + 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 302 + 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 299 + 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 305 879, `Badly formatted Resource Container link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 763 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 567 @@ -131,14 +136,14 @@ Got 445 notices: 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 823 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 829 - 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 288 + 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 294 849, `Unexpected '$badCharCombination' character combination`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 368 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 - 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 745 - 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 749 - 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 756 + 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 750 + 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 754 + 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 761 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 857 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 859 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 843 @@ -152,72 +157,78 @@ Got 445 notices: 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 883 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 311 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 362 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 385 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 281 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 387 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 332 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 362 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 316 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 367 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 390 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 286 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 392 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 337 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 367 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 329 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 299 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 380 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 400 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 402 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 350 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 380 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 335 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 386 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 405 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 305 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 407 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 356 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 386 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 338 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv5-row-check.js line 389 - 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 408 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 308 + 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 410 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv7-row-check.js line 359 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 389 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 347 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 398 - 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 417 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 317 + 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 419 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 368 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 398 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 351 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv5-row-check.js line 402 - 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 421 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 321 + 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 423 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 372 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 353 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 404 - 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 423 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 323 + 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 425 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 374 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 404 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 357 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv5-row-check.js line 408 - 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 427 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 327 + 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 429 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv7-row-check.js line 378 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 408 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 360 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv5-row-check.js line 411 - 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 430 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 330 + 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 432 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv7-row-check.js line 381 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 411 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 408 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 500 + 799, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 412 + 798, "Field doesn't contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 396 + 797, "Field doesn't contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation from twl-tsv6-row-check.js line 403 + 796, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 393 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 378 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 502 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 429 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 487 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 413 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 505 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 383 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 507 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 434 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 492 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 227 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 219 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv5-table-check.js line 219 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 232 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 220 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from notes-tsv7-table-check.js line 219 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 461 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv7-table-check.js line 219 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 463 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 447 - 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 466 + 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 468 787, "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 539 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 541 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 512 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 363 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv5-row-check.js line 414 - 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 433 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 333 + 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 435 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 384 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 414 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 366 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 417 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 436 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 336 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 438 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 387 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 417 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 200 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 750 @@ -231,199 +242,194 @@ Got 445 notices: 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation from plain-text-check.js line 225 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,089 765, "Unexpected link", characterIndex, excerpt, location: ourLocation from field-text-check.js line 441 - 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 - 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 + 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 + 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 - 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 - 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 702 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 399 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 491 + 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 + 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 707 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 369 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 493 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 420 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 478 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 390 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 482 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 360 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 484 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 411 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 469 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 140 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 149 - 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 107 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 112 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from twl-tsv6-table-check.js line 101 - 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv5-table-check.js line 101 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from notes-tsv7-table-check.js line 101 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-tsv9-table-check.js line 122 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from twl-tsv6-table-check.js line 117 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from questions-tsv5-table-check.js line 117 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 117 - 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 177 - 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 180 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 353 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 483 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 535 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 643 - 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 696 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 359 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 396 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 435 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 489 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 541 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 593 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 649 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 440 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 547 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 599 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 204 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 196 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv5-table-check.js line 196 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv7-table-check.js line 101 + 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 182 + 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 185 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 358 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 488 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 540 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 648 + 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 701 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 364 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 401 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 440 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 494 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 546 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 598 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 654 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 445 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 552 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 604 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 209 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 197 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from notes-tsv7-table-check.js line 196 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 223 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 215 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 215 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv7-table-check.js line 196 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 228 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 216 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 215 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 191 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 183 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv5-table-check.js line 183 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 215 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 196 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 184 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 183 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 195 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 187 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 187 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 183 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 200 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 188 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 187 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 197 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 189 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 189 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 187 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 202 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 190 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 189 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 201 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 213 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 193 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 205 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 193 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 205 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 189 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 206 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 218 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 194 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 206 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 193 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 205 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 217 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 209 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 209 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 193 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 205 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 222 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 210 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 209 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 233 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 225 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 225 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 209 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 238 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 226 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 225 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 231 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 223 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv5-table-check.js line 223 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 225 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 236 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 224 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 223 - 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 - 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, halfLength)$rest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 - 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, halfLength)$restRest.length > halfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 223 + 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 + 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 + 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 422 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 952 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,020 - 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 718 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 375 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 412 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 453 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 505 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 563 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 665 - 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 720 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 377 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 414 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 455 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 507 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 565 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 615 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 667 - 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"'+leftoverLinksList2[0]+'"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 737 - 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"'+leftoverLinksList1[0]+'"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 731 + 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 723 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 380 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 417 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 458 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 510 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 568 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 670 + 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 725 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 382 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 419 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 460 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 512 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 570 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 620 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 672 + 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 742 + 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 736 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 254 638, "Only found whitespace", location: ourLocation from field-text-check.js line 108 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 128 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 990 - 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 111 - 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 143 - 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 151 + 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 117 + 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 149 + 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 157 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 153 583, "Unexpected newLine character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 236 582, "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 242 581, "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 248 - 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 347 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 211 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 203 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv5-table-check.js line 203 + 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 352 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 216 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 204 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 203 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 189 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 181 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv5-table-check.js line 181 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 203 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 194 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 182 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 181 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 181 539, "File starts with empty line", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 150 538, "File ends without newline character", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 155 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 - 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 222 + 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 225 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 135 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 106 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 950 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,124 - 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 247 - 375, "Ellipsis without surrounding snippet", location: ourLocation from orig-quote-check.js line 325 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 420 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 439 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 464 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 470 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 512 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 527 + 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 270 + 375, "Divider without surrounding snippet", location: ourLocation from orig-quote-check.js line 331 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 390 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 472 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 514 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 529 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 441 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 466 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 457 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 499 - 373, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 423 - 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 442 - 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 467 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 454 - 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 515 - 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 530 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 456 + 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 517 + 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 532 + 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 444 + 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 469 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 438 373, "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 502 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 684 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 948 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 149 - 282, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 215 - 274, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 440 - 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 459 - 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv5-row-check.js line 484 - 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 545 + 282, "Nesting of header levels seems confused", details: `recent indent levels=$JSON.stringify(indentLevels) but now $numLeadingSpaces`, lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 236 + 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 547 + 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 461 + 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 486 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 - 256, "Possibly missing current copyright year", details: fullYearString, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 262 + 256, "Possibly missing current copyright year", details: `possibly expecting '$fullYearString'`, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 262 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 319 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 264 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 270 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 373 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 424 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 443 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 343 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 394 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 424 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 375 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 426 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 345 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 396 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 377 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 428 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 347 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 398 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 379 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv5-row-check.js line 430 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 349 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 451 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 400 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 - 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 208 - 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 249 - 158, "Unexpected space(s) beside ellipse character", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 258 - 157, "Unexpected space(s) beside ↔ divider character", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 265 - 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 272 + 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 209 + 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 255 + 158, `Unexpected space(s) beside divider $discontiguousDivider`, characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 264 + 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 278 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 643 - 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 687 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 337 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 474 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 526 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 584 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 634 + 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 692 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 342 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 479 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 531 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 589 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 639 138, "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 160 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 117 110, `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 137 @@ -440,8 +446,8 @@ Got 445 notices: 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 468 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 152 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 157 - 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 298 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 260 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 252 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv5-table-check.js line 252 + 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 304 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 265 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 253 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 252 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv7-table-check.js line 252 diff --git a/package.json b/package.json index 0cac689f7..a01644fcf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha2", + "version": "2.0.0_alpha3", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/fixtures/unfoldingWord/en_tn/README.md b/src/__tests__/fixtures/unfoldingWord/en_tn/README.md index 81bd9dc30..0e412acc1 100644 --- a/src/__tests__/fixtures/unfoldingWord/en_tn/README.md +++ b/src/__tests__/fixtures/unfoldingWord/en_tn/README.md @@ -63,7 +63,7 @@ The UTN are structured as TSV files to simplify importing and exporting into var A Tab Separated Value (TSV) file is like a Comma Separated Value file except that the tab character is what divides the values instead of a comma. This makes it easier to include prose text in the files because many languages require the use of commas, single quotes, and double quotes in their sentences and paragraphs. -The UTN are structured as one file per book of the bible and encoded in TSV format, for example, `01-GEN.tsv`. The columns are `Book`, `Chapter`, `Verse`, `ID`, `SupportReference`, `OrigQuote`, `Occurrence`, `GLQuote`, and `OccurrenceNote`. +The UTN are structured as one file per book of the bible and encoded in TSV format, for example, `01-GEN.tsv`. The columns are `Book`, `Chapter`, `Verse`, `ID`, `SupportReference`, `Quote`, `Occurrence`, `GLQuote`, and `OccurrenceNote`. ### UTN TSV Column Description @@ -80,14 +80,14 @@ The following lists each column with a brief description and example. * `SupportReference` * Normally a link to a supporting reference text or blank * This will usually be a link to translationAcademy, like `rc://*/ta/man/translate/figs-metaphor` -* `OrigQuote` - Original language quote (e.g. `ἐφανέρωσεν ... τὸν λόγον αὐτοῦ`) +* `Quote` - Original language quote (e.g. `ἐφανέρωσεν ... τὸν λόγον αὐτοῦ`) * Software (such as tC) should use this for determining what is highlighted rather than using the `GLQuote` field * Three periods (...), forming an ellipsis, indicates that the quote is discontinuous, software should interpret this in a non-greedy manner * `Occurrence` - Specifies which occurrence in the original language text the entry applies to. - * `-1`: entry applies to every occurrence of OrigQuote in the verse + * `-1`: entry applies to every occurrence of Quote in the verse * `0`: entry does not occur in original language (for example, “Connecting Statement:”) - * `1`: entry applies to first occurrence of OrigQuote only - * `2`: entry applies to second occurrence of OrigQuote only + * `1`: entry applies to first occurrence of Quote only + * `2`: entry applies to second occurrence of Quote only * etc. * `GLQuote` (OPTIONAL) - Gateway language quote (e.g. `he revealed his word`) * Software (such as tC) should disregard this field. diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index 540f5511b..e172d1770 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -277,7 +277,7 @@ describe('checkTN_TSV9DataRow() - ', () => { }); it('header should succeed', async () => { - const chosenLine = "Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote"; + const chosenLine = "Book\tChapter\tVerse\tID\tSupportReference\tQuote\tOccurrence\tGLQuote\tOccurrenceNote"; const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); diff --git a/src/core/BCS-usfm-grammar-check.js b/src/core/BCS-usfm-grammar-check.js index 103186922..eaa12eddf 100644 --- a/src/core/BCS-usfm-grammar-check.js +++ b/src/core/BCS-usfm-grammar-check.js @@ -23,9 +23,9 @@ export function runBCSGrammarCheck(strictnessString, fileText, filename, givenLo } // else // debugLog(`Using supplied excerptLength=${excerptLength} cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); // Now create the parser and run the check const ourUsfmParser = new grammar.USFMParser(fileText, @@ -60,7 +60,7 @@ export function runBCSGrammarCheck(strictnessString, fileText, filename, givenLo characterIndex = errorLine.indexOf('^') - 8; if (characterIndex < 0) characterIndex = 0; // Just in case if (excerpt.length) - excerpt = (characterIndex > halfLength ? '…' : '') + excerpt.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < excerpt.length ? '…' : '') + excerpt = (characterIndex > excerptHalfLength ? '…' : '') + excerpt.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < excerpt.length ? '…' : '') } else ourErrorMessage = errorLine; // We only want the last one } diff --git a/src/core/field-link-check.js b/src/core/field-link-check.js index 7c6020d25..49d204236 100644 --- a/src/core/field-link-check.js +++ b/src/core/field-link-check.js @@ -1,4 +1,4 @@ -import { checkTextField } from './field-text-check' +// import { checkTextField } from './field-text-check' import { cachedGetFileUsingFullURL } from './getApi'; import { userLog, parameterAssert } from './utilities'; @@ -50,7 +50,18 @@ export async function startLiveLinksCheck(linksList, existingNoticeList, callbac } -export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalFieldLocation, checkingOptions) { +/** + * + * @param {string} languageCode + * @param {string} repoCode + * @param {string} fieldName + * @param {string} fieldText + * @param {Object} linkOptions + * @param {string} optionalFieldLocation + * @param {Object} checkingOptions + */ +/* +export function checkFieldLinks(languageCode, repoCode, fieldName, fieldText, linkOptions, optionalFieldLocation, checkingOptions) { // Does basic checks for fields that are links or that contain links // We assume that checking for compulsory fields is done elsewhere @@ -64,6 +75,10 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField userLog(`checkFieldLinks('${fieldName}', '${fieldText}')…`); // debugLog( "linkOptions", JSON.stringify(linkOptions)); // debugLog( "linkOptionsEC", linkOptions.expectedCount); + parameterAssert(languageCode !== undefined, "checkFieldLinks: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkFieldLinks: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(repoCode !== undefined, "checkFieldLinks: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkFieldLinks: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(fieldName !== undefined, "checkFieldLinks: 'fieldName' parameter should be defined"); parameterAssert(typeof fieldName === 'string', `checkFieldLinks: 'fieldName' parameter should be a string not a '${typeof fieldName}': ${fieldName}`); parameterAssert(fieldText !== undefined, "checkFieldLinks: 'fieldText' parameter should be defined"); @@ -108,9 +123,8 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField } // Ok, we have something in our field - const languageCode = ''; if (linkOptions.otherTextAllowed) - result = checkTextField(languageCode, 'link', fieldName, fieldText, true, optionalFieldLocation, checkingOptions); + result = checkTextField(languageCode, repoCode, 'link', fieldName, fieldText, true, optionalFieldLocation, checkingOptions); // Parameter nonsense check if (linkOptions.allowedCount > 0 && linkOptions.expectedCount > linkOptions.allowedCount) @@ -158,3 +172,4 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField return result; } // end of checkFieldLinks function +*/ diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index 75545716f..7f43662f1 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -8,6 +8,7 @@ import { debugLog, parameterAssert } from './utilities'; /** * @description -- Does basic checks for small errors like leading/trailing spaces, etc. * @param {string} languageCode -- can be an empty string + * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. * @param {string} fieldType -- classification, e.g., TSV, USFM, YAML, link, markdown, raw * @param {string} fieldName -- used for identification * @param {string} fieldText -- the field being checked @@ -15,7 +16,7 @@ import { debugLog, parameterAssert } from './utilities'; * @param {string} optionalFieldLocation -- used to inform where this field is located * @param {Object} checkingOptions */ -export function checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions) { +export function checkTextField(languageCode, repoCode, fieldType, fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions) { // We assume that checking for compulsory fields is done elsewhere // Returns a single notice list @@ -30,6 +31,8 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al parameterAssert(languageCode !== undefined, "checkTextField: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkTextField: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); parameterAssert(languageCode !== 'unfoldingWord', `checkTextField: 'languageCode' ${languageCode} parameter should be not be 'unfoldingWord'`); + parameterAssert(repoCode !== undefined, "checkTextField: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkTextField: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(fieldType !== undefined, "checkTextField: 'fieldType' parameter should be defined"); parameterAssert(typeof fieldType === 'string', `checkTextField: 'fieldType' parameter should be a string not a '${typeof fieldType}': ${fieldType}`); parameterAssert(fieldType !== '', `checkTextField: 'fieldType' ${fieldType} parameter should be not be an empty string`); @@ -88,9 +91,9 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); let suggestion = fieldText.trim(); @@ -98,7 +101,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 895) && (characterIndex = fieldText.indexOf('\u200B')) >= 0) { const charCount = countOccurrences(fieldText, '\u200B'); - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u200B/g, '‼') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/\u200B/g, '‼') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 895, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\u200B/g, ''); // Or should it be space ??? } @@ -111,21 +114,21 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 993) && (characterIndex = fieldText.indexOf('<<<<<<<')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + fieldText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 993, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 992) && (characterIndex = fieldText.indexOf('=======')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + fieldText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 992, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 991) && (characterIndex = fieldText.indexOf('>>>>>>>>')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + fieldText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 991, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } } @@ -148,12 +151,12 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 64) && (characterIndex = fieldText.indexOf('<br> ')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 64, message: "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation }); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 63) && (characterIndex = fieldText.indexOf('\\n ')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 63, message: "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation }); } @@ -194,12 +197,12 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 94) && (characterIndex = fieldText.indexOf(' <br')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 94, message: "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation }); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 93) && (characterIndex = fieldText.indexOf(' \\n')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 93, message: "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation }); } @@ -217,7 +220,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 124) && (characterIndex = fieldText.indexOf(' ')) >= 0 && (fieldType !== 'markdown' || characterIndex !== fieldText.length - 2)) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') const doubleCount = countOccurrences(fieldText, ' '); let notice; if (doubleCount === 1) @@ -232,41 +235,41 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 583) && (characterIndex = fieldText.indexOf('\n')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 583, message: "Unexpected newLine character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\n/g, ' '); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 582) && (characterIndex = fieldText.indexOf('\r')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 582, message: "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\r/g, ' '); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 581) && (characterIndex = fieldText.indexOf('\xA0')) >= 0) { // non-break space - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\xA0/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/\xA0/g, '⍽') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 581, message: "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/\xA0/g, ' '); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 580) && (characterIndex = fieldText.indexOf('\u202F')) >= 0) { // narrow non-break space - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\u202F/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/\u202F/g, '⍽') + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') const notice = { priority: 580, message: "Unexpected narrow non-break space character", excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); suggestion = suggestion.replace(/\u202F/g, ' '); } - if (fieldName === 'OrigQuote' || fieldName === 'Quote') { + if (fieldName === 'Quote' || fieldName === 'Quote') { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 179) && (characterIndex = fieldText.indexOf(' …')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 179, message: "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/ …/g, '…'); } if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 178) && (characterIndex = fieldText.indexOf('… ')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 178, message: "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation }); suggestion = suggestion.replace(/… /g, '…'); } @@ -285,7 +288,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al doubledPunctuationCheckList += '-'; for (const punctChar of doubledPunctuationCheckList) { if ((characterIndex = fieldText.indexOf(punctChar + punctChar)) >= 0) { - let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') const notice = { priority: 177, message: `Unexpected doubled ${punctChar} characters`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM @@ -300,11 +303,11 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if (fieldType !== 'markdown') afterSpaceCheckList += '_*~'; // These are used for markdown formatting if (fieldType !== 'USFM' || (fieldText.indexOf('x-lemma') < 0 && fieldText.indexOf('x-tw') < 0)) afterSpaceCheckList += '|'; if (fieldType !== 'YAML') afterSpaceCheckList += '\'"'; // These are used for YAML strings, e.g., version: '0.15' - // if (fieldName === 'OrigQuote' || fieldName === 'Quote') afterSpaceCheckList += '…'; // NOT NEEDED -- this is specifically checked elsewhere + // if (fieldName === 'Quote' || fieldName === 'Quote') afterSpaceCheckList += '…'; // NOT NEEDED -- this is specifically checked elsewhere for (const punctChar of afterSpaceCheckList) { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 191) && (characterIndex = fieldText.indexOf(' ' + punctChar)) >= 0) { - let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') const notice = { priority: 191, message: `Unexpected ${punctChar} character after space`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM @@ -315,7 +318,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al && (punctChar !== '!' || fieldType !== 'markdown') // image tag && fieldText[0] === punctChar) { characterIndex = 0; - let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 195, message: `Unexpected ${punctChar} character at start of line`, characterIndex, excerpt, location: ourLocation }); } } @@ -333,7 +336,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if (fieldType !== 'YAML') beforeSpaceCheckList += '['; for (const punctChar of beforeSpaceCheckList) { if ((characterIndex = fieldText.indexOf(punctChar + ' ')) >= 0) { - let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') const notice = { priority: 192, message: `Unexpected space after ${punctChar} character`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM @@ -351,7 +354,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al for (const punctChar of beforeEOLCheckList) { if (punctChar !== '—' && fieldText[fieldText.length - 1] === punctChar) { characterIndex = fieldText.length - 1; - let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') const notice = { priority: 193, message: `Unexpected ${punctChar} character at end of line`, excerpt, location: ourLocation }; if ((fieldType !== 'raw' && fieldType !== 'text') || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM @@ -364,7 +367,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al // Check for bad combinations of characters for (const badCharCombination of BAD_CHARACTER_COMBINATIONS) if ((characterIndex = fieldText.indexOf(badCharCombination)) >= 0) { - let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); addNoticePartial({ priority: 849, message: `Unexpected '${badCharCombination}' character combination`, characterIndex, excerpt, location: ourLocation }); } @@ -372,7 +375,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al // characterIndex = fieldText.indexOf('\\['); // if (characterIndex === -1) characterIndex = fieldText.indexOf('\\]'); // if (characterIndex !== -1) { - // let excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + // let excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); // addNoticePartial({ priority: 849, message: "Unexpected \\[ or \\] characters", characterIndex, excerpt, location: ourLocation }); // } @@ -437,7 +440,7 @@ export function checkTextField(languageCode, fieldType, fieldName, fieldText, al if (characterIndex === -1) characterIndex = fieldText.indexOf('.info'); if (characterIndex === -1) characterIndex = fieldText.indexOf('.bible'); if (characterIndex >= 0) { - let excerpt = `${characterIndex > halfLength ? '…' : ''}${fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus)}${characterIndex + halfLengthPlus < fieldText.length ? '…' : ''}` + let excerpt = `${characterIndex > excerptHalfLength ? '…' : ''}${fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus)}${characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''}` addNoticePartial({ priority: 765, message: "Unexpected link", characterIndex, excerpt, location: ourLocation }); } } diff --git a/src/core/field-text-check.md b/src/core/field-text-check.md index 6b421afe3..626aae8e5 100644 --- a/src/core/field-text-check.md +++ b/src/core/field-text-check.md @@ -27,7 +27,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'TN', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; diff --git a/src/core/file-text-check.js b/src/core/file-text-check.js index 29f6003b8..21b6e452c 100644 --- a/src/core/file-text-check.js +++ b/src/core/file-text-check.js @@ -4,7 +4,17 @@ import { parameterAssert } from './utilities'; // const FILE_TEXT_VALIDATOR_VERSION_STRING = '0.3.1'; -export function checkTextfileContents(languageCode, fileType, filename, fileText, optionalFileLocation, checkingOptions) { +/** + * + * @param {string} languageCode + * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. + * @param {string} fileType + * @param {string} filename + * @param {string} fileText + * @param {string} optionalFileLocation + * @param {Object} checkingOptions + */ +export function checkTextfileContents(languageCode, repoCode, fileType, filename, fileText, optionalFileLocation, checkingOptions) { // Does basic checks for small errors like mismatched punctuation pairs, etc. // (Used by ourBasicFileChecks() in checkUSFMText() in usfm-text-check.js) @@ -24,6 +34,8 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText // functionLog(`checkTextfileContents(${filename}, ${fileText.length.toLocaleString()} chars, '${optionalFileLocation}')…`); parameterAssert(languageCode !== undefined, "checkTextfileContents: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkTextfileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(repoCode !== undefined, "checkTextfileContents: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkTextfileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(fileType !== undefined, "checkTextfileContents: 'fileType' parameter should be defined"); parameterAssert(typeof fileType === 'string', `checkTextfileContents: 'fileType' parameter should be a string not a '${typeof fileType}': ${fileType}`); parameterAssert(fileType !== '', `checkTextfileContents: 'fileType' ${fileType} parameter should be not be an empty string`); @@ -71,7 +83,7 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText parameterAssert(typeof plainText === 'string', `cPT ourCheckPlainText: 'plainText' parameter should be a string not a '${typeof plainText}'`); parameterAssert(checkingOptions !== undefined, "cPT ourCheckPlainText: 'checkingOptions' parameter should be defined"); - const resultObject = checkPlainText(languageCode, textType, textFilename, plainText, givenLocation, checkingOptions); + const resultObject = checkPlainText(languageCode, repoCode, textType, textFilename, plainText, givenLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -102,9 +114,9 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); */ /* @@ -126,7 +138,7 @@ export function checkTextfileContents(languageCode, fileType, filename, fileText // if (ix === -1) ix = fileText.indexOf('.info'); // if (ix === -1) ix = fileText.indexOf('.bible'); // if (ix >= 0) { - // let excerpt = (ix>halfLength ? '…' : '') + fileText.substring(ix-halfLength, ix+halfLengthPlus) + (ix+halfLengthPlus < fileText.length ? '…' : '') + // let excerpt = (ix>excerptHalfLength ? '…' : '') + fileText.substring(ix-excerptHalfLength, ix+excerptHalfLengthPlus) + (ix+excerptHalfLengthPlus < fileText.length ? '…' : '') // addNotice({765, "Unexpected link", ix,excerpt, ourAtString}); // } // } diff --git a/src/core/file-text-check.md b/src/core/file-text-check.md index 16606dc03..b4f884c52 100644 --- a/src/core/file-text-check.md +++ b/src/core/file-text-check.md @@ -28,7 +28,7 @@ const chosenTextName = "textB"; const chosenText = textB; const checkingOptions = {}; -const rawResults = checkTextfileContents('en', 'text', 'Sample', chosenText, 'in '+chosenTextName+' that was supplied', checkingOptions); +const rawResults = checkTextfileContents('en', 'TN', 'text', 'Sample', chosenText, 'in '+chosenTextName+' that was supplied', checkingOptions); // Because we know here that we're only checking one file, we don’t need the filename field in the notices function deleteFilenameField(notice) { delete notice.filename; return notice; } diff --git a/src/core/index.js b/src/core/index.js index 254f3580e..c6a1150d8 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -11,8 +11,8 @@ export * from './manifest-text-check'; export * from './notes-tsv7-row-check'; export * from './notes-tsv7-table-check'; export * from './plain-text-check'; -export * from './questions-tsv5-row-check'; -export * from './questions-tsv5-table-check'; +export * from './questions-tsv7-row-check'; +export * from './questions-tsv7-table-check'; export * from './notes-links-check'; export * from './tn-tsv9-row-check'; export * from './tn-tsv9-table-check'; diff --git a/src/core/manifest-text-check.js b/src/core/manifest-text-check.js index 806328b09..cb9ca38b3 100644 --- a/src/core/manifest-text-check.js +++ b/src/core/manifest-text-check.js @@ -540,7 +540,18 @@ const ajv = new Ajv(); const validate = ajv.compile(MANIFEST_SCHEMA); -export async function checkManifestText(username, repoName, repoBranch, manifestText, givenLocation, checkingOptions) { +/** + * + * @param {string} languageCode + * @param {string} repoCode + * @param {string} username + * @param {string} repoName + * @param {string} repoBranch + * @param {string} manifestText + * @param {string} givenLocation + * @param {Object} checkingOptions + */ +export async function checkManifestText(languageCode, repoCode, username, repoName, repoBranch, manifestText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire file, i.e., all lines. See the specification at https://resource-container.readthedocs.io/en/latest/manifest.html. @@ -548,6 +559,10 @@ export async function checkManifestText(username, repoName, repoBranch, manifest Returns a result object containing a successList and a noticeList */ // functionLog(`checkManifestText(${username}, ${repoName}, ${repoBranch}, ${manifestText.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkManifestText: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkManifestText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(repoCode !== undefined, "checkManifestText: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkManifestText: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(username !== undefined, "checkManifestText: 'username' parameter should be defined"); parameterAssert(typeof username === 'string', `checkManifestText: 'username' parameter should be a string not a '${typeof username}': ${username}`); parameterAssert(repoName !== undefined, "checkManifestText: 'repoName' parameter should be defined"); @@ -576,9 +591,9 @@ export async function checkManifestText(username, repoName, repoBranch, manifest } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const cmtResult = { successList: [], noticeList: [] }; @@ -618,7 +633,7 @@ export async function checkManifestText(username, repoName, repoBranch, manifest parameterAssert(typeof manifestText === 'string', `cManT ourYAMLTextChecks: 'manifestText' parameter should be a string not a '${typeof manifestText}'`); // parameterAssert( allowedLinks===true || allowedLinks===false, "cManT ourYAMLTextChecks: allowedLinks parameter must be either true or false"); - const cYtResultObject = checkYAMLText('en', textName, manifestText, givenLocation, checkingOptions); + const cYtResultObject = checkYAMLText('en', repoCode, textName, manifestText, givenLocation, checkingOptions); // Concat is faster if we don’t need to process each notice individually cmtResult.successList = cmtResult.successList.concat(cYtResultObject.successList); diff --git a/src/core/markdown-file-contents-check.js b/src/core/markdown-file-contents-check.js index 892c1dcf6..32fbc6912 100644 --- a/src/core/markdown-file-contents-check.js +++ b/src/core/markdown-file-contents-check.js @@ -10,12 +10,13 @@ const MARKDOWN_FILE_VALIDATOR_VERSION_STRING = '0.4.0'; /** * * @param {string} languageCode + * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. * @param {string} markdownFilename -- used for identification * @param {string} markdownText -- the actual text to be checked * @param {string} givenLocation * @param {Object} checkingOptions */ -export function checkMarkdownFileContents(languageCode, markdownFilename, markdownText, givenLocation, checkingOptions) { +export function checkMarkdownFileContents(languageCode, repoCode, markdownFilename, markdownText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire markdown file, i.e., all lines. Note: This function does not check that any link targets in the markdown are valid links. @@ -25,7 +26,9 @@ export function checkMarkdownFileContents(languageCode, markdownFilename, markdo // functionLog(`checkMarkdownFileContents(${languageCode}, ${markdownFilename}, ${markdownText.length}, ${givenLocation})…`); parameterAssert(languageCode !== undefined, "checkMarkdownFileContents: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkMarkdownFileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); - parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'markdownFilename' parameter should be defined"); + parameterAssert(repoCode !== undefined, "checkMarkdownFileContents: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkMarkdownFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); +parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'markdownFilename' parameter should be defined"); parameterAssert(typeof markdownFilename === 'string', `checkMarkdownFileContents: 'markdownFilename' parameter should be a string not a '${typeof markdownFilename}': ${markdownFilename}`); parameterAssert(markdownText !== undefined, "checkMarkdownFileContents: 'markdownText' parameter should be defined"); parameterAssert(typeof markdownText === 'string', `checkMarkdownFileContents: 'markdownText' parameter should be a string not a '${typeof markdownText}': ${markdownText}`); @@ -48,9 +51,9 @@ export function checkMarkdownFileContents(languageCode, markdownFilename, markdo } // else // debugLog("Using supplied excerptLength=" + excerptLength, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog("Using halfLength=" + halfLength, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog("Using excerptHalfLength=" + excerptHalfLength, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const result = { successList: [], noticeList: [] }; @@ -95,7 +98,7 @@ export function checkMarkdownFileContents(languageCode, markdownFilename, markdo parameterAssert(optionalFieldLocation !== undefined, "cMdFC ourCheckMarkdownText: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cMdFC ourCheckMarkdownText: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const dbtcResultObject = await checkMarkdownText(languageCode, markdownFilename, markdownText, optionalFieldLocation, checkingOptions); + const dbtcResultObject = await checkMarkdownText(languageCode, repoCode, markdownFilename, markdownText, optionalFieldLocation, checkingOptions); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line @@ -122,7 +125,7 @@ export function checkMarkdownFileContents(languageCode, markdownFilename, markdo parameterAssert(typeof markdownText === 'string', `cMdFC ourFileTextCheck: 'markdownText' parameter should be a string not a '${typeof markdownText}'`); parameterAssert(checkingOptions !== undefined, "cMdFC ourFileTextCheck: 'checkingOptions' parameter should be defined"); - const dbtcResultObject = checkTextfileContents(languageCode, 'markdown', markdownFilename, markdownText, optionalFieldLocation, checkingOptions); + const dbtcResultObject = checkTextfileContents(languageCode, repoCode, 'markdown', markdownFilename, markdownText, optionalFieldLocation, checkingOptions); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 0e8822201..bcc9da13b 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -13,12 +13,13 @@ const IMAGE_REGEX = new RegExp('!\\[([^\\]]+?)\\]\\(([^ \\]]+?)\\)', 'g'); /** * * @param {string} languageCode + * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. * @param {string} textOrFileName -- used for identification * @param {string} markdownText -- the actual text to be checked * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkMarkdownText(languageCode, textOrFileName, markdownText, givenLocation, checkingOptions) { +export async function checkMarkdownText(languageCode, repoCode, textOrFileName, markdownText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire markdown text, i.e., all lines. This text may not necessarily be from a file -- it may be from a (multiline) field within a file @@ -31,6 +32,8 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe parameterAssert(languageCode !== undefined, "checkMarkdownText: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkMarkdownText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); parameterAssert(languageCode !== 'unfoldingWord', `checkMarkdownText: 'languageCode' ${languageCode} parameter should be not be 'unfoldingWord'`); + parameterAssert(repoCode !== undefined, "checkMarkdownText: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkMarkdownText: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(textOrFileName !== undefined, "checkMarkdownText: 'textOrFileName' parameter should be defined"); parameterAssert(typeof textOrFileName === 'string', `checkMarkdownText: 'textOrFileName' parameter should be a string not a '${typeof textOrFileName}': ${textOrFileName}`); parameterAssert(markdownText !== undefined, "checkMarkdownText: 'markdownText' parameter should be defined"); @@ -55,9 +58,9 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe } // else // debugLog("Using supplied excerptLength=" + excerptLength, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog("Using halfLength=" + halfLength, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog("Using excerptHalfLength=" + excerptHalfLength, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const result = { successList: [], noticeList: [] }; @@ -108,7 +111,7 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe parameterAssert(optionalFieldLocation !== undefined, "cMdT ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cMdT ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const dbtcResultObject = checkTextField(languageCode, 'markdown', fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions); + const dbtcResultObject = checkTextField(languageCode, repoCode, 'markdown', fieldName, fieldText, allowedLinks, optionalFieldLocation, checkingOptions); // If we need to put everything through addNotice, e.g., for debugging or filtering // process results line by line @@ -265,8 +268,8 @@ export async function checkMarkdownText(languageCode, textOrFileName, markdownTe const count = ((markdownText || '').match(thisRegex) || []).length; // Finds only NON-OVERLAPPING matches hopefully if (count && (count % 2) !== 0) { const characterIndex = markdownText.indexOf(thisField); - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = /*(iy > halfLength ? '…' : '') +*/ markdownText.substring(iy - halfLength, iy + halfLengthPlus) + (iy + halfLengthPlus < markdownText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = /*(iy > excerptHalfLength ? '…' : '') +*/ markdownText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus) + (iy + excerptHalfLengthPlus < markdownText.length ? '…' : '') addNotice({ priority: 378, message: `Possible mismatched '${thisField}' markdown formatting pairs`, details: `${count.toLocaleString()} total occurrence${count === 1 ? '' : 's'}`, characterIndex, excerpt, location: ourLocation }); break; // Only want one warning per text } diff --git a/src/core/markdown-text-check.md b/src/core/markdown-text-check.md index 088b6de9b..0b27c9d06 100644 --- a/src/core/markdown-text-check.md +++ b/src/core/markdown-text-check.md @@ -44,11 +44,12 @@ const data = { chosenTextName : 'textSB', chosenText : textSB, languageCode : 'en', + repoCode : 'TN', givenLocation : "that was supplied", } function CheckMarkdownText(props) { - const { languageCode, chosenText, chosenTextName, givenLocation } = props.data; + const { languageCode, repoCode, chosenText, chosenTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -60,7 +61,7 @@ function CheckMarkdownText(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {chosenTextName}…</p>); const checkingOptions = {}; - const rawResults = await checkMarkdownText(languageCode, chosenTextName, chosenText, givenLocation, checkingOptions); + const rawResults = await checkMarkdownText(languageCode, repoCode, chosenTextName, chosenText, givenLocation, checkingOptions); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done markdown text checks"]; setResults( diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index 5376df579..64f724afb 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -75,6 +75,7 @@ async function alreadyChecked({ username, repository, path, branch }) { /** * + * @param {string} languageCode, e.g., 'en' * @param {string} repoCode, e.g., 'TN', 'SN', 'TN2', or even 'TWL' * @param {string} bookID * @param {string} fieldName, e.g., 'OccurrenceNote' or 'Note' or 'TWLink' @@ -82,7 +83,7 @@ async function alreadyChecked({ username, repository, path, branch }) { * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, fieldText, givenLocation, checkingOptions) { +export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, fieldText, givenLocation, checkingOptions) { /* This is for the case of the OccurrenceNote or Note field containing markdown links bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. @@ -111,6 +112,8 @@ export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, */ // functionLog(`checkNotesLinksToOutside v${NOTES_LINKS_VALIDATOR_VERSION_STRING} ${repoCode} ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, …)…`); + parameterAssert(languageCode !== undefined, "checkNotesLinksToOutside: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkNotesLinksToOutside: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode !== undefined, "checkNotesLinksToOutside: 'repoCode' parameter should be defined"); parameterAssert(typeof repoCode === 'string', `checkNotesLinksToOutside: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); parameterAssert(bookID !== undefined, "checkNotesLinksToOutside: 'bookID' parameter should be defined"); @@ -162,9 +165,9 @@ export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const getFile_ = (checkingOptions && checkingOptions?.getFile) ? checkingOptions?.getFile : cachedGetFile; let defaultLanguageCode; @@ -221,12 +224,12 @@ export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, let languageCode = regexResultArray[1]; if (languageCode !== '*') { const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); } else if (repoCode === 'TN') { // but not TN2 // At the moment, tC can’t handle these links with * so we have to ensure that they're not there const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); } if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; @@ -256,7 +259,7 @@ export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); if (await alreadyChecked(taPathParameters) !== true) { // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); - const checkTAFileResult = await checkMarkdownText(languageCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); + const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); for (const noticeObject of checkTAFileResult.noticeList) ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); ctarResult.checkedFileCount += 1; @@ -307,7 +310,7 @@ export async function checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); if (await alreadyChecked(twPathParameters) !== true) { // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); - const checkTWFileResult = await checkMarkdownText(languageCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); + const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); for (const noticeObject of checkTWFileResult.noticeList) ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); ctarResult.checkedFileCount += 1; diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index 190060894..4be1ca3a2 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -51,6 +51,8 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // functionLog(`checkNotesTSV7DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkNotesTSV7DataRow: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkNotesTSV7DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode !== undefined, "checkNotesTSV7DataRow: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkNotesTSV7DataRow: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); parameterAssert(line !== undefined, "checkNotesTSV7DataRow: 'line' parameter should be defined"); parameterAssert(typeof line === 'string', `checkNotesTSV7DataRow: 'line' parameter should be a string not a '${typeof line}'`); parameterAssert(bookID !== undefined, "checkNotesTSV7DataRow: 'bookID' parameter should be defined"); @@ -135,7 +137,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID parameterAssert(typeof rowLocation === 'string', `checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); + const omtcResultObject = await checkMarkdownText(languageCode, repoCode, fieldName, fieldText, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -184,7 +186,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkNotesTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'Note' ? 'markdown' : 'raw'; - const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + const octfResultObject = checkTextField(languageCode, repoCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -275,7 +277,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coqResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); // Choose only ONE of the following @@ -323,9 +325,9 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook; diff --git a/src/core/notes-tsv7-table-check.js b/src/core/notes-tsv7-table-check.js index fd803f8ce..17c3e6555 100644 --- a/src/core/notes-tsv7-table-check.js +++ b/src/core/notes-tsv7-table-check.js @@ -2,13 +2,13 @@ import * as books from './books/books'; import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkNotesTSV7DataRow } from './notes-tsv7-row-check'; import { removeDisabledNotices } from './disabled-notices'; -import { functionLog, parameterAssert } from './utilities'; +import { parameterAssert } from './utilities'; const NOTES_TABLE_VALIDATOR_VERSION_STRING = '0.3.2'; const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line -const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; +const EXPECTED_NOTES_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; /** @@ -30,10 +30,10 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena Returns a result object containing a successList and a noticeList */ - functionLog(`checkNotesTSV7Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkNotesTSV7Table(${languageCode}, ${repoCode}, ${bookID}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkNotesTSV7Table: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkNotesTSV7Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(repoCode === 'TN' || repoCode === 'SN', `checkTWL_TSV6Table: repoCode expected 'TN' or 'SN' not '${repoCode}'`); + parameterAssert(repoCode === 'TN' || repoCode === 'TN2' || repoCode === 'SN', `checkTWL_TSV6Table: repoCode expected 'TN', 'TN2', or 'SN' not '${repoCode}'`); parameterAssert(bookID !== undefined, "checkNotesTSV7Table: 'bookID' parameter should be defined"); parameterAssert(typeof bookID === 'string', `checkNotesTSV7Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); parameterAssert(bookID.length === 3, `checkNotesTSV7Table: 'bookID' parameter should be three characters long not ${bookID.length}`); @@ -83,9 +83,9 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook = 0; @@ -111,10 +111,10 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena for (let n = 0; n < lines.length; n++) { // functionLog(`checkNotesTSV7Table checking line ${n}: ${JSON.stringify(lines[n])}`); if (n === 0) { - if (lines[0] === EXPECTED_TN_HEADING_LINE) + if (lines[0] === EXPECTED_NOTES_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); else - addNoticePartial({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); + addNoticePartial({ priority: 988, message: "Bad TSV header", details: `expected '${EXPECTED_NOTES_HEADING_LINE}'`, excerpt: lines[0], lineNumber: 1, location: ourLocation }); } else // not the header { @@ -237,7 +237,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_NOTES_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 983, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_NOTES_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/orig-quote-check.js b/src/core/orig-quote-check.js index 9e936bf81..b472fa688 100644 --- a/src/core/orig-quote-check.js +++ b/src/core/orig-quote-check.js @@ -118,7 +118,7 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa } if (!originalMarkdown) return ''; - let gotIt = false; + let gotIt = V === 'intro'; // normally false, but true for intro (so grabs first line of text = heading line) const searchString = `-${adjC}-${adjV}.`; // NOTE: Bible references get appended to the last frame text (but I don’t think it does any harm) for (const line of originalMarkdown.split('\n')) { @@ -128,8 +128,9 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa if (line.indexOf('[OBS Image]') > 0) // This is the next frame break; else - verseText += line; + verseText += line; // NOTE: works coz all text on one line, otherwise would need to insert spaces here } + // debugLog(`Got OBS ${V}:${C} '${verseText}'`); } else { // not OBS, so a USFM Bible book const bookNumberAndName = books.usfmNumberName(bookID); const whichTestament = books.testament(bookID); // returns 'old' or 'new' @@ -235,9 +236,9 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); let occurrence = 1; try { occurrence = ourParseInt(occurrenceString); } catch { } // errors in this field are noted elsewhere @@ -249,9 +250,9 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa // fieldText = fieldText.strip() # so we don’t get consequential errors let characterIndex; - if (discontiguousDivider==='…' && (characterIndex = fieldText.indexOf('...')) >= 0) { + if (discontiguousDivider === '…' && (characterIndex = fieldText.indexOf('...')) >= 0) { // debugLog(`Bad ellipse characters in '${fieldText}'`); - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); addNotice({ priority: 159, message: "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation }); } @@ -260,21 +261,21 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa quoteBits = fieldText.split(discontiguousDivider); if ((characterIndex = fieldText.indexOf(` ${discontiguousDivider}`)) >= 0 || (characterIndex = fieldText.indexOf(`${discontiguousDivider} `)) >= 0) { // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - const excerpt = (characterIndex > halfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? discontiguousDivider : ''); + const excerpt = (characterIndex > excerptHalfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? discontiguousDivider : ''); addNotice({ priority: 158, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); } - // } else if (fieldText.indexOf('↔') >= 0) { - // quoteBits = fieldText.split('↔'); - // if ((characterIndex = fieldText.indexOf(' ↔')) >= 0 || (characterIndex = fieldText.indexOf('↔ ')) >= 0) { - // // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - // const excerpt = (characterIndex > halfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); - // addNotice({ priority: 157, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); - // } - } else if (discontiguousDivider==='…' && fieldText.indexOf('...') >= 0) { // Yes, we still actually allow this + // } else if (fieldText.indexOf('↔') >= 0) { + // quoteBits = fieldText.split('↔'); + // if ((characterIndex = fieldText.indexOf(' ↔')) >= 0 || (characterIndex = fieldText.indexOf('↔ ')) >= 0) { + // // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); + // const excerpt = (characterIndex > excerptHalfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); + // addNotice({ priority: 157, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); + // } + } else if (discontiguousDivider === '…' && fieldText.indexOf('...') >= 0) { // Yes, we still actually allow this quoteBits = fieldText.split('...'); if ((characterIndex = fieldText.indexOf(' ...')) >= 0 || (characterIndex = fieldText.indexOf('... ')) >= 0) { // debugLog(`Unexpected space(s) beside ellipse characters in '${fieldText}'`); - const excerpt = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : ''); + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); addNotice({ priority: 156, message: "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation }); } } @@ -334,7 +335,7 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa if (occurrence > 1) { // functionLog(`checkOriginalLanguageQuote is checking for ${occurrence} occurrences of ${fieldText}`); if (verseText.split(fieldText).length <= occurrence) { // There's not enough of them - const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? discontiguousDivider : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); + const excerpt = fieldText.substring(0, excerptHalfLength) + (fieldText.length > 2 * excerptHalfLength ? discontiguousDivider : '') + fieldText.substring(fieldText.length - excerptHalfLength, fieldText.length); addNotice({ priority: 917, message: "Unable to find duplicate original language quote in verse text", details: `occurrence=${occurrenceString}, passage ►${verseText}◄`, excerpt, location: ourLocation }); } } else { // We only need to check for one occurrence @@ -365,7 +366,7 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa // const offendingChar = remainingBits[1][0]; // const badCharString = ` by '${offendingChar}' {unicodedata.name(offendingChar)}={hex(ord(offendingChar))}`; // debugLog(`Seems '${fieldText}' might not finish at the end of a word—it’s followed ${badCharString} in '${verseText}'`); - const excerpt = (fieldText.length > excerptLength - 3 ? discontiguousDivider : '') + fieldText.substring(fieldText.length - excerptLength + 3, fieldText.length) + `(${remainingBits[1][0]}=D${remainingBits[1].charCodeAt(0)}/H${remainingBits[1].charCodeAt(0).toString(16)})`; + const excerpt = (fieldText.length > excerptLength - 3 ? '…' : '') + fieldText.substring(fieldText.length - excerptLength + 3, fieldText.length) + `(${remainingBits[1][0]}=D${remainingBits[1].charCodeAt(0)}/H${remainingBits[1].charCodeAt(0).toString(16)})`; addNotice({ priority: 908, message: "Seems original language quote might not finish at the end of a word", details: `passage ►${verseText}◄`, characterIndex: fieldText.length, excerpt, location: ourLocation }); } } @@ -376,31 +377,31 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa // debugLog(`722 fieldText='${fieldText}'${extraText}`); // debugLog(`722 verseText='${verseText}'`); if (fieldText[0] === ' ') { - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; + const excerpt = fieldText.substring(0, excerptLength) + (fieldText.length > excerptLength ? '…' : ''); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith(' ')) { - const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = (fieldText.length > excerptLength ? '…' : '') + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u2060') { // Word joiner - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; + const excerpt = fieldText.substring(0, excerptLength) + (fieldText.length > excerptLength ? '…' : ''); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u2060')) { // Word joiner - const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = (fieldText.length > excerptLength ? '…' : '') + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u200B') { // Zero-width space - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; + const excerpt = fieldText.substring(0, excerptLength) + (fieldText.length > excerptLength ? '…' : ''); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u200B')) { // Zero-width space - const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = (fieldText.length > excerptLength ? '…' : '') + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText[0] === '\u200D') { // Zero-width joiner - const excerpt = fieldText.substring(0, excerptLength) + fieldText.length > excerptLength ? discontiguousDivider : ''; + const excerpt = fieldText.substring(0, excerptLength) + (fieldText.length > excerptLength ? '…' : ''); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else if (fieldText.endsWith('\u200D')) { // Zero-width joiner - const excerpt = fieldText.length > excerptLength ? discontiguousDivider : '' + fieldText.substring(fieldText.length - excerptLength, fieldText.length); + const excerpt = (fieldText.length > excerptLength ? '…' : '') + fieldText.substring(fieldText.length - excerptLength, fieldText.length); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation }); } else { - const excerpt = fieldText.substring(0, halfLength) + (fieldText.length > 2 * halfLength ? discontiguousDivider : '') + fieldText.substring(fieldText.length - halfLength, fieldText.length); + const excerpt = fieldText.length <= excerptLength ? fieldText : (fieldText.substring(0, excerptHalfLength) + (fieldText.length > 2 * excerptHalfLength ? '…' : '') + fieldText.substring(fieldText.length - excerptHalfLength, fieldText.length)); addNotice({ priority: 916, message: "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►${verseText}◄`, excerpt, location: ourLocation }); } } diff --git a/src/core/plain-text-check.js b/src/core/plain-text-check.js index 891635d4a..dc1433468 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -10,12 +10,13 @@ const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.4.0'; /** * * @param {string} textType 'markdown', 'USFM', 'YAML', 'text', or 'raw' + * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. * @param {string} textName * @param {string} plainText -- text to be checked * @param {string} givenLocation * @param {Object} checkingOptions */ -export function checkPlainText(languageCode, textType, textName, plainText, givenLocation, checkingOptions) { +export function checkPlainText(languageCode, repoCode, textType, textName, plainText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire text, i.e., all lines. It is used in checkFileContents() in book-package-check.js @@ -27,6 +28,8 @@ export function checkPlainText(languageCode, textType, textName, plainText, give parameterAssert(languageCode !== undefined, "checkPlainText: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkPlainText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); parameterAssert(languageCode !== 'markdown' && languageCode !== 'USFM' && languageCode !== 'YAML' && languageCode !== 'text' && languageCode !== 'raw' && languageCode !== 'unfoldingWord', `checkPlainText: 'languageCode' ${languageCode} parameter should be not be '${languageCode}'`); + parameterAssert(repoCode !== undefined, "checkPlainText: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkPlainText: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(textType !== undefined, "checkPlainText: 'textType' parameter should be defined"); parameterAssert(typeof textType === 'string', `checkPlainText: 'textType' parameter should be a string not a '${typeof textType}': ${textType}`); parameterAssert(textType === 'markdown' || textType === 'USFM' || textType === 'YAML' || textType === 'text' || textType === 'raw', `checkPlainText: unrecognised 'textType' parameter: '${textType}'`); @@ -49,9 +52,9 @@ export function checkPlainText(languageCode, textType, textName, plainText, give } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const cptResult = { successList: [], noticeList: [] }; @@ -99,7 +102,7 @@ export function checkPlainText(languageCode, textType, textName, plainText, give parameterAssert(optionalFieldLocation !== undefined, "cPT ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cPT ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const resultObject = checkTextField(languageCode, textType, '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); + const resultObject = checkTextField(languageCode, repoCode, textType, '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -131,16 +134,16 @@ export function checkPlainText(languageCode, textType, textName, plainText, give let characterIndex; if ((characterIndex = plainText.indexOf('<<<<<<<')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + plainText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < plainText.length ? '…' : '') addNotice({ priority: 993, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else if ((characterIndex = plainText.indexOf('=======')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + plainText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < plainText.length ? '…' : '') addNotice({ priority: 992, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } else if ((characterIndex = plainText.indexOf('>>>>>>>>')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + plainText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < plainText.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + plainText.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < plainText.length ? '…' : '') addNotice({ priority: 991, message: "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation }); } @@ -195,7 +198,7 @@ export function checkPlainText(languageCode, textType, textName, plainText, give } else // something is still open and this isn’t a match -- might just be consequential error if (char !== '’' // Closing single quote is also used as apostrophe in English && (textType !== 'markdown' || char !== '>' || characterIndex > 4)) { // Markdown uses > or >> or > > or > > > for block indents so ignore these -- might just be consequential error - const excerpt = (characterIndex > halfLength ? '…' : '') + line.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < line.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + line.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < line.length ? '…' : '') const details = `'${lastEntry.char}' opened on line ${lastEntry.n} character ${lastEntry.x + 1}`; addNotice({ priority: 777, message: `Bad punctuation nesting: ${char} closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation }); // debugLog(` ERROR 777: mismatched characters: ${details}`); @@ -203,7 +206,7 @@ export function checkPlainText(languageCode, textType, textName, plainText, give } else // Closed something unexpectedly without an opener if (char !== '’' // Closing single quote is also used as apostrophe in English && (textType !== 'markdown' || char !== '>')) { // Markdown uses > for block indents so ignore these - const excerpt = (characterIndex > halfLength ? '…' : '') + line.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < line.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + line.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < line.length ? '…' : '') addNotice({ priority: 774, message: `Unexpected ${char} closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation }); // debugLog(` ERROR 774: closed with nothing open: ${char}`); } @@ -220,7 +223,7 @@ export function checkPlainText(languageCode, textType, textName, plainText, give if (openMarkers.length) { const [{ char, n, x }] = openMarkers.slice(-1); const line = lines[n - 1]; - const excerpt = (x > halfLength ? '…' : '') + line.substring(x - halfLength, x + halfLengthPlus).replace(/ /g, '␣') + (x + halfLengthPlus < line.length ? '…' : '') + const excerpt = (x > excerptHalfLength ? '…' : '') + line.substring(x - excerptHalfLength, x + excerptHalfLengthPlus).replace(/ /g, '␣') + (x + excerptHalfLengthPlus < line.length ? '…' : '') const details = openMarkers.length > 1 ? `${openMarkers.length} unclosed set${openMarkers.length === 1 ? '' : 's'}` : null; addNotice({ priority: 768, message: `At end of text with unclosed ${char} opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation }); } diff --git a/src/core/plain-text-check.md b/src/core/plain-text-check.md index e2c567ab6..27d843b1c 100644 --- a/src/core/plain-text-check.md +++ b/src/core/plain-text-check.md @@ -43,7 +43,7 @@ const chosenText = textSB; const chosenTextName = 'textSB'; const checkingOptions = {}; -const rawResults = checkPlainText('en', 'raw', chosenTextName, chosenText, 'that was supplied', checkingOptions); +const rawResults = checkPlainText('en', 'TN', 'raw', chosenTextName, chosenText, 'that was supplied', checkingOptions); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done plain text checks"]; diff --git a/src/core/questions-tsv5-row-check.js b/src/core/questions-tsv7-row-check.js similarity index 64% rename from src/core/questions-tsv5-row-check.js rename to src/core/questions-tsv7-row-check.js index 2ea8ac35f..017679fd0 100644 --- a/src/core/questions-tsv5-row-check.js +++ b/src/core/questions-tsv7-row-check.js @@ -1,17 +1,15 @@ import { DEFAULT_EXCERPT_LENGTH, isWhitespace, countOccurrences } from './text-handling-functions' import * as books from './books/books'; -// import { checkTextField } from './field-text-check'; +import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; -// import { checkSupportReferenceInTA } from './ta-reference-check'; -// import { checkNotesLinksToOutside } from './notes-links-check'; -// import { checkOriginalLanguageQuote } from './orig-quote-check'; +import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const QUESTIONS_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.1.1'; +// const QUESTIONS_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.2.0'; -const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 5; // so expects 4 tabs per line -const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse'; +const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 7; // so expects 6 tabs per line +const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuote\tOccurrence\tQuestion\tResponse'; const LC_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'; const LC_ALPHABET_PLUS_DIGITS = 'abcdefghijklmnopqrstuvwxyz0123456789'; @@ -33,7 +31,7 @@ const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz012345678 * @param {Object} checkingOptions - may contain excerptLength parameter * @return {Object} - containing noticeList */ -export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { +export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { /* This function is only for checking one data row and the function doesn’t assume that it has any previous context. @@ -48,23 +46,25 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo Returns an object containing the noticeList. */ - // functionLog(`checkQuestionsTSV5DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); - parameterAssert(languageCode !== undefined, "checkQuestionsTSV5DataRow: 'languageCode' parameter should be defined"); - parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV5DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(line !== undefined, "checkQuestionsTSV5DataRow: 'line' parameter should be defined"); - parameterAssert(typeof line === 'string', `checkQuestionsTSV5DataRow: 'line' parameter should be a string not a '${typeof line}'`); - parameterAssert(bookID !== undefined, "checkQuestionsTSV5DataRow: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkQuestionsTSV5DataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkQuestionsTSV5DataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkQuestionsTSV5DataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkQuestionsTSV5DataRow: '${bookID}' is not a valid USFM book identifier`); - // parameterAssert(givenC !== undefined, "checkQuestionsTSV5DataRow: 'givenC' parameter should be defined"); - if (givenC) parameterAssert(typeof givenC === 'string', `checkQuestionsTSV5DataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); - // parameterAssert(givenV !== undefined, "checkQuestionsTSV5DataRow: 'givenV' parameter should be defined"); - if (givenV) parameterAssert(typeof givenV === 'string', `checkQuestionsTSV5DataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); - parameterAssert(givenRowLocation !== undefined, "checkQuestionsTSV5DataRow: 'givenRowLocation' parameter should be defined"); - parameterAssert(typeof givenRowLocation === 'string', `checkQuestionsTSV5DataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); - parameterAssert(givenRowLocation.indexOf('true') === -1, "checkQuestionsTSV5DataRow: 'givenRowLocation' parameter should not be 'true'"); + // functionLog(`checkQuestionsTSV7DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkQuestionsTSV7DataRow: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV7DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode !== undefined, "checkQuestionsTSV7DataRow: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkQuestionsTSV7DataRow: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + parameterAssert(line !== undefined, "checkQuestionsTSV7DataRow: 'line' parameter should be defined"); + parameterAssert(typeof line === 'string', `checkQuestionsTSV7DataRow: 'line' parameter should be a string not a '${typeof line}'`); + parameterAssert(bookID !== undefined, "checkQuestionsTSV7DataRow: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkQuestionsTSV7DataRow: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkQuestionsTSV7DataRow: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkQuestionsTSV7DataRow: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkQuestionsTSV7DataRow: '${bookID}' is not a valid USFM book identifier`); + // parameterAssert(givenC !== undefined, "checkQuestionsTSV7DataRow: 'givenC' parameter should be defined"); + if (givenC) parameterAssert(typeof givenC === 'string', `checkQuestionsTSV7DataRow: 'givenC' parameter should be a string not a '${typeof givenC}'`); + // parameterAssert(givenV !== undefined, "checkQuestionsTSV7DataRow: 'givenV' parameter should be defined"); + if (givenV) parameterAssert(typeof givenV === 'string', `checkQuestionsTSV7DataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); + parameterAssert(givenRowLocation !== undefined, "checkQuestionsTSV7DataRow: 'givenRowLocation' parameter should be defined"); + parameterAssert(typeof givenRowLocation === 'string', `checkQuestionsTSV7DataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); + parameterAssert(givenRowLocation.indexOf('true') === -1, "checkQuestionsTSV7DataRow: 'givenRowLocation' parameter should not be 'true'"); let ourRowLocation = givenRowLocation; if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; @@ -85,22 +85,22 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo * @param {string} excerpt - short excerpt from the line centred on the problem (if available) * @param {string} location - description of where the issue is located */ - // functionLog(`checkQuestionsTSV5DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); - parameterAssert(noticeObject.priority !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'priority' parameter should be defined"); - parameterAssert(typeof noticeObject.priority === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); - parameterAssert(noticeObject.message !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'message' parameter should be defined"); - parameterAssert(typeof noticeObject.message === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); - // parameterAssert(lineNumber !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'lineNumber' parameter should be defined"); - // parameterAssert(typeof lineNumber === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); - // parameterAssert(characterIndex !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'characterIndex' parameter should be defined"); - if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkQuestionsTSV5DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); - // parameterAssert(excerpt !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'excerpt' parameter should be defined"); - if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); - parameterAssert(noticeObject.location !== undefined, "checkQuestionsTSV5DataRow addNoticePartial: 'location' parameter should be defined"); - parameterAssert(typeof noticeObject.location === 'string', `checkQuestionsTSV5DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + // functionLog(`checkQuestionsTSV7DataRow addNoticePartial(priority=${noticeObject.priority}) ${noticeObject.message}, ${noticeObject.characterIndex}, ${noticeObject.excerpt}, ${noticeObject.location}`); + parameterAssert(noticeObject.priority !== undefined, "checkQuestionsTSV7DataRow addNoticePartial: 'priority' parameter should be defined"); + parameterAssert(typeof noticeObject.priority === 'number', `checkQuestionsTSV7DataRow addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + parameterAssert(noticeObject.message !== undefined, "checkQuestionsTSV7DataRow addNoticePartial: 'message' parameter should be defined"); + parameterAssert(typeof noticeObject.message === 'string', `checkQuestionsTSV7DataRow addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // parameterAssert(lineNumber !== undefined, "checkQuestionsTSV7DataRow addNoticePartial: 'lineNumber' parameter should be defined"); + // parameterAssert(typeof lineNumber === 'number', `checkQuestionsTSV7DataRow addNoticePartial: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); + // parameterAssert(characterIndex !== undefined, "checkQuestionsTSV7DataRow addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) parameterAssert(typeof noticeObject.characterIndex === 'number', `checkQuestionsTSV7DataRow addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // parameterAssert(excerpt !== undefined, "checkQuestionsTSV7DataRow addNoticePartial: 'excerpt' parameter should be defined"); + if (noticeObject.excerpt) parameterAssert(typeof noticeObject.excerpt === 'string', `checkQuestionsTSV7DataRow addNoticePartial: 'excerpt' parameter should be a string not a '${typeof noticeObject.excerpt}': ${noticeObject.excerpt}`); + parameterAssert(noticeObject.location !== undefined, "checkQuestionsTSV7DataRow addNoticePartial: 'location' parameter should be defined"); + parameterAssert(typeof noticeObject.location === 'string', `checkQuestionsTSV7DataRow addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); // Also uses the given bookID,C,V, parameters from the main function call - // noticeObject.debugChain = noticeObject.debugChain ? `checkQuestionsTSV5DataRow ${noticeObject.debugChain}` : `checkQuestionsTSV5DataRow(${repoCode})`; + // noticeObject.debugChain = noticeObject.debugChain ? `checkQuestionsTSV7DataRow ${noticeObject.debugChain}` : `checkQuestionsTSV7DataRow(${repoCode})`; drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); } @@ -122,20 +122,20 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // We don’t currently use the allowedLinks parameter - // functionLog(`checkQuestionsTSV5DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Question' || fieldName === 'Response', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: Only run this check on Questions and Responses not '${fieldName}'`); - parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); - parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); - parameterAssert(rowLocation !== undefined, "checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); - parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - - const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); + // functionLog(`checkQuestionsTSV7DataRow ourMarkdownTextChecks(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Question' || fieldName === 'Response', `checkQuestionsTSV7DataRow ourMarkdownTextChecks: Only run this check on Questions and Responses not '${fieldName}'`); + parameterAssert(fieldText !== undefined, "checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV7DataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV7DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const omtcResultObject = await checkMarkdownText(languageCode, repoCode, fieldName, fieldText, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -155,110 +155,82 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo } // end of ourMarkdownTextChecks function - // function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { - // /** - // * @description - checks the given text field and processes the returned results - // * @param {string} rowID - 4-character row ID field - // * @param {string} fieldName - name of the field being checked - // * @param {string} fieldText - the actual text of the field being checked - // * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false - // * @param {string} rowLocation - description of where the line is located - // * @param {Object} checkingOptions - parameters that might affect the check - // */ - // // Does basic checks for small errors like leading/trailing spaces, etc. - - // // We assume that checking for compulsory fields is done elsewhere - - // // Updates the global list of notices - - // // functionLog(`checkQuestionsTSV5DataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); - // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'rowID' parameter should be defined"); - // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - // parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'fieldText' parameter should be defined"); - // parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - // parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV5DataRow ourCheckTextField: allowedLinks parameter must be either true or false"); - // parameterAssert(rowLocation !== undefined, "checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be defined"); - // parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); - // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - - // const fieldType = fieldName === 'Question' ? 'markdown' : 'raw'; - // const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); - - // // Choose only ONE of the following - // // This is the fast way of append the results from this field - // // result.noticeList = result.noticeList.concat(dbtcResultObject.noticeList); - // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // // process results line by line - // for (const noticeEntry of octfResultObject.noticeList) { - // // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); - // addNoticePartial({ ...noticeEntry, rowID, fieldName }); - // } - // return octfResultObject.suggestion; // There may or may not be one! - // } - // // end of ourCheckTextField function - - // async function ourCheckSupportReferenceInTA(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { - // // Checks that the TA reference can be found + function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions) { + /** + * @description - checks the given text field and processes the returned results + * @param {string} rowID - 4-character row ID field + * @param {string} fieldName - name of the field being checked + * @param {string} fieldText - the actual text of the field being checked + * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false + * @param {string} rowLocation - description of where the line is located + * @param {Object} checkingOptions - parameters that might affect the check + */ + // Does basic checks for small errors like leading/trailing spaces, etc. - // // Updates the global list of notices + // We assume that checking for compulsory fields is done elsewhere - // // functionLog(`checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be defined"); - // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be defined"); - // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckSupportReferenceInTA: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // Updates the global list of notices - // const coqResultObject = await checkSupportReferenceInTA(fieldName, taLinkText, rowLocation, { ...checkingOptions, taRepoLanguageCode: languageCode, expectFullLink: true }); + // functionLog(`checkQuestionsTSV7DataRow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkQuestionsTSV7DataRow ourCheckTextField: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkQuestionsTSV7DataRow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkQuestionsTSV7DataRow ourCheckTextField: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV7DataRow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkQuestionsTSV7DataRow ourCheckTextField: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV7DataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(allowedLinks === true || allowedLinks === false, "checkQuestionsTSV7DataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + parameterAssert(rowLocation !== undefined, "checkQuestionsTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + parameterAssert(typeof rowLocation === 'string', `checkQuestionsTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV7DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + + const fieldType = fieldName === 'Question' ? 'markdown' : 'raw'; + const octfResultObject = checkTextField(languageCode, repoCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); - // // Choose only ONE of the following - // // This is the fast way of append the results from this field - // // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); - // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // // process results line by line - // for (const noticeEntry of coqResultObject.noticeList) { - // // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckSupportReferenceInTA notice length=${Object.keys(noticeEntry).length}`); - // addNoticePartial({ ...noticeEntry, rowID, fieldName }); - // } - // } - // // end of ourCheckSupportReferenceInTA function + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(dbtcResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of octfResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + return octfResultObject.suggestion; // There may or may not be one! + } + // end of ourCheckTextField function - // async function ourCheckTNOriginalLanguageQuote(rowID, fieldName, fieldText, occurrence, rowLocation, checkingOptions) { - // // Checks that the Hebrew/Greek quote can be found in the original texts + async function ourCheckQOriginalLanguageQuote(rowID, fieldName, fieldText, occurrence, rowLocation, checkingOptions) { + // Checks that the Hebrew/Greek quote can be found in the original texts - // // Uses the bookID,C,V values from the main function call + // Uses the bookID,C,V values from the main function call - // // Updates the global list of notices + // Updates the global list of notices - // // functionLog(`checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); - // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be defined"); - // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - // parameterAssert(fieldText !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); - // parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - // parameterAssert(occurrence !== undefined, "checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be defined"); - // parameterAssert(typeof occurrence === 'string', `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); - // parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV5DataRow ourCheckTNOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); + // functionLog(`checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldText !== undefined, "checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'fieldText' parameter should be defined"); + parameterAssert(typeof fieldText === 'string', `checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); + parameterAssert(occurrence !== undefined, "checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'occurrence' parameter should be defined"); + parameterAssert(typeof occurrence === 'string', `checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'occurrence' parameter should be a string not a '${typeof occurrence}'`); + parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkQuestionsTSV7DataRow ourCheckQOriginalLanguageQuote: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - // const coqResultObject = await checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); + const coqResultObject = await checkOriginalLanguageQuote(languageCode, repoCode, fieldName, fieldText, occurrence, bookID, givenC, givenV, rowLocation, checkingOptions); - // // Choose only ONE of the following - // // This is the fast way of append the results from this field - // // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); - // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // // process results line by line - // for (const noticeEntry of coqResultObject.noticeList) { - // // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); - // addNoticePartial({ ...noticeEntry, rowID, fieldName }); - // } - // } - // // end of ourCheckTNOriginalLanguageQuote function + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const noticeEntry of coqResultObject.noticeList) { + // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourCheckQOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); + addNoticePartial({ ...noticeEntry, rowID, fieldName }); + } + } + // end of ourCheckQOriginalLanguageQuote function // async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { @@ -266,16 +238,16 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // // Updates the global list of notices - // // functionLog(`checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - // parameterAssert(rowID !== undefined, "checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); - // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - // parameterAssert(fieldName === 'Question', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'Question' not '${fieldName}'`); - // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); - // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV5DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // // functionLog(`checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(fieldName === 'Question', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'Question' not '${fieldName}'`); + // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - // const coqResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + // const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // // debugLog("coqResultObject", JSON.stringify(coqResultObject)); // // Choose only ONE of the following @@ -309,7 +281,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo // // end of ourcheckNotesLinksToOutside function - // Main code for checkQuestionsTSV5DataRow function + // Main code for checkQuestionsTSV7DataRow function if (line === EXPECTED_QUESTIONS_HEADING_LINE) // Assume it must be ok return drResult; // We can’t detect if it’s in the wrong place @@ -323,9 +295,9 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook; @@ -336,15 +308,15 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } catch (tlcNCerror) { - addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkQuestionsTSV5DataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); + addNoticePartial({ priority: 979, message: "Invalid book identifier passed to checkQuestionsTSV7DataRow", location: ` '${bookID}' in first parameter: ${tlcNCerror}` }); } } const haveGoodBookID = numChaptersThisBook !== undefined; let fields = line.split('\t'); - let RIDSuggestion, QSuggestion, RSuggestion; + let RIDSuggestion, OQSuggestion, OSuggestion, QuSuggestion, RSuggestion; if (fields.length === NUM_EXPECTED_QUESTIONS_TSV_FIELDS) { - const [reference, rowID, tags, question, response] = fields; + const [reference, rowID, tags, quote, occurrence, question, response] = fields; // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; @@ -433,6 +405,38 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo if (tags.length) ; + if (quote.length) { // need to check UTN against UHB and UGNT + OQSuggestion = ourCheckTextField(rowID, 'Quote', quote, false, ourRowLocation, checkingOptions); + if (occurrence.length) + await ourCheckQOriginalLanguageQuote(rowID, 'Quote', quote, occurrence, ourRowLocation, checkingOptions); + else + addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); + } + else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? + if (repoCode === 'TN2' && V !== 'intro' && occurrence !== '0') + addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); + + if (occurrence.length) { // This should usually be a digit + if (occurrence === '0') { // zero means that it doesn’t occur + if (quote.length) { + addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); + OSuggestion = '1'; + } + // if (V !== 'intro') + // addNoticePartial({priority:500, message:"Invalid zero occurrence field", rowID, location:rowLocation); + } + else if (occurrence === '-1') // TODO check the special conditions when this can occur??? + ; + else if ('1234567'.indexOf(occurrence) < 0) { // it’s not one of these integers + addNoticePartial({ priority: 792, message: `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); + OSuggestion = '1'; + } + } + else if (quote.length) { + addNoticePartial({ priority: 791, message: `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation }); + OSuggestion = '1'; + } + if (question.length) { if (question.indexOf('\u200B') >= 0) { const charCount = countOccurrences(question, '\u200B'); @@ -484,7 +488,7 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo addNoticePartial({ priority: 274, message: "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation }); // 7 [reference, rowID, tags, question, answer] - const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${QSuggestion === undefined ? question : QSuggestion}\t${RSuggestion === undefined ? response : RSuggestion}`; + const suggestion = `${reference}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${tags}\t${OQSuggestion === undefined ? quote : OQSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${QuSuggestion === undefined ? question : QuSuggestion}\t${RSuggestion === undefined ? response : RSuggestion}`; if (suggestion !== line) { // debugLog(`Had question ${line}`); // debugLog(`Sug question ${suggestion}`); @@ -498,8 +502,8 @@ export async function checkQuestionsTSV5DataRow(languageCode, repoCode, line, bo addNoticePartial({ priority: 984, message: `Found wrong number of TSV fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, details: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, rowID, location: ourRowLocation }); } - // debugLog(` checkQuestionsTSV5DataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); - // debugLog("checkQuestionsTSV5DataRow result is", JSON.stringify(drResult)); + // debugLog(` checkQuestionsTSV7DataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkQuestionsTSV7DataRow result is", JSON.stringify(drResult)); return drResult; // object with noticeList and possibly suggestion only } -// end of checkQuestionsTSV5DataRow function +// end of checkQuestionsTSV7DataRow function diff --git a/src/core/questions-tsv5-row-check.md b/src/core/questions-tsv7-row-check.md similarity index 99% rename from src/core/questions-tsv5-row-check.md rename to src/core/questions-tsv7-row-check.md index 3d584982d..f3e047483 100644 --- a/src/core/questions-tsv5-row-check.md +++ b/src/core/questions-tsv7-row-check.md @@ -11,12 +11,12 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkQuestionsTSV7DataRow } from './questions-tsv5-row-check'; +import { checkQuestionsTSV7DataRow } from './questions-tsv7-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples const lineE = ""; -const lineH = "Reference\tID\tTags\tQuestion\tResponse"; +const lineH = "Reference\tID\tTags\tQuote\tOccurrence\tQuestion\tResponse"; const lineN = "Peace on Earth, good will to all men/people!"; const lineG = "2:3\tw3r5\t\t1\t\tThis is an optional note"; const lineB1 = "2:3\tw3r5\t\t1\t\t<br>Boo"; diff --git a/src/core/questions-tsv5-table-check.js b/src/core/questions-tsv7-table-check.js similarity index 86% rename from src/core/questions-tsv5-table-check.js rename to src/core/questions-tsv7-table-check.js index 5c1515e56..81d484584 100644 --- a/src/core/questions-tsv5-table-check.js +++ b/src/core/questions-tsv7-table-check.js @@ -1,14 +1,14 @@ import * as books from './books/books'; import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' -import { checkQuestionsTSV5DataRow } from './questions-tsv5-row-check'; +import { checkQuestionsTSV7DataRow } from './questions-tsv7-row-check'; import { removeDisabledNotices } from './disabled-notices'; -import { functionLog, parameterAssert } from './utilities'; +import { parameterAssert } from './utilities'; -const QUESTIONS_TABLE_VALIDATOR_VERSION_STRING = '0.1.1'; +const QUESTIONS_TABLE_VALIDATOR_VERSION_STRING = '0.2.0'; -const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 5; // so expects 4 tabs per line -const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse'; +const NUM_EXPECTED_QUESTIONS_TSV_FIELDS = 7; // so expects 6 tabs per line +const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuote\tOccurrence\tQuestion\tResponse'; /** @@ -21,7 +21,7 @@ const EXPECTED_QUESTIONS_HEADING_LINE = 'Reference\tID\tTags\tQuestion\tResponse * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions) { +export async function checkQuestionsTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -30,17 +30,17 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi Returns a result object containing a successList and a noticeList */ - functionLog(`checkQuestionsTSV5Table(${languageCode}, ${repoCode}, ${bookID}, ${filename}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); - parameterAssert(languageCode !== undefined, "checkQuestionsTSV5Table: 'languageCode' parameter should be defined"); - parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV5Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(repoCode === 'TQ' || repoCode === 'SQ', `checkTWL_TSV6Table: repoCode expected 'TQ' or 'SQ' not '${repoCode}'`); - parameterAssert(bookID !== undefined, "checkQuestionsTSV5Table: 'bookID' parameter should be defined"); - parameterAssert(typeof bookID === 'string', `checkQuestionsTSV5Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkQuestionsTSV5Table: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkQuestionsTSV5Table: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkQuestionsTSV5Table: '${bookID}' is not a valid USFM book identifier`); - parameterAssert(givenLocation !== undefined, "checkQuestionsTSV5Table: 'givenLocation' parameter should be defined"); - parameterAssert(typeof givenLocation === 'string', `checkQuestionsTSV5Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); + // functionLog(`checkQuestionsTSV7Table(${languageCode}, ${repoCode}, ${bookID}, ${filename}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); + parameterAssert(languageCode !== undefined, "checkQuestionsTSV7Table: 'languageCode' parameter should be defined"); + parameterAssert(typeof languageCode === 'string', `checkQuestionsTSV7Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode === 'TQ'||repoCode === 'TQ2' || repoCode === 'SQ', `checkTWL_TSV6Table: repoCode expected 'TQ', 'TQ2', or 'SQ' not '${repoCode}'`); + parameterAssert(bookID !== undefined, "checkQuestionsTSV7Table: 'bookID' parameter should be defined"); + parameterAssert(typeof bookID === 'string', `checkQuestionsTSV7Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); + parameterAssert(bookID.length === 3, `checkQuestionsTSV7Table: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkQuestionsTSV7Table: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkQuestionsTSV7Table: '${bookID}' is not a valid USFM book identifier`); + parameterAssert(givenLocation !== undefined, "checkQuestionsTSV7Table: 'givenLocation' parameter should be defined"); + parameterAssert(typeof givenLocation === 'string', `checkQuestionsTSV7Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -48,11 +48,11 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi const carResult = { successList: [], noticeList: [] }; function addSuccessMessage(successString) { - // functionLog(`checkQuestionsTSV5Table success: ${successString}`); + // functionLog(`checkQuestionsTSV7Table success: ${successString}`); carResult.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkQuestionsTSV5Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); + // functionLog(`checkQuestionsTSV7Table notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex})` : ""}${excerpt ? ` ${excerpt}` : ""}${location}`); parameterAssert(noticeObject.priority !== undefined, "ATSV addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `TSV addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "ATSV addNoticePartial: 'message' parameter should be defined"); @@ -68,7 +68,7 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi parameterAssert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `TSV addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - if (noticeObject.debugChain) noticeObject.debugChain = `checkQuestionsTSV5Table ${noticeObject.debugChain}`; + if (noticeObject.debugChain) noticeObject.debugChain = `checkQuestionsTSV7Table ${noticeObject.debugChain}`; carResult.noticeList.push({ ...noticeObject, bookID, filename, repoCode }); } @@ -83,16 +83,16 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook = 0; if (bookID === 'OBS') numChaptersThisBook = 50; // There's 50 Open Bible Stories else { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkQuestionsTSV5Table"); + parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in checkQuestionsTSV7Table"); try { numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } @@ -109,23 +109,23 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi let rowIDList = [], uniqueRowList = []; let numVersesThisChapter = 0; for (let n = 0; n < lines.length; n++) { - // functionLog(`checkQuestionsTSV5Table checking line ${n}: ${JSON.stringify(lines[n])}`); + // functionLog(`checkQuestionsTSV7Table checking line ${n}: ${JSON.stringify(lines[n])}`); if (n === 0) { if (lines[0] === EXPECTED_QUESTIONS_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); else - addNoticePartial({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); + addNoticePartial({ priority: 988, message: "Bad TSV header", details: `expected '${EXPECTED_QUESTIONS_HEADING_LINE}'`, excerpt: lines[0], lineNumber: 1, location: ourLocation }); } else // not the header { let fields = lines[n].split('\t'); if (fields.length === NUM_EXPECTED_QUESTIONS_TSV_FIELDS) { // eslint-disable-next-line no-unused-vars - const [reference, rowID, tags, question, answer] = fields; + const [reference, rowID, tags, quote, occurrence, question, answer] = fields; const [C, V] = reference.split(':') // Use the row check to do most basic checks - const drResultObject = await checkQuestionsTSV5DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); + const drResultObject = await checkQuestionsTSV7DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); @@ -237,13 +237,13 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 983, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_QUESTIONS_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } if (!checkingOptions?.suppressNoticeDisablingFlag) { - // functionLog(`checkQuestionsTSV5Table: calling removeDisabledNotices(${carResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); + // functionLog(`checkQuestionsTSV7Table: calling removeDisabledNotices(${carResult.noticeList.length}) having ${JSON.stringify(checkingOptions)}`); carResult.noticeList = removeDisabledNotices(carResult.noticeList); } @@ -253,11 +253,11 @@ export async function checkQuestionsTSV5Table(languageCode, repoCode, bookID, fi addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); if (carResult.noticeList) - addSuccessMessage(`checkQuestionsTSV5Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkQuestionsTSV7Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); else - addSuccessMessage(`No errors or warnings found by checkQuestionsTSV5Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING}`) - // debugLog(` checkQuestionsTSV5Table returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); - // debugLog("checkQuestionsTSV5Table result is", JSON.stringify(carResult)); + addSuccessMessage(`No errors or warnings found by checkQuestionsTSV7Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING}`) + // debugLog(` checkQuestionsTSV7Table returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); + // debugLog("checkQuestionsTSV7Table result is", JSON.stringify(carResult)); return carResult; } -// end of checkQuestionsTSV5Table function +// end of checkQuestionsTSV7Table function diff --git a/src/core/questions-tsv5-table-check.md b/src/core/questions-tsv7-table-check.md similarity index 97% rename from src/core/questions-tsv5-table-check.md rename to src/core/questions-tsv7-table-check.md index 4b79caaf3..fae77af12 100644 --- a/src/core/questions-tsv5-table-check.md +++ b/src/core/questions-tsv7-table-check.md @@ -11,11 +11,11 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkQuestionsTSV5Table } from './questions-tsv5-table-check'; +import { checkQuestionsTSV7Table } from './questions-tsv7-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Text samples -const textA = `Reference\tID\tTags\tQuestion\tResponse +const textA = `Reference\tID\tTags\tQuote\tOccurrence\tQuestion\tResponse 2:3\tw3r5\t\t\t\t1\t<br>Boo 99:3\tw3r5\t\t\t\t1\tBad chapter number 2:boo\tw3r5\t\t\t\t1\tBad verse number @@ -25,7 +25,7 @@ const textA = `Reference\tID\tTags\tQuestion\tResponse 2:3\tw3r5\t\t\t\t17\tNote7 2:3\tw3r5\t\t\tBad ellipse...\t1\tNote8 2:3\tw3r5\t\t\t\t1\t<br>Boo hoo,, lost my shoe !`; -const textG = `Reference\tID\tTags\tQuestion\tResponse +const textG = `Reference\tID\tTags\tQuote\tOccurrence\tQuestion\tResponse front:intro\td9wn\t\t\t\t0\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; const lineA2 = "1:intro\tzb6f\t\t\t\t0\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist. 1:1\tf2mg\t\t\t0\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story. @@ -48,12 +48,12 @@ const data = { givenLocation : 'that was supplied', } -function CheckQuestionsTSV5Table(props) { +function CheckQuestionsTSV7Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkQuestionsTSV5Table is an ASYNC function + // We need the following construction because checkQuestionsTSV7Table is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -61,7 +61,7 @@ function CheckQuestionsTSV5Table(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {languageCode} {repoCode} for {tableTextName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkQuestionsTSV5Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); + const rawResults = await checkQuestionsTSV7Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> @@ -72,7 +72,7 @@ function CheckQuestionsTSV5Table(props) { }, []); // end of useEffect part return results; -} // end of CheckQuestionsTSV5Table function +} // end of CheckQuestionsTSV7Table function -<CheckQuestionsTSV5Table data={data}/> +<CheckQuestionsTSV7Table data={data}/> ``` diff --git a/src/core/ta-reference-check.js b/src/core/ta-reference-check.js index 871516661..36695ff6f 100644 --- a/src/core/ta-reference-check.js +++ b/src/core/ta-reference-check.js @@ -63,9 +63,9 @@ export async function checkSupportReferenceInTA(fieldName, fieldText, givenLocat } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, "cf. default="+DEFAULT_EXCERPT_LENGTH); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, "halfLengthPlus="+halfLengthPlus); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, "excerptHalfLengthPlus="+excerptHalfLengthPlus); */ let taRepoUsername; diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index 45c4326c8..e9bf03969 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -24,7 +24,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * * @description - Checks one TSV data row of translation notes (TN2) * @param {string} languageCode - the language code, e.g., 'en' - * @param {string} repoCode - TN2, TQ2, TWL, SN, or SQ -- allows more specific checks + * @param {string} repoCode - 'TN' * @param {string} line - the TSV line to be checked * @param {string} bookID - 3-character UPPERCASE USFM book identifier or 'OBS' * @param {string} givenC - chapter number or (for OBS) story number string @@ -44,8 +44,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // functionLog(`checkTN_TSV9DataRow(${languageCode}, ${repoCode}, ${line}, ${bookID}, ${givenRowLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkTN_TSV9DataRow: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkTN_TSV9DataRow: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); - parameterAssert(repoCode !== undefined, "checkTN_TSV9DataRow: 'repoCode' parameter should be defined"); - parameterAssert(typeof repoCode === 'string', `checkTN_TSV9DataRow: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + parameterAssert(repoCode === 'TN', `checkTN_TSV9DataRow: repoCode expected 'TN' not '${repoCode}'`); parameterAssert(line !== undefined, "checkTN_TSV9DataRow: 'line' parameter should be defined"); parameterAssert(typeof line === 'string', `checkTN_TSV9DataRow: 'line' parameter should be a string not a '${typeof line}'`); parameterAssert(bookID !== undefined, "checkTN_TSV9DataRow: 'bookID' parameter should be defined"); @@ -128,7 +127,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, parameterAssert(typeof rowLocation === 'string', `checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const omtcResultObject = await checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, checkingOptions); + const omtcResultObject = await checkMarkdownText(languageCode, repoCode, fieldName, fieldText, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -138,7 +137,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, for (const noticeEntry of omtcResultObject.noticeList) { // parameterAssert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); // NOTE: Ellipses in OccurrenceNote have the normal meaning - // not like the specialised meaning in the snippet fields OrigQuote and GLQuote + // not like the specialised meaning in the snippet fields Quote and GLQuote if (noticeEntry.priority !== 178 && noticeEntry.priority !== 179 // unexpected space after ellipse, ellipse after space && !noticeEntry.message.startsWith("Unexpected … character after space") // 191 ) @@ -177,7 +176,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSV9DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'OccurrenceNote' ? 'markdown' : 'raw'; - const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + const octfResultObject = checkTextField(languageCode, repoCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -298,7 +297,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coqResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); // Choose only ONE of the following @@ -346,9 +345,9 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook; @@ -363,7 +362,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, let fields = line.split('\t'); let RIDSuggestion, SRSuggestion, GLQSuggestion, OQSuggestion, OSuggestion, ONSuggestion; if (fields.length === NUM_EXPECTED_TN_TSV_FIELDS) { - const [B, C, V, rowID, supportReference, origQuote, occurrence, GLQuote, occurrenceNote] = fields; + const [B, C, V, rowID, supportReference, quote, occurrence, GLQuote, occurrenceNote] = fields; // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; @@ -476,20 +475,20 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // else if (/^\d+$/.test(C) && /^\d+$/.test(V)) // C:V are both digits // addNoticePartial({ priority: 877, message: "Missing SupportReference field", fieldName: 'SupportReference', rowID, location: ourRowLocation }); - if (origQuote.length) { // need to check UTN against UHB and UGNT - OQSuggestion = ourCheckTextField(rowID, 'OrigQuote', origQuote, false, ourRowLocation, checkingOptions); + if (quote.length) { // need to check UTN against UHB and UGNT + OQSuggestion = ourCheckTextField(rowID, 'Quote', quote, false, ourRowLocation, checkingOptions); if (occurrence.length) - await ourCheckTNOriginalLanguageQuote(rowID, 'OrigQuote', origQuote, occurrence, ourRowLocation, checkingOptions); + await ourCheckTNOriginalLanguageQuote(rowID, 'Quote', quote, occurrence, ourRowLocation, checkingOptions); else addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); } else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (V !== 'intro' && occurrence !== '0') - addNoticePartial({ priority: 919, message: "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn’t occur - if (origQuote.length) { + if (quote.length) { addNoticePartial({ priority: 751, message: "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation }); OSuggestion = '1'; } @@ -503,7 +502,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, OSuggestion = '1'; } } - else if (origQuote.length) { + else if (quote.length) { addNoticePartial({ priority: 791, message: `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation }); OSuggestion = '1'; } @@ -546,8 +545,8 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? addNoticePartial({ priority: 274, message: "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation }); - // 9 [B, C, V, rowID, supportReference, origQuote, occurrence, GLQuote, occurrenceNote] - const suggestion = `${B}\t${C}\t${V}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${SRSuggestion === undefined ? supportReference : SRSuggestion}\t${OQSuggestion === undefined ? origQuote : OQSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${GLQSuggestion === undefined ? GLQuote : GLQSuggestion}\t${ONSuggestion === undefined ? occurrenceNote : ONSuggestion}`; + // 9 [B, C, V, rowID, supportReference, quote, occurrence, GLQuote, occurrenceNote] + const suggestion = `${B}\t${C}\t${V}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${SRSuggestion === undefined ? supportReference : SRSuggestion}\t${OQSuggestion === undefined ? quote : OQSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${GLQSuggestion === undefined ? GLQuote : GLQSuggestion}\t${ONSuggestion === undefined ? occurrenceNote : ONSuggestion}`; if (suggestion !== line) { // debugLog(`Had TN2 ${line}`); // debugLog(`Sug TN2 ${suggestion}`); diff --git a/src/core/tn-tsv9-row-check.md b/src/core/tn-tsv9-row-check.md index e20e14158..ad9c0db08 100644 --- a/src/core/tn-tsv9-row-check.md +++ b/src/core/tn-tsv9-row-check.md @@ -16,7 +16,7 @@ import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples const lineE = ""; -const lineH = "Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote"; +const lineH = "Book\tChapter\tVerse\tID\tSupportReference\tQuote\tOccurrence\tGLQuote\tOccurrenceNote"; const lineN = "Peace on Earth, good will to all men/people!"; const lineG = "GEN\t2\t3\tw3r5\t\t1\t\tThis is an optional note"; const lineB1 = "EXO\t2\t3\tw3r5\t\t1\t\t<br>Boo"; diff --git a/src/core/tn-tsv9-table-check.js b/src/core/tn-tsv9-table-check.js index 76fa909c8..c043b9039 100644 --- a/src/core/tn-tsv9-table-check.js +++ b/src/core/tn-tsv9-table-check.js @@ -14,16 +14,15 @@ const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOr /** * * @param {string} languageCode + * @param {string} repoCode - 'TN' -- keeps parameter set consistent with other similar functions * @param {string} bookID * @param {string} filename * @param {string} tableText * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkTN_TSV9Table(languageCode, bookID, filename, tableText, givenLocation, checkingOptions) { +export async function checkTN_TSV9Table(languageCode, repoCode, bookID, filename, tableText, givenLocation, checkingOptions) { /* - repoCode is not passed through here, as can only be 'TN' - This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -35,6 +34,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex // functionLog(`checkTN_TSV9Table(${languageCode}, ${bookID}, ${filename}, ${tableText.length}, ${givenLocation},${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkTN_TSV9Table: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkTN_TSV9Table: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + parameterAssert(repoCode === 'TN', `checkTN_TSV9Table: repoCode expected 'TN' not '${repoCode}'`); parameterAssert(bookID !== undefined, "checkTN_TSV9Table: 'bookID' parameter should be defined"); parameterAssert(typeof bookID === 'string', `checkTN_TSV9Table: 'bookID' parameter should be a string not a '${typeof bookID}'`); parameterAssert(bookID.length === 3, `checkTN_TSV9Table: 'bookID' parameter should be three characters long not ${bookID.length}`); @@ -44,8 +44,6 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex parameterAssert(typeof givenLocation === 'string', `checkTN_TSV9Table: 'givenLocation' parameter should be a string not a '${typeof givenLocation}'`); parameterAssert(checkingOptions !== undefined, "checkTN_TSV9Table: 'checkingOptions' parameter should be defined"); - const repoCode = 'TN'; - let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -97,9 +95,9 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook = 0; @@ -124,14 +122,14 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex if (lines[0] === EXPECTED_TN_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); else - addNoticePartial({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); + addNoticePartial({ priority: 988, message: "Bad TSV header", details: `expected '${EXPECTED_TN_HEADING_LINE}'`, excerpt: lines[0], lineNumber: 1, location: ourLocation }); } else // not the header { let fields = lines[n].split('\t'); if (fields.length === NUM_EXPECTED_TN_TSV_FIELDS) { // eslint-disable-next-line no-unused-vars - const [B, C, V, rowID, supportReference, origQuote, occurrence, _GLQuote, _occurrenceNote] = fields; + const [B, C, V, rowID, supportReference, quote, occurrence, _GLQuote, _occurrenceNote] = fields; // Use the row check to do most basic checks const drResultObject = await checkTN_TSV9DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); @@ -170,7 +168,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex // TODO: Check if we need this at all (even though tC 3.0 can’t display these "duplicate" notes) // Check for duplicate notes - const uniqueID = C + V + supportReference + origQuote + occurrence; // This combination should not be repeated + const uniqueID = C + V + supportReference + quote + occurrence; // This combination should not be repeated // if (uniqueRowList.includes(uniqueID)) // addNoticePartial({ priority: 880, C, V, message: `Duplicate note`, rowID, lineNumber: n + 1, location: ourLocation }); // if (uniqueRowList.includes(uniqueID)) @@ -250,7 +248,7 @@ export async function checkTN_TSV9Table(languageCode, bookID, filename, tableTex try { C = fields[1]; } catch { } try { V = fields[2]; } catch { } try { rowID = fields[3]; } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 983, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/tn-tsv9-table-check.md b/src/core/tn-tsv9-table-check.md index 4d496ce25..0c08c2a55 100644 --- a/src/core/tn-tsv9-table-check.md +++ b/src/core/tn-tsv9-table-check.md @@ -15,7 +15,7 @@ import { checkTN_TSV9Table } from './tn-tsv9-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Text samples -const textA = `Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote +const textA = `Book\tChapter\tVerse\tID\tSupportReference\tQuote\tOccurrence\tGLQuote\tOccurrenceNote EXO\t2\t3\tw3r5\t\t\t1\t\t<br>Boo GEN\t99\t3\tw3r5\t\\tt1\t\tBoo GEN\t2\tboo\tw3r5\t\\tt1\t\tNote3 @@ -25,7 +25,7 @@ GEN\t2\t3\tw3r5\t\tCan’t remember\t\t1\t\tNote6 GEN\t2\t3\tw3r5\t\t\t17\t\tNote7 GEN\t2\t3\tw3r5\t\t\t1\tBad ellipse...\tNote8 GEN\t2\t3\tw3r5\t\t\t1\t\t<br>Boo hoo,, lost my shoe !`; -const textG = `Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote +const textG = `Book\tChapter\tVerse\tID\tSupportReference\tQuote\tOccurrence\tGLQuote\tOccurrenceNote GEN\tfront\tintro\td9wn\t\t\t0\t\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; const lineA2 = "GEN\t1\tintro\tzb6f\t\t\t0\t\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist. GEN\t1\t1\tf2mg\t\t0\t\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story. @@ -60,7 +60,7 @@ function checkTN_TSV9Table(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {tableTextName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkTN_TSV9Table(languageCode, bookID, filename, tableText, givenLocation, checkingOptions); + const rawResults = await checkTN_TSV9Table(languageCode, 'TN', bookID, filename, tableText, givenLocation, checkingOptions); setResults( <div> <b>Check</b> {tableTextName}: "{tableText.substr(0,256)}…"<br/><br/> diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index fe888196f..541afdb54 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -131,7 +131,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, parameterAssert(rowLocation.indexOf(fieldName) < 0, `checkTWL_TSV6DataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = 'raw'; - const octfResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); + const octfResultObject = checkTextField(languageCode, repoCode, fieldType, fieldName, fieldText, allowedLinks, rowLocation, checkingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -194,7 +194,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - const coTNlResultObject = await checkNotesLinksToOutside(repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); // Choose only ONE of the following @@ -242,9 +242,9 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook; @@ -397,10 +397,10 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, else { // it starts correctly const bits = TWLink.substring('rc://*/tw/dict/bible/'.length).split('/'); // debugLog(`checkTWL_TSV6DataRow checking ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); - if (bits[0] !== 'kt' && bits[0] !== 'name' && bits[0] !== 'other') { + if (bits[0] !== 'kt' && bits[0] !== 'names' && bits[0] !== 'other') { const characterIndex = 'rc://*/tw/dict/bible/'.length; - const excerpt = (characterIndex > halfLength ? '…' : '') + TWLink.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < TWLink.length ? '…' : '') - addNoticePartial({ priority: 797, message: "Field doesn't contain proper TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + TWLink.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < TWLink.length ? '…' : '') + addNoticePartial({ priority: 797, message: "Field doesn't contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); } else { // all good so far // debugLog(`checkTWL_TSV6DataRow looking up ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); await ourcheckNotesLinksToOutside(rowID, 'TWLink', TWLink, ourRowLocation, linkCheckingOptions); diff --git a/src/core/twl-tsv6-table-check.js b/src/core/twl-tsv6-table-check.js index 4cd486349..9d2a6e77c 100644 --- a/src/core/twl-tsv6-table-check.js +++ b/src/core/twl-tsv6-table-check.js @@ -83,9 +83,9 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); let lowercaseBookID = bookID.toLowerCase(); let numChaptersThisBook = 0; @@ -114,7 +114,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam if (lines[0] === EXPECTED_TWL_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); else - addNoticePartial({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); + addNoticePartial({ priority: 988, message: "Bad TSV header", details: `expected '${EXPECTED_TWL_HEADING_LINE}'`, excerpt: lines[0], lineNumber: 1, location: ourLocation }); } else // not the header { @@ -238,7 +238,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam try { reference = fields[0]; } catch { } try { rowID = fields[1]; } catch { } try { [C, V] = reference.split(':'); } catch { } - addNoticePartial({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TWL_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); + addNoticePartial({ priority: 983, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TWL_TSV_FIELDS})`, excerpt: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, C, V, rowID, lineNumber: n + 1, location: ourLocation }); } } } diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 5238b4a4a..627597b6c 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -129,7 +129,7 @@ const ATTRIBUTE_REGEX = new RegExp('[ |]([^ |]+?)="([^"]*?)"', 'g'); /** * * @param {string} languageCode - * @param {string} repoCode + * @param {string} repoCode -- e.g., 'UHB', 'UGNT', 'LT' or 'ST' * @param {string} bookID * @param {string} filename * @param {string} givenText @@ -174,9 +174,9 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } // else // debugLog(`Using supplied excerptLength=${excerptLength} cf. default=${DEFAULT_EXCERPT_LENGTH}`); - const halfLength = Math.floor(excerptLength / 2); // rounded down - const halfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + const excerptHalfLengthPlus = Math.floor((excerptLength + 1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const lowercaseBookID = bookID.toLowerCase(); @@ -519,7 +519,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex parameterAssert(fieldLocation !== undefined, "cUSFM ourCheckTextField: 'fieldLocation' parameter should be defined"); parameterAssert(typeof fieldLocation === 'string', `cUSFM ourCheckTextField: 'fieldLocation' parameter should be a string not a '${typeof fieldLocation}'`); - const dbtcResultObject = checkTextField(languageCode, fieldType, fieldName, fieldText, allowedLinks, fieldLocation, checkingOptions); + const dbtcResultObject = checkTextField(languageCode, repoCode, fieldType, fieldName, fieldText, allowedLinks, fieldLocation, checkingOptions); // Process noticeList line by line to filter out potential false positives // for this particular kind of text field @@ -545,7 +545,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex parameterAssert(typeof fileText === 'string', `cUSFM ourBasicFileChecks: 'fileText' parameter should be a string not a '${typeof fileText}'`); parameterAssert(checkingOptions !== undefined, "cUSFM ourBasicFileChecks: 'checkingOptions' parameter should be defined"); - const resultObject = checkTextfileContents(languageCode, 'USFM', filename, fileText, fileLocation, checkingOptions); + const resultObject = checkTextfileContents(languageCode, repoCode, 'USFM', filename, fileText, fileLocation, checkingOptions); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line @@ -656,7 +656,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const ixWordEnd = adjustedRest.indexOf('|'); if (ixWordEnd < 0 && adjustedRest.indexOf('lemma="') >= 0) { const characterIndex = 5; // Presumably, a little bit into the word - const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + adjustedRest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < adjustedRest.length ? '…' : '') addNoticePartial({ priority: 912, message: 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); } parameterAssert(ixWordEnd >= 1, `Why1 is w| = ${ixWordEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); @@ -712,7 +712,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const ixWordEnd = adjustedRest.indexOf('|'); if (ixWordEnd < 0 && adjustedRest.indexOf('lemma="') >= 0) { const characterIndex = nextWIndex + 5; // Presumably, a little bit into the word - const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + adjustedRest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < adjustedRest.length ? '…' : '') addNoticePartial({ priority: 911, message: 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); adjustedRest = ''; // Avoid follow-on errors break; @@ -746,12 +746,12 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (adjustedRest) { let characterIndex; if ((characterIndex = adjustedRest.indexOf('"')) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + adjustedRest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < adjustedRest.length ? '…' : '') addNoticePartial({ priority: 776, message: 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation }); // debugLog(`ERROR 776: in ${marker} '${adjustedRest}' from '${rest}'`); } if ((characterIndex = adjustedRest.indexOf("'")) >= 0) { - const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + adjustedRest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < adjustedRest.length ? '…' : '') addNoticePartial({ priority: 775, message: "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation }); // debugLog(`ERROR 775: in ${marker} '${adjustedRest}' from '${rest}'`); } @@ -759,7 +759,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // functionLog(`checkUSFMLineText ${languageCode} ${filename} ${lineNumber} ${C}:${V} somehow ended up with ${marker}='${adjustedRest}'`); characterIndex = adjustedRest.indexOf('\\'); if (characterIndex === -1) characterIndex = adjustedRest.indexOf('|'); - const excerpt = (characterIndex > halfLength ? '…' : '') + adjustedRest.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < adjustedRest.length ? '…' : '') + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + adjustedRest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < adjustedRest.length ? '…' : '') addNoticePartial({ priority: 875, message: "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation }); } if (adjustedRest !== rest) // Only re-check if line has changed (because original is checked in checkUSFMLineInternals()) @@ -1015,8 +1015,8 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } let characterIndex; if ((characterIndex = line.indexOf('\r')) >= 0) { - const iy = characterIndex + halfLength; // Want excerpt to focus more on what follows - const excerpt = (iy > halfLength ? '…' : '') + line.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < line.length ? '…' : '') + const iy = characterIndex + excerptHalfLength; // Want excerpt to focus more on what follows + const excerpt = (iy > excerptHalfLength ? '…' : '') + line.substring(iy - excerptHalfLength, iy + excerptHalfLengthPlus).replace(/ /g, '␣') + (iy + excerptHalfLengthPlus < line.length ? '…' : '') addNoticePartial({ priority: 703, C, V, message: "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation }); } @@ -1053,11 +1053,11 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex try { intC = ourParseInt(C); } catch (usfmICerror) { - addNoticePartial({ priority: 724, C, V, message: "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 724, C, V, message: "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, excerptHalfLength)}${rest.length > excerptHalfLength ? '…' : ''}`, location: ourLocation }); intC = -999; // Used to prevent consequential errors } if (C === lastC || (intC > 0 && intC !== lastIntC + 1)) - addNoticePartial({ priority: 764, C, V, message: "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''} (${lastC ? lastC : '0'} → ${C})`, location: ourLocation }); + addNoticePartial({ priority: 764, C, V, message: "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, excerptHalfLength)}${rest.length > excerptHalfLength ? '…' : ''} (${lastC ? lastC : '0'} → ${C})`, location: ourLocation }); lastC = C; lastV = '0'; lastIntC = intC; lastIntV = 0; } else if (marker === 'v') { @@ -1066,11 +1066,11 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex try { intV = ourParseInt(V); } catch (usfmIVerror) { - addNoticePartial({ priority: 723, C, V, message: "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 723, C, V, message: "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, excerptHalfLength)}${rest.length > excerptHalfLength ? '…' : ''}`, location: ourLocation }); intV = -999; // Used to prevent consequential errors } if (V === lastV || (intV > 0 && intV !== lastIntV + 1)) - addNoticePartial({ priority: 763, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); + addNoticePartial({ priority: 763, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${rest.substring(0, excerptHalfLength)}${rest.length > excerptHalfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); lastV = V; lastIntV = intV; } else { // handle verse bridge const bits = V.split('-'); @@ -1097,11 +1097,11 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex intV = parseInt(restRest); // debugLog("Got", intV); } catch (usfmIIVerror) { - addNoticePartial({ priority: 720, C, V, message: "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `${restRest.substring(0, halfLength)}${restRest.length > halfLength ? '…' : ''}`, location: ourLocation }); + addNoticePartial({ priority: 720, C, V, message: "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `${restRest.substring(0, excerptHalfLength)}${restRest.length > excerptHalfLength ? '…' : ''}`, location: ourLocation }); intV = -999; // Used to prevent consequential errors } if (intV > 0 && intV !== lastIntV + 1) - addNoticePartial({ priority: 761, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${restRest.substring(0, halfLength)}${restRest.length > halfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); + addNoticePartial({ priority: 761, C, V, message: "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `${restRest.substring(0, excerptHalfLength)}${restRest.length > excerptHalfLength ? '…' : ''} (${lastV ? lastV : '0'} → ${V})`, location: ourLocation }); lastV = intV.toString(); lastIntV = intV; } diff --git a/src/core/yaml-text-check.js b/src/core/yaml-text-check.js index 32354f80f..9ec5f4745 100644 --- a/src/core/yaml-text-check.js +++ b/src/core/yaml-text-check.js @@ -9,7 +9,16 @@ import { parameterAssert } from './utilities'; const YAML_VALIDATOR_VERSION_STRING = '0.4.3'; -export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, checkingOptions) { +/** + * + * @param {string} languageCode + * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. + * @param {string} textName + * @param {string} YAMLText + * @param {string} givenLocation + * @param {Object} checkingOptions + */ +export function checkYAMLText(languageCode, repoCode, textName, YAMLText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire file, i.e., all lines. Returns a result object containing a successList and a noticeList, @@ -19,6 +28,8 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c // functionLog(`checkYAMLText(${textName}, ${YAMLText.length}, ${givenLocation})…`); parameterAssert(languageCode !== undefined, "checkYAMLText: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkYAMLText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + parameterAssert(repoCode !== undefined, "checkYAMLText: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `checkYAMLText: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); parameterAssert(textName !== undefined, "checkYAMLText: 'textName' parameter should be defined"); parameterAssert(typeof textName === 'string', `checkYAMLText: 'textName' parameter should be a string not a '${typeof textName}': ${textName}`); parameterAssert(YAMLText !== undefined, "checkYAMLText: 'YAMLText' parameter should be defined"); @@ -44,9 +55,9 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c } // else // debugLog(`Using supplied excerptLength=${excerptLength}`, `cf. default=${DEFAULT_EXCERPT_LENGTH}`); - // const halfLength = Math.floor(excerptLength / 2); // rounded down - // const halfLengthPlus = Math.floor((excerptLength+1) / 2); // rounded up - // debugLog(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); + // const excerptHalfLength = Math.floor(excerptLength / 2); // rounded down + // const excerptHalfLengthPlus = Math.floor((excerptLength+1) / 2); // rounded up + // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const cytResult = { successList: [], noticeList: [] }; @@ -91,7 +102,7 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c parameterAssert(optionalFieldLocation !== undefined, "cYt ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cYt ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const resultObject = checkTextField(languageCode, 'YAML', '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); + const resultObject = checkTextField(languageCode, repoCode, 'YAML', '', fieldText, allowedLinks, optionalFieldLocation, checkingOptions); // Concat is faster if we don’t need to process each notice individually // cytResult.noticeList = cytResult.noticeList.concat(resultObject.noticeList); @@ -138,7 +149,7 @@ export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, c parameterAssert(typeof fileText === 'string', `cYT ourBasicFileChecks: 'fileText' parameter should be a string not a '${typeof fileText}'`); parameterAssert(checkingOptions !== undefined, "cYT ourBasicFileChecks: 'checkingOptions' parameter should be defined"); - const resultObject = checkTextfileContents(languageCode, 'YAML', filename, fileText, fileLocation, checkingOptions); + const resultObject = checkTextfileContents(languageCode, repoCode, 'YAML', filename, fileText, fileLocation, checkingOptions); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index b28f9c68b..7cc94b4a1 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -1,6 +1,6 @@ import React from 'react'; import { forwardRef } from 'react'; -import { parameterAssert, userLog } from '../core/utilities'; +import { parameterAssert, userLog, debugLog } from '../core/utilities'; // NOTE: The following line is currently giving compile warnings -- a problem in a dependency it seems import MaterialTable from 'material-table'; @@ -21,23 +21,23 @@ import Search from '@material-ui/icons/Search'; import ViewColumn from '@material-ui/icons/ViewColumn'; const tableIcons = { - Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />), - Check: forwardRef((props, ref) => <Check {...props} ref={ref} />), - Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />), - Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />), - DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />), - Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />), - Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />), - Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />), - FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />), - LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />), - NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />), - PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />), - ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />), - Search: forwardRef((props, ref) => <Search {...props} ref={ref} />), - SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />), - ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />), - ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />) + Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />), + Check: forwardRef((props, ref) => <Check {...props} ref={ref} />), + Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />), + Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />), + DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />), + Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />), + Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />), + Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />), + FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />), + LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />), + NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />), + PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />), + ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />), + Search: forwardRef((props, ref) => <Search {...props} ref={ref} />), + SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />), + ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />), + ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />) }; @@ -252,34 +252,39 @@ function RenderBCV({ bookID, C, V }) { * @param {string} fieldName - (optional) name of field * @return {String} - rendered HTML for the given reference */ -function RenderFileDetails({ username, repoName, filename, lineNumber, rowID, fieldName }) { +function RenderFileDetails({ username, repoName, branch, filename, lineNumber, rowID, fieldName }) { // These are all optional parameters - they may be undefined or blank if irrelevant - // debugLog(`RenderFileDetails(${repoName}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); + debugLog(`RenderFileDetails(${repoName}, ${branch}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); if (!repoName && !filename && !lineNumber && !rowID && !fieldName) return null; // They're all undefined or blank! + if (!branch) branch = repoName.endsWith('2')? 'newFormat':'master'; // default but with TEMP code for newFormat // debugLog(`RenderFileDetails2 ${repoName}, ${filename}, ${lineNumber}`); - let resultStart = '', lineResult = '', resultEnd = '', fileLink = ''; + let resultStart = '', lineResult = '', resultEnd = '', fileLineLink = '', fileLink = ''; if (repoName && repoName.length) resultStart += ` in ${repoName} repository`; - if (filename && filename.length) resultStart += ` in file ${filename}`; - if (lineNumber) { - resultStart += ' on '; - if (username && repoName && filename && lineNumber) { - try { - if (filename.endsWith('.tsv') || filename.endsWith('.md')) { // use blame so we can see the line! - const folder = repoName.endsWith('_obs') && filename !== 'README.md' && filename !== 'LICENSE.md' ? 'content/' : ''; - fileLink = `https://git.door43.org/${username}/${repoName}/blame/branch/master/${folder}${filename}#L${lineNumber}`; - } else fileLink = `https://git.door43.org/${username}/${repoName}/src/branch/master/${filename}#L${lineNumber}`; - } catch { } + if (username && repoName && filename) { + if (filename && filename.length) resultStart += ` in file ${filename}`; + try { + if (filename.endsWith('.tsv') || filename.endsWith('.md')) { // use blame so we can see the actual line! + const folder = repoName.endsWith('_obs') && filename !== 'README.md' && filename !== 'LICENSE.md' ? 'content/' : ''; + fileLink = `https://git.door43.org/${username}/${repoName}/blame/branch/${branch}/${folder}${filename}`; + } else fileLink = `https://git.door43.org/${username}/${repoName}/src/branch/${branch}/${filename}`; + } catch { } + if (lineNumber) { + resultStart += ' on '; + if (fileLink && lineNumber) + fileLineLink = `${fileLink}#L${lineNumber}`; + lineResult = `line ${lineNumber.toLocaleString()}`; } - // else if (!username) resultEnd += " no username"; - // else if (!repoName) resultEnd += " no repoName"; - // else if (!filename) resultEnd += " no filename"; - lineResult = `line ${lineNumber.toLocaleString()}`; + // else resultEnd += " no lineNumber"; } - // else resultEnd += " no lineNumber"; + // else if (!username) resultEnd += " no username"; + // else if (!repoName) resultEnd += " no repoName"; + // else if (!filename) resultEnd += " no filename"; if (rowID && rowID.length) resultEnd += ` with row ID ${rowID}`; if (fieldName && fieldName.length) resultEnd += ` in ${fieldName} field`; - if (fileLink) return <>{resultStart}<a rel="noopener noreferrer" target="_blank" href={fileLink}>{lineResult}</a>{resultEnd}</>; + + if (fileLineLink) return <>{resultStart}<a rel="noopener noreferrer" target="_blank" href={fileLineLink}>{lineResult}</a>{resultEnd}</>; + else if (fileLink) return <>{resultStart} in file <a rel="noopener noreferrer" target="_blank" href={fileLink}>{filename}</a>{resultEnd}</>; else return <>{resultStart}<b>{lineResult}</b>{resultEnd}</>; } @@ -340,7 +345,7 @@ function RenderProcessedArray({ arrayType, results }) { return <li key={index}> <RenderMessage color={arrayType === 'e' ? 'red' : 'orange'} message={listEntry.message} details={listEntry.details} /> <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> - <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> + <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} branch={listEntry.branch} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex > 0 ? " (at character " + (listEntry.characterIndex + 1) + ")" : ""} <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> {listEntry.location} @@ -368,7 +373,7 @@ function RenderGivenArray({ array, color }) { return <li key={index}> <RenderMessage color={color} message={listEntry.message} details={listEntry.details} /> <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> - <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> + <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} branch={listEntry.branch} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> {listEntry.location} @@ -406,7 +411,7 @@ function RenderWarningsGradient({ results }) { return <li key={index}> <RenderMessage color={thiscolor} message={listEntry.message} details={listEntry.details} /> <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> - <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> + <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} branch={listEntry.branch} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> {listEntry.location} diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 799229d25..12215fd2a 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -8,7 +8,7 @@ import { checkBookPackage } from './checkBookPackage'; import { userLog, debugLog, parameterAssert } from '../../core/utilities'; -// const BP_VALIDATOR_VERSION_STRING = '0.3.8'; +// const BP_VALIDATOR_VERSION_STRING = '0.4.0'; function BookPackageCheck(/*username, languageCode, bookID,*/ props) { @@ -82,22 +82,31 @@ function BookPackageCheck(/*username, languageCode, bookID,*/ props) { else await clearCheckedArticleCache(); // Load whole repos, especially if we are going to check files in manifests - let repoPreloadList = ['LT', 'ST', 'TN', 'TA', 'TW', 'TQ']; // for DEFAULT - if (dataSet === 'OLD') - repoPreloadList = ['LT', 'ST', 'TN', 'TA', 'TW', 'TQ']; - else if (dataSet === 'NEW') - repoPreloadList = ['LT', 'ST', 'TN2', 'TWL', 'TA', 'TW', 'TQ2']; - else if (dataSet === 'BOTH') - repoPreloadList = ['LT', 'ST', 'TN', 'TN2', 'TWL', 'TA', 'TW', 'TQ', 'TQ2']; - if (bookID !== 'OBS') { + let repoPreloadList; + if (bookID === 'OBS') { + repoPreloadList = ['OBS', 'TN', 'TA', 'TW', 'TQ', 'SN', 'SQ']; // for DEFAULT + if (dataSet === 'OLD') + repoPreloadList = ['OBS', 'TN', 'TA', 'TW', 'TQ', 'SN', 'SQ']; + else if (dataSet === 'NEW') + repoPreloadList = ['OBS', 'TN2', 'TWL', 'TA', 'TW', 'TQ2', 'SN', 'SQ']; + else if (dataSet === 'BOTH') + repoPreloadList = ['OBS', 'TN', 'TN2', 'TWL', 'TA', 'TW', 'TQ', 'TQ2', 'SN', 'SQ']; + } else { // not OBS + repoPreloadList = ['LT', 'ST', 'TN', 'TA', 'TW', 'TQ']; // for DEFAULT + if (dataSet === 'OLD') + repoPreloadList = ['LT', 'ST', 'TN', 'TA', 'TW', 'TQ']; + else if (dataSet === 'NEW') + repoPreloadList = ['LT', 'ST', 'TN2', 'TWL', 'TA', 'TW', 'TQ2']; + else if (dataSet === 'BOTH') + repoPreloadList = ['LT', 'ST', 'TN', 'TN2', 'TWL', 'TA', 'TW', 'TQ', 'TQ2']; const whichTestament = books.testament(bookID); // returns 'old' or 'new' const origLangRepo = whichTestament === 'old' ? 'UHB' : 'UGNT'; repoPreloadList.unshift(origLangRepo); - } - // TODO: Eventually we'll have all books here, so the repos can be included above - if (bookID === 'OBS' || bookID === 'TIT') { - repoPreloadList.push('SN'); - repoPreloadList.push('SQ'); + // TODO: Eventually we'll have all books here, so the repos can be included above + if (bookID === 'TIT') { + repoPreloadList.push('SN'); + repoPreloadList.push('SQ'); + } } debugLog(`BookPackageCheck got repoPreloadList=${repoPreloadList} for dataSet=${dataSet}`) diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index abf6fe08b..a0d2c8c0e 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -6,7 +6,7 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { checkRepo } from '../repo-check/checkRepo'; -// const BP_VALIDATOR_VERSION_STRING = '0.5.7'; +// const BP_VALIDATOR_VERSION_STRING = '0.6.0'; const MANIFEST_FILENAME = 'manifest.yaml'; @@ -99,12 +99,16 @@ export async function checkBookPackage(username, languageCode, bookID, setResult } - async function ourCheckBPFileContents(repoCode, repoName, cfFilename, fileContent, fileLocation, checkingOptions) { + async function ourCheckBPFileContents(repoCode, repoName, branch, cfFilename, fileContent, fileLocation, checkingOptions) { // functionLog(`checkBookPackage ourCheckBPFileContents(${repoCode}, ${cfFilename}, ${fileContent.length}, ${fileLocation}, ${JSON.stringify(checkingOptions)})…`); // Updates the global list of notices parameterAssert(repoCode !== undefined, "cBP ourCheckBPFileContents: 'repoCode' parameter should be defined"); parameterAssert(typeof repoCode === 'string', `cBP ourCheckBPFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + parameterAssert(repoName !== undefined, "cBP ourCheckBPFileContents: 'repoName' parameter should be defined"); + parameterAssert(typeof repoName === 'string', `cBP ourCheckBPFileContents: 'repoName' parameter should be a string not a '${typeof repoName}': ${repoName}`); + parameterAssert(branch !== undefined, "cBP ourCheckBPFileContents: 'branch' parameter should be defined"); + parameterAssert(typeof branch === 'string', `cBP ourCheckBPFileContents: 'branch' parameter should be a string not a '${typeof branch}': ${branch}`); parameterAssert(cfFilename !== undefined, "cBP ourCheckBPFileContents: 'cfFilename' parameter should be defined"); parameterAssert(typeof cfFilename === 'string', `cBP ourCheckBPFileContents: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); parameterAssert(fileContent !== undefined, "cBP ourCheckBPFileContents: 'fileContent' parameter should be defined"); @@ -113,7 +117,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult parameterAssert(typeof fileLocation === 'string', `cBP ourCheckBPFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); parameterAssert(checkingOptions !== undefined, "cBP ourCheckBPFileContents: 'checkingOptions' parameter should be defined"); - const cfcResultObject = await checkFileContents(username, languageCode, repoCode, originalBranch, cfFilename, fileContent, fileLocation, checkingOptions); + const cfcResultObject = await checkFileContents(username, languageCode, repoCode, branch, cfFilename, fileContent, fileLocation, checkingOptions); // debugLog("checkFileContents() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); // for (const successEntry of cfResultObject.successList) userLog(" ourCheckBPFileContents:", successEntry); // debugLog("cfcResultObject", JSON.stringify(cfcResultObject)); @@ -123,7 +127,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (cfcNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check checkBookPackageResult.noticeList.push(cfcNoticeEntry); // Just copy the complete notice as is else // For our direct checks, we add the repoCode as an extra value (unless it’s already there from a TA or TW check) - addNoticePartial({ ...cfcNoticeEntry, repoCode, repoName, filename: cfFilename, extra: cfcNoticeEntry.extra ? cfcNoticeEntry.extra : repoCode }); + addNoticePartial({ ...cfcNoticeEntry, repoCode, repoName, branch, filename: cfFilename, extra: cfcNoticeEntry.extra ? cfcNoticeEntry.extra : repoCode }); // The following is needed coz we might be checking the linked TA and/or TW articles from TN2 TSV files if (cfcResultObject.checkedFileCount && cfcResultObject.checkedFileCount > 0) { checkedFileCount += cfcResultObject.checkedFileCount; @@ -179,7 +183,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult } } if (manifestFileContent) { - const cmtResultObject = await checkManifestText(username, repoName, repoBranch, manifestFileContent, manifestLocation, checkingOptions); + const cmtResultObject = await checkManifestText(languageCode, repoCode, username, repoName, repoBranch, manifestFileContent, manifestLocation, checkingOptions); // debugLog(`ourCheckManifest checkManifestText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); // debugLog(`ourCheckManifest checkManifestText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); // NOTE: We ignore the returned success messages here @@ -236,11 +240,11 @@ export async function checkBookPackage(username, languageCode, bookID, setResult else { // eslint-disable-next-line eqeqeq if (cBPgfError != 'TypeError: repoFileContent is null') details += ` error=${cBPgfError}`; - addNoticePartial({ priority: 996, message: "Unable to load", details: `username=${username} error=${cBPgfError}`, repoName, filename, location: markdownLocation, extra: repoCode }); + addNoticePartial({ priority: 996, message: "Unable to load", details: `username=${username} error=${cBPgfError}`, username, repoName, filename, location: markdownLocation, extra: repoCode }); } } if (markdownFileContent) { - const cmtResultObject = await checkMarkdownText(languageCode, repoName, markdownFileContent, markdownLocation, checkingOptions); + const cmtResultObject = await checkMarkdownText(languageCode, repoCode, repoName, markdownFileContent, markdownLocation, checkingOptions); // debugLog(`ourCheckMarkdown checkMarkdownText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); // debugLog(`ourCheckMarkdown checkMarkdownText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); // NOTE: We ignore the returned success messages here @@ -259,7 +263,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // debugLog(`Year ${fullYearString} is ${typeof fullYearString}`); if (markdownFileContent.indexOf(fullYearString) === -1) // Can't find this year string in file // NOTE: We don’t use addNoticePartial, because it adds a misleading BookID - checkBookPackageResult.noticeList.push({ priority: 256, message: "Possibly missing current copyright year", details: `possibly expecting '${fullYearString}'`, repoName, filename, location: markdownLocation, extra: repoCode }); + checkBookPackageResult.noticeList.push({ priority: 256, message: "Possibly missing current copyright year", details: `possibly expecting '${fullYearString}'`, username, repoName, filename, location: markdownLocation, extra: repoCode }); } return markdownFileContent.length; @@ -280,7 +284,14 @@ export async function checkBookPackage(username, languageCode, bookID, setResult let bookNumberAndName, whichTestament; if (bookID === 'OBS') { // NOTE: No code below to handle OBS TN and TQ which are markdown repos - repoCodeList = ['TWL', 'OBS', 'TN', 'TQ', 'SN', 'SQ']; + if (dataSet === 'DEFAULT') + repoCodeList = ['OBS', 'TWL', 'TN2', 'TQ2', 'SN', 'SQ']; + else if (dataSet === 'OLD') + repoCodeList = ['OBS', 'TN', 'TQ', 'SN', 'SQ']; + else if (dataSet === 'NEW') + repoCodeList = ['OBS', 'TWL', 'TN2', 'TQ2', 'SN', 'SQ']; + else if (dataSet === 'BOTH') + repoCodeList = ['OBS', 'TWL', 'TN', 'TN2', 'TQ', 'TQ2', 'SN', 'SQ']; } else { // not OBS // We also need to know the number for USFM books try { @@ -320,7 +331,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult adjustedBranch = 'newFormat'; } let repoName = formRepoName(languageCode, adjustedRepoCode); - if (bookID === 'OBS' && repoCode !== 'OBS' && repoCode !== 'TWL' && repoName === `${languageCode}_${adjustedRepoCode.toLowerCase()}`) + if (bookID === 'OBS' && dataSet === 'OLD' && repoCode !== 'OBS' && repoCode !== 'TWL' && repoName === `${languageCode}_${adjustedRepoCode.toLowerCase()}`) repoName = `${languageCode}_obs-${adjustedRepoCode.toLowerCase()}`; userLog(`checkBookPackage: check ${languageCode} ${bookID} in ${repoCode} from ${username} ${repoName}…`); @@ -389,7 +400,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (repoFileContent) { // We use the generalLocation here (does not include repo name) // so that we can adjust the returned strings ourselves - await ourCheckBPFileContents(repoCode, repoName, filename, repoFileContent, generalLocation, newCheckingOptions); // Adds the notices to checkBookPackageResult + await ourCheckBPFileContents(repoCode, repoName, adjustedBranch, filename, repoFileContent, generalLocation, newCheckingOptions); // Adds the notices to checkBookPackageResult checkedFileCount += 1; checkedFilenameExtensions.add(filename.split('.').pop()); addSuccessMessage(`Checked ${repoCode.toUpperCase()} file: ${filename}`); diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index 938104f47..c9cb823fb 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -43,9 +43,11 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { bookIDInvalid = bookID; } bookIDList.push(bookID); - const whichTestament = books.testament(bookID); - if (whichTestament==='old') haveOT = true; - if (whichTestament==='new') haveNT = true; + if (books.isValidBookID(bookID)) { + const whichTestament = books.testament(bookID); + if (whichTestament==='old') haveOT = true; + if (whichTestament==='new') haveNT = true; + } } // debugLog(`bookIDList (${bookIDList.length}) = ${bookIDList.join(', ')}`); diff --git a/src/demos/file-check/checkFileContents.js b/src/demos/file-check/checkFileContents.js index 28b587638..48cc3c459 100644 --- a/src/demos/file-check/checkFileContents.js +++ b/src/demos/file-check/checkFileContents.js @@ -3,7 +3,7 @@ import { userLog, parameterAssert, logicAssert, formRepoName, checkUSFMText, checkMarkdownFileContents, checkPlainText, checkYAMLText, checkManifestText, - checkTN_TSV9Table, checkNotesTSV7Table, checkQuestionsTSV5Table, checkTWL_TSV6Table, + checkTN_TSV9Table, checkNotesTSV7Table, checkQuestionsTSV7Table, checkTWL_TSV6Table, } from '../../core'; @@ -47,6 +47,7 @@ export async function checkFileContents(username, languageCode, repoCode, branch if (ourCFLocation[0] !== ' ') ourCFLocation = ' ' + ourCFLocation; const filenameLower = filename.toLowerCase(); + const repoName = formRepoName(languageCode, repoCode); let checkFileResult = { checkedFileCount: 0 }; if (filenameLower.endsWith('.tsv')) { @@ -57,12 +58,12 @@ export async function checkFileContents(username, languageCode, repoCode, branch parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); if (filename.startsWith(`${languageCode}_`) || filenameMain.startsWith('en_')) { logicAssert(repoCode==='TN', `These filenames ${filenameMain} are only for TN ${repoCode}`); - checkFileResult = await checkTN_TSV9Table(languageCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = await checkTN_TSV9Table(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); } else { logicAssert(repoCode!=='TN', `This code with ${filenameMain} is not for TN`); let checkFunction = { TN2: checkNotesTSV7Table, SN: checkNotesTSV7Table, - TQ2: checkQuestionsTSV5Table, SQ: checkQuestionsTSV5Table, + TQ2: checkQuestionsTSV7Table, SQ: checkQuestionsTSV7Table, TWL: checkTWL_TSV6Table, }[repoCode]; checkFileResult = await checkFunction(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); @@ -83,15 +84,15 @@ export async function checkFileContents(username, languageCode, repoCode, branch parameterAssert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); checkFileResult = checkUSFMText(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filenameLower.endsWith('.md')) - checkFileResult = checkMarkdownFileContents(languageCode, filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkMarkdownFileContents(languageCode, repoCode, filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower.endsWith('.txt')) - checkFileResult = checkPlainText(languageCode, 'text', filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkPlainText(languageCode, repoCode, 'text', filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower === 'manifest.yaml') - checkFileResult = await checkManifestText(username, formRepoName(languageCode, repoCode), branch, fileContent, ourCFLocation, checkingOptions); // don’t know username or branch + checkFileResult = await checkManifestText(languageCode, repoCode, username, repoName, branch, fileContent, ourCFLocation, checkingOptions); // don’t know username or branch else if (filenameLower.endsWith('.yaml')) - checkFileResult = checkYAMLText(languageCode, filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkYAMLText(languageCode, repoCode, filename, fileContent, ourCFLocation, checkingOptions); else { - checkFileResult = checkPlainText(languageCode, 'raw', filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkPlainText(languageCode, repoCode, 'raw', filename, fileContent, ourCFLocation, checkingOptions); checkFileResult.noticeList.unshift({ priority: 995, message: "File extension is not recognized, so treated as plain text.", filename, location: filename }); } // functionLog(`checkFileContents got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); @@ -100,7 +101,8 @@ export async function checkFileContents(username, languageCode, repoCode, branch function addFilenameField(noticeObject) { if (noticeObject.debugChain) noticeObject.debugChain = `checkFileContents ${noticeObject.debugChain}`; if (noticeObject.fieldName === filename) delete noticeObject.fieldName; - return noticeObject.extra ? noticeObject : { ...noticeObject, filename }; // Might be an indirect check on a TA or TW article + // TODO: Might we need to add username, repoName, or branch here ??? + return noticeObject.extra ? noticeObject : { ...noticeObject, filename }; // NOTE: might be an indirect check on a TA or TW article } checkFileResult.noticeList = checkFileResult.noticeList.map(addFilenameField); diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index 1552961c6..e7c2b1e84 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -2,7 +2,7 @@ import { userLog, parameterAssert } from '../core/utilities'; import { isDisabledNotice } from '../core/disabled-notices'; -// const NOTICE_PROCESSOR_VERSION_STRING = '0.9.10'; +// const NOTICE_PROCESSOR_VERSION_STRING = '0.9.11'; // All of the following can be overriden with optionalProcessingOptions const DEFAULT_MAXIMUM_SIMILAR_MESSAGES = 3; // Zero means no suppression of similar messages @@ -145,7 +145,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { const ALL_TSV_FIELDNAMES = ['Book', 'Chapter', 'Verse', 'Reference', 'ID', 'Tags', 'SupportReference', 'OrigWords', 'TWLink', - 'OrigQuote', 'Quote', 'Occurrence', 'GLQuote', + 'Quote', 'Quote', 'Occurrence', 'GLQuote', 'Question', 'Response', 'OccurrenceNote', 'Note']; const numberStore = {}, duplicatePriorityList = []; @@ -202,7 +202,8 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { if (thisC) parameterAssert(thisC === 'front' || !isNaN(thisC * 1), `C '${thisC}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisV) // TODO: We'll need to remove this check once we start getting verse ranges, etc. - parameterAssert(thisV === 'intro' || !isNaN(thisV * 1), `V '${thisV}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); + // NOTE: Question mark below is in "bad verse number" notices + parameterAssert(thisV === 'intro' || thisV === '?' || !isNaN(thisV * 1), `V '${thisV}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisRowID) { parameterAssert(thisRowID.indexOf(' ') < 0 && thisRowID.indexOf('/') < 0 && thisRowID.indexOf('\\') < 0, `rowID '${thisRowID}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisLocation) diff --git a/src/demos/notice-processing1.md b/src/demos/notice-processing1.md index 3a427cc3b..73a40113c 100644 --- a/src/demos/notice-processing1.md +++ b/src/demos/notice-processing1.md @@ -41,7 +41,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'TN', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; const processOptions = { diff --git a/src/demos/notice-processing2.md b/src/demos/notice-processing2.md index 316178e02..fb4be818d 100644 --- a/src/demos/notice-processing2.md +++ b/src/demos/notice-processing2.md @@ -41,7 +41,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'TN', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; const processOptions = { diff --git a/src/demos/notice-processing3.md b/src/demos/notice-processing3.md index 7a2b8012a..82a268e51 100644 --- a/src/demos/notice-processing3.md +++ b/src/demos/notice-processing3.md @@ -41,7 +41,7 @@ const chosenTextName = "textB"; const chosenText = textB; // The third parameter is "linksAllowed" -const rawResults = checkTextField('en', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextField('en', 'TN', 'raw', 'Sample', chosenText, false, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic text checks"]; const processOptions = { diff --git a/styleguide.config.js b/styleguide.config.js index b659fd09e..7bd86ff0e 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -123,13 +123,13 @@ let sections = [ // content: 'src/core/README.md', sections: [ { - name: 'TQ/SQ TSV5 table check', - content: 'src/core/questions-tsv5-table-check.md', + name: 'TWLLinks TSV6 table check', + content: 'src/core/twl-tsv6-table-check.md', // description: '' }, { - name: 'TWLLinks TSV6 table check', - content: 'src/core/twl-tsv6-table-check.md', + name: 'TQ/SQ TSV7 table check', + content: 'src/core/questions-tsv7-table-check.md', // description: '' }, { @@ -207,13 +207,13 @@ let sections = [ // content: 'src/core/README.md', sections: [ { - name: 'TQ/SQ TSV5 row check', - content: 'src/core/questions-tsv5-row-check.md', + name: 'TWLinks TSV6 row check', + content: 'src/core/twl-tsv6-row-check.md', // description: '' }, { - name: 'TWLinks TSV6 row check', - content: 'src/core/twl-tsv6-row-check.md', + name: 'TQ/SQ TSV7 row check', + content: 'src/core/questions-tsv7-row-check.md', // description: '' }, { diff --git a/yarn.lock b/yarn.lock index 0d3a6b365..af43c15ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4895,9 +4895,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.664" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.664.tgz#8fb039e2fa8ef3ab2568308464a28425d4f6e2a3" - integrity sha512-yb8LrTQXQnh9yhnaIHLk6CYugF/An50T20+X0h++hjjhVfgSp1DGoMSYycF8/aD5eiqS4QwaNhiduFvK8rifRg== + version "1.3.665" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.665.tgz#6d0937376f6a919c0f289202c4be77790a6175e5" + integrity sha512-LIjx1JheOz7LM8DMEQ2tPnbBzJ4nVG1MKutsbEMLnJfwfVdPIsyagqfLp56bOWhdBrYGXWHaTayYkllIU2TauA== elliptic@^6.5.3: version "6.5.4" From 6858334cddb4640bc013e2d9a8a6033f8a25c932 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Wed, 17 Feb 2021 16:00:46 +1300 Subject: [PATCH 07/16] markdown check improvements; better support for new TSV formats --- package.json | 2 +- .../tn-table-row-check.test.js.snap | 56 +++------- src/__tests__/tn-table-row-check.test.js | 4 +- src/core/field-text-check.js | 8 +- src/core/markdown-text-check.js | 103 ++++++++++++++---- src/core/notes-links-check.js | 88 ++++++++++++--- src/core/notes-tsv7-row-check.js | 9 +- src/core/orig-quote-check.js | 8 +- src/core/tn-tsv9-row-check.js | 13 ++- src/demos/RenderProcessedResults.js | 4 +- src/demos/notice-processing-functions.js | 2 +- yarn.lock | 30 ++--- 12 files changed, 207 insertions(+), 120 deletions(-) diff --git a/package.json b/package.json index a01644fcf..07ea95be5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha3", + "version": "2.0.0_alpha4", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap index a6546a87d..df9011606 100644 --- a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap +++ b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap @@ -40,7 +40,7 @@ Object { "bookID": "GEN", "fieldName": "OrigQuote", "location": " that was supplied", - "message": "Missing OrigQuote field", + "message": "Missing Quote field", "priority": 919, "rowID": "w3r5", }, @@ -152,7 +152,7 @@ Object { "V": "2", "bookID": "GEN", "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "excerpt": "וְחֹ֖שחֹ֖שֶךְ", + "excerpt": "וְחֹ֖שֶךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -240,7 +240,7 @@ Object { "V": "2", "bookID": "GEN", "details": "quote which starts with 'word joiner'", - "excerpt": "", + "excerpt": "וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -284,7 +284,7 @@ Object { "V": "2", "bookID": "GEN", "details": "quote which starts with 'zero-width joiner'", - "excerpt": "", + "excerpt": "וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -316,7 +316,7 @@ Object { "V": "2", "bookID": "GEN", "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "excerpt": "וְחֹֹ֖֖שֶׁךְ", + "excerpt": "וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -467,7 +467,7 @@ Object { "V": "2", "bookID": "GEN", "details": "passage ►וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃◄", - "excerpt": "וְחֹ֖ש֖שֶׁךְ", + "excerpt": "וְחֹ֖שֶׁךְ", "fieldName": "OrigQuote", "location": " that was supplied", "message": "Unable to find original language quote in verse text", @@ -499,7 +499,7 @@ Object { "bookID": "GEN", "fieldName": "OrigQuote", "location": " that was supplied", - "message": "Missing OrigQuote field", + "message": "Missing Quote field", "priority": 919, "rowID": "a7qw", }, @@ -1191,7 +1191,7 @@ Object { "bookID": "GEN", "fieldName": "OrigQuote", "location": " that was supplied", - "message": "Missing OrigQuote field", + "message": "Missing Quote field", "priority": 919, "rowID": "W-3r5", }, @@ -1222,36 +1222,10 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "characterIndex": 13, - "excerpt": "…o␣hoo,,<br>␣los…", + "characterIndex": 7, + "excerpt": "Boo hoo,,", "fieldName": "OccurrenceNote", - "lineNumber": 1, - "location": " that was supplied", - "message": "Unexpected leading space(s) after break", - "priority": 64, - "rowID": "W-3r5", - }, - Object { - "C": "1", - "V": "2", - "bookID": "GEN", - "characterIndex": 0, - "excerpt": "<br>Boo hoo,,<b…", - "fieldName": "OccurrenceNote", - "lineNumber": 1, - "location": " that was supplied", - "message": "Unexpected leading line break", - "priority": 107, - "rowID": "W-3r5", - }, - Object { - "C": "1", - "V": "2", - "bookID": "GEN", - "characterIndex": 11, - "excerpt": "…Boo hoo,,<br> l…", - "fieldName": "OccurrenceNote", - "lineNumber": 1, + "lineNumber": 2, "location": " that was supplied", "message": "Unexpected doubled , characters", "priority": 177, @@ -1261,17 +1235,17 @@ Object { "C": "1", "V": "2", "bookID": "GEN", - "characterIndex": 30, + "characterIndex": 12, "excerpt": "…my shoe !", "fieldName": "OccurrenceNote", - "lineNumber": 1, + "lineNumber": 3, "location": " that was supplied", "message": "Unexpected ! character after space", "priority": 191, "rowID": "W-3r5", }, ], - "suggestion": "GIN 200 9 W-3r5 Laugh 1 Bad ellipse... Boo hoo,,<br> lost my shoe !", + "suggestion": "GIN 200 9 W-3r5 Laugh 1 Bad ellipse... <br>Boo hoo,,<br> lost my shoe !", } `; @@ -1317,7 +1291,7 @@ Object { "bookID": "GEN", "fieldName": "OrigQuote", "location": " that was supplied", - "message": "Missing OrigQuote field", + "message": "Missing Quote field", "priority": 919, "rowID": "w3r5", }, diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index e172d1770..636d4f3cc 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -277,7 +277,7 @@ describe('checkTN_TSV9DataRow() - ', () => { }); it('header should succeed', async () => { - const chosenLine = "Book\tChapter\tVerse\tID\tSupportReference\tQuote\tOccurrence\tGLQuote\tOccurrenceNote"; + const chosenLine = "Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote"; const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); expect(rawResults.noticeList.length).toEqual(0); }); @@ -339,7 +339,7 @@ describe('checkTN_TSV9DataRow() - ', () => { it('should find invalid Book ID, chapter number, ID, SupportReference, quotes, OccurrenceNote', async () => { const chosenLine = "GIN\t200\t9\tW-3r5\tLaugh\t\t17\tBad ellipse...\t<br>Boo hoo,,<br> lost my shoe !"; const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '2', 'that was supplied', optionalCheckingOptions); - expect(rawResults.noticeList.length).toEqual(16); + expect(rawResults.noticeList.length).toEqual(14); expect(rawResults).toMatchSnapshot(); }); diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index 7f43662f1..23764720e 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -1,5 +1,5 @@ import { DEFAULT_EXCERPT_LENGTH, OPEN_CLOSE_PUNCTUATION_PAIRS, BAD_CHARACTER_COMBINATIONS, isWhitespace, countOccurrences } from './text-handling-functions' -import { debugLog, parameterAssert } from './utilities'; +import { parameterAssert } from './utilities'; // const FIELD_TEXT_VALIDATOR_VERSION_STRING = '0.3.5'; @@ -260,7 +260,7 @@ export function checkTextField(languageCode, repoCode, fieldType, fieldName, fie addNoticePartial(notice); suggestion = suggestion.replace(/\u202F/g, ' '); } - if (fieldName === 'Quote' || fieldName === 'Quote') { + if (fieldName === 'OrigQuote' || fieldName === 'Quote') { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 179) && (characterIndex = fieldText.indexOf(' …')) >= 0) { const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') @@ -303,7 +303,7 @@ export function checkTextField(languageCode, repoCode, fieldType, fieldName, fie if (fieldType !== 'markdown') afterSpaceCheckList += '_*~'; // These are used for markdown formatting if (fieldType !== 'USFM' || (fieldText.indexOf('x-lemma') < 0 && fieldText.indexOf('x-tw') < 0)) afterSpaceCheckList += '|'; if (fieldType !== 'YAML') afterSpaceCheckList += '\'"'; // These are used for YAML strings, e.g., version: '0.15' - // if (fieldName === 'Quote' || fieldName === 'Quote') afterSpaceCheckList += '…'; // NOT NEEDED -- this is specifically checked elsewhere + // if (fieldName === 'OrigQuote' || fieldName === 'Quote') afterSpaceCheckList += '…'; // NOT NEEDED -- this is specifically checked elsewhere for (const punctChar of afterSpaceCheckList) { if ((!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < 191) && (characterIndex = fieldText.indexOf(' ' + punctChar)) >= 0) { @@ -410,7 +410,7 @@ export function checkTextField(languageCode, repoCode, fieldType, fieldName, fie && (fieldType !== 'YAML' || leftChar !== '{') // TODO: We have to allow for a blank language code until we change checkPlainText() && (languageCode !== 'en' || regexResultArray[0][2] !== 's' || fieldText.indexOf('(s)') === -1)) { - debugLog(`Got misplaced '${languageCode}' left ${leftChar} in ${fieldType} ${fieldName} '${fieldText}': ${JSON.stringify(regexResultArray)}`); + // debugLog(`Got possible misplaced '${languageCode}' left ${leftChar} in ${fieldType} ${fieldName} '${fieldText}': ${JSON.stringify(regexResultArray)}`); let thisPriority = 717, thisMessage = `Misplaced ${leftChar} character`; if (leftChar === '(' && regexResultArray[0][2] === 's') { thisPriority = 17; thisMessage = `Possible misplaced ${leftChar} character`; } // Lower priority for words like 'thing(s)' if (!checkingOptions?.cutoffPriorityLevel || checkingOptions?.cutoffPriorityLevel < thisPriority) diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index bcc9da13b..c34346c6c 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -2,17 +2,18 @@ import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTextField } from './field-text-check'; import { cachedGetFileUsingFullURL } from '../core/getApi'; import { removeDisabledNotices } from './disabled-notices'; -import { userLog, parameterAssert } from './utilities'; +import { userLog, parameterAssert, dataAssert } from './utilities'; -const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.5.0'; +const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.6.0'; -const IMAGE_REGEX = new RegExp('!\\[([^\\]]+?)\\]\\(([^ \\]]+?)\\)', 'g'); +const SIMPLE_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ "\\)]+?)\\)', 'g'); // ![alt](y) +const TITLED_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ \\)]+?) "([^"\\)]+?)"\\)', 'g'); // ![alt](link "title") /** * - * @param {string} languageCode + * @param {string} languageCode, e.g., 'en' * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. * @param {string} textOrFileName -- used for identification * @param {string} markdownText -- the actual text to be checked @@ -28,7 +29,7 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, Returns a result object containing a successList and a noticeList */ - // functionLog(`checkMarkdownText(${textName}, ${markdownText.length}, ${givenLocation})…`); + // functionLog(`checkMarkdownText(${languageCode}, ${repoCode}, ${textOrFileName}, ${markdownText.length}, ${givenLocation}, …)…`); parameterAssert(languageCode !== undefined, "checkMarkdownText: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkMarkdownText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); parameterAssert(languageCode !== 'unfoldingWord', `checkMarkdownText: 'languageCode' ${languageCode} parameter should be not be 'unfoldingWord'`); @@ -135,17 +136,40 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, // Check for image links let regexResultArray; - while ((regexResultArray = IMAGE_REGEX.exec(lineText))) { + while ((regexResultArray = SIMPLE_IMAGE_REGEX.exec(lineText))) { // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); - if (regexResultArray[1] !== 'OBS Image') userLog("This code was only checked for 'OBS Image' links"); - const fetchLink = regexResultArray[2]; + const [totalLink, altText, fetchLink] = regexResultArray; + // if (altText !== 'OBS Image') userLog("This code was only checked for 'OBS Image' links"); + if (!altText) + addNotice({ priority: 349, message: "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation }); if (!fetchLink.startsWith('https://')) addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { // debugLog(`Need to check existence of ${fetchLink}`); try { const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); - parameterAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); + dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); + // debugLog("Markdown link fetch got response: ", responseData.length); + } catch (flError) { + console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); + addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation }); + } + } + } + while ((regexResultArray = TITLED_IMAGE_REGEX.exec(lineText))) { + // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); + const [totalLink, alt, fetchLink, title] = regexResultArray; + if (!alt) + addNotice({ priority: 349, message: "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation }); + if (!title) + addNotice({ priority: 348, message: "Markdown image link has no title text", lineNumber, excerpt: totalLink, location: lineLocation }); + if (!fetchLink.startsWith('https://')) + addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); + else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { + // debugLog(`Need to check existence of ${fetchLink}`); + try { + const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); + dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); // debugLog("Markdown link fetch got response: ", responseData.length); } catch (flError) { console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); @@ -187,7 +211,7 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, if (thisText === lineText) // i.e., we didn’t premodify the field being checked (otherwise suggestion could be wrong) return suggestion; } - // end of checkMarkdownLine function + // end of checkMarkdownLineContents function // Main code for checkMarkdownText function @@ -195,21 +219,42 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, // debugLog(` '${location}' has ${lines.length.toLocaleString()} total lines`); let headerLevel = 0; - // let lastNumLeadingSpaces = 0; - // let lastLineContents; + let lastLine; let indentLevels = []; const suggestedLines = []; + let notifiedBlankLines = false; for (let n = 1; n <= lines.length; n++) { const line = lines[n - 1]; + const nextLine = (n < lines.length - 1) ? lines[n] : undefined; + + // Markdown headers should be preceded and followed by a blank line + if (line.startsWith('#')) { + if (n > 1 && lastLine.length !== 0) { + const notice = { priority: 252, message: "Markdown headers should be preceded by a blank line", lineNumber: n, location: ourLocation }; + if (textOrFileName === 'Note' || textOrFileName === 'OccurrenceNote') + notice.details = `markdown line ${n}`; + addNotice(notice); + } + if (nextLine?.length !== 0) { + const notice = { priority: 252, message: "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation }; + if (textOrFileName === 'Note' || textOrFileName === 'OccurrenceNote') + notice.details = `markdown line ${n}`; + addNotice(notice); + } + } + let numLeadingSpaces; if (line) { - const thisHeaderLevel = line.match(/^#*/)[0].length; // debugLog(`Got thisHeaderLevel=${thisHeaderLevel} for ${line}${atString}`); if (thisHeaderLevel > headerLevel + 1 - && !textOrFileName.startsWith('TA ')) // Suppress this notice for translationAcademy subsections - addNotice({ priority: 172, message: "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation }); + && !textOrFileName.startsWith('TA ')) { // Suppress this notice for translationAcademy subsections + const notice = { priority: 172, message: "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation }; + if (textOrFileName === 'Note' || textOrFileName === 'OccurrenceNote') + notice.details = `markdown line ${n}`; + addNotice(notice); + } if (thisHeaderLevel > 0) { headerLevel = thisHeaderLevel; indentLevels = []; // reset @@ -219,7 +264,7 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, // debugLog(`Got numLeadingSpaces=${numLeadingSpaces} with indentLevels=${JSON.stringify(indentLevels)} for ${line}${ourLocation}`); const previousIndentLevel = (indentLevels.length > 0) ? indentLevels[indentLevels.length - 1] : 0; if ((numLeadingSpaces > previousIndentLevel) // We have an indent level increase - || (numLeadingSpaces===0 && line.length > 0 && indentLevels.length===0)) // we have our first zero-level indent + || (numLeadingSpaces === 0 && line.length > 0 && indentLevels.length === 0)) // we have our first zero-level indent indentLevels.push(numLeadingSpaces); else if (numLeadingSpaces < previousIndentLevel) { // We have an indent level decrease if (indentLevels.length > 1 && indentLevels[indentLevels.length - 2] === numLeadingSpaces) @@ -227,17 +272,21 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, indentLevels.pop(); else { // seems we didn't go back to the previous level ??? let foundPreviousLevel = false; - for (let z = indentLevels.length-1; z>= 0; z--) { + for (let z = indentLevels.length - 1; z >= 0; z--) { if (indentLevels[z] === numLeadingSpaces) { // debugLog(`After finding ${numLeadingSpaces} spaces, reducing length of ${JSON.stringify(indentLevels)} to ${z+1}`); - indentLevels.length = z+1; + indentLevels.length = z + 1; foundPreviousLevel = true; break; } } - if (!foundPreviousLevel) - addNotice({ priority: 282, message: "Nesting of header levels seems confused", details: `recent indent levels=${JSON.stringify(indentLevels)} but now ${numLeadingSpaces}`, lineNumber: n, characterIndex: 0, location: ourLocation }); - } + if (!foundPreviousLevel) { + const notice = { priority: 282, message: "Nesting of header levels seems confused", details: `recent indent levels=${JSON.stringify(indentLevels)} but now ${numLeadingSpaces}`, lineNumber: n, characterIndex: 0, location: ourLocation }; + if (textOrFileName === 'Note' || textOrFileName === 'OccurrenceNote') + notice.details = `markdown line ${n}`; + addNotice(notice); + } + } } const suggestedLine = await checkMarkdownLineContents(n, line, ourLocation); @@ -246,12 +295,22 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, // This is a blank line numLeadingSpaces = 0; suggestedLines.push(''); + + // Should only ever have single blank lines in markdown + if (n > 1 && lastLine.length === 0 && nextLine?.length === 0 && !notifiedBlankLines) { + const notice = { priority: 250, message: "Multiple blank lines are not expected in markdown", lineNumber: n, location: ourLocation }; + if (textOrFileName === 'Note' || textOrFileName === 'OccurrenceNote') + notice.details = `markdown line ${n}`; + addNotice(notice); + notifiedBlankLines = true; + } } - // lastLineContents = line; + lastLine = line; // lastNumLeadingSpaces = numLeadingSpaces; } + // Check for an uneven number of sets of symmetrical (i.e., opener == closer) multicharacter markdown formatting sequences for (const thisSet of [ // Put longest ones first // Seems that the fancy ones (commented out) don't find occurrences at the start (or end?) of the text diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index 64f724afb..ce12ac2bb 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -7,7 +7,7 @@ import { userLog, debugLog, parameterAssert, logicAssert, ourParseInt } from './ // import { consoleLogObject } from '../core/utilities'; -// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.7'; +// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.8'; const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; @@ -23,10 +23,11 @@ const TWL_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g') // (we don't care about the displayed text) doesn't specify superfluous levels/information // TODO: We need a decision on hyphen vs en-dash in verse references // TODO: Test to see if "[2:23](../02/03.md)" is found by more than one regex below -const OTHER_BOOK_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(([123A-Z]{2,3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); -const THIS_BOOK_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); +const BIBLE_REGEX_OTHER_BOOK_ABSOLUTE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](rev/03/11.md) +const BIBLE_REGEX_OTHER_BOOK_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(\\.{2}/\\.{2}/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](../../rev/03/11.md) +const BIBLE_REGEX_THIS_BOOK_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](../03/11.md) const BCV_V_TO_THIS_BOOK_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})[–-](\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Genesis 26:12-14](../26/12.md) or [4:11–16](../04/11.md) NOTE en-dash -const THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(?:(\\d{1,3}):)?(\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); +const BIBLE_REGEX_THIS_CHAPTER_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(?:(\\d{1,3}):)?(\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); const THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g');// [27](../11/27.md) const THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})[–-](\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g');// [2–7](../09/2.md) NOTE en-dash const BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})[–-](\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); // [Genesis 26:12-14](./12.md) NOTE en-dash @@ -328,11 +329,11 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // debugLog("checkNotesLinksToOutside: Search for Bible links") // Check for this-chapter Bible links like [Revelation 3:11](./11.md) - while ((regexResultArray = THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + while ((regexResultArray = BIBLE_REGEX_THIS_CHAPTER_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisChapterBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 6, `THIS_CHAPTER_BIBLE_REGEX expected 6 fields (not ${regexResultArray.length})`); + parameterAssert(regexResultArray.length === 6, `BIBLE_REGEX_THIS_CHAPTER_RELATIVE expected 6 fields (not ${regexResultArray.length})`); let [totalLink, optionalN1, optionalB1, C1, V1, V2] = regexResultArray; if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); @@ -351,7 +352,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g const linkVerseInt = ourParseInt(V2); if (C1 === undefined) { if (!books.isOneChapterBook(linkBookCode)) { - // debugLog(` checkNotesLinksToOutside C1 missing in THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside C1 missing in BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); } C1 = '0'; // Try to avoid consequential errors @@ -465,12 +466,12 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g } // Check for this-book Bible links like [Revelation 3:11](../03/11.md) - while ((regexResultArray = THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + while ((regexResultArray = BIBLE_REGEX_THIS_BOOK_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); thisBookBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 8, `THIS_BOOK_BIBLE_REGEX expected 8 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + parameterAssert(regexResultArray.length === 7, `BIBLE_REGEX_THIS_BOOK_RELATIVE expected 7 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, C2, V2] = regexResultArray; if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); if (optionalB1) { @@ -483,8 +484,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g } } - let linkBookCode = B2 === '..' ? bookID : B2; - + let linkBookCode = bookID; const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { if (ourParseInt(C1) !== linkChapterInt) @@ -624,12 +624,64 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g } } - // Check for other book Bible links like [Revelation 3:11](../03/11.md) - while ((regexResultArray = OTHER_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside OTHER_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // Check for other book Bible links like [Revelation 3:11](rev/03/11.md) + while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_ABSOLUTE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_ABSOLUTE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_ABSOLUTE expected 8 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } + + let linkBookCode = B2 === '..' ? bookID : B2; + + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } + + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } + + // Check for other book Bible links like [Revelation 3:11](../../rev/03/11.md) + while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); otherBookBibleLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 8, `OTHER_BOOK_BIBLE_REGEX expected 8 fields (not ${regexResultArray.length})`); + parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_RELATIVE expected 8 fields (not ${regexResultArray.length})`); let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index 4be1ca3a2..251fa3d62 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -8,7 +8,7 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.8'; +// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.9'; const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_NOTES_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; @@ -503,10 +503,11 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID if (isWhitespace(note)) addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation }); else { // More than just whitespace - ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', note, true, ourRowLocation, checkingOptions); - await ourcheckNotesLinksToOutside(rowID, 'Note', note, ourRowLocation, linkCheckingOptions); + const adjustedNote = note.replace(/\\n/g, '\n'); + ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', adjustedNote, true, ourRowLocation, checkingOptions); + await ourcheckNotesLinksToOutside(rowID, 'Note', adjustedNote, ourRowLocation, linkCheckingOptions); let regexResultArray; - while ((regexResultArray = TA_REGEX.exec(note))) { + while ((regexResultArray = TA_REGEX.exec(adjustedNote))) { // debugLog("Got TA Regex in Note", JSON.stringify(regexResultArray)); const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) if (supportReference !== adjustedLink && V !== 'intro') { diff --git a/src/core/orig-quote-check.js b/src/core/orig-quote-check.js index b472fa688..ca67681f6 100644 --- a/src/core/orig-quote-check.js +++ b/src/core/orig-quote-check.js @@ -261,14 +261,14 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa quoteBits = fieldText.split(discontiguousDivider); if ((characterIndex = fieldText.indexOf(` ${discontiguousDivider}`)) >= 0 || (characterIndex = fieldText.indexOf(`${discontiguousDivider} `)) >= 0) { // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - const excerpt = (characterIndex > excerptHalfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? discontiguousDivider : ''); + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); addNotice({ priority: 158, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); } // } else if (fieldText.indexOf('↔') >= 0) { // quoteBits = fieldText.split('↔'); // if ((characterIndex = fieldText.indexOf(' ↔')) >= 0 || (characterIndex = fieldText.indexOf('↔ ')) >= 0) { // // debugLog(`Unexpected space(s) beside ellipse in '${fieldText}'`); - // const excerpt = (characterIndex > excerptHalfLength ? discontiguousDivider : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); + // const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : ''); // addNotice({ priority: 157, message: `Unexpected space(s) beside divider ${discontiguousDivider}`, characterIndex, excerpt, location: ourLocation }); // } } else if (discontiguousDivider === '…' && fieldText.indexOf('...') >= 0) { // Yes, we still actually allow this @@ -335,7 +335,7 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa if (occurrence > 1) { // functionLog(`checkOriginalLanguageQuote is checking for ${occurrence} occurrences of ${fieldText}`); if (verseText.split(fieldText).length <= occurrence) { // There's not enough of them - const excerpt = fieldText.substring(0, excerptHalfLength) + (fieldText.length > 2 * excerptHalfLength ? discontiguousDivider : '') + fieldText.substring(fieldText.length - excerptHalfLength, fieldText.length); + const excerpt = fieldText.substring(0, excerptHalfLength) + (fieldText.length > 2 * excerptHalfLength ? '…' : '') + fieldText.substring(fieldText.length - excerptHalfLength, fieldText.length); addNotice({ priority: 917, message: "Unable to find duplicate original language quote in verse text", details: `occurrence=${occurrenceString}, passage ►${verseText}◄`, excerpt, location: ourLocation }); } } else { // We only need to check for one occurrence @@ -357,7 +357,7 @@ export async function checkOriginalLanguageQuote(languageCode, repoCode, fieldNa if (offendingChar === '\u2060') precederDescription = 'WordJoiner'; else if (offendingChar === '\u200D') precederDescription = 'ZeroWidth-WordJoiner'; else precederDescription = `${offendingChar}=D${offendingChar.charCodeAt()}/H${offendingChar.charCodeAt().toString(16)}`; - const excerpt = `(${precederDescription})` + fieldText.substring(0, excerptLength - 3) + (fieldText.length > excerptLength - 3 ? discontiguousDivider : ''); + const excerpt = `(${precederDescription})` + fieldText.substring(0, excerptLength - 3) + (fieldText.length > excerptLength - 3 ? '…' : ''); addNotice({ priority: 909, message: "Seems original language quote might not start at the beginning of a word", details: `passage ►${verseText}◄`, characterIndex: 0, excerpt, location: ourLocation }); } // Note: There's some Hebrew (RTL) characters at the beginning of the following regex diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index e9bf03969..fb678cc31 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -476,15 +476,15 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // addNoticePartial({ priority: 877, message: "Missing SupportReference field", fieldName: 'SupportReference', rowID, location: ourRowLocation }); if (quote.length) { // need to check UTN against UHB and UGNT - OQSuggestion = ourCheckTextField(rowID, 'Quote', quote, false, ourRowLocation, checkingOptions); + OQSuggestion = ourCheckTextField(rowID, 'OrigQuote', quote, false, ourRowLocation, checkingOptions); if (occurrence.length) - await ourCheckTNOriginalLanguageQuote(rowID, 'Quote', quote, occurrence, ourRowLocation, checkingOptions); + await ourCheckTNOriginalLanguageQuote(rowID, 'OrigQuote', quote, occurrence, ourRowLocation, checkingOptions); else addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); } else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (V !== 'intro' && occurrence !== '0') - addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation }); if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn’t occur @@ -530,10 +530,11 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, if (isWhitespace(occurrenceNote)) addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation }); else { // More than just whitespace - ONSuggestion = await ourMarkdownTextChecks(rowID, 'OccurrenceNote', occurrenceNote, true, ourRowLocation, checkingOptions); - await ourcheckNotesLinksToOutside(rowID, 'OccurrenceNote', occurrenceNote, ourRowLocation, linkCheckingOptions); + const adjustedOccurrenceNote = occurrenceNote.replace(/<br>/g, '\n'); + ONSuggestion = await ourMarkdownTextChecks(rowID, 'OccurrenceNote', adjustedOccurrenceNote, true, ourRowLocation, checkingOptions); + await ourcheckNotesLinksToOutside(rowID, 'OccurrenceNote', adjustedOccurrenceNote, ourRowLocation, linkCheckingOptions); let regexResultArray; - while ((regexResultArray = TA_REGEX.exec(occurrenceNote))) { + while ((regexResultArray = TA_REGEX.exec(adjustedOccurrenceNote))) { // debugLog("Got TA Regex in OccurrenceNote", JSON.stringify(regexResultArray)); if (supportReference !== regexResultArray[1] && V !== 'intro') { const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index 7cc94b4a1..d39c7ef28 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -1,6 +1,6 @@ import React from 'react'; import { forwardRef } from 'react'; -import { parameterAssert, userLog, debugLog } from '../core/utilities'; +import { parameterAssert, userLog } from '../core/utilities'; // NOTE: The following line is currently giving compile warnings -- a problem in a dependency it seems import MaterialTable from 'material-table'; @@ -254,7 +254,7 @@ function RenderBCV({ bookID, C, V }) { */ function RenderFileDetails({ username, repoName, branch, filename, lineNumber, rowID, fieldName }) { // These are all optional parameters - they may be undefined or blank if irrelevant - debugLog(`RenderFileDetails(${repoName}, ${branch}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); + // debugLog(`RenderFileDetails(${repoName}, ${branch}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); if (!repoName && !filename && !lineNumber && !rowID && !fieldName) return null; // They're all undefined or blank! if (!branch) branch = repoName.endsWith('2')? 'newFormat':'master'; // default but with TEMP code for newFormat diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index e7c2b1e84..e1b1f5cda 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -145,7 +145,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { const ALL_TSV_FIELDNAMES = ['Book', 'Chapter', 'Verse', 'Reference', 'ID', 'Tags', 'SupportReference', 'OrigWords', 'TWLink', - 'Quote', 'Quote', 'Occurrence', 'GLQuote', + 'OrigQuote', 'Quote', 'Occurrence', 'GLQuote', 'Question', 'Response', 'OccurrenceNote', 'Note']; const numberStore = {}, duplicatePriorityList = []; diff --git a/yarn.lock b/yarn.lock index af43c15ef..822a475c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4433,9 +4433,9 @@ cssstyle@^2.2.0: cssom "~0.3.6" csstype@^2.5.2: - version "2.6.14" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.14.tgz#004822a4050345b55ad4dcc00be1d9cf2f4296de" - integrity sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A== + version "2.6.15" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.15.tgz#655901663db1d652f10cb57ac6af5a05972aea1f" + integrity sha512-FNeiVKudquehtR3t9TRRnsHL+lJhuHF5Zn9dt01jpojlurLEPDhhEtUkWmAUJ7/fOLaLG4dCDEnUsR0N1rZSsg== csstype@^3.0.2: version "3.0.6" @@ -4895,9 +4895,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.665" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.665.tgz#6d0937376f6a919c0f289202c4be77790a6175e5" - integrity sha512-LIjx1JheOz7LM8DMEQ2tPnbBzJ4nVG1MKutsbEMLnJfwfVdPIsyagqfLp56bOWhdBrYGXWHaTayYkllIU2TauA== + version "1.3.666" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.666.tgz#59f3ce1e45b860a0ebe439b72664354efbb8bc62" + integrity sha512-/mP4HFQ0fKIX4sXltG6kfcoGrfNDZwCIyWbH2SIcVaa9u7Rm0HKjambiHNg5OEruicTl9s1EwbERLwxZwk19aw== elliptic@^6.5.3: version "6.5.4" @@ -9619,9 +9619,9 @@ open@^6.3.0: is-wsl "^1.1.0" open@^7.0.2: - version "7.4.1" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.1.tgz#4ccedc11ca348d398378ffb39c71357df55fe6f7" - integrity sha512-Pxv+fKRsd/Ozflgn2Gjev1HZveJJeKR6hKKmdaImJMuEZ6htAvCTbcMABJo+qevlAelTLCrEK3YTKZ9fVTcSPw== + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== dependencies: is-docker "^2.0.0" is-wsl "^2.1.1" @@ -12534,9 +12534,9 @@ stack-utils@^2.0.2: escape-string-regexp "^2.0.0" stackblur-canvas@^2.0.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/stackblur-canvas/-/stackblur-canvas-2.4.0.tgz#2b2eba910cb46f6feae918e1c402f863d602c01b" - integrity sha512-Z+HixfgYV0ss3C342DxPwc+UvN1SYWqoz7Wsi3xEDWEnaBkSCL3Ey21gF4io+WlLm8/RIrSnCrDBIEcH4O+q5Q== + version "2.5.0" + resolved "https://registry.yarnpkg.com/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz#aa87bbed1560fdcd3138fff344fc6a1c413ebac4" + integrity sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ== state-toggle@^1.0.0: version "1.0.3" @@ -13239,9 +13239,9 @@ type@^1.0.1: integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.2.0.tgz#3edd448793f517d8b9dd108b486a043f5befd91f" - integrity sha512-M/u37b4oSGlusaU8ZB96BfFPWQ8MbsZYXB+kXGMiDj6IKinkcNaQvmirBuWj8mAXqP6LYn1rQvbTYum3yPhaOA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.3.0.tgz#ada7c045f07ead08abf9e2edd29be1a0c0661132" + integrity sha512-rgPIqOdfK/4J9FhiVrZ3cveAjRRo5rsQBAIhnylX874y1DX/kEKSVdLsnuHB6l1KTjHyU01VjiMBHgU2adejyg== typedarray-to-buffer@^3.1.5: version "3.1.5" From 4c26f323c7425c57119e3e6c93c78b65405e2706 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Wed, 17 Feb 2021 20:41:50 +1300 Subject: [PATCH 08/16] Update tests to handle sn and sq esp. failure to find test files --- noticeList.txt | 584 +- .../book-package-check.test.js.snap | 10678 +++++++++++++++- src/__tests__/book-package-check.test.js | 2 +- .../fixtures/unfoldingWord/en_sn/LICENSE.md | 29 + .../fixtures/unfoldingWord/en_sn/OBS_sn.tsv | 798 ++ .../fixtures/unfoldingWord/en_sn/README.md | 3 + .../fixtures/unfoldingWord/en_sn/TIT_sn.tsv | 62 + .../unfoldingWord/en_sn/manifest.yaml | 52 + .../fixtures/unfoldingWord/en_sq/LICENSE.md | 29 + .../fixtures/unfoldingWord/en_sq/OBS_sq.tsv | 736 ++ .../fixtures/unfoldingWord/en_sq/README.md | 3 + .../fixtures/unfoldingWord/en_sq/TIT_sq.tsv | 188 + .../unfoldingWord/en_sq/manifest.yaml | 53 + .../book-package-check/checkBookPackage.js | 116 +- 14 files changed, 12880 insertions(+), 453 deletions(-) create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sn/LICENSE.md create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sn/OBS_sn.tsv create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sn/README.md create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sn/TIT_sn.tsv create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sn/manifest.yaml create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sq/LICENSE.md create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sq/OBS_sq.tsv create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sq/README.md create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sq/TIT_sq.tsv create mode 100644 src/__tests__/fixtures/unfoldingWord/en_sq/manifest.yaml diff --git a/noticeList.txt b/noticeList.txt index 00319cb95..a16e030fd 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,126 +1,136 @@ -Last updated 2021-02-16 12:00:30.263351 by makeNoticeList.py -Got 451 notices: +Last updated 2021-02-17 20:41:30.385127 by makeNoticeList.py +Got 469 notices: checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 256 languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 927 marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 955 `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,034 C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,127 - const notice = 95, "Unexpected trailing space(s)", excerpt, location: ourLocation ; from field-text-check.js line 190 - notice from field-text-check.js line 193 - notice = 124, "Unexpected double spaces", excerpt, location: ourLocation ; from field-text-check.js line 224 - notice = 224, "Multiple unexpected double spaces", details: `$doubleCount occurrences—only first is displayed`, excerpt, location: ourLocation ; from field-text-check.js line 226 - notice from field-text-check.js line 230 - const notice = 580, "Unexpected narrow non-break space character", excerpt, location: ourLocation ; from field-text-check.js line 254 - notice from field-text-check.js line 257 - const notice = 177, `Unexpected doubled $punctChar characters`, excerpt, location: ourLocation ; from field-text-check.js line 289 - notice from field-text-check.js line 292 - const notice = 191, `Unexpected $punctChar character after space`, excerpt, location: ourLocation ; from field-text-check.js line 308 - notice from field-text-check.js line 311 - const notice = 192, `Unexpected space after $punctChar character`, excerpt, location: ourLocation ; from field-text-check.js line 337 - notice from field-text-check.js line 340 - const notice = 193, `Unexpected $punctChar character at end of line`, excerpt, location: ourLocation ; from field-text-check.js line 355 - notice from field-text-check.js line 358 - thisPriority, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from field-text-check.js line 399 - thisPriority, thisMessage, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 414 - leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from plain-text-check.js line 240 + const notice = 95, "Unexpected trailing space(s)", excerpt, location: ourLocation ; from field-text-check.js line 193 + notice from field-text-check.js line 196 + notice = 124, "Unexpected double spaces", excerpt, location: ourLocation ; from field-text-check.js line 227 + notice = 224, "Multiple unexpected double spaces", details: `$doubleCount occurrences—only first is displayed`, excerpt, location: ourLocation ; from field-text-check.js line 229 + notice from field-text-check.js line 233 + const notice = 580, "Unexpected narrow non-break space character", excerpt, location: ourLocation ; from field-text-check.js line 257 + notice from field-text-check.js line 260 + const notice = 177, `Unexpected doubled $punctChar characters`, excerpt, location: ourLocation ; from field-text-check.js line 292 + notice from field-text-check.js line 295 + const notice = 191, `Unexpected $punctChar character after space`, excerpt, location: ourLocation ; from field-text-check.js line 311 + notice from field-text-check.js line 314 + const notice = 192, `Unexpected space after $punctChar character`, excerpt, location: ourLocation ; from field-text-check.js line 340 + notice from field-text-check.js line 343 + const notice = 193, `Unexpected $punctChar character at end of line`, excerpt, location: ourLocation ; from field-text-check.js line 358 + notice from field-text-check.js line 361 + thisPriority, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from field-text-check.js line 402 + thisPriority, thisMessage, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 417 + const notice = 252, "Markdown headers should be preceded by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 234 + notice from markdown-text-check.js line 237 + const notice = 252, "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 240 + notice from markdown-text-check.js line 243 + const notice = 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 253 + notice from markdown-text-check.js line 256 + const notice = 282, "Nesting of header levels seems confused", details: `recent indent levels=$JSON.stringify(indentLevels) but now $numLeadingSpaces`, lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 284 + notice from markdown-text-check.js line 287 + const notice = 250, "Multiple blank lines are not expected in markdown", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 301 + notice from markdown-text-check.js line 304 + leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from plain-text-check.js line 243 999, "checkRepo function FAILED", repoName, excerpt: checkRepoError, location: repoName from RepoCheck.js line 107 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 174 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 235 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 389 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 582 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 608 - 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 178 - 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 239 - 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 393 - 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 584 - 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 612 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 179 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 243 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 399 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 592 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 618 + 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 183 + 996, "Unable to load", details: `username=$username error=$cBPgfError`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 247 + 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 403 + 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 594 + 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 622 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 260 - 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 95 - 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 117 - 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 136 - 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 123 - 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 140 - 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 129 - 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 144 + 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 96 + 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 120 + 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 139 + 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 126 + 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 143 + 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 132 + 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 147 990, "Unable to load file", details: `username=$username`, repoName, filename ], elapsedSeconds: 0 ; from FileCheck.js line 63 989, "Unable to find/load repository", location: ourLocation from checkRepo.js line 186 - 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-tsv9-table-check.js line 127 - 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from twl-tsv6-table-check.js line 117 - 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from notes-tsv7-table-check.js line 117 - 988, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from questions-tsv7-table-check.js line 117 + 988, "Bad TSV header", details: `expected '$EXPECTED_TN_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from tn-tsv9-table-check.js line 125 + 988, "Bad TSV header", details: `expected '$EXPECTED_TWL_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from twl-tsv6-table-check.js line 117 + 988, "Bad TSV header", details: `expected '$EXPECTED_NOTES_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from notes-tsv7-table-check.js line 117 + 988, "Bad TSV header", details: `expected '$EXPECTED_QUESTIONS_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from questions-tsv7-table-check.js line 117 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,111 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 - 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 676 + 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 691 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 561 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv7-row-check.js line 500 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 533 - 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 253 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv7-row-check.js line 502 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 536 + 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 251 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 241 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 240 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 240 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 258 - 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 359 - 979, "Invalid book identifier passed to checkQuestionsTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv7-row-check.js line 309 - 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 339 - 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 374 - 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 377 + 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 358 + 979, "Invalid book identifier passed to checkQuestionsTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv7-row-check.js line 311 + 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 341 + 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 373 + 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 376 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 276 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 382 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv7-row-check.js line 327 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 357 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 381 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv7-row-check.js line 329 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 359 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 312 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 414 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 363 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 393 - 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 199 - 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 269 - 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 230 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 413 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 365 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 395 + 956, "Got empty manifest file", repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 204 + 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 277 + 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 234 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 285 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 283 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 943, `USFM3 toJSON Check doesn’t pass`, location: ourLocation from usfm-js-check.js line 91 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,161 - 939, "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 688 - 938, `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 705 - 937, `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 707 - 936, `Error loading manifest project link`, details: trcGCerror, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 709 - 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 641 - 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 639 - 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 163 + 939, "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 703 + 938, `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 720 + 937, `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 722 + 936, `Error loading manifest project link`, details: trcGCerror, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 724 + 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 656 + 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 654 + 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 174 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 364 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 488 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 415 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 473 - 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 338 - 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 380 - 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 383 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 386 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 389 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 392 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 395 - 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 398 - 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 401 - 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 404 - 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 325 - 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 322 + 919, "Missing Quote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 487 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 417 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 475 + 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 339 + 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 381 + 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 384 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 387 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'word joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 390 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 393 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width space'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 396 + 916, "Unable to find original language quote in verse text", details: "quote which starts with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 399 + 916, "Unable to find original language quote in verse text", details: "quote which ends with 'zero-width joiner'" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 402 + 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 405 + 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 326 + 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 323 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 660 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 716 - 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 360 - 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 369 + 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 361 + 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 370 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 - 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 300 + 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 308 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 76 - 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 102 + 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 105 889, `Unable to find TA link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 888, `Error loading TA link`, excerpt: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 887, `Linked TA article seems empty`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 - 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 252 - 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 247 - 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 254 - 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 302 - 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 299 - 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 305 + 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 256 + 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 251 + 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 258 + 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 306 + 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 303 + 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 309 879, `Badly formatted Resource Container link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 763 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 567 @@ -136,14 +146,14 @@ Got 451 notices: 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 823 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 829 - 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 294 - 849, `Unexpected '$badCharCombination' character combination`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 368 + 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 295 + 849, `Unexpected '$badCharCombination' character combination`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 371 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 - 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 750 - 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 754 - 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 761 + 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 805 + 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 809 + 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 816 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 857 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 859 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 843 @@ -158,296 +168,304 @@ Got 451 notices: 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 281 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 387 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 332 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 362 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 386 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 334 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 364 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 286 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 392 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 337 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 367 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 391 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 339 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 369 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 299 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 402 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 350 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 380 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 401 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 352 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 382 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 305 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 407 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 356 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 386 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 406 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 358 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 388 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 308 - 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 410 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv7-row-check.js line 359 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 389 + 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 409 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv7-row-check.js line 361 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 391 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 317 - 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 419 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 368 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 398 + 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 418 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 370 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 400 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 321 - 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 423 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 372 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 422 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 374 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 404 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 323 - 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 425 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 374 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 404 + 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 424 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 376 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 406 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 327 - 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 429 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv7-row-check.js line 378 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 408 + 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 428 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv7-row-check.js line 380 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 410 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 330 - 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 432 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv7-row-check.js line 381 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 411 + 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 431 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv7-row-check.js line 383 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 413 799, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 412 798, "Field doesn't contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 396 797, "Field doesn't contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation from twl-tsv6-row-check.js line 403 796, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 393 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 378 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 502 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 429 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 487 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 501 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 431 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 489 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 383 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 507 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 434 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 492 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 232 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 506 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 436 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 494 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 230 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 220 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from notes-tsv7-table-check.js line 219 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv7-table-check.js line 219 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 463 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 447 - 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 468 - 787, "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 452 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 462 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 449 + 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 467 + 787, "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 454 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 541 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 512 + 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 515 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 333 - 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 435 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 384 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 414 + 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 434 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 386 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 416 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 336 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 438 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 387 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 417 - 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 200 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 437 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 389 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 419 + 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 203 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 750 775, "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 755 - 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 207 - 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 168 - 772, `Unexpected trailing word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 163 - 771, `Unexpected leading zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 146 - 770, `Unexpected leading word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 142 + 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 210 + 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 171 + 772, `Unexpected trailing word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 166 + 771, `Unexpected leading zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 149 + 770, `Unexpected leading word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 145 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,087 - 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation from plain-text-check.js line 225 + 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation from plain-text-check.js line 228 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,089 - 765, "Unexpected link", characterIndex, excerpt, location: ourLocation from field-text-check.js line 441 + 765, "Unexpected link", characterIndex, excerpt, location: ourLocation from field-text-check.js line 444 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 - 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 707 + 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 762 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 369 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 493 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 420 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 478 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 492 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 422 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 480 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 360 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 484 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 411 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 469 - 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 140 - 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 149 - 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 112 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 483 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 413 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 471 + 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 146 + 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 167 + 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 155 + 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 176 + 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 110 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from twl-tsv6-table-check.js line 101 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from notes-tsv7-table-check.js line 101 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv7-table-check.js line 101 - 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 182 - 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 185 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 358 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 488 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 540 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 648 - 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 701 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 364 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 401 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 440 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 494 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 546 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 598 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 654 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 445 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 552 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 604 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 209 + 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 180 + 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 183 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 362 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 491 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 543 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 651 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 703 + 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 756 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 368 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 405 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 444 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 497 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 549 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 601 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 657 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 709 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 449 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 555 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 607 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 207 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 197 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from notes-tsv7-table-check.js line 196 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv7-table-check.js line 196 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 228 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 226 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 216 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 215 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 215 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 196 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 194 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 184 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 183 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 183 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 200 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 198 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 188 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 187 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 187 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 202 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 200 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 190 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 189 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 189 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 206 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 218 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 204 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 216 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 194 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 206 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 193 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 205 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 193 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 205 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 222 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 220 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 210 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 209 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 209 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 238 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 236 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 226 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 225 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 225 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 236 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 234 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 224 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 223 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 223 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 - 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 422 + 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 425 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 952 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,020 - 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 723 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 380 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 417 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 458 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 510 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 568 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 670 - 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 725 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 382 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 419 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 460 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 512 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 570 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 620 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 672 - 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 742 - 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 736 + 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 778 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 384 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 421 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 462 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 513 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 571 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 673 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 725 + 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 780 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 386 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 423 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 464 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 515 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 573 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 623 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 675 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 727 + 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 797 + 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 791 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 254 - 638, "Only found whitespace", location: ourLocation from field-text-check.js line 108 - 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 128 + 638, "Only found whitespace", location: ourLocation from field-text-check.js line 111 + 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 131 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 990 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 117 - 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 149 - 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 157 - 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 153 - 583, "Unexpected newLine character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 236 - 582, "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 242 - 581, "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 248 - 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 352 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 216 + 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 150 + 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 158 + 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 167 + 583, "Unexpected newLine character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 239 + 582, "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 245 + 581, "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 251 + 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 356 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 214 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 204 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 203 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 203 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 194 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 192 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 182 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 181 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 181 - 539, "File starts with empty line", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 150 - 538, "File ends without newline character", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 155 + 539, "File starts with empty line", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 153 + 538, "File ends without newline character", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 158 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 - 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 225 - 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 135 + 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 229 + 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 149 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 - 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 106 + 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 121 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 950 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,124 - 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 270 - 375, "Divider without surrounding snippet", location: ourLocation from orig-quote-check.js line 331 + 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 332 + 375, "Divider without surrounding snippet", location: ourLocation from orig-quote-check.js line 332 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 390 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 472 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 514 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 529 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 441 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 466 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 457 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 499 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 456 - 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 517 - 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 532 - 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 444 - 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 469 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 438 - 373, "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 502 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 471 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 513 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 528 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 443 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 468 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 459 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 501 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 455 + 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 516 + 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 531 + 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 446 + 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 471 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 440 + 373, "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 504 + 349, "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 144 + 349, "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 163 + 348, "Markdown image link has no title text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 165 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 684 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 948 - 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 149 - 282, "Nesting of header levels seems confused", details: `recent indent levels=$JSON.stringify(indentLevels) but now $numLeadingSpaces`, lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 236 + 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 163 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 547 - 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 461 - 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 486 - 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 519 - 256, "Possibly missing current copyright year", details: `possibly expecting '$fullYearString'`, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 262 + 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 463 + 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 488 + 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 522 + 256, "Possibly missing current copyright year", details: `possibly expecting '$fullYearString'`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 270 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 - 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 319 - 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 264 - 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 270 + 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 322 + 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 267 + 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 273 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 343 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 445 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 394 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 424 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 444 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 396 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 345 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 447 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 396 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 446 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 398 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 347 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 449 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 398 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 448 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 400 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 349 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 451 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 400 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 - 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 209 - 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 255 - 158, `Unexpected space(s) beside divider $discontiguousDivider`, characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 264 - 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 278 - 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 643 - 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 692 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 342 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 479 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 531 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 589 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 639 - 138, "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 160 - 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 117 - 110, `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 137 - 109, `Unexpected leading space`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 139 - 107, "Unexpected leading line break", characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 178 - 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, excerpt, location: ourLocation from field-text-check.js line 211 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 450 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 402 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 432 + 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 256 + 158, `Unexpected space(s) beside divider $discontiguousDivider`, characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 265 + 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 279 + 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 658 + 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 747 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 346 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 483 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 534 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 592 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 642 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 694 + 138, "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 163 + 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 131 + 110, `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 140 + 109, `Unexpected leading space`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 142 + 107, "Unexpected leading line break", characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 181 + 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, excerpt, location: ourLocation from field-text-check.js line 214 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,165 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 248 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 184 - 94, "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 198 - 93, "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 203 + 94, "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 201 + 93, "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 206 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,117 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,119 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 468 - 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 152 - 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 157 - 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 304 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 265 + 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 155 + 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 160 + 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 305 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 263 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 253 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 252 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv7-table-check.js line 252 diff --git a/src/__tests__/__snapshots__/book-package-check.test.js.snap b/src/__tests__/__snapshots__/book-package-check.test.js.snap index ede570f79..2b0b02750 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -72,6 +72,7 @@ Object { "C": "1", "V": "1", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -89,6 +90,7 @@ Object { "C": "1", "V": "2", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -106,6 +108,7 @@ Object { "C": "1", "V": "6", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -123,6 +126,7 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -140,6 +144,7 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -157,6 +162,7 @@ Object { "C": "1", "V": "22", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -174,6 +180,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -191,6 +198,7 @@ Object { "C": "4", "V": "11", "bookID": "RUT", + "branch": "master", "details": "Expected 3-4 attributes but only found 2", "excerpt": "\\\\w שֵׁ֖ם|lemma=\\"שֵׁם\\" strong=\\"H8034\\"\\\\w*", "extra": "UHB", @@ -207,6 +215,7 @@ Object { "C": "4", "V": "11", "bookID": "RUT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-tw=\\"…", "extra": "UHB", @@ -224,6 +233,7 @@ Object { "C": "2", "V": "1", "bookID": "RUT", + "branch": "master", "excerpt": "…ew␣Ketiv)␣", "extra": "LT", "fieldName": "from \\\\f", @@ -240,6 +250,7 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "branch": "master", "excerpt": "…uncertain␣", "extra": "LT", "fieldName": "from \\\\f", @@ -256,6 +267,7 @@ Object { "C": "3", "V": "3", "bookID": "RUT", + "branch": "master", "excerpt": "…rew␣Qere)␣", "extra": "LT", "fieldName": "from \\\\f", @@ -272,6 +284,7 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "branch": "master", "excerpt": "…uscripts)␣", "extra": "LT", "fieldName": "from \\\\f", @@ -288,6 +301,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "it,'", "extra": "LT", @@ -304,6 +318,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "excerpt": "…uscripts)␣", "extra": "LT", "fieldName": "from \\\\f", @@ -320,6 +335,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "excerpt": "…rew␣Qere)␣", "extra": "LT", "fieldName": "from \\\\f", @@ -336,6 +352,7 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "branch": "master", "excerpt": "…ew␣Ketiv)␣", "extra": "LT", "fieldName": "from \\\\f", @@ -350,6 +367,7 @@ Object { }, Object { "bookID": "RUT", + "branch": "master", "characterIndex": 311926, "excerpt": "…n-e\\\\*\\\\zaln-e\\\\*.", "extra": "LT", @@ -363,6 +381,7 @@ Object { }, Object { "bookID": "RUT", + "branch": "master", "characterIndex": 54, "details": "'‘' opened on line 2217 character 179", "excerpt": "…ln-e\\\\*.”", @@ -378,6 +397,7 @@ Object { }, Object { "bookID": "RUT", + "branch": "master", "characterIndex": 178, "details": "2 unclosed sets", "excerpt": "…n-e\\\\*,␣‘\\\\zaln-s…", @@ -393,6 +413,7 @@ Object { }, Object { "bookID": "RUT", + "branch": "master", "details": "left=4, right=3", "extra": "LT", "filename": "08-RUT.usfm", @@ -407,6 +428,7 @@ Object { "C": "1", "V": "3", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Naomi's", "extra": "ST", @@ -423,6 +445,7 @@ Object { "C": "1", "V": "8", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…n-law,␣\\"Each", "extra": "ST", @@ -439,6 +462,7 @@ Object { "C": "1", "V": "8", "bookID": "RUT", + "branch": "master", "excerpt": "…in-law, \\"Each", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -455,6 +479,7 @@ Object { "C": "1", "V": "8", "bookID": "RUT", + "branch": "master", "characterIndex": 271, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -472,6 +497,7 @@ Object { "C": "1", "V": "8", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "mother's", "extra": "ST", @@ -488,6 +514,7 @@ Object { "C": "1", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "home.\\"", "extra": "ST", @@ -504,6 +531,7 @@ Object { "C": "1", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "said,␣\\"No!", "extra": "ST", @@ -520,6 +548,7 @@ Object { "C": "1", "V": "10", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"No!", "extra": "ST", "fieldName": "from \\\\w", @@ -536,6 +565,7 @@ Object { "C": "1", "V": "10", "bookID": "RUT", + "branch": "master", "characterIndex": 61, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -553,6 +583,7 @@ Object { "C": "1", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…atives.\\"", "extra": "ST", @@ -569,6 +600,7 @@ Object { "C": "1", "V": "11", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "said,␣\\"No,", "extra": "ST", @@ -585,6 +617,7 @@ Object { "C": "1", "V": "11", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"No,", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -601,6 +634,7 @@ Object { "C": "1", "V": "11", "bookID": "RUT", + "branch": "master", "characterIndex": 173, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -618,6 +652,7 @@ Object { "C": "1", "V": "13", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "mine.\\"", "extra": "ST", @@ -634,6 +669,7 @@ Object { "C": "1", "V": "15", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "her,␣\\"Look!", "extra": "ST", @@ -650,6 +686,7 @@ Object { "C": "1", "V": "15", "bookID": "RUT", + "branch": "master", "excerpt": "her, \\"Look!", "extra": "ST", "fieldName": "from \\\\w", @@ -666,6 +703,7 @@ Object { "C": "1", "V": "15", "bookID": "RUT", + "branch": "master", "characterIndex": 51, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -683,6 +721,7 @@ Object { "C": "1", "V": "15", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "her!\\"", "extra": "ST", @@ -699,6 +738,7 @@ Object { "C": "1", "V": "16", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…plied,␣\\"No!", "extra": "ST", @@ -715,6 +755,7 @@ Object { "C": "1", "V": "16", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"No!", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -731,6 +772,7 @@ Object { "C": "1", "V": "16", "bookID": "RUT", + "branch": "master", "characterIndex": 176, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -748,6 +790,7 @@ Object { "C": "1", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "die.\\"", "extra": "ST", @@ -764,6 +807,7 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…aimed,␣\\"It", "extra": "ST", @@ -780,6 +824,7 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "branch": "master", "excerpt": "…laimed, \\"It", "extra": "ST", "fieldName": "from \\\\w", @@ -796,6 +841,7 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "branch": "master", "characterIndex": 57, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -813,6 +859,7 @@ Object { "C": "1", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Naomi!\\"", "extra": "ST", @@ -829,6 +876,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "them,␣\\"You", "extra": "ST", @@ -845,6 +893,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "excerpt": "them, \\"You", "extra": "ST", "fieldName": "from \\\\w", @@ -861,6 +910,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -878,6 +928,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "means␣'pleasan…", "extra": "ST", @@ -894,6 +945,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "excerpt": "means 'pleasa…", "extra": "ST", "fieldName": "from \\\\w", @@ -910,6 +962,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…aln-e\\\\* '\\\\zaln-…", "extra": "ST", @@ -927,6 +980,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "means␣'bitter.…", "extra": "ST", @@ -943,6 +997,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "excerpt": "means 'bitter…", "extra": "ST", "fieldName": "from \\\\w", @@ -959,6 +1014,7 @@ Object { "C": "1", "V": "20", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…aln-e\\\\* '\\\\zaln-…", "extra": "ST", @@ -976,6 +1032,7 @@ Object { "C": "1", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "badly.\\"", "extra": "ST", @@ -992,6 +1049,7 @@ Object { "C": "2", "V": "1", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Naomi's", "extra": "ST", @@ -1008,6 +1066,7 @@ Object { "C": "2", "V": "1", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…limelek's", "extra": "ST", @@ -1024,6 +1083,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Naomi,␣\\"Let", "extra": "ST", @@ -1040,6 +1100,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "excerpt": "Naomi, \\"Let", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -1056,6 +1117,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "characterIndex": 165, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1073,6 +1135,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…ission.\\"", "extra": "ST", @@ -1089,6 +1152,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"Go", "extra": "ST", @@ -1105,6 +1169,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"Go", "extra": "ST", "fieldName": "from \\\\w", @@ -1121,6 +1186,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "characterIndex": 64, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1138,6 +1204,7 @@ Object { "C": "2", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…ughter.\\"", "extra": "ST", @@ -1154,6 +1221,7 @@ Object { "C": "2", "V": "3", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…limelek's", "extra": "ST", @@ -1170,6 +1238,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…aying,␣\\"May", "extra": "ST", @@ -1186,6 +1255,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "excerpt": "saying, \\"May", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -1202,6 +1272,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "characterIndex": 175, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1219,6 +1290,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "you!\\"", "extra": "ST", @@ -1235,6 +1307,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"May", "extra": "ST", @@ -1251,6 +1324,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"May", "extra": "ST", "fieldName": "from \\\\w", @@ -1267,6 +1341,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "characterIndex": 55, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1284,6 +1359,7 @@ Object { "C": "2", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "you!\\"", "extra": "ST", @@ -1300,6 +1376,7 @@ Object { "C": "2", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…reman,␣\\"Who", "extra": "ST", @@ -1316,6 +1393,7 @@ Object { "C": "2", "V": "5", "bookID": "RUT", + "branch": "master", "excerpt": "…oreman, \\"Who", "extra": "ST", "fieldName": "from \\\\w", @@ -1332,6 +1410,7 @@ Object { "C": "2", "V": "5", "bookID": "RUT", + "branch": "master", "characterIndex": 82, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1349,6 +1428,7 @@ Object { "C": "2", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "to?\\"", "extra": "ST", @@ -1365,6 +1445,7 @@ Object { "C": "2", "V": "6", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"She", "extra": "ST", @@ -1381,6 +1462,7 @@ Object { "C": "2", "V": "6", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"She", "extra": "ST", "fieldName": "from \\\\w", @@ -1397,6 +1479,7 @@ Object { "C": "2", "V": "6", "bookID": "RUT", + "branch": "master", "characterIndex": 100, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1414,6 +1497,7 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "me,␣'Please", "extra": "ST", @@ -1430,6 +1514,7 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "branch": "master", "excerpt": "me, 'Please", "extra": "ST", "fieldName": "from \\\\w", @@ -1446,6 +1531,7 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "branch": "master", "characterIndex": 50, "excerpt": "…ln-e\\\\*, '\\\\zaln-…", "extra": "ST", @@ -1463,6 +1549,7 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "behind.'", "extra": "ST", @@ -1479,6 +1566,7 @@ Object { "C": "2", "V": "7", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…helter.\\"", "extra": "ST", @@ -1495,6 +1583,7 @@ Object { "C": "2", "V": "8", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Ruth,␣\\"Young", "extra": "ST", @@ -1511,6 +1600,7 @@ Object { "C": "2", "V": "8", "bookID": "RUT", + "branch": "master", "excerpt": "Ruth, \\"Young", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -1527,6 +1617,7 @@ Object { "C": "2", "V": "8", "bookID": "RUT", + "branch": "master", "characterIndex": 158, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1544,6 +1635,7 @@ Object { "C": "2", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "filled.\\"", "extra": "ST", @@ -1560,6 +1652,7 @@ Object { "C": "2", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…aimed,␣\\"Why", "extra": "ST", @@ -1576,6 +1669,7 @@ Object { "C": "2", "V": "10", "bookID": "RUT", + "branch": "master", "excerpt": "…laimed, \\"Why", "extra": "ST", "fieldName": "from \\\\w", @@ -1592,6 +1686,7 @@ Object { "C": "2", "V": "10", "bookID": "RUT", + "branch": "master", "characterIndex": 57, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1609,6 +1704,7 @@ Object { "C": "2", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…eigner!\\"", "extra": "ST", @@ -1625,6 +1721,7 @@ Object { "C": "2", "V": "11", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"People", "extra": "ST", @@ -1641,6 +1738,7 @@ Object { "C": "2", "V": "11", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"People", "extra": "ST", "fieldName": "from \\\\w", @@ -1657,6 +1755,7 @@ Object { "C": "2", "V": "11", "bookID": "RUT", + "branch": "master", "characterIndex": 82, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1674,6 +1773,7 @@ Object { "C": "2", "V": "12", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "full.\\"", "extra": "ST", @@ -1690,6 +1790,7 @@ Object { "C": "2", "V": "13", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"Sir,", "extra": "ST", @@ -1706,6 +1807,7 @@ Object { "C": "2", "V": "13", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"Sir,", "extra": "ST", "fieldName": "from \\\\w", @@ -1722,6 +1824,7 @@ Object { "C": "2", "V": "13", "bookID": "RUT", + "branch": "master", "characterIndex": 55, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1739,6 +1842,7 @@ Object { "C": "2", "V": "13", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "girls!\\"", "extra": "ST", @@ -1755,6 +1859,7 @@ Object { "C": "2", "V": "14", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "her,␣\\"Come", "extra": "ST", @@ -1771,6 +1876,7 @@ Object { "C": "2", "V": "14", "bookID": "RUT", + "branch": "master", "excerpt": "her, \\"Come", "extra": "ST", "fieldName": "from \\\\w", @@ -1787,6 +1893,7 @@ Object { "C": "2", "V": "14", "bookID": "RUT", + "branch": "master", "characterIndex": 51, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1804,6 +1911,7 @@ Object { "C": "2", "V": "14", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "it.\\"", "extra": "ST", @@ -1820,6 +1928,7 @@ Object { "C": "2", "V": "15", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…rkers,␣\\"Even", "extra": "ST", @@ -1836,6 +1945,7 @@ Object { "C": "2", "V": "15", "bookID": "RUT", + "branch": "master", "excerpt": "…orkers, \\"Even", "extra": "ST", "fieldName": "from \\\\w", @@ -1852,6 +1962,7 @@ Object { "C": "2", "V": "15", "bookID": "RUT", + "branch": "master", "characterIndex": 64, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1869,6 +1980,7 @@ Object { "C": "2", "V": "16", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "her.\\"", "extra": "ST", @@ -1885,6 +1997,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "her,␣\\"Where", "extra": "ST", @@ -1901,6 +2014,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "excerpt": "her, \\"Where", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -1917,6 +2031,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "characterIndex": 155, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1934,6 +2049,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "you.\\"", "extra": "ST", @@ -1950,6 +2066,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "said,␣\\"The", "extra": "ST", @@ -1966,6 +2083,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"The", "extra": "ST", "fieldName": "from \\\\w", @@ -1982,6 +2100,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -1999,6 +2118,7 @@ Object { "C": "2", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Boaz.\\"", "extra": "ST", @@ -2015,6 +2135,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…n-law,␣\\"May", "extra": "ST", @@ -2031,6 +2152,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "excerpt": "…in-law, \\"May", "extra": "ST", "fieldName": "from \\\\w", @@ -2047,6 +2169,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "characterIndex": 145, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2064,6 +2187,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "died.\\"", "extra": "ST", @@ -2080,6 +2204,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "added,␣\\"That", "extra": "ST", @@ -2096,6 +2221,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "excerpt": "added, \\"That", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -2112,6 +2238,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "characterIndex": 292, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2129,6 +2256,7 @@ Object { "C": "2", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "family.\\"", "extra": "ST", @@ -2145,6 +2273,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "said,␣\\"He", "extra": "ST", @@ -2161,6 +2290,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"He", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -2177,6 +2307,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "characterIndex": 173, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2194,6 +2325,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "me,␣'Stay", "extra": "ST", @@ -2210,6 +2342,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "excerpt": "me, 'Stay", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -2226,6 +2359,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "characterIndex": 162, "excerpt": "…ln-e\\\\*, '\\\\zaln-…", "extra": "ST", @@ -2243,6 +2377,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "field.'\\"", "extra": "ST", @@ -2259,6 +2394,7 @@ Object { "C": "2", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "field.'\\"", "extra": "ST", @@ -2275,6 +2411,7 @@ Object { "C": "2", "V": "22", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Ruth,␣\\"My", "extra": "ST", @@ -2291,6 +2428,7 @@ Object { "C": "2", "V": "22", "bookID": "RUT", + "branch": "master", "excerpt": "Ruth, \\"My", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -2307,6 +2445,7 @@ Object { "C": "2", "V": "22", "bookID": "RUT", + "branch": "master", "characterIndex": 158, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2324,6 +2463,7 @@ Object { "C": "2", "V": "22", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "else's", "extra": "ST", @@ -2340,6 +2480,7 @@ Object { "C": "2", "V": "22", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "you.\\"", "extra": "ST", @@ -2356,6 +2497,7 @@ Object { "C": "2", "V": "23", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Boaz's", "extra": "ST", @@ -2372,6 +2514,7 @@ Object { "C": "3", "V": "1", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Ruth,␣\\"My", "extra": "ST", @@ -2388,6 +2531,7 @@ Object { "C": "3", "V": "1", "bookID": "RUT", + "branch": "master", "excerpt": "Ruth, \\"My", "extra": "ST", "fieldName": "from \\\\w", @@ -2404,6 +2548,7 @@ Object { "C": "3", "V": "1", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2421,6 +2566,7 @@ Object { "C": "3", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Boaz's", "extra": "ST", @@ -2437,6 +2583,7 @@ Object { "C": "3", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "do.\\"", "extra": "ST", @@ -2453,6 +2600,7 @@ Object { "C": "3", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"I", "extra": "ST", @@ -2469,6 +2617,7 @@ Object { "C": "3", "V": "5", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"I", "extra": "ST", "fieldName": "from \\\\w", @@ -2485,6 +2634,7 @@ Object { "C": "3", "V": "5", "bookID": "RUT", + "branch": "master", "characterIndex": 64, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2502,6 +2652,7 @@ Object { "C": "3", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "do.\\"", "extra": "ST", @@ -2518,6 +2669,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "her,␣\\"Who", "extra": "ST", @@ -2534,6 +2686,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "excerpt": "her, \\"Who", "extra": "ST", "fieldName": "from \\\\w", @@ -2550,6 +2703,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "characterIndex": 51, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2567,6 +2721,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "you?\\"", "extra": "ST", @@ -2583,6 +2738,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"I", "extra": "ST", @@ -2599,6 +2755,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"I", "extra": "ST", "fieldName": "from \\\\w", @@ -2615,6 +2772,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "characterIndex": 55, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2632,6 +2790,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "husband's", "extra": "ST", @@ -2648,6 +2807,7 @@ Object { "C": "3", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "me.\\"", "extra": "ST", @@ -2664,6 +2824,7 @@ Object { "C": "3", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"May", "extra": "ST", @@ -2680,6 +2841,7 @@ Object { "C": "3", "V": "10", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"May", "extra": "ST", "fieldName": "from \\\\w", @@ -2696,6 +2858,7 @@ Object { "C": "3", "V": "10", "bookID": "RUT", + "branch": "master", "characterIndex": 55, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2713,6 +2876,7 @@ Object { "C": "3", "V": "12", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Naomi's", "extra": "ST", @@ -2729,6 +2893,7 @@ Object { "C": "3", "V": "13", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…orning.\\"", "extra": "ST", @@ -2745,6 +2910,7 @@ Object { "C": "3", "V": "14", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "added,␣\\"It", "extra": "ST", @@ -2761,6 +2927,7 @@ Object { "C": "3", "V": "14", "bookID": "RUT", + "branch": "master", "excerpt": "added, \\"It", "extra": "ST", "fieldName": "from \\\\w", @@ -2777,6 +2944,7 @@ Object { "C": "3", "V": "14", "bookID": "RUT", + "branch": "master", "characterIndex": 53, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2794,6 +2962,7 @@ Object { "C": "3", "V": "14", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "here.\\"", "extra": "ST", @@ -2810,6 +2979,7 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "her,␣\\"Bring", "extra": "ST", @@ -2826,6 +2996,7 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "branch": "master", "excerpt": "her, \\"Bring", "extra": "ST", "fieldName": "from \\\\w", @@ -2842,6 +3013,7 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "branch": "master", "characterIndex": 51, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2859,6 +3031,7 @@ Object { "C": "3", "V": "15", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "out.\\"", "extra": "ST", @@ -2875,6 +3048,7 @@ Object { "C": "3", "V": "16", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "her,␣\\"Is", "extra": "ST", @@ -2891,6 +3065,7 @@ Object { "C": "3", "V": "16", "bookID": "RUT", + "branch": "master", "excerpt": "her, \\"Is", "extra": "ST", "fieldName": "from \\\\w", @@ -2907,6 +3082,7 @@ Object { "C": "3", "V": "16", "bookID": "RUT", + "branch": "master", "characterIndex": 51, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2924,6 +3100,7 @@ Object { "C": "3", "V": "16", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…ughter?\\"", "extra": "ST", @@ -2940,6 +3117,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Naomi,␣\\"He", "extra": "ST", @@ -2956,6 +3134,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "excerpt": "Naomi, \\"He", "extra": "ST", "fieldName": "from \\\\w", @@ -2972,6 +3151,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "characterIndex": 53, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -2989,6 +3169,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…aying,␣'I", "extra": "ST", @@ -3005,6 +3186,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "excerpt": "saying, 'I", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -3021,6 +3203,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "characterIndex": 286, "excerpt": "…ln-e\\\\*, '\\\\zaln-…", "extra": "ST", @@ -3038,6 +3221,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…thing.'\\"", "extra": "ST", @@ -3054,6 +3238,7 @@ Object { "C": "3", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…othing.'\\"", "extra": "ST", @@ -3070,6 +3255,7 @@ Object { "C": "3", "V": "18", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "said,␣\\"My", "extra": "ST", @@ -3086,6 +3272,7 @@ Object { "C": "3", "V": "18", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"My", "extra": "ST", "fieldName": "from \\\\w", @@ -3102,6 +3289,7 @@ Object { "C": "3", "V": "18", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3119,6 +3307,7 @@ Object { "C": "3", "V": "18", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "today.\\"", "extra": "ST", @@ -3135,6 +3324,7 @@ Object { "C": "4", "V": "1", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "said,␣\\"Come", "extra": "ST", @@ -3151,6 +3341,7 @@ Object { "C": "4", "V": "1", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"Come", "extra": "ST", "fieldName": "from \\\\w", @@ -3167,6 +3358,7 @@ Object { "C": "4", "V": "1", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3184,6 +3376,7 @@ Object { "C": "4", "V": "1", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "down.\\"", "extra": "ST", @@ -3200,6 +3393,7 @@ Object { "C": "4", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "them,␣\\"Please", "extra": "ST", @@ -3216,6 +3410,7 @@ Object { "C": "4", "V": "2", "bookID": "RUT", + "branch": "master", "excerpt": "them, \\"Please", "extra": "ST", "fieldName": "from \\\\w", @@ -3232,6 +3427,7 @@ Object { "C": "4", "V": "2", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3249,6 +3445,7 @@ Object { "C": "4", "V": "2", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…siness.\\"", "extra": "ST", @@ -3265,6 +3462,7 @@ Object { "C": "4", "V": "3", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…ative,␣\\"Did", "extra": "ST", @@ -3281,6 +3479,7 @@ Object { "C": "4", "V": "3", "bookID": "RUT", + "branch": "master", "excerpt": "…lative, \\"Did", "extra": "ST", "fieldName": "from \\\\w", @@ -3297,6 +3496,7 @@ Object { "C": "4", "V": "3", "bookID": "RUT", + "branch": "master", "characterIndex": 56, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3314,6 +3514,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "you.\\"", "extra": "ST", @@ -3330,6 +3531,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…plied,␣\\"I", "extra": "ST", @@ -3346,6 +3548,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "excerpt": "…eplied, \\"I", "extra": "ST", "fieldName": "from \\\\w", @@ -3362,6 +3565,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "characterIndex": 55, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3379,6 +3583,7 @@ Object { "C": "4", "V": "4", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "it!\\"", "extra": "ST", @@ -3395,6 +3600,7 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "him,␣\\"When", "extra": "ST", @@ -3411,6 +3617,7 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "branch": "master", "excerpt": "him, \\"When", "extra": "ST", "fieldName": "from \\\\w", @@ -3427,6 +3634,7 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "branch": "master", "characterIndex": 51, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3444,6 +3652,7 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…elative's", "extra": "ST", @@ -3460,6 +3669,7 @@ Object { "C": "4", "V": "5", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "…usband.\\"", "extra": "ST", @@ -3476,6 +3686,7 @@ Object { "C": "4", "V": "6", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "said,␣\\"Then", "extra": "ST", @@ -3492,6 +3703,7 @@ Object { "C": "4", "V": "6", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"Then", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -3508,6 +3720,7 @@ Object { "C": "4", "V": "6", "bookID": "RUT", + "branch": "master", "characterIndex": 173, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3525,6 +3738,7 @@ Object { "C": "4", "V": "6", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "son's", "extra": "ST", @@ -3541,6 +3755,7 @@ Object { "C": "4", "V": "6", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "it.\\"", "extra": "ST", @@ -3557,6 +3772,7 @@ Object { "C": "4", "V": "8", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Boaz,␣\\"You", "extra": "ST", @@ -3573,6 +3789,7 @@ Object { "C": "4", "V": "8", "bookID": "RUT", + "branch": "master", "excerpt": "Boaz, \\"You", "extra": "ST", "fieldName": "from \\\\w", @@ -3589,6 +3806,7 @@ Object { "C": "4", "V": "8", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3606,6 +3824,7 @@ Object { "C": "4", "V": "8", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "…urself!\\"", "extra": "ST", @@ -3622,6 +3841,7 @@ Object { "C": "4", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "there,␣\\"Today", "extra": "ST", @@ -3638,6 +3858,7 @@ Object { "C": "4", "V": "9", "bookID": "RUT", + "branch": "master", "excerpt": "there, \\"Today", "extra": "ST", "fieldName": "from \\\\w", @@ -3654,6 +3875,7 @@ Object { "C": "4", "V": "9", "bookID": "RUT", + "branch": "master", "characterIndex": 53, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3671,6 +3893,7 @@ Object { "C": "4", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Mahlon's", "extra": "ST", @@ -3687,6 +3910,7 @@ Object { "C": "4", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "Mahlon's", "extra": "ST", @@ -3703,6 +3927,7 @@ Object { "C": "4", "V": "10", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "them.\\"", "extra": "ST", @@ -3719,6 +3944,7 @@ Object { "C": "4", "V": "11", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "said,␣\\"Yes,", "extra": "ST", @@ -3735,6 +3961,7 @@ Object { "C": "4", "V": "11", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"Yes,", "extra": "ST", "fieldName": "from \\\\w", @@ -3751,6 +3978,7 @@ Object { "C": "4", "V": "11", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3768,6 +3996,7 @@ Object { "C": "4", "V": "12", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "woman.\\"", "extra": "ST", @@ -3784,6 +4013,7 @@ Object { "C": "4", "V": "14", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Naomi,␣\\"Praise", "extra": "ST", @@ -3800,6 +4030,7 @@ Object { "C": "4", "V": "14", "bookID": "RUT", + "branch": "master", "excerpt": "Naomi, \\"Praise", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -3816,6 +4047,7 @@ Object { "C": "4", "V": "14", "bookID": "RUT", + "branch": "master", "characterIndex": 165, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3833,6 +4065,7 @@ Object { "C": "4", "V": "15", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "old.\\"", "extra": "ST", @@ -3849,6 +4082,7 @@ Object { "C": "4", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "said,␣\\"It", "extra": "ST", @@ -3865,6 +4099,7 @@ Object { "C": "4", "V": "17", "bookID": "RUT", + "branch": "master", "excerpt": "said, \\"It", "extra": "ST", "fieldName": "from \\\\zaln-s", @@ -3881,6 +4116,7 @@ Object { "C": "4", "V": "17", "bookID": "RUT", + "branch": "master", "characterIndex": 167, "excerpt": "…ln-e\\\\*, \\"\\\\zaln-…", "extra": "ST", @@ -3898,6 +4134,7 @@ Object { "C": "4", "V": "17", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\w)", "excerpt": "son!\\"", "extra": "ST", @@ -3914,6 +4151,7 @@ Object { "C": "4", "V": "18", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Perez's", "extra": "ST", @@ -3930,6 +4168,7 @@ Object { "C": "4", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\v)", "excerpt": "…␣Hezron's", "extra": "ST", @@ -3946,6 +4185,7 @@ Object { "C": "4", "V": "19", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Ram's", "extra": "ST", @@ -3962,6 +4202,7 @@ Object { "C": "4", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\v)", "excerpt": "…minadab's", "extra": "ST", @@ -3978,6 +4219,7 @@ Object { "C": "4", "V": "20", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Nahshon's", "extra": "ST", @@ -3994,6 +4236,7 @@ Object { "C": "4", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\v)", "excerpt": "…␣Salmon's", "extra": "ST", @@ -4010,6 +4253,7 @@ Object { "C": "4", "V": "21", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Boaz's", "extra": "ST", @@ -4026,6 +4270,7 @@ Object { "C": "4", "V": "22", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\v)", "excerpt": "22␣Obed's", "extra": "ST", @@ -4042,6 +4287,7 @@ Object { "C": "4", "V": "22", "bookID": "RUT", + "branch": "master", "details": "(line marker=\\\\zaln-s)", "excerpt": "Jesse's", "extra": "ST", @@ -4056,6 +4302,7 @@ Object { }, Object { "bookID": "RUT", + "branch": "master", "characterIndex": 324394, "excerpt": "…n-e\\\\*\\\\zaln-e\\\\*.", "extra": "ST", @@ -4071,6 +4318,7 @@ Object { "C": "1", "V": "6", "bookID": "RUT", + "branch": "master", "excerpt": "figs-idiom", "extra": "TN", "fieldName": "SupportReference", @@ -4088,6 +4336,7 @@ Object { "C": "1", "V": "6", "bookID": "RUT", + "branch": "master", "details": "(SR='figs-idiom')", "excerpt": "figs-synecdoche", "extra": "TN", @@ -4106,6 +4355,7 @@ Object { "C": "1", "V": "7", "bookID": "RUT", + "branch": "master", "excerpt": "figs-idiom", "extra": "TN", "fieldName": "SupportReference", @@ -4123,6 +4373,7 @@ Object { "C": "2", "V": "9", "bookID": "RUT", + "branch": "master", "characterIndex": 52, "excerpt": "…itality - that …", "extra": "TN", @@ -4141,6 +4392,7 @@ Object { "C": "2", "V": "9", "bookID": "RUT", + "branch": "master", "details": "(empty SR field)", "excerpt": "figs-euphemism", "extra": "TN", @@ -4159,6 +4411,7 @@ Object { "C": "2", "V": "11", "bookID": "RUT", + "branch": "master", "excerpt": "figs-idiom", "extra": "TN", "fieldName": "SupportReference", @@ -4176,6 +4429,7 @@ Object { "C": "2", "V": "12", "bookID": "RUT", + "branch": "master", "details": "need to carefully check \\"[Doublet](../figs-doublet/01.md)\\"", "extra": "TN", "fieldName": "OccurrenceNote", @@ -4193,6 +4447,7 @@ Object { "C": "3", "V": "12", "bookID": "RUT", + "branch": "master", "details": "(empty SR field)", "excerpt": "grammar-connect-logic-contrast", "extra": "TN", @@ -4211,15 +4466,16 @@ Object { "C": "4", "V": "intro", "bookID": "RUT", - "characterIndex": 407, - "excerpt": "…in␣him.␣<br><br…", + "branch": "master", + "characterIndex": 313, + "excerpt": "…t␣in␣him.␣", "extra": "TN", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", "lineNumber": 205, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected trailing space(s) before break", - "priority": 94, + "message": "Unexpected trailing space(s)", + "priority": 95, "repoCode": "TN", "repoName": "en_tn", "rowID": "pz6m", @@ -4229,6 +4485,7 @@ Object { "C": "4", "V": "7", "bookID": "RUT", + "branch": "master", "details": "(empty SR field)", "excerpt": "figs-idiom", "extra": "TN", @@ -4247,6 +4504,7 @@ Object { "C": "4", "V": "14", "bookID": "RUT", + "branch": "master", "characterIndex": 155, "excerpt": "…se” or “ we giv…", "extra": "TN", @@ -4262,155 +4520,9318 @@ Object { "username": "unfoldingWord", }, Object { - "C": "4", - "V": "15", + "C": "4", + "V": "15", + "bookID": "RUT", + "branch": "master", + "excerpt": "grammar-connect-logic-result", + "extra": "TN", + "fieldName": "SupportReference", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 260, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Link to TA should also be in OccurrenceNote", + "priority": 787, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab48", + "username": "unfoldingWord", + }, + Object { + "C": "1", + "V": "3", + "bookID": "RUT", + "characterIndex": 69, + "excerpt": "…aomi␣a␣widow.\\\\n\\\\n", + "extra": "TQ", + "filename": "rut/01/03.md", + "location": " in unfoldingWord (master)", + "message": "File ends with additional blank line(s)", + "priority": 138, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "1", + "V": "20", + "bookID": "RUT", + "characterIndex": 166, + "excerpt": "…erly␣with␣her.␣", + "extra": "TQ", + "filename": "rut/01/20.md", + "location": " in unfoldingWord (master)", + "message": "File ends without newline character", + "priority": 538, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "20", + "bookID": "RUT", + "characterIndex": 122, + "excerpt": "…ed␣by␣Yahweh”\\\\n\\\\n", + "extra": "TQ", + "filename": "rut/02/20.md", + "location": " in unfoldingWord (master)", + "message": "File ends with additional blank line(s)", + "priority": 138, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "3", + "V": "9", + "bookID": "RUT", + "characterIndex": 75, + "excerpt": "…deemer.”", + "extra": "TQ", + "filename": "rut/03/09.md", + "lineNumber": 3, + "location": " in unfoldingWord (master)", + "message": "Unexpected ” closing character (no matching opener)", + "priority": 774, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "3", + "V": "9", + "bookID": "RUT", + "details": "left=0, right=1", + "extra": "TQ", + "filename": "rut/03/09.md", + "location": " in unfoldingWord (master)", + "message": "Mismatched “” characters", + "priority": 162, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "4", + "V": "5", + "bookID": "RUT", + "characterIndex": 188, + "excerpt": "…␣inheritance.\\\\n\\\\n", + "extra": "TQ", + "filename": "rut/04/05.md", + "location": " in unfoldingWord (master)", + "message": "File ends with additional blank line(s)", + "priority": 138, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "4", + "V": "12", + "bookID": "RUT", + "characterIndex": 147, + "excerpt": "…son␣to␣Judah.\\\\n\\\\n", + "extra": "TQ", + "filename": "rut/04/12.md", + "location": " in unfoldingWord (master)", + "message": "File ends with additional blank line(s)", + "priority": 138, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "4", + "V": "15", + "bookID": "RUT", + "characterIndex": 179, + "excerpt": "…on␣for␣Naomi.\\\\n\\\\n", + "extra": "TQ", + "filename": "rut/04/15.md", + "location": " in unfoldingWord (master)", + "message": "File ends with additional blank line(s)", + "priority": 138, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "C": "4", + "V": "17", + "bookID": "RUT", + "characterIndex": 157, + "excerpt": "…her␣of␣David.\\\\n\\\\n", + "extra": "TQ", + "filename": "rut/04/17.md", + "location": " in unfoldingWord (master)", + "message": "File ends with additional blank line(s)", + "priority": 138, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, + Object { + "details": "username=unfoldingWord", + "extra": "SN", + "location": " in SN in en RUT book package from unfoldingWord master branch", + "message": "Repository doesn’t exist", + "priority": 997, + "repoCode": "SN", + "repoName": "en_sn", + "username": "unfoldingWord", + }, + Object { + "bookID": "RUT", + "branch": "master", + "details": "expected 'Reference ID Tags SupportReference Quote Occurrence Note'", + "excerpt": "Book Chapter Verse ID SupportReference OrigQuote Occurrence GLQuote OccurrenceNote", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 1, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Bad TSV header", + "priority": 988, + "repoCode": "SN", + "repoName": "en_sn", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 2, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "front", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 3, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 4, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 5, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 6, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 7, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 8, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 9, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 10, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 11, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 12, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 13, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 14, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 15, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 16, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 17, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 18, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 19, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 20, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 21, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 22, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 23, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 24, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 25, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 26, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 27, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 28, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 29, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 30, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 31, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 32, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 33, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 34, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 35, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 36, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 37, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 38, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 39, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 40, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 41, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 42, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 43, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 44, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 45, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 46, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 47, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 48, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 49, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 50, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 51, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 52, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 53, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 54, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 55, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 56, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 57, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 58, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 59, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 60, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 61, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 62, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 63, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 64, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 65, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 66, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 67, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 68, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 69, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 70, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 71, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 72, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 73, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 74, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 75, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 76, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 77, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 78, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 79, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 80, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 81, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 82, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 83, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 84, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 85, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 86, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 87, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 88, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 89, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 90, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 91, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 92, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 93, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 94, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 95, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 96, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 97, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 98, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 99, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 100, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 101, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 102, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 103, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 104, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 105, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 106, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 107, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 108, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 109, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 110, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 111, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 112, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 113, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 114, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 115, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 116, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 117, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 118, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 119, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 120, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 121, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 122, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 123, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 124, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 125, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 126, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 127, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 128, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 129, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 130, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 131, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 132, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 133, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 134, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 135, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 136, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 137, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 138, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 139, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 140, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 141, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 142, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 143, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 144, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 145, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 146, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 147, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 148, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 149, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 150, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 151, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 152, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 153, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 154, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 155, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 156, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 157, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 158, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 159, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 160, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 161, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 162, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 163, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 164, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 165, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 166, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 167, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 168, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 169, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 170, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 171, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 172, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 173, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 174, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 175, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 176, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 177, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 178, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 179, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 180, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 181, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 182, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 183, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 184, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 185, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 186, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 187, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 188, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 189, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 190, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 191, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 192, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 193, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 194, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 195, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 196, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 197, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 198, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 199, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 200, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 201, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 202, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 203, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 204, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 205, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 206, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 207, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 208, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 209, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 210, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 211, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 212, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 213, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 214, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 215, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 216, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 217, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 218, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 219, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 220, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 221, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 222, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 223, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 224, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 225, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 226, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 227, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 228, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 229, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 230, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 231, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 232, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 233, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 234, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 235, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 236, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 237, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 238, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 239, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 240, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 241, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 242, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 243, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 244, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 245, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 246, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 247, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 248, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 249, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 250, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 251, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 252, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 253, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 254, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 255, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 256, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 257, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 258, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 259, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 260, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 261, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 262, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 263, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 264, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 265, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 266, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 267, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 268, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SN", + "filename": "RUT_sn.tsv", + "lineNumber": 269, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "details": "username=unfoldingWord", + "extra": "SQ", + "location": " in SQ in en RUT book package from unfoldingWord master branch", + "message": "Repository doesn’t exist", + "priority": 997, + "repoCode": "SQ", + "repoName": "en_sq", + "username": "unfoldingWord", + }, + Object { + "bookID": "RUT", + "branch": "master", + "details": "expected 'Reference ID Tags Quote Occurrence Question Response'", + "excerpt": "Book Chapter Verse ID SupportReference OrigQuote Occurrence GLQuote OccurrenceNote", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 1, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Bad TSV header", + "priority": 988, + "repoCode": "SQ", + "repoName": "en_sq", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 2, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "front", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 3, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 4, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 5, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 6, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 7, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 8, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 9, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 10, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 11, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 12, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 13, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 14, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 15, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 16, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 17, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 18, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 19, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 20, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 21, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 22, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 23, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 24, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 25, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 26, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 27, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 28, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 29, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 30, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 31, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 32, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 33, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 34, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 35, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 36, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 37, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 38, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 39, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 40, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 41, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 42, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 43, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 44, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 45, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 46, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 47, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 48, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 49, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 50, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 51, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 52, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 53, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 54, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 55, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 56, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 57, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 58, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 59, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 60, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 61, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 62, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 63, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 64, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 65, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 66, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 67, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "1", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 68, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 69, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 70, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 71, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 72, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 73, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 74, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 75, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 76, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 77, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 78, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 79, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 80, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 81, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 82, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 83, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 84, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 85, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 86, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 87, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 88, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 89, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 90, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 91, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 92, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 93, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 94, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 95, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 96, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 97, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 98, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 99, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 100, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 101, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 102, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 103, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 104, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 105, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 106, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 107, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 108, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 109, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 110, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 111, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 112, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 113, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 114, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 115, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 116, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 117, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 118, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 119, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 120, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 121, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 122, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 123, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 124, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 125, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 126, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 127, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 128, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 129, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 130, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 131, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 132, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 133, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 134, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 135, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 136, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 137, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 138, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 139, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 140, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 141, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 142, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 143, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "2", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 144, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 145, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 146, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 147, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 148, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 149, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 150, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 151, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 152, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 153, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 154, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 155, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 156, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 157, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 158, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 159, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 160, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 161, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 162, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 163, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 164, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 165, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 166, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 167, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 168, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 169, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 170, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 171, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 172, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 173, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 174, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 175, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 176, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 177, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 178, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 179, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 180, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 181, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 182, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 183, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 184, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 185, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 186, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 187, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 188, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 189, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 190, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 191, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 192, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 193, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 194, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 195, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 196, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 197, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 198, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 199, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 200, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 201, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 202, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 203, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 204, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "3", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 205, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 206, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 207, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 208, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 209, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 210, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 211, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 212, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 213, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 214, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 215, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 216, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 217, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 218, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 219, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 220, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 221, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 222, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 223, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 224, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 225, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 226, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 227, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 228, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 229, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 230, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 231, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 232, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 233, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 234, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 235, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 236, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 237, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 238, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 239, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 240, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 241, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 242, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 243, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 244, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 245, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 246, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 247, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 248, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 249, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 250, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 251, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 252, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 253, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 254, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 255, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 256, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 257, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 258, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, + "bookID": "RUT", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 259, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", + "username": "unfoldingWord", + }, + Object { + "C": "RUT", + "V": undefined, "bookID": "RUT", - "excerpt": "grammar-connect-logic-result", - "extra": "TN", - "fieldName": "SupportReference", - "filename": "en_tn_08-RUT.tsv", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", "lineNumber": 260, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Link to TA should also be in OccurrenceNote", - "priority": 787, - "repoCode": "TN", - "repoName": "en_tn", - "rowID": "ab48", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "3", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 69, - "excerpt": "…aomi␣a␣widow.\\\\n\\\\n", - "extra": "TQ", - "filename": "rut/01/03.md", - "location": " in unfoldingWord (master)", - "message": "File ends with additional blank line(s)", - "priority": 138, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 261, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "20", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 166, - "excerpt": "…erly␣with␣her.␣", - "extra": "TQ", - "filename": "rut/01/20.md", - "location": " in unfoldingWord (master)", - "message": "File ends without newline character", - "priority": 538, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 262, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "20", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 122, - "excerpt": "…ed␣by␣Yahweh”\\\\n\\\\n", - "extra": "TQ", - "filename": "rut/02/20.md", - "location": " in unfoldingWord (master)", - "message": "File ends with additional blank line(s)", - "priority": 138, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 263, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "3", - "V": "9", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 75, - "excerpt": "…deemer.”", - "extra": "TQ", - "filename": "rut/03/09.md", - "lineNumber": 3, - "location": " in unfoldingWord (master)", - "message": "Unexpected ” closing character (no matching opener)", - "priority": 774, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 264, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "3", - "V": "9", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "details": "left=0, right=1", - "extra": "TQ", - "filename": "rut/03/09.md", - "location": " in unfoldingWord (master)", - "message": "Mismatched “” characters", - "priority": 162, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 265, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "4", - "V": "5", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 188, - "excerpt": "…␣inheritance.\\\\n\\\\n", - "extra": "TQ", - "filename": "rut/04/05.md", - "location": " in unfoldingWord (master)", - "message": "File ends with additional blank line(s)", - "priority": 138, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 266, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "4", - "V": "12", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 147, - "excerpt": "…son␣to␣Judah.\\\\n\\\\n", - "extra": "TQ", - "filename": "rut/04/12.md", - "location": " in unfoldingWord (master)", - "message": "File ends with additional blank line(s)", - "priority": 138, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 267, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "4", - "V": "15", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 179, - "excerpt": "…on␣for␣Naomi.\\\\n\\\\n", - "extra": "TQ", - "filename": "rut/04/15.md", - "location": " in unfoldingWord (master)", - "message": "File ends with additional blank line(s)", - "priority": 138, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 268, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, Object { - "C": "4", - "V": "17", + "C": "RUT", + "V": undefined, "bookID": "RUT", - "characterIndex": 157, - "excerpt": "…her␣of␣David.\\\\n\\\\n", - "extra": "TQ", - "filename": "rut/04/17.md", - "location": " in unfoldingWord (master)", - "message": "File ends with additional blank line(s)", - "priority": 138, - "repoCode": "TQ", - "repoName": "en_tq", + "branch": "master", + "excerpt": "Found 9 fields", + "extra": "SQ", + "filename": "RUT_sq.tsv", + "lineNumber": 269, + "location": " in en RUT book package from unfoldingWord master branch", + "message": "Wrong number of tabbed fields (expected 7)", + "priority": 983, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "4", "username": "unfoldingWord", }, ], @@ -4420,6 +13841,8 @@ Object { "Checked ST file: 08-RUT.usfm", "Checked TN file: en_tn_08-RUT.tsv", "Checked 52 TQ files", + "Checked SN file: RUT_sn.tsv", + "Checked SQ file: RUT_sq.tsv", ], } `; @@ -4574,6 +13997,8 @@ Object { "tit/03/09.md", "tit/03/10.md", "tit/03/14.md", + "TIT_sn.tsv", + "TIT_sq.tsv", ], "checkedRepoNames": Array [ "el-x-koine_ugnt", @@ -4581,12 +14006,15 @@ Object { "en_ust", "en_tn", "en_tq", + "en_sn", + "en_sq", ], "noticeList": Array [ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -4604,6 +14032,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4621,6 +14050,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4638,6 +14068,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4655,6 +14086,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4672,6 +14104,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4689,6 +14122,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4706,6 +14140,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4723,6 +14158,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4740,6 +14176,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4757,6 +14194,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4774,6 +14212,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4791,6 +14230,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4808,6 +14248,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4825,6 +14266,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4842,6 +14284,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4859,6 +14302,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "excerpt": "odliness,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -4875,6 +14319,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 181, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -4892,6 +14337,7 @@ Object { "C": "1", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4909,6 +14355,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -4926,6 +14373,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4943,6 +14391,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4960,6 +14409,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4977,6 +14427,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -4994,6 +14445,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5011,6 +14463,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5028,6 +14481,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5045,6 +14499,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5062,6 +14517,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5079,6 +14535,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5096,6 +14553,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5113,6 +14571,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5130,6 +14589,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "excerpt": "time.␣", "extra": "LT", "fieldName": "from \\\\w", @@ -5146,6 +14606,7 @@ Object { "C": "1", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 52, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -5163,6 +14624,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -5180,6 +14642,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5197,6 +14660,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5214,6 +14678,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5231,6 +14696,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5248,6 +14714,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5265,6 +14732,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5282,6 +14750,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5299,6 +14768,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5316,6 +14786,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5333,6 +14804,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5350,6 +14822,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5367,6 +14840,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5384,6 +14858,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5401,6 +14876,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5418,6 +14894,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5435,6 +14912,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5452,6 +14930,7 @@ Object { "C": "1", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5469,6 +14948,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -5486,6 +14966,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5503,6 +14984,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5520,6 +15002,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5537,6 +15020,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5554,6 +15038,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5571,6 +15056,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5588,6 +15074,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5605,6 +15092,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5622,6 +15110,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5639,6 +15128,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5656,6 +15146,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5673,6 +15164,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5690,6 +15182,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5707,6 +15200,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5724,6 +15218,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5741,6 +15236,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5758,6 +15254,7 @@ Object { "C": "1", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5775,6 +15272,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -5792,6 +15290,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5809,6 +15308,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5826,6 +15326,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5843,6 +15344,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5860,6 +15362,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5877,6 +15380,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5894,6 +15398,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5911,6 +15416,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5928,6 +15434,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5945,6 +15452,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5962,6 +15470,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5979,6 +15488,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -5996,6 +15506,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6013,6 +15524,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6030,6 +15542,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6047,6 +15560,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6064,6 +15578,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6081,6 +15596,7 @@ Object { "C": "1", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6098,6 +15614,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -6115,6 +15632,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6132,6 +15650,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6149,6 +15668,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6166,6 +15686,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6183,6 +15704,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6200,6 +15722,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6217,6 +15740,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6234,6 +15758,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6251,6 +15776,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6268,6 +15794,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6285,6 +15812,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6302,6 +15830,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6319,6 +15848,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6336,6 +15866,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6353,6 +15884,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "excerpt": "ebellion.␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -6369,6 +15901,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 185, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -6386,6 +15919,7 @@ Object { "C": "1", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6403,6 +15937,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -6420,6 +15955,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6437,6 +15973,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6454,6 +15991,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6471,6 +16009,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6488,6 +16027,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6505,6 +16045,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6522,6 +16063,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6539,6 +16081,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6556,6 +16099,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6573,6 +16117,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6590,6 +16135,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6607,6 +16153,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6624,6 +16171,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6641,6 +16189,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6658,6 +16207,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6675,6 +16225,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6692,6 +16243,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6709,6 +16261,7 @@ Object { "C": "1", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6726,6 +16279,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -6743,6 +16297,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6760,6 +16315,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6777,6 +16333,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6794,6 +16351,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6811,6 +16369,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6828,6 +16387,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6845,6 +16405,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "excerpt": "…ntrolled.␣", "extra": "LT", "fieldName": "from \\\\w", @@ -6861,6 +16422,7 @@ Object { "C": "1", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 104, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -6878,6 +16440,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -6895,6 +16458,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6912,6 +16476,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6929,6 +16494,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6946,6 +16512,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6963,6 +16530,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6980,6 +16548,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -6997,6 +16566,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7014,6 +16584,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7031,6 +16602,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7048,6 +16620,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7065,6 +16638,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7082,6 +16656,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7099,6 +16674,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7116,6 +16692,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7133,6 +16710,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7150,6 +16728,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7167,6 +16746,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7184,6 +16764,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7201,6 +16782,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -7218,6 +16800,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7235,6 +16818,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7252,6 +16836,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7269,6 +16854,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7286,6 +16872,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7303,6 +16890,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7320,6 +16908,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7337,6 +16926,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7354,6 +16944,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7371,6 +16962,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7388,6 +16980,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "excerpt": "umcision.␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -7404,6 +16997,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 184, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -7421,6 +17015,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7438,6 +17033,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -7455,6 +17051,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7472,6 +17069,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7489,6 +17087,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7506,6 +17105,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7523,6 +17123,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7540,6 +17141,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7557,6 +17159,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7574,6 +17177,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7591,6 +17195,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7608,6 +17213,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7625,6 +17231,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7642,6 +17249,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7659,6 +17267,7 @@ Object { "C": "1", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7676,6 +17285,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -7693,6 +17303,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7710,6 +17321,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7727,6 +17339,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7744,6 +17357,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7761,6 +17375,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7778,6 +17393,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7795,6 +17411,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 62, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -7812,6 +17429,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7829,6 +17447,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7846,6 +17465,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7863,6 +17483,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7880,6 +17501,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7897,6 +17519,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7914,6 +17537,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "excerpt": "bellies.”␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -7930,6 +17554,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 177, "excerpt": "…aln-e\\\\*.”␣", "extra": "LT", @@ -7947,6 +17572,7 @@ Object { "C": "1", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7964,6 +17590,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -7981,6 +17608,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -7998,6 +17626,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8015,6 +17644,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8032,6 +17662,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8049,6 +17680,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8066,6 +17698,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8083,6 +17716,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8100,6 +17734,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8117,6 +17752,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8134,6 +17770,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8151,6 +17788,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8168,6 +17806,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8185,6 +17824,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8202,6 +17842,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "excerpt": "faith,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -8218,6 +17859,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 172, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -8235,6 +17877,7 @@ Object { "C": "1", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8252,6 +17895,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -8269,6 +17913,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8286,6 +17931,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8303,6 +17949,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8320,6 +17967,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8337,6 +17985,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8354,6 +18003,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8371,6 +18021,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8388,6 +18039,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8405,6 +18057,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8422,6 +18075,7 @@ Object { "C": "1", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8439,6 +18093,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -8456,6 +18111,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8473,6 +18129,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8490,6 +18147,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8507,6 +18165,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8524,6 +18183,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8541,6 +18201,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8558,6 +18219,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8575,6 +18237,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8592,6 +18255,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8609,6 +18273,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8626,6 +18291,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8643,6 +18309,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8660,6 +18327,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8677,6 +18345,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8694,6 +18363,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8711,6 +18381,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8728,6 +18399,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8745,6 +18417,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8762,6 +18435,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "excerpt": "orrupted.␣", "extra": "LT", "fieldName": "from \\\\w", @@ -8778,6 +18452,7 @@ Object { "C": "1", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 57, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -8795,6 +18470,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -8812,6 +18488,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8829,6 +18506,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8846,6 +18524,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8863,6 +18542,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8880,6 +18560,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8897,6 +18578,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8914,6 +18596,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8931,6 +18614,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8948,6 +18632,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8965,6 +18650,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8982,6 +18668,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -8999,6 +18686,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9016,6 +18704,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9033,6 +18722,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9050,6 +18740,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9067,6 +18758,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9084,6 +18776,7 @@ Object { "C": "1", "V": "16", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9101,6 +18794,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -9118,6 +18812,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9135,6 +18830,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9152,6 +18848,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9169,6 +18866,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9186,6 +18884,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9203,6 +18902,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9220,6 +18920,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "excerpt": "teaching.␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -9236,6 +18937,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 183, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -9253,6 +18955,7 @@ Object { "C": "2", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9270,6 +18973,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -9287,6 +18991,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9304,6 +19009,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9321,6 +19027,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9338,6 +19045,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9355,6 +19063,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9372,6 +19081,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9389,6 +19099,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9406,6 +19117,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9423,6 +19135,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9440,6 +19153,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9457,6 +19171,7 @@ Object { "C": "2", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9474,6 +19189,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -9491,6 +19207,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9508,6 +19225,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9525,6 +19243,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9542,6 +19261,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9559,6 +19279,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9576,6 +19297,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9593,6 +19315,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9610,6 +19333,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9627,6 +19351,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9644,6 +19369,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9661,6 +19387,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9678,6 +19405,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9695,6 +19423,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "excerpt": "good.␣", "extra": "LT", "fieldName": "from \\\\w", @@ -9711,6 +19440,7 @@ Object { "C": "2", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 52, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -9728,6 +19458,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -9745,6 +19476,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9762,6 +19494,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9779,6 +19512,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9796,6 +19530,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9813,6 +19548,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9830,6 +19566,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9847,6 +19584,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "excerpt": "children,␣", "extra": "LT", "fieldName": "from \\\\w", @@ -9863,6 +19601,7 @@ Object { "C": "2", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 56, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -9880,6 +19619,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -9897,6 +19637,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9914,6 +19655,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9931,6 +19673,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9948,6 +19691,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9965,6 +19709,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9982,6 +19727,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -9999,6 +19745,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10016,6 +19763,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10033,6 +19781,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10050,6 +19799,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10067,6 +19817,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10084,6 +19835,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10101,6 +19853,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10118,6 +19871,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10135,6 +19889,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10152,6 +19907,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10169,6 +19925,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -10186,6 +19943,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10203,6 +19961,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10220,6 +19979,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10237,6 +19997,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10254,6 +20015,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "excerpt": "sensible.␣", "extra": "LT", "fieldName": "from \\\\w", @@ -10270,6 +20032,7 @@ Object { "C": "2", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 56, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -10287,6 +20050,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -10304,6 +20068,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10321,6 +20086,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10338,6 +20104,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10355,6 +20122,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10372,6 +20140,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10389,6 +20158,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10406,6 +20176,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10423,6 +20194,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10440,6 +20212,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10457,6 +20230,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10474,6 +20248,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10491,6 +20266,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10508,6 +20284,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "excerpt": "dignity,␣", "extra": "LT", "fieldName": "from \\\\w", @@ -10524,6 +20301,7 @@ Object { "C": "2", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 55, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -10541,6 +20319,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -10558,6 +20337,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10575,6 +20355,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10592,6 +20373,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10609,6 +20391,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10626,6 +20409,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10643,6 +20427,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10660,6 +20445,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10677,6 +20463,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10694,6 +20481,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10711,6 +20499,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10728,6 +20517,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10745,6 +20535,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10762,6 +20553,7 @@ Object { "C": "2", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10779,6 +20571,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -10796,6 +20589,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10813,6 +20607,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10830,6 +20625,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10847,6 +20643,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10864,6 +20661,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10881,6 +20679,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10898,6 +20697,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10915,6 +20715,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10932,6 +20733,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10949,6 +20751,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -10966,6 +20769,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "excerpt": "argue,␣", "extra": "LT", "fieldName": "from \\\\w", @@ -10982,6 +20786,7 @@ Object { "C": "2", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 53, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -10999,6 +20804,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -11016,6 +20822,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11033,6 +20840,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11050,6 +20858,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11067,6 +20876,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11084,6 +20894,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11101,6 +20912,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11118,6 +20930,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11135,6 +20948,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11152,6 +20966,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11169,6 +20984,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11186,6 +21002,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11203,6 +21020,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11220,6 +21038,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11237,6 +21056,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11254,6 +21074,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11271,6 +21092,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11288,6 +21110,7 @@ Object { "C": "2", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11305,6 +21128,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -11322,6 +21146,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11339,6 +21164,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11356,6 +21182,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11373,6 +21200,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11390,6 +21218,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11407,6 +21236,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11424,6 +21254,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11441,6 +21272,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11458,6 +21290,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "excerpt": "people,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -11474,6 +21307,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 178, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -11491,6 +21325,7 @@ Object { "C": "2", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11508,6 +21343,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -11525,6 +21361,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11542,6 +21379,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11559,6 +21397,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11576,6 +21415,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11593,6 +21433,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11610,6 +21451,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11627,6 +21469,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11644,6 +21487,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11661,6 +21505,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11678,6 +21523,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11695,6 +21541,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11712,6 +21559,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11729,6 +21577,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11746,6 +21595,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11763,6 +21613,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11780,6 +21631,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11797,6 +21649,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "excerpt": "age,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -11813,6 +21666,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 167, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -11830,6 +21684,7 @@ Object { "C": "2", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11847,6 +21702,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -11864,6 +21720,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11881,6 +21738,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11898,6 +21756,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11915,6 +21774,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11932,6 +21792,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11949,6 +21810,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11966,6 +21828,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -11983,6 +21846,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12000,6 +21864,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12017,6 +21882,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12034,6 +21900,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12051,6 +21918,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12068,6 +21936,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12085,6 +21954,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12102,6 +21972,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12119,6 +21990,7 @@ Object { "C": "2", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12136,6 +22008,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -12153,6 +22026,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12170,6 +22044,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12187,6 +22062,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12204,6 +22080,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12221,6 +22098,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12238,6 +22116,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12255,6 +22134,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12272,6 +22152,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12289,6 +22170,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12306,6 +22188,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12323,6 +22206,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12340,6 +22224,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12357,6 +22242,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12374,6 +22260,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12391,6 +22278,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12408,6 +22296,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12425,6 +22314,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12442,6 +22332,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12459,6 +22350,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12476,6 +22368,7 @@ Object { "C": "2", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12493,6 +22386,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -12510,6 +22404,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12527,6 +22422,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12544,6 +22440,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12561,6 +22458,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12578,6 +22476,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12595,6 +22494,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12612,6 +22512,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12629,6 +22530,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12646,6 +22548,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12663,6 +22566,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12680,6 +22584,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12697,6 +22602,7 @@ Object { "C": "2", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12714,6 +22620,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -12731,6 +22638,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12748,6 +22656,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12765,6 +22674,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12782,6 +22692,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12799,6 +22710,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12816,6 +22728,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12833,6 +22746,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12850,6 +22764,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12867,6 +22782,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12884,6 +22800,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12901,6 +22818,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "excerpt": "work,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -12917,6 +22835,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 169, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -12934,6 +22853,7 @@ Object { "C": "3", "V": "1", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12951,6 +22871,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -12968,6 +22889,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -12985,6 +22907,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13002,6 +22925,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13019,6 +22943,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13036,6 +22961,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13053,6 +22979,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13070,6 +22997,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13087,6 +23015,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13104,6 +23033,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13121,6 +23051,7 @@ Object { "C": "3", "V": "2", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13138,6 +23069,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -13155,6 +23087,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13172,6 +23105,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13189,6 +23123,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13206,6 +23141,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13223,6 +23159,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13240,6 +23177,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13257,6 +23195,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13274,6 +23213,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13291,6 +23231,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13308,6 +23249,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13325,6 +23267,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13342,6 +23285,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13359,6 +23303,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13376,6 +23321,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13393,6 +23339,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13410,6 +23357,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13427,6 +23375,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13444,6 +23393,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13461,6 +23411,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13478,6 +23429,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13495,6 +23447,7 @@ Object { "C": "3", "V": "3", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13512,6 +23465,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -13529,6 +23483,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13546,6 +23501,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13563,6 +23519,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13580,6 +23537,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13597,6 +23555,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13614,6 +23573,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13631,6 +23591,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13648,6 +23609,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13665,6 +23627,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13682,6 +23645,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13699,6 +23663,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "excerpt": "appeared,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -13715,6 +23680,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 178, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -13732,6 +23698,7 @@ Object { "C": "3", "V": "4", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13749,6 +23716,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -13766,6 +23734,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13783,6 +23752,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13800,6 +23770,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13817,6 +23788,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13834,6 +23806,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13851,6 +23824,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13868,6 +23842,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13885,6 +23860,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13902,6 +23878,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13919,6 +23896,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13936,6 +23914,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13953,6 +23932,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13970,6 +23950,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -13987,6 +23968,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14004,6 +23986,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14021,6 +24004,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14038,6 +24022,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14055,6 +24040,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14072,6 +24058,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14089,6 +24076,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14106,6 +24094,7 @@ Object { "C": "3", "V": "5", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14123,6 +24112,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -14140,6 +24130,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14157,6 +24148,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14174,6 +24166,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14191,6 +24184,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14208,6 +24202,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14225,6 +24220,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14242,6 +24238,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14259,6 +24256,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14276,6 +24274,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14293,6 +24292,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "excerpt": "Christ,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -14309,6 +24309,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 175, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -14326,6 +24327,7 @@ Object { "C": "3", "V": "6", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14343,6 +24345,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -14360,6 +24363,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14377,6 +24381,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14394,6 +24399,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14411,6 +24417,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14428,6 +24435,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14445,6 +24453,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14462,6 +24471,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14479,6 +24489,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14496,6 +24507,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14513,6 +24525,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14530,6 +24543,7 @@ Object { "C": "3", "V": "7", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14547,6 +24561,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -14564,6 +24579,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14581,6 +24597,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14598,6 +24615,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14615,6 +24633,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14632,6 +24651,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14649,6 +24669,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14666,6 +24687,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14683,6 +24705,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14700,6 +24723,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14717,6 +24741,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14734,6 +24759,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14751,6 +24777,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14768,6 +24795,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14785,6 +24813,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14802,6 +24831,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14819,6 +24849,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14836,6 +24867,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14853,6 +24885,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14870,6 +24903,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14887,6 +24921,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14904,6 +24939,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14921,6 +24957,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14938,6 +24975,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14955,6 +24993,7 @@ Object { "C": "3", "V": "8", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -14972,6 +25011,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 10, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -14989,6 +25029,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15006,6 +25047,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15023,6 +25065,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15040,6 +25083,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15057,6 +25101,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15074,6 +25119,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15091,6 +25137,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15108,6 +25155,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15125,6 +25173,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15142,6 +25191,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15159,6 +25209,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15176,6 +25227,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15193,6 +25245,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15210,6 +25263,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15227,6 +25281,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "excerpt": "orthless.␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -15243,6 +25298,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 178, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -15260,6 +25316,7 @@ Object { "C": "3", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15277,6 +25334,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -15294,6 +25352,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15311,6 +25370,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15328,6 +25388,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15345,6 +25406,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15362,6 +25424,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15379,6 +25442,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15396,6 +25460,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15413,6 +25478,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "excerpt": "warnings,␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -15429,6 +25495,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 180, "excerpt": "…zaln-e\\\\*,␣", "extra": "LT", @@ -15446,6 +25513,7 @@ Object { "C": "3", "V": "10", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15463,6 +25531,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -15480,6 +25549,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15497,6 +25567,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15514,6 +25585,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15531,6 +25603,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15548,6 +25621,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15565,6 +25639,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15582,6 +25657,7 @@ Object { "C": "3", "V": "11", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15599,6 +25675,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -15616,6 +25693,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15633,6 +25711,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15650,6 +25729,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15667,6 +25747,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15684,6 +25765,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15701,6 +25783,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15718,6 +25801,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15735,6 +25819,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15752,6 +25837,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15769,6 +25855,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15786,6 +25873,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15803,6 +25891,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15820,6 +25909,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15837,6 +25927,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15854,6 +25945,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15871,6 +25963,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "excerpt": "there.␣", "extra": "LT", "fieldName": "from \\\\zaln-s", @@ -15887,6 +25980,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 168, "excerpt": "…zaln-e\\\\*.␣", "extra": "LT", @@ -15904,6 +25998,7 @@ Object { "C": "3", "V": "12", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15921,6 +26016,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -15938,6 +26034,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15955,6 +26052,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15972,6 +26070,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -15989,6 +26088,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16006,6 +26106,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16023,6 +26124,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16040,6 +26142,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16057,6 +26160,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16074,6 +26178,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16091,6 +26196,7 @@ Object { "C": "3", "V": "13", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16108,6 +26214,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -16125,6 +26232,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16142,6 +26250,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16159,6 +26268,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16176,6 +26286,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16193,6 +26304,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16210,6 +26322,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16227,6 +26340,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16244,6 +26358,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16261,6 +26376,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16278,6 +26394,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16295,6 +26412,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16312,6 +26430,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16329,6 +26448,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16346,6 +26466,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16363,6 +26484,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 11, "excerpt": "…zaln-s | x-stro…", "extra": "LT", @@ -16380,6 +26502,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16397,6 +26520,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16414,6 +26538,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16431,6 +26556,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16448,6 +26574,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16465,6 +26592,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16482,6 +26610,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16499,6 +26628,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16516,6 +26646,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16533,6 +26664,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16550,6 +26682,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16567,6 +26700,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16584,6 +26718,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16601,6 +26736,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16618,6 +26754,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "characterIndex": 0, "excerpt": "| x-stro…", "extra": "LT", @@ -16633,6 +26770,7 @@ Object { }, Object { "bookID": "TIT", + "branch": "master", "characterIndex": 134985, "excerpt": "…2\\"\\\\w*\\\\zaln-e\\\\*.", "extra": "LT", @@ -16646,6 +26784,7 @@ Object { }, Object { "bookID": "TIT", + "branch": "master", "characterIndex": 176298, "excerpt": "…2\\"\\\\w*\\\\zaln-e\\\\*.", "extra": "ST", @@ -16661,6 +26800,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 304, "excerpt": "… (See: \\\\[\\\\[rc:/…", "extra": "TN", @@ -16679,6 +26819,7 @@ Object { "C": "1", "V": "9", "bookID": "TIT", + "branch": "master", "characterIndex": 359, "excerpt": "…ic-goal\\\\]\\\\])", "extra": "TN", @@ -16697,6 +26838,7 @@ Object { "C": "1", "V": "10", "bookID": "TIT", + "branch": "master", "details": "(empty SR field)", "excerpt": "figs-metaphor", "extra": "TN", @@ -16715,6 +26857,7 @@ Object { "C": "2", "V": "5", "bookID": "TIT", + "branch": "master", "details": "(SR='figs-activepassive')", "excerpt": "figs-metonymy", "extra": "TN", @@ -16733,6 +26876,7 @@ Object { "C": "3", "V": "14", "bookID": "TIT", + "branch": "master", "excerpt": "figs-inclusive", "extra": "TN", "fieldName": "SupportReference", @@ -16750,6 +26894,7 @@ Object { "C": "3", "V": "15", "bookID": "TIT", + "branch": "master", "excerpt": "figs-inclusive", "extra": "TN", "fieldName": "SupportReference", @@ -16763,6 +26908,309 @@ Object { "rowID": "xy35", "username": "unfoldingWord", }, + Object { + "C": "1", + "V": "2", + "bookID": "TIT", + "branch": "master", + "details": "passage ►ἐπ’ ἐλπίδι ζωῆς αἰωνίου, ἣν ἐπηγγείλατο ὁ ἀψευδὴς Θεὸς πρὸ χρόνων αἰωνίων,◄", + "excerpt": "ἣν ἐπηγ…αἰωνίων", + "extra": "SN", + "fieldName": "Quote", + "filename": "TIT_sn.tsv", + "lineNumber": 9, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unable to find original language quote in verse text", + "priority": 916, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "r2gj", + "username": "unfoldingWord", + }, + Object { + "C": "1", + "V": "3", + "bookID": "TIT", + "branch": "master", + "details": "passage ►ἐφανέρωσεν δὲ καιροῖς ἰδίοις τὸν λόγον αὐτοῦ ἐν κηρύγματι, ὃ ἐπιστεύθην ἐγὼ, κατ’ ἐπιταγὴν τοῦ Σωτῆρος ἡμῶν, Θεοῦ;◄", + "excerpt": "κατ’ ἐπ…ὴν…Θεοῦ", + "extra": "SN", + "fieldName": "Quote", + "filename": "TIT_sn.tsv", + "lineNumber": 10, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unable to find original language quote in verse text", + "priority": 916, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "b22h", + "username": "unfoldingWord", + }, + Object { + "C": "1", + "V": "7", + "bookID": "TIT", + "branch": "master", + "details": "passage ►δεῖ γὰρ τὸν ἐπίσκοπον ἀνέγκλητον εἶναι, ὡς Θεοῦ οἰκονόμον; μὴ αὐθάδη, μὴ ὀργίλον, μὴ πάροινον, μὴ πλήκτην, μὴ αἰσχροκερδῆ,◄", + "excerpt": "δεῖ…τὸν…ν…εἶναι", + "extra": "SN", + "fieldName": "Quote", + "filename": "TIT_sn.tsv", + "lineNumber": 19, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unable to find original language quote in verse text", + "priority": 916, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "s3yr", + "username": "unfoldingWord", + }, + Object { + "C": "1", + "V": "16", + "bookID": "TIT", + "branch": "master", + "details": "passage ►Θεὸν ὁμολογοῦσιν εἰδέναι, τοῖς δὲ ἔργοις ἀρνοῦνται, βδελυκτοὶ ὄντες καὶ ἀπειθεῖς, καὶ πρὸς πᾶν ἔργον ἀγαθὸν ἀδόκιμοι.◄", + "excerpt": "τοῖς…ἔρ…νοῦνται", + "extra": "SN", + "fieldName": "Quote", + "filename": "TIT_sn.tsv", + "lineNumber": 26, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unable to find original language quote in verse text", + "priority": 916, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "jen8", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "intro", + "bookID": "TIT", + "branch": "master", + "characterIndex": 79, + "excerpt": "…ievers.␣␣Verses…", + "extra": "SN", + "fieldName": "Note", + "filename": "TIT_sn.tsv", + "lineNumber": 27, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unexpected double spaces", + "priority": 124, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "h3il", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "12", + "bookID": "TIT", + "branch": "master", + "characterIndex": 261, + "excerpt": "…s calls \\"this w…", + "extra": "SN", + "fieldName": "Note", + "filename": "TIT_sn.tsv", + "lineNumber": 37, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unexpected \\" character after space", + "priority": 191, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "z14y", + "username": "unfoldingWord", + }, + Object { + "C": "3", + "V": "9", + "bookID": "TIT", + "branch": "master", + "details": "passage ►μωρὰς δὲ ζητήσεις, καὶ γενεαλογίας, καὶ ἔρεις, καὶ μάχας νομικὰς, περιΐστασο; εἰσὶν γὰρ ἀνωφελεῖς καὶ μάταιοι.◄", + "excerpt": "μωρὰς…ζ…ιΐστασο", + "extra": "SN", + "fieldName": "Quote", + "filename": "TIT_sn.tsv", + "lineNumber": 52, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unable to find original language quote in verse text", + "priority": 916, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "bl8e", + "username": "unfoldingWord", + }, + Object { + "C": "3", + "V": "10", + "bookID": "TIT", + "branch": "master", + "details": "passage ►αἱρετικὸν ἄνθρωπον μετὰ μίαν καὶ δευτέραν νουθεσίαν παραιτοῦ,◄", + "excerpt": "αἱρετικ…αραιτοῦ", + "extra": "SN", + "fieldName": "Quote", + "filename": "TIT_sn.tsv", + "lineNumber": 53, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unable to find original language quote in verse text", + "priority": 916, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "rrx9", + "username": "unfoldingWord", + }, + Object { + "C": "3", + "V": "13", + "bookID": "TIT", + "branch": "master", + "details": "left=0, right=2", + "extra": "SN", + "fieldName": "Note", + "filename": "TIT_sn.tsv", + "lineNumber": 60, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Mismatched () characters", + "priority": 563, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "ba5a", + "username": "unfoldingWord", + }, + Object { + "C": "3", + "V": "15", + "bookID": "TIT", + "branch": "master", + "characterIndex": 40, + "excerpt": "…e faith \\"believ…", + "extra": "SN", + "fieldName": "Note", + "filename": "TIT_sn.tsv", + "lineNumber": 62, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unexpected \\" character after space", + "priority": 191, + "repoCode": "SN", + "repoName": "en_sn", + "rowID": "abch", + "username": "unfoldingWord", + }, + Object { + "C": "front", + "V": "intro", + "bookID": "TIT", + "branch": "master", + "extra": "SQ", + "fieldName": "Question", + "filename": "TIT_sq.tsv", + "lineNumber": 2, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Markdown headers should be followed by a blank line", + "priority": 252, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "gtn1", + "username": "unfoldingWord", + }, + Object { + "C": "1", + "V": "13", + "bookID": "TIT", + "branch": "master", + "characterIndex": 37, + "excerpt": "…elders, \\"**For …", + "extra": "SQ", + "fieldName": "Question", + "filename": "TIT_sq.tsv", + "lineNumber": 71, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unexpected \\" character after space", + "priority": 191, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "a8pm", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "2", + "bookID": "TIT", + "branch": "master", + "characterIndex": 83, + "excerpt": "…oes for \\"teachi…", + "extra": "SQ", + "fieldName": "Question", + "filename": "TIT_sq.tsv", + "lineNumber": 96, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unexpected \\" character after space", + "priority": 191, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "z12q", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "4", + "bookID": "TIT", + "branch": "master", + "characterIndex": 8, + "excerpt": "…ow does \\"they m…", + "extra": "SQ", + "fieldName": "Question", + "filename": "TIT_sq.tsv", + "lineNumber": 101, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Unexpected \\" character after space", + "priority": 191, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "x3mi", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "4", + "bookID": "TIT", + "branch": "master", + "characterIndex": 24, + "details": "3 total occurrences", + "excerpt": "** in this vers…", + "extra": "SQ", + "fieldName": "Question", + "filename": "TIT_sq.tsv", + "lineNumber": 101, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Possible mismatched '**' markdown formatting pairs", + "priority": 378, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "x3mi", + "username": "unfoldingWord", + }, + Object { + "C": "2", + "V": "9", + "bookID": "TIT", + "branch": "master", + "characterIndex": 41, + "details": "3 total occurrences", + "excerpt": "**slaves to be …", + "extra": "SQ", + "fieldName": "Question", + "filename": "TIT_sq.tsv", + "lineNumber": 122, + "location": " in en TIT book package from unfoldingWord master branch", + "message": "Possible mismatched '**' markdown formatting pairs", + "priority": 378, + "repoCode": "SQ", + "repoName": "en_sq", + "rowID": "gj1q", + "username": "unfoldingWord", + }, ], "successList": Array [ "Checked UGNT file: 57-TIT.usfm", @@ -16770,6 +27218,8 @@ Object { "Checked ST file: 57-TIT.usfm", "Checked TN file: en_tn_57-TIT.tsv", "Checked 32 TQ files", + "Checked SN file: TIT_sn.tsv", + "Checked SQ file: TIT_sq.tsv", ], } `; diff --git a/src/__tests__/book-package-check.test.js b/src/__tests__/book-package-check.test.js index 91c35efa0..65aeefe5b 100644 --- a/src/__tests__/book-package-check.test.js +++ b/src/__tests__/book-package-check.test.js @@ -22,7 +22,7 @@ const optionalCheckingOptions = { return fs.readFileSync(filePath).toString(); } // eslint-disable-next-line no-throw-literal - throw `Could not find ${filePath}`; + throw `Tests could not find ${filePath}`; }, getFileListFromZip: params => { const { username, repository, optionalPrefix } = params; diff --git a/src/__tests__/fixtures/unfoldingWord/en_sn/LICENSE.md b/src/__tests__/fixtures/unfoldingWord/en_sn/LICENSE.md new file mode 100644 index 000000000..da5406769 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sn/LICENSE.md @@ -0,0 +1,29 @@ +*unfoldingWord® Study Notes* + +*Copyright © 2021 by unfoldingWord* + +# License + +## Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) + +This is a human-readable summary of (and not a substitute for) the full license found at http://creativecommons.org/licenses/by-sa/4.0/. + +### You are free to: + + * **Share**—copy and redistribute the material in any medium or format + * **Adapt**—remix, transform, and build upon the material for any purpose, even commercially. + +The licensor cannot revoke these freedoms as long as you follow the license terms. + +### Under the following conditions: + + * **Attribution**—You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. + * **ShareAlike**—If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. + +**No additional restrictions**—You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. + +### Notices: + +You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. + +No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sn/OBS_sn.tsv b/src/__tests__/fixtures/unfoldingWord/en_sn/OBS_sn.tsv new file mode 100644 index 000000000..2a6332068 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sn/OBS_sn.tsv @@ -0,0 +1,798 @@ +Reference ID Tags SupportReference Quote Occurrence Note +1:1 e8wx God 1 The term **God** refers to the eternal being who created the universe out of nothing. God exists as Father, Son, and Holy Spirit. God’s personal name is ‘Yahweh.’ +1:1 q1we the beginning 1 This refers to the time before anything except God existed. +1:1 imqp created 1 This term here means that God made it from nothing. +1:1 lcot God’s Spirit 1 This is the Holy Spirit (See: [24:08](24/08), [42:10](42/10)). +1:2 y178 light 1 This light was different than the sun. God did not create the sun until the fourth day (See: [01:06](01/06)). +1:2 o5wt good 1 Each time God created something, it was good. When he finished creating everything, it was very good (See: [01:15](01/15)). +1:2 i22f creation 1 This refers to the six-day period when God created everything. +1:3 prtd sky 1 This refers to all the space above the earth including, the air we breathe and the heavens. God did not create the sun, moon, and stars until the fourth day (See: [01:06](01/06)). +1:6 grg3 the sun, the moon, and the stars 1 God created these and placed them in the empty sky that he had created on the second day (See: [01:03](01/03)). +1:9 bees us & our & us 1 God used plural words to speak about himself. Kings sometimes speak about themselves in that way. However, God the Father may have been speaking to the Son and the Spirit, who are all God. +1:9 z4j9 in our image 1 People are similar to God in many ways, but they are not equal to him, or the same as he is. +1:9 v9kx like us 1 Perhaps God was saying that people are like God in ways that animals are not. +1:10 jvdn took some soil, formed it 1 When God created all the other things, he simply spoke and they appeared. But God formed the man from the soil. +1:10 pc81 breathed life into him 1 When God breathed into the man, he became alive. +1:12 y3l2 Adam’s helper 1 None of the animals was similar enough to Adam to be able to help Adam do what God wanted him to do. +1:13 mp5e one of Adam’s ribs 1 God made the woman from a part of Adam, rather than making her from the soil. +1:14 jh54 At last! 1 Adam knew there was no one like him. He had been waiting for her. +1:14 we46 like me 1 The woman was the same kind of being as Adam, even though she was not exactly the same as he was. +1:14 rpvr Woman 1 This is the feminine form of the word ‘man.’ +1:15 rvj7 in his own image 1 God made people to show some of his qualities, but not to be equal to him. +1:15 h86s very good 1 As God made each thing, it was good. But, together, everything he created was very good because it was complete. +1:16 gg8d the seventh day 1 In modern calendars, the seventh day is Saturday. +1:16 x4gf finished all the work that he had been doing 1 God finished creating the earth and everything in it. He continues to do other work. +1:16 xdh6 holy 1 God set the seventh day apart from the other days. He did not want people to use it the same way as the other six days of the week. +2:2 nuyw a snake 1 Some scholars think the snake represents Satan. Other scholars think the snake was a real snake, and that Satan was the one who was speaking through it. +2:2 ikgp Did God really tell you not to eat the fruit from any of the trees in the garden? 1 The snake asked this question to cause the woman to think about the things that God told her not to do, instead of the things he said she could do. +2:3 fo62 good 1 Something is **good** if it fits with God’s character, purposes, and will. Good is the opposite of evil. +2:3 q9wt evil 1 Something is **evil** if it is opposed to God’s holy character and will. Evil is the opposite of good. +2:3 c8mh or even touch it 1 God told the man and the woman not to eat the fruit of that tree, but he did not tell them not to touch it. +2:4 t9y9 That is not true! 1 The snake now plainly implied that God was a liar. +2:4 wb5j will understand good and evil like he does 1 They already understood **good** from what God had done for them. Now the snake says they will also understand evil. The snake spoke as if this was good for them. Instead, understanding evil would cause them to die. +2:5 o0gt The woman saw 1 The woman decide to eat the fruit because of what she saw, instead of rejecting it because of what God had said. +2:5 k4ty he ate it too 1 The man also decided to eat the fruit, even though he knew that God had told him not to do that. +2:6 vfn2 They tried to cover their bodies 1 Before this time, people were not ashamed, and did not have any reason to be ashamed. Their shame began when they disobeyed God. +2:7 xmnq Where are you? 1 God knew where Adam was. He asked this question to make Adam say that he had disobeyed God. +2:7 xxu5 They both hid from God 1 When people sin, they feel shame. They know that they have done wrong and that God is angry with them. +2:8 c7v1 Did you eat the fruit I told you not to eat? 1 Adam did not answer the question, but instead blamed the woman. He also meant to blame God who gave the woman to him. +2:8 hn70 What have you done? 1 The woman also refused to answer God. Instead, she blamed the snake. +2:9 t5d2 You are cursed! 1 This means that God will cause bad things to happen to the snake because he deceived the woman. +2:9 zqo5 You and the woman will hate each other, and your children and her children will hate each other too. 1 People and snakes became enemies at this time, and still hate each other. +2:9 u2xu The woman’s descendant 1 Most scholars think this refers to the Messiah who would later rescue people from Satan. +2:9 qhst will crush your head 1 Most scholars think this means the woman’s descendant will fatally wound Satan. +2:9 o9b4 will wound his heel 1 Most scholars think this means Satan will wound the Messiah. +2:10 v5c5 he will rule over you 1 God will punish the woman by giving her husband power over her. +2:11 us18 work hard to grow food 1 Because the man ate the fruit his wife gave him, God would make it hard for him to grow food to eat. +2:11 g0ks your body will return to soil 1 Adam was made from soil (See: [01:10](01/10)). When he died, his body would become soil again. +2:11 sbqz Eve, which means “life-giver,” 1 The name **Eve** sounds like the Hebrew word that means ‘living.’ +2:11 u78s God clothed Adam and Eve with animal skins 1 Adam and Eve tried to cover themselves with leaves (See: [02:06](02/06)). God did not accept that. Instead, he covered them with the skins of animals. This is the first instance of animals being sacrificed in order to cover the sins of people. +2:12 wz6u they must not be allowed to eat the fruit of the tree of life and live forever 1 Adam and Eve were now sinners and ashamed. God did not want them to live forever in that condition. Therefore, he did not allow them to eat from the tree of life. +2:12 o5s1 the tree of life 1 This is the same tree God planted in the garden (See: [01:11](01/11)). +2:12 t8tn angels 1 An angel is a powerful spirit being whom God created. Angels exist to serve God by doing whatever he tells them to do. +3:2 psg2 God was pleased with Noah 1 God was pleased with the way that Noah lived. Therefore, God decided to tell Noah to build a boat to protect him and his family from the flood. +3:2 kplr a righteous man 1 The term **righteous** describes a person who obeys God and is morally good. However, because all people have sinned, no one except God is completely righteous. +3:3 fcyv the boat 1 The boat needed to be big enough to hold eight people, two of every kind of animal, and food for them to eat for about a year. +3:6 zsao every kind of animal and bird 1 Only the animals and birds who could not live on the water came to Noah. Animals that lived in the sea did not need to come to the boat. +3:8 qbh2 Everything that lived on the dry land died 1 The other people and animals could not enter the boat because God had shut the door before the rain started. +3:9 wm5r the boat rested on the top of a mountain 1 The boat was stuck on the top of the mountain that was still under the water. +3:10 dgpf it could not find any 1 Perhaps the dove was not able to fly far enough to find dry ground, although the tops of the mountains were visible far away. +3:11 hg1j could not find any dry land 1 Perhaps the dry land on the mountain tops were too far away for the dove to fly there. +3:11 vllw an olive branch 1 Plants were beginning to grow in the wet ground. +3:13 p4j9 Two months later 1 The land was already dry enough for the dove to live. But it took two more months until there was enough dry land for Noah’s family and all of the animals to be able to leave the boat. +3:14 m2bk sacrificed some of each kind of animal 1 People offered animals as special gifts to God as a way of worshiping him. They normally killed the animals and then burned them in a fire on an altar. +3:14 mqgi each kind of animal that could be used for a sacrifice 1 These were seven males and females of these animals in the boat (See: [03:06](03/06)). After Noah sacrificed some of them, there were still enough left to fill the earth again. +3:16 a5ux his promise 1 This refers to God’s promise not to destroy the earth with a flood again (See: [03:15](03/15)). +4:1 sj56 spreading out over the earth as God had commanded 1 God told Noah and his family to spread out over the earth after the flood (See: [03:13](03/13)). +4:3 n4uy spread the people out all over the world 1 The people did not stay together because they could no longer speak to each other in the same language. +4:3 hskf confused 1 The people were confused by what other people said. They were confused because God changed their language so they could not understand each other. +4:4 mumu Abram 1 God would later change Abram’s name to Abraham. +4:4 vlyq Leave your country and family 1 God told Abram to leave his relatives and the place he lived, but not to leave his wife. +4:4 spvl bless you 1 To **bless** someone or something means to cause good and beneficial things to happen to the person or thing that is being blessed. +4:4 fy3f All families on earth will be blessed because of you 1 When Abram obeyed God, God used him to bless every people group. +4:6 poya Canaan 1 This is the land that is called ‘Israel’ in modern times. +4:6 ibx7 your descendants will always possess it 1 God promised to give the land of Canaan to Abram and his descendants in the same way a father gives his land to his children. +4:7 xuo4 Abram gave Melchizedek a tenth of everything he had won in the battle 1 Abram gave this gift to Melchizedek to honor God. Melchizedek was a representative of God in Canaan. +4:8 sgyk Abram and Sarai still did not have a son 1 Abram needed to have a son because God had promised to make him a great nation (See: [04:04](04/04)). God also said he would give the land of Canaan to Abram’s descendants (See: [04:06](04/06)). +4:8 foeq Sarai 1 God would later change Sarai’s name to Sarah. +4:8 xrwg God declared that Abram was righteous 1 Because Abram believed God, God decided to treat Abram as if he had fully obeyed God in everything he had done. +4:9 p6h1 God made a covenant with Abram 1 God had already said he would give Canaan to Abram’s descendants (See: [04:06](04/06)). Now God stated the same thing again to Abram as an official promise. +5:1 d2by I am too old to have children 1 Sarai did not believe God could cause her to have a child when she was very old. She decided she should find a way to help God keep his promise. +5:1 ngh1 Marry her also 1 The custom of that time allowed a man to have more than one wife. +5:1 hav3 have a child for me 1 Because Hagar was Sarai’s servant, she did not have the same rights as Sarai. Sarai would treat any children she had as if they were Sarai’s children. +5:2 n6nj Sarai became jealous of Hagar 1 Even though Sarai told Abram to take Hagar as his wife, she was jealous that Hagar was able to have a child when Sarai was not able. +5:3 r4ge I will make a covenant with you 1 God had already made this covenant with Abram (See: [04:09](04/09)). Now, God added to that covenant by telling Abram to circumcise the males in his family. +5:3 lf1o circumcise every male 1 The term **circumcise** means to cut off the foreskin of a man or male child. A circumcision ceremony may be performed in connection with this. +5:4 drel the son of promise 1 Through Isaac, God would keep his promise to make Abram a great nation and to give the land of Canaan to his descendants. +5:4 hozo my covenant will be with Isaac 1 God would bless Abram’s son, Ishmael. However, God would cause Abram’s other son, Isaac, and his descendants to receive the blessings of God’s covenant with Abram. +5:5 sbew Sarah gave birth to Abraham’s son 1 Sarai had been wrong to believe that God could not give her a son when she was very old (See: [05:01](05/01)). +5:6 kqap God tested Abraham’s faith 1 God wanted to show that Abram would obey God in whatever he asked. He did not want Abraham to actually kill Isaac. However, Abraham did not yet know that he would not have to kill Isaac. +5:7 co04 wood for the sacrifice 1 Abraham planned to kill Isaac and offer him as a burnt offering. He brought the wood to make the fire. +5:7 k9m2 the lamb 1 A lamb was the normal sacrifice to God in that day. +5:8 h02j He was about to kill his son 1 Abraham showed that he was willing even to kill Isaac if God told him to do that. +5:8 v1rp Stop! Do not hurt the boy! 1 God did not want Abraham to kill Isaac. He only told Abraham to do that so that he could test Abraham’s faith (See: [05:06](05/06)). +5:9 y1v5 a ram that was stuck in a bush 1 God provided this ram. It would be very unusual for a ram to be stuck in a bush. +5:10 ymx7 all the families of the world 1 This refers to the other people groups who are not descendants of Abraham. +5:10 vdh6 your family 1 This refers to the Jews, because they are the descendants of Abraham. +6:1 ub6p a wife for his son 1 The people of Canaan did not worship God. Therefore, Abraham did not want Isaac to marry a woman from Canaan. Instead, he sent his servant to bring a wife for Isaac from Abraham’s relatives where Abraham lived before coming to Canaan. +6:3 es21 Rebekah agreed to leave her family 1 Although parents arranged marriages in that day, they apparently asked Rebekah if she was willing to go to Canaan and marry Isaac. +6:4 q1em God then blessed Abraham’s son Isaac 1 God chose to give to Isaac and his descendants the things he promised in his covenant with Abraham (See: [05:04](05/04)). Ishmael did not receive those blessings, even though he was a son of Abraham. +6:6 cdp1 Their descendants will become two different nations 1 The descendants of Jacob, the younger son, were the Israelites. The descendants of Esau, the older son, were the Edomites. The Israelites and the Edomites often fought against each other, but the Israelites would eventually become stronger than the Edomites. +6:7 eaiv they named him Jacob 1 The name, **Jacob** means “the one who grabs the heel.” They named him Jacob because he was holding Esau’s heel when he was born. +7:2 bgpx everything you should receive because you were born first 1 The older son always inherited twice as much of his father’s possessions as the younger son. These things belonged to Esau, but Jacob wanted Esau to trade them to him for food. +7:3 azjx give his blessing 1 Isaac loved Esau more than he loved Jacob. Therefore, before he died, Isaac wanted to formally ask God to bless and provide for Esau more than for Jacob. Isaac was following the normal custom of giving the best blessing to the oldest son. +7:5 dbzm had stolen his rights as oldest son 1 Jacob did not steal Esau’s rights as the older son. Esau traded them to Jacob for food (See: [07:02](07/02)). But Esau hated Jacob as if Jacob had stolen what belonged to him. +7:6 xo1u far away to live with her relatives 1 Rebekah’s relatives were Abram’s family. They lived in the land that Abram left when he came to Canaan (See: [04:04](04/04), [06:01](06/01), [06:02](06/02)). +7:10 h6zn The covenant promises God had made to Abraham now passed on from Isaac to Jacob 1 The descendants of Jacob would receive the land and blessings that God promised to Abraham and Isaac (See: [05:03](05/03), [06:04](06/04)). Esau did not receive those blessings even though he was a son of Isaac. +8:1 rt3w his favorite son, Joseph 1 Jacob had four wives and 12 sons. Joseph was the son of Rachel, whom Jacob loved more than his other wives. Therefore, Jacob loved Joseph more than his other sons. +8:1 rt9s taking care of the flocks 1 People at that time allowed their animals to go wherever they could find grass to eat. Someone traveled along with the animals to protect them. +8:2 fr4f slave traders 1 Slave traders bought people to be used as slaves. They then sold them to other people for a profit. They often traveled very far to buy and sell slaves. +8:3 x0y6 dipped it in goat’s blood 1 Joseph’s brothers wanted their father to think the blood on the robe was Joseph’s blood. +8:5 bg6j She became angry 1 The wife of the government official who bought Joseph was angry that Joseph would not sleep with her. She lied about Joseph to her husband so he would be angry with Joseph and put him in prison. +8:6 mufp the meaning of the dreams 1 The Egyptians believed that God spoke to the Pharaoh through his dreams. Pharaoh’s advisors normally helped him understand what his dreams meant. +8:8 ki52 Pharaoh was so impressed with Joseph 1 Pharaoh was impressed with Joseph because Joseph was the only person who was able to to tell Pharaoh what God was saying through Pharaoh’s dreams. +8:10 smfo The famine 1 The famine began seven years later, after the seven years of good harvests (See: [08:07](08/07)). +8:11 pyxs The brothers did not recognize Joseph 1 The brothers came to Egypt at least ten years after they sold Joseph into slavery. They did not recognize Joseph because he was ten years older and was dressed as an Egyptian official. +8:12 ukrr if they had changed 1 Joseph’s brothers did evil when they sold him as a slave (See: [08:02](08/02)). He now wanted to know if his brothers would still treat people badly. +8:12 fs14 God used the evil for good 1 Joseph was willing to forgive his brothers because he believed that God had caused their evil action to result in a good thing. By going to Egypt as a slave, Joseph gained the power to save his whole family from the famine. +8:13 ndme Joseph’s brothers returned home 1 The brothers returned home in order to bring their father and their families from Canaan to Egypt so they would survive the famine. +8:15 cd5p The covenant promises that God gave to Abraham were passed on to Isaac, then to Jacob, and then to Jacob’s 12 sons and their families 1 All the descendants of Jacob would receive the land and blessings that God promised to Abraham and Isaac (See: [05:03](05/03), [06:04](06/04), [07:10](07/10)). +8:15 zd0i the 12 tribes of Israel 1 God changed Jacob’s name to Israel. Therefore, the descendants of his 12 sons were called the 12 tribes of Israel. +9:1 iecw the Israelites 1 God changed Jacob’s name to Israel. Therefore, Jacob’s descendants were called the Israelites. +9:2 wytr Joseph had done so much to help them 1 Joseph warned the Egyptians about the famine so they could store up grain in advance (See: [08:08](08/08)). In this way, he saved the Egyptians. +9:3 xv7e God blessed them 1 The Egyptians made the Israelites slaves so they would become weaker. But God blessed the Israelites so they became stronger instead. +9:7 bznl she took him as her own son 1 Pharaoh’s daughter treated Moses as if he were her own Egyptian son. For that reason, the Egyptians did not kill him as they killed the other Israelite baby boys (See: [09:04](09/04)). +9:9 wnve buried his body 1 Moses buried the Egyptian’s body to hide it. Moses did not want anyone to know that he had killed an Egyptian. +9:10 yea5 He tried to kill him 1 Pharaoh realized that Moses was helping the Israelites and was against the Egyptians. That is why he wanted to kill Moses. +9:10 vcbt the wilderness 1 The wilderness where Moses fled was a desert area that was east of Egypt. This area today is called the Sinai. +9:12 gy5o take off your shoes 1 God told Moses to take off his shoes to show his respect for God. The ground around the burning bush was a special place because God was there. +9:12 gymh holy ground 1 The term **holy** refers to the character of God. He is totally set apart and separated from everything that is sinful and imperfect. The place where Moses stood was also set apart for God. +9:13 q7p8 my people 1 God said the descendants of Abraham were his people. God wanted to say that the Israelites were special to him. He would treat them better than other people because Abraham honored him (See: [05:10](05/10)). +9:13 l6lp I will give them the land of Canaan 1 God was going to keep his promise to give the land of Canaan to Abraham’s descendants, even though they were slaves at that time (See: [08:15](08/15), [09:02](09/02)). +9:14 d9yi I AM WHO I AM 1 God wanted to say that he has always existed as God, and was not created by anyone else. +9:14 u8bi Yahweh 1 This is the name that God has chosen for himself. Hebrew was originally written without vowels, so the letters written for this name were YHWH, which would be spoken as **Yahweh**. +9:15 aqcs did not want to go to Pharaoh 1 Moses knew that Pharaoh wanted to kill him (See: [09:10](09/10)). +9:15 wbnh he thought he could not speak well 1 Moses said this was why he did not want to go to Pharaoh, but the real reason was that Moses was afraid of Pharaoh. +10:1 aswe the God of Israel 1 Pharaoh may have thought that this **God of Israel** only ruled over the Israelites. He did not yet understand that the God who ruled over Israel also ruled over the entire world. +10:1 ts47 Let my people go! 1 God told Moses to bring the Israelites out of Egypt (See: [09:13](09/13)). +10:1 cbzk Pharaoh did not listen to them 1 Pharaoh heard what Moses and Aaron said, but did not do what they told him to do. +10:1 tc01 he forced them to work even harder 1 Pharaoh was angry that the Israelites wanted to leave Egypt. He made them work harder as a way to punish them for that desire. +10:2 mtum ten terrible plagues 1 Plagues are events which cause suffering or death to a large number of people. Often a plague is a disease that spreads quickly and causes many people to die before it can be stopped. +10:2 v097 he is more powerful than Pharaoh and all of Egypt’s gods 1 Pharaoh asked the false gods of Egypt to stop the plagues, but the plagues continued. This proved to Pharaoh and the Egyptians that the God of Israel also ruled over Egypt. +10:4 n1sw Pharaoh hardened his heart 1 Pharaoh became stubborn and decided not to believe and obey God. Pharaoh did this after most of the plagues. +10:7 tjwb but not on the Israelites 1 God caused the sores to affect only the Egyptians in order to show that he was against the Egyptians, but not against the Israelites. +10:8 pa3f hail 1 Hail is chunks of ice that fall from the sky. These chunks are often large enough to destroy plants, and can even kill people or animals. +10:8 eo40 I have sinned 1 Pharaoh finally realized that he had disobeyed God and that the plagues were God’s punishment for not letting the Israelites leave Egypt. +10:11 jn97 there was light where the Israelites lived 1 This was not a normal darkness. The parts of Egypt where the Egyptians lived was completely dark even during the daytime. But the places in Egypt where the Israelites lived had sunshine in the daytime as they normally did. +10:12 rf2a one last plague 1 This final plague would be much worse than the previous ones. It would be so terrible that it would force Pharaoh to finally agree to let the Israelites leave Egypt. +11:2 y0yn Each family 1 Every Egyptian and Israelite family had to select and kill a lamb in the way that God told them to do it. If any family obeyed and did this, God would not kill their firstborn son. +11:3 sy1m to put the blood of this lamb around the door of their houses 1 The Israelites put the blood on the frame of the door of their houses to show that they had killed the lamb just as God told them to do. +11:3 wfuc unleavened bread 1 Unleavened bread is bread that is prepared without yeast. People can make unleavened bread very quickly because they do not need to wait for the dough to rise before they bake it. The unleavened bread shows that this meal was urgent and the people needed to do it quickly. +11:5 oo6e God passed over those houses 1 God did not enter into the houses with blood on the doors to kill the firstborn sons in those houses. +11:5 ta9c passed over 1 God later told the Israelites to remember this day in a festival called the Passover. In this way, they would always remember that he passed over their houses on that day and did not kill their firstborn sons. +11:6 nxvz did not believe God or obey his commands 1 The Egyptians did not believe God would kill their firstborn sons, and therefore did not obey his commands to kill a lamb and put its blood around their doors. +11:8 awch leave Egypt immediately 1 God had promised that he would send one last plague to Pharaoh to let the Israelites leave Egypt (See: [04:09](04/09)). After God killed every firstborn son of the Egyptians in this final, terrible plague, Pharaoh and all the Egyptians urged the Israelites to leave Egypt. +12:1 fabu the Promised Land 1 God had promised Abraham to give the land of Canaan to Abraham’s descendants. The Israelites were finally going there to possess that land. +12:1 steb The Egyptians gave the Israelites whatever they asked for 1 The Egyptian had suffered greatly during the plagues. They very much wanted the Israelites to leave Egypt and the plagues to stop. Therefore, they gave the Israelites anything they asked for in order to encourage them to leave Egypt quickly. +12:1 ee8h Some people from other nations believed in God 1 God chose the descendants of Abraham for his own people, but he was always willing to accept people from other nations if they would believe in him and obey him. +12:2 a1y0 A tall pillar 1 The people could not see God, but they could see the pillar and know that he was going before them as they traveled from Egypt to the Promised Land. +12:3 ks8x It was God who made them change their minds 1 Pharaoh and the Egyptians had already learned that God was powerful. However, God also wanted the other nations to know that he is the only God who rules the earth. Therefore, God caused Pharaoh to chase after the Israelites so that God could destroy the Egyptian army. This would show the other nations how powerful God is. +12:4 gioi they were trapped between Pharaoh’s army and the Red Sea 1 God had led the Israelites to the shore of the Red Sea without a way to cross the deep water of the sea. God also allowed the Egyptians to catch up with the Israelites there. He did this so that he could show the Israelites the he could protect them even in that hopeless situation. +12:4 rx9c We are going to die! 1 The Israelites thought they would either be killed by the Egyptian army or would go into the sea and drown. +12:6 rmoh The Egyptians were not able to come near the Israelites all night 1 The Egyptians were not able to go through the pillar. In this way, God protected the Israelites from the Egyptians. +12:8 pbp4 on dry ground 1 God not only moved the water away from the path of the Israelites, but also dried up the ground at the bottom of the sea so they could walk on it. +12:10 c0dx caused their chariots to get stuck 1 God made the ground at the bottom of the sea to be dry for the Israelites. But when the Egyptians followed them, God caused the bottom of the sea to become muddy again so the heavy chariots of the Egyptian became stuck in it and could not move. +12:10 x9p0 Run away! 1 The Egyptians realized they were in danger, and tried to escape from the path through the sea. +12:11 s9l3 the water fell on the Egyptian army 1 The Red Sea is very wide. The Egyptians had followed the Israelites too far into the sea and were not able to escape before the water closed back over them and they drowned. +12:12 qodw They believed that Moses was a prophet of God 1 God had told Moses to stretch out his arm over the sea when God made a path through it, and when he closed the water again over the Egyptians. In this way, God showed the Israelites that he was speaking to them through Moses. +12:12 t22s a prophet of God 1 A prophet is a person through whom God speaks to the people. +12:14 tkk9 the Passover 1 The festival was called the Passover because God “passed over” the houses of the Israelites that had the blood of a lamb around their doors. He did not enter into those houses to kill their firstborn sons. God told the Israelites to celebrate this festival every year so they would remember how he had save them. +12:14 zfks bread made without yeast 1 **Yeast** is a specific kind of leaven. **Yeast** is a general term for a substance that causes bread dough to expand and rise. +13:1 gqp2 a mountain called Sinai 1 Mount Sinai is a mountain that was probably located in the southern part of what is now called the Sinai Peninsula. It was also known as ‘Mount Horeb.’ +13:1 igpc where Moses had seen the burning bush 1 God spoke to Moses from a bush that was on fire, but did not burn up (See: [09:12](09/12)). +13:1 a1n1 set up their tents 1 The Israelites had to travel a great distance from Egypt to the Promised Land. So they took tents with them so that they could set them up as shelters and sleep in them along the way. +13:2 pwvq the covenant I am making with you 1 God was going to make a new covenant with the Israelites (See: [13:04](13/04)). +13:2 lhq2 my prized possession 1 The Israelites would belong to God and he would value them more than any other people group. +13:2 kp49 a kingdom of priests 1 The Israelites were supposed to teach the other nations about God and be a mediator between God and the nations just as there were priests in the nation of Israel to go between God and the Israelites. +13:3 bphk the people made themselves ready 1 The Israelites did three days of ceremonial cleansing in preparation to meet with God. +13:4 ab6c God made a covenant with the people 1 This was a new covenant between God and the Israelites. This covenant told the Israelites how they should worship God. This covenant was in addition to the covenant that God made with Abraham, the ancestor of the Israelites (See: [04:09](04/09)). +13:5 i6bs the Sabbath day 1 The Sabbath day was the seventh day of the week. This is Saturday in a modern calendar. God had said that the Sabbath should be holy because that was the day that he finished creating the earth and everything in it (See: [01:16](01/16)). +13:5 un6o a day for you to rest and to remember me 1 The two reasons for the Sabbath were for people to rest from their work and to think about God and what he had done for them. +13:8 ab8i the Tent of Meeting 1 The **Tent of Meeting** was called by that name because it was the place where God would come to meet with Moses or the high priest of the Israelites. +13:8 ahp1 God would come into the room behind the curtain 1 God is spirit and is everywhere, all the time. However, he appeared to Moses in a special way in the Tent of Meeting. +13:8 qsyd the high priest 1 The term **high priest** refers to a special priest who was appointed to serve for one year as the leader of all the other Israelite priests. +13:9 t5h0 disobeyed God’s law 1 This refers to all of the laws that God gave to the Israelites—not only to the Ten Commandments. +13:9 tfj8 the animal’s blood would cover that person’s sin 1 The sin of the person would still exist, but the blood would cover it. This is like hiding something that is ugly or dirty by covering it. +13:9 mb44 God would not see that sin any longer 1 This does not mean that God was not able to see the person’s sin. Rather, it means that God would choose not to look at the person’s sin. Because that person had offered the sacrifice, God would not punish them for that sin. In this way, they would be clean. +13:10 di8f these Ten Commandments 1 The Ten Commandments were main commands that God gave to Moses for the Israelites to obey. They are listed in [13:05](13/05) and [13:06](13/06). +13:10 akig two stone tablets 1 The stone tablets were two flat pieces of stone on which God wrote the Ten Commandments. +13:12 saw4 to wildly worship the idol 1 The people were sinning by worshiping the idol and also by doing sinful things as they worshiped it. +13:12 b45t God was very angry with them 1 God knew what the people had done and told Moses about it while Moses was still the mountain with God. Moses prayed for the people before he came down from the mountain. +13:13 zowy he smashed the tablets 1 Moses threw the stone tablets down on the ground and they broke into little pieces. Moses did that to show that the Israelites had broken the Ten Commandments that God had written on the tablets. +13:14 hpfs Moses burned the idol and ground it into powder 1 Moses was so angry that they had made the idol that he ground it into fine particles. +13:14 v7b5 made the people drink the water 1 Moses made the people drink the water with the particles of the idol in it as a symbol that they were guilty for making that idol. +13:14 g5pv God sent a plague on the people 1 God sent ten plagues on the Egyptians to force Pharaoh to set the people free from being slaves in Egypt. But now, the Israelites sinned so terribly that God sent a plague on them to punish them. +14:1 u3oi all the laws 1 These laws included many more commands in addition to the Ten Commandments. (See: [13:07](13/07)). +14:1 hcxo the pillar of cloud 1 This was the same pillar of cloud which led the Israelites out of Egypt. (See: [12:02](12/02)). +14:2 x3u9 God had promised Abraham, Isaac, and Jacob that he would give the Promised Land to their descendants 1 God made this promise to Abraham (See: [04:06](04/06)). That promise was later passed on to Isaac and Jacob. +14:3 bjmy you will end up worshiping their idols 1 God wanted the Israelites to be completely separate from the other people groups who worshiped idols. Otherwise, the Israelites might also start worshiping the false gods of the Canaanites. +14:4 crnm to see if they were strong or weak 1 Moses wanted to know how difficult it would be to defeat the Canaanites and to take their land. He also wanted to know the best way to attack the Canaanites. +14:6 h9no Caleb and Joshua, the other two spies 1 Moses sent 12 men to spy on the Canaanites. Ten of those men said the Israelites could not defeat them. Only Caleb and Joshua believed that God was powerful enough to help them defeat the Canaanites. The 12 men saw the same things, but Caleb and Joshua were not afraid as the other ten men were. +14:6 bpdy God will fight for us! 1 Caleb and Joshua knew that the Israelites alone could not defeat the Canaanites, but with God's help, they could win against them. +14:8 s9hj you will have to wander in the wilderness 1 God would lead the people around in the wilderness with no specific destination until all of the adults who rebelled against him died. +14:8 r012 Everyone who is 20 years or older will die 1 God would allow only the children to enter the Promised Land after their parents had died. +14:10 c0fe they would wander through the wilderness 1 They lived in the wilderness, and together they moved from place to place in that large, dry land, looking for food and water for themselves and their animals. +14:11 ne50 bread from heaven, called manna 1 Overnight, this thin, bread-like food fell onto the grass like dew from the sky. They called it **manna**. Almost every day the people gathered this manna and cooked it as their food. +14:11 cfvr their camp 1 The place where the Israelites set up their tents to sleep in was called a **camp**. It was like a city with tents instead of buildings, and it could be moved around. +14:12 lfcy the people of Israel complained and grumbled against God and against Moses 1 The people had refused to go into the Promised Land. Now they continued to complain against God and Moses until they died in the wilderness. +14:12 bt8n God was still faithful 1 Even though all of the adult Israelites disobeyed God and complained against him, God did not forget his promise to Abraham. He continued to take care of the people in the wilderness so that he could lead their children into the Promised Land. +14:13 hgun he dishonored God 1 God had a specific way He wanted Moses to show the people God’s power to provide for them. When Moses disobeyed God by doing it in a different way, he showed a lack of respect for God. Because of that, Moses would die before the Israelites would enter the Promised Land. +14:14 ugq1 all of those who had rebelled against God 1 The people who died were the ones who were over 20 years old at the time when they rebelled (See: [14:08](14/08)). Their children lived and entered the Promised Land. +14:14 xp85 another prophet like Moses 1 Like Moses, this man would be an Israelite, he would speak God’s words to the people, and he would lead the people. +14:15 iwlk he could see the Promised Land 1 The mountain was just across the Jordan River from Canaan. Moses was able to see the land from that high place. +14:15 jglt Joshua became their new leader 1 This was the same Joshua who was one of the 12 who spied on the land when Israel first arrived at Canaan (See: [14:06](14/06)). Joshua and Caleb wanted the people to go into the land at that time. Because they trusted God, he said they would enter the land after the other people died (See: [14:08](14/08)). +15:1 f2dq Joshua sent two spies to that city 1 Joseph sent the spies to find out information about the city so the Israelites could attack it. +15:2 ozrq the Jordan River 1 The Jordan River is a river that flows from north to south, and forms the eastern boundary of the land that was called Canaan. It flows through the Sea of Galilee and then empties into the Dead Sea. +15:2 js9n on dry ground 1 God not only stopped the river from flowing, but also dried up the ground on the bottom of the river so the people could walk across it easily. +15:5 npen the walls around Jericho fell down 1 The walls around Jericho were made of stone and were very strong. They did not fall down on their own. God caused them to fall down when the Israelites shouted and blew the trumpets as he told them to do. +15:6 n2sb Joshua and the other leaders of the Israelites did not ask God what they should do. 1 Joshua and the other leaders acted very foolishly. The peace treaty was a very important decision. They should have asked God what to do, but they did not think they needed to do that. +15:7 iyel they combined their armies into one large army and attacked Gibeon 1 The Amorites were angry with the Gibeonites because they made a peace treaty with the Israelites instead of helping the Amorites to fight against them. They may also have been afraid that the Gibeonites would help Israel fight against the Amorites. Therefore, they decided to destroy the Gibeonites. +15:9 hvg4 he sent large hailstones that killed many of the Amorites 1 The hailstones were large balls of ice that fell from the sky. God also killed many Egyptians with hail during one of the plagues in Egypt (See: [10:10](10/10)). +15:10 gdq2 caused the sun to stay in one place in the sky 1 God caused the sun to stay in one place in order to make the day longer. That gave the Israelites more time to defeat the Amorites before nighttime when they might escape in the dark. +15:13 vckp Joshua was an old man 1 Joshua was over 100 years old when the Israelites finished taking control of the land. +15:13 eahp the covenant 1 This was the covenant that God made with the Israelites through Moses after they left Egypt (See: [13:04](13/04)). +16:1 ksff After Joshua died, the Israelites disobeyed God 1 Joshua led the people well, so they obeyed God as Joshua did until he died. But when he was no longer alive to lead them, they began to disobey God. +16:1 sbar they did not drive out the rest of the Canaanites 1 While Joshua was alive, the Israelites defeated all the large Canaanite armies. However, many Canaanite people and cities remained in the land. The Israelites did not finish driving them out of the Promised Land. +16:1 uzz6 The Israelites began to worship the Canaanite gods 1 Before the Israelites came to the Promised Land, God had warned them that they would begin to worship false gods if they did not drive out the Canaanites (See: [14:03](14/03)). +16:1 yidn everyone did what they thought was right for themselves 1 The people did what they thought was right, instead of doing what God told them was right. Unfortunately, many of the things that they wanted to do were actually sinful. +16:2 e1wn a pattern that repeated many times 1 Each time the Israelites asked God to help them, he rescued them from their enemies. But their children would not remember that God had saved their parents. So they would sin against God just as their parents had done. This same thing happened with every generation. +16:3 f5ns a deliverer 1 God sent many of these deliverers. After each one defeated Israel’s enemies, the deliverer ruled over Israel until they died. +16:5 yzxg threshing grain 1 The grain was wheat, which has a head of many small grains, or seeds, on the top of a thin stalk. **Grain** is separating the seeds of the plant from the stalks by beating the heads of grain. The seeds are food, but the stalks are not. +16:5 nxbk in a hidden place 1 People normally thresh grain on a high, open place where the wind can blow away the chaff of the wheat that people cannot eat. However, Gideon was so afraid of the Midiantes that he was in a secluded place where it would be difficult to separate out the grain. +16:6 gvy9 Gideon’s father had an altar dedicated to an idol 1 Gideon’s own father worshiped false gods rather than Yahweh, the true God. +16:6 d42s The first thing God told Gideon to do was to tear down that altar 1 God would not help Gideon rescue Israel until he destroyed the altar of the idol that his family worshiped. +16:6 byqt Gideon was afraid of the people 1 The Israelites who lived around Gideon also worshiped idols. Gideon was afraid that they would be angry with him if he destroyed the altar where his father worshiped idols. +16:6 d79a he waited until nighttime 1 Because Gideon was afraid of the people, he tore the altar down at night when no one would see him do it and try to stop him. +16:6 wl05 He built a new altar to God 1 Gideon not only destroyed his father’s altar so he could not worship the false gods, but he also built an altar to God and worshiped God by sacrificing an animal on it. +16:8 jm5r came again to steal from the Israelites 1 The Midianites would come to Israel at harvest time when there would be a lot of food for them to steal. +16:9 g1qt a sheepskin 1 This is the skin of a sheep that has all of the wool on it. Wool is a very thick and curly hair that would hold a lot of water. +16:9 sm03 the ground be wet but the sheepskin dry 1 Gideon did not yet trust God enough to believe the first sign. So he asked God to do the opposite thing—make the ground wet instead of the skin, and the skin dry instead of the ground. He wanted to be sure that the first sign did not happen by itself. +16:10 e1t2 God told him this was too many 1 This was more soldiers than God wanted for this fight. If that many soldiers fought and won, they would think that they won the battle with their own strength, and they would not know that God did it. +16:10 a7ne 300 soldiers 1 The Midianite army was **so many of them that they could not be counted** (See: [16:08](16/08)). God planned to cause Gideon to defeat all of them with only 300 soldiers. +16:11 yzxo you will no longer be afraid to attack them 1 Even after God gave Gideon the two miraculous signs, he was still afraid of the Midianites. +16:11 yadq Gideon went down to the camp 1 Gideon secretly went down near the enemy camp in the dark. He found a place where he could hear them, but they could not see him. +16:11 rzk5 something he had dreamed 1 God had caused one of the Midianites to have a strange dream. He also caused another Midianite soldier to understand that the dream meant that Gideon would defeat them. God did this so that Gideon would hear them and trust God enough to attack the Midianites. +16:13 di3q A sword for Yahweh and for Gideon! 1 This was the battle cry of Gideon’s soldiers. This means: ‘We fight for Yahweh and for Gideon!’ They yelled this out to encourage themselves, and to scare the Midianites. +16:14 eso5 they started attacking and killing each other 1 The Midianites wanted to attack the Israelites, but because God caused them to be confused, they attacked each other instead. +16:14 q30h many other Israelites 1 This refers to the other Israelite soldiers that Gideon previously sent home (See: [16:10](16/10)). +16:15 nuno wanted to make Gideon their king 1 The Israelites had not yet had a king. Instead, God was their king. Gideon knew that they should not have a human king. +16:15 bn29 a large amount of gold 1 Even though each person gave Gideon only a small piece of gold, there were so many Israelites that the total amount of gold was very large. +16:16 nfbf the people started worshiping it as if it were an idol 1 Gideon made the garment to honor God, but it became a problem for him. He and the people soon began to worship the garment as an idol. In this way, the Israelites followed the same pattern as before. They worshiped idols instead of God, and God, therefore, allowed their enemies to defeat them. +16:18 cz6a a king like all the other nations had 1 Other nations had a king. Israel wanted to be like them and have a king too. +16:18 yfco God did not like this request 1 God knew that they were rejecting him as their ruler and were choosing to follow a human leader instead. +17:1 plg7 would one day be king in his place 1 God did not immediately remove Saul from being king. Instead, he allowed Saul to continue to rule for several more years while God prepared a man to replace him as king. +17:3 uf7p a giant named Goliath 1 The word **giant** here describes a person who is unusually tall and powerful. Goliath was a huge soldier in an army that was fighting against Israel. +17:3 pnwg he led Israel’s army 1 David led the army, but Saul was still the king of Israel at this time. +17:4 fjmu David shouted to him to look at the cloth he was holding 1 David cut off the piece of Saul’s clothing to show Saul that David was close enough to kill Saul, but did not do it. In this way, David wanted to prove to Saul that he, David, was not trying to kill him. +17:4 yfn0 David refused to kill him 1 David would not dishonor God by killing Saul, whom God had placed as king over Israel. Instead, he waited until God was ready to make David king. +17:6 seos to build a temple 1 David wanted to construct a permanent building for worshiping God that would replace the portable Tent of Meeting (See: [13:08](13/08)). +17:7 euka The only descendant of David who could rule forever was the Messiah 1 All of the normal descendants of David eventually died. The Messiah, however, would live forever and continue to rule. +17:7 dbs1 the Messiah 1 The term **Messiah** means ‘Anointed One.’ It refers to the person that God would send to save his people and to rule over his kingdom forever. In the New Testament, **Messiah** is translated as ‘Christ.’ +17:10 wvuj saw a beautiful woman bathing 1 Bathsheba may have been bathing at her own house, but David’s palace was very high and he was able to see over walls that were lower. +17:11 uw66 He slept with her 1 This is a polite way to say that David had sexual relations with Bathsheba. David was married and so was Bathsheba. Therefore, when he slept with her, he not only sinned against God, but also against his wives and her husband. +17:12 fmux He was one of David’s best soldiers 1 David knew Uriah well, because he was one of the best soldiers in Israel. For that reason, it was especially evil that David slept with Uriah’s wife. +17:12 mh2l told him to go be with his wife 1 This could mean ‘go home to be intimate with his wife.’ David wanted people, especially Uriah, to believe that Bathsheba was pregnant with Uriah’s child. +17:12 vddv so that he would be killed 1 When David told his general to place Uriah where the enemies would kill him, David became guilty of murdering Uriah. +17:14 ucm9 God punished David 1 When David repented about sleeping with Bathsheba and murdering Uriah, God forgave him and was no longer angry with him. However, God still needed to punish David so that the Israelites would know that they should not disobey God. Therefore, God caused David’s baby to die, and also caused David’s children to fight against him and against each other. +18:2 f1ts was present in the Temple 1 This could mean ‘was present in the Temple in a special way.’ Even though God was also present everywhere else at the same time, he made himself especially available to the people at the Temple. +18:3 bhan brought their gods with them 1 His wives brought their idols and their methods of worshiping idols with them to Israel. As a result, Solomon himself also began to worship those idols. +18:4 rrmg because of this 1 God was angry with Solomon for worshiping idols. +18:6 xt8p I will make you suffer worse 1 Rehoboah was a very selfish person. The people asked him to treat them better than Solomon treated them, but he said he would treat them even worse. +18:7 fwz2 tribes 1 The descendants of each of Jacob’s 12 sons had become a **tribe** or very large family group in the nation of Israel. Everyone in Israel belonged to one of the 12 tribes. +18:7 yw30 the kingdom of Judah 1 The tribe of Judah was the largest of the 12 tribes of Israel. The kingdom of Judah was made up of the tribes of Judah and Benjamin. They were called by the name of Judah, a larger tribe than Benjamin. +18:8 wdke the kingdom of Israel 1 The ten tribes were the majority of Israel. Therefore, they called themselves the kingdom of Israel. +18:9 q9g2 They no longer went to Jerusalem 1 Jereboam placed his two idols in two temples in Dan and Bethel. The people in the kingdom of Israel went there to worship instead of going to Jerusalem. +18:12 gzel slept with prostitutes 1 They slept with prostitutes as an evil form of worship of their idols. +18:13 c1jc Judah 1 The kingdom of Judah was often called “Judah.” +18:13 gs16 the people of Judah also rebelled against God 1 The people of Judah usually did whatever their kings did. If the kings worshiped God, the people did that also. But if the kings worshiped idols, the people also worshiped those false gods. +19:3 d46d birds would bring Elijah bread and meat 1 God sent the birds to bring food to Elijah so that Elijah could eat. Elijah drank water from the stream. +19:4 vigz another country close by 1 Elijah would be safe in this country, because Ahab would not go there to look for him to kill him. +19:4 hg1l took care of Elijah 1 The widow and her son gave Elijah a place to stay in their house and provided food for him. +19:4 q7qy jar of flour 1 This refers to a clay jar in which the widow kept her supply of flour. +19:4 l5qk bottle of oil 1 In Israel, olive oil is used for cooking. The widow used the flour and the oil for making bread. +19:5 vp45 you troublemaker! 1 This means: ‘You are a troublemaker!’ Ahab was accusing Elijah of causing trouble by telling the king that he was doing wrong and also by stopping the rain. +19:5 tjol You have abandoned Yahweh 1 That is, Ahab had led Israel to stop worshiping and obeying Yahweh. +19:5 x6wi Mount Carmel 1 Mount Carmel is the name of a mountain located in northern Israel. It is over 500 meters high. +19:6 ngsa If Yahweh is God, worship him! But if Baal is God, worship him! 1 This does not mean that Elijah was undecided. He knew that Yahweh is the real God. He wanted the people to understand that when they worship false gods, they are rejecting Yahweh as the only true God. +19:8 khvd prayed to Baal 1 The prophets of Baal asked Baal to send fire onto the bull they prepared as a sacrifice. +19:8 fpgw cut themselves with knives 1 They injured themselves with knives as an extreme way to show their devotion to Baal, hoping that this would persuade him to listen to them. +19:9 f08m he told the people to pour 12 huge pots of water on top of the sacrifice 1 Elijah told the people to pour the water on the sacrifice so that it would be more difficult to burn. In this way, the people would know for certain that God had answered when he sent fire onto the sacrifice. +19:11 tpjj the rocks, the soil 1 Rocks and dirt do not burn. But God sent fire that was so hot that it even melted the rocks of the altar and the dirt underneath it. This showed the people that Yahweh is God, because only the true God could send fire that hot. +19:13 g4j3 Yahweh was ending the drought 1 God caused it not to rain for about three years in order to punish the people for worshiping Baal. Now, however, the people had rejected Baal and killed his prophets. Therefore, God was going to send rain on the kingdom of Israel again. +19:14 ofx2 Elijah finished his work 1 By that time, Elijah was very old. He had done everything that God told him to do. +19:14 y1j3 Naaman heard about Elisha 1 This means that people had told Naaman that Elisha was able to perform miracles. +19:14 pbor he went to Elisha 1 Naaman had to go into Israel to find Elisha and ask him to do this. +19:15 wnwq it seemed foolish 1 Naaman would not do what Elisha said because he knew that washing alone could not heal his disease. +19:17 sxyv a dry well 1 The well had water in it, but there was still mud in the bottom. +20:1 lpq9 broke the covenant 1 The people disobeyed the commands God had given them in his covenant with them at Mount Sinai (See: [13:04](13/04)). +20:4 jsx6 foreigners 1 This refers to people who were not Israelites. +20:4 j5vx Samaritans 1 When the foreigners married the Israelites, their children were neither foreigners nor Israelites. They were a mixed race. These children were called Samaritans. +20:5 ap9r The people in the kingdom of Judah saw how God had punished the people of the kingdom of Israel 1 God punished the kingdom of Israel first by sending the Assyrians to defeat them. The people in the kingdom of Judah saw this happen, and had time to repent. Instead, they continued to worship idols rather than worship God. +20:6 so2c agreed to be 1 The king of Judah was forced to either serve the Babylonian king or be destroyed. +20:7 tqz7 the Babylonians came back and attacked the kingdom of Judah 1 This was the second time that the Babylonians attacked the kingdom of Judah. The first time, they forced the king of Judah to serve them. This second time, they destroyed Jerusalem. +20:8 zzj9 then made him blind 1 The Babylonians were very cruel. They made the king blind to punish him, but also so that the last thing he would remember seeing was them killing his sons. +20:9 supn the Exile 1 The word **exile** means someone is removed from their country by force. The **Exile** is the term for this 70-year period when the Israelites were forced to live in Babylon. +20:11 wibh the Persian Empire 1 The Persian Empire grew to cover the area from central Asia to Egypt. It was located in the region of what is Iran today. +20:11 noh2 the land of Judah 1 That is, the area where the kingdom of Judah was located before the Exile. Jerusalem was the capital city of Judah. +20:12 xptw go back to Judah 1 Since most of these Jews were the children and grandchildren of those who left Judah, they had never lived in Judah before. +20:13 ehbu the people 1 That is, the Israelites, the descendants of Jacob, who were now called the Jews. +20:13 cnfm the wall 1 This wall was very thick (2.5 meters) and was built to protect the city from attackers. +21:1 vnid crush the snake’s head 1 A venomous snake cannot hurt anyone after its head has been crushed. To crush the snake’s head is to completely destroy the snake. +21:1 voyu Satan appeared as a snake in order to deceive Eve 1 Satan spoke to Eve in the form of a snake. This does not mean that he is a snake now. +21:1 jc2h to deceive Eve 1 The snake deceived Eve by making her doubt what God had said and tricking her into disobeying God. +21:2 mnhy through him 1 The blessing that would come to all the people groups would be through Abraham because it would come through one of Abraham’s descendants. +21:3 m3pq prophet like Moses 1 To be like Moses, the future prophet would need to have great authority from God to lead and rescue his people. +21:5 w4jz a New Covenant 1 The New Covenant would be truly effective. People really would know God. They would truly live as his people. And God would forgive their sins completely. God would make this New Covenant because the Messiah would die as a sacrifice for all who would believe in him. +21:5 l5zw writing his law on their hearts 1 This is in contrast with the way God had written his law on stone tablets for the Israelites. +21:7 m6jp in place of God punishing the people 1 The people sin, but God would punish the Messiah for their sins. In this way, God would not need to punish anyone who believes in the Messiah. +21:7 fohd the perfect high priest 1 The sacrifices the Israelite priests kept making were never good enough because the priests sinned. The Messiah would never sin. Therefore, his sacrifice was perfect and would satisfy God completely. +21:7 qfyx the perfect high priest 1 The sacrifices the Israelite priests kept making were never good enough because the priests sinned. The Messiah would never sin. Therefore, his sacrifice was perfect and would satisfy God completely. +21:7 u63x offer himself 1 The Messiah would offer himself as a sacrifice by allowing himself to be killed. +21:7 i8q6 a perfect sacrifice 1 There was no fault or imperfection in the Messiah’s sacrifice. +21:9 ylcb Malachi 1 Malachi was the last prophet in the Old Testament. +21:9 dg7p Micah 1 Micah was an Old Testament prophet of God who, like Isaiah, spoke his messages from God almost 800 years before the Messiah came. +21:10 q77e set prisoners free 1 This means he would set free those who have unjustly been put into prison. This could also refer to setting people free from the bondage of sin. +21:11 yjn7 Zechariah 1 Zechariah was an Old Testament prophet who spoke to God’s people after they returned to the Promised Land from the Exile in Babylon. This was about 500 years before the Messiah came. +21:11 rzj0 30 silver coins 1 At the time, each of these coins was worth the amount of money a person could earn in four days. +21:15 ivo6 at exactly the right time 1 God decided that he would send the Messiah at a specific time in history. God prepared everything so that the events his prophets spoke about would happen at that time. +22:1 tkem his people 1 This refers to the Israelites. +22:1 n0or Then came 400 years of silence 1 The last Old Testament prophet, Malachi, has prophesied 400 years before. +22:1 wzvx Zechariah 1 This was not the same person as the Old Testament prophet by that name. +22:2 nhzq The angel 1 This refers to the angel that came to Zechariah in [22:01](22/01). +22:2 ayj3 fill him with the Holy Spirit 1 That is, God will give him wisdom and power through the Holy Spirit. +22:4 sfrd Elizabeth 1 She was Zechariah’s wife. +22:4 j29d Elizabeth’s relative 1 Mary may have been Elizabeth’s cousin, but we don’t know exactly how these two women were related. +22:5 e4s8 How can this be 1 Mary was not doubting the truth of the angel’s words, but was asking how it would happen. +22:5 s365 Holy Spirit will come to you, and the power of God will come to you 1 By the power of God, the Holy Spirit miraculously caused Mary to become pregnant. This was not a physical act. This was a miracle. +22:5 g5zh the baby will be holy 1 The word **holy** here means the baby will belong to God. +22:6 xwfl baby jumped inside her 1 The baby moved suddenly inside Elizabeth’s womb in response to Mary’s greeting to Elizabeth. +22:6 rvqv what God had done for them 1 This refers to the fact that both women were pregnant through God’s supernatural intervention. Mary had conceived without a man, and Elizabeth had conceived with Zechariah after she was too old to have a child. +22:7 vw9w the prophet 1 John would be the prophet that the Old Testament prophets had predicted would come before the Messiah. +22:7 rbe3 the Most High God 1 This title refers to the fact that God rules over everything. +23:1 e79i he knew it was not his baby 1 Joseph knew that he was not the one who had caused Mary to be pregnant. +23:1 wgmy to shame Mary 1 Joseph was merciful to Mary, even though it seemed like she was an adulteress. +23:1 j5sq divorce her 1 In Jewish culture, an engagement was binding. The only way to end the engagement was to divorce the woman. +23:3 scan he did not sleep with her 1 Joseph kept Mary a virgin until after the baby was born. +23:4 g5ey When the time was near for Mary to give birth 1 This could mean ‘When it was near the end of Mary’s pregnancy.’ +23:4 jjdh the Roman officials 1 Rome had conquered and ruled over Israel at this time. +23:4 k32h to count all the people 1 The Romans probably counted the people so they could tax them. +23:5 vtwk no place for them to stay 1 Because Bethlehem was so crowded at that time, the usual rooms for guests were already full of people. +23:5 cew8 where some animals were kept 1 This was a place for sheltering animals, not a place where people lived. +23:5 t1aw a feeding trough 1 This refers to an animal feed box. The box could have been filled with hay to provide a padded surface for the baby to lie on. +23:6 pjyc guarding their flocks 1 A **flock** is a group of sheep. The shepherds were caring for their sheep, and protecting them from harm or theft. +23:6 lv1h they were terrified 1 The shepherds were very afraid when a supernatural angel appeared. +23:7 qpw4 wrapped in pieces of cloth 1 The custom of that time was to tightly wrap newborn babies in long strips of cloth. +23:8 nlff everything they had heard and seen 1 This included the glorious angels and their amazing message, as well as seeing the newborn Messiah himself. +23:9 lxan a country far to the east 1 This country was to the east of Israel. Many scholars think it was near Persia, which is modern-day Iran or Iraq. +23:9 vxo5 They studied the stars 1 These men may also have had access to the Old Testament prophets’ writings that predicted the birth of the Messiah. +23:9 biba an unusual star 1 The star that they noticed was not a normal star. It was something that appeared at the time of Jesus’ birth. +23:9 gskw the child 1 As much as a year or two passed before the men arrived in Bethlehem. Jesus was no longer a baby. +23:9 iqj6 the house 1 They were no longer staying in the place for animals where he was born. +23:10 ed1o bowed down 1 At that time, this was the customary way of showing great respect or reverence. +24:1 jyeq wild honey 1 This honey was the natural product of bees in the wilderness; it was not cultivated by people. +24:1 f2wz locusts 1 These were large, hopping insects with wings, like very large grasshoppers. Some people who live in the desert eat them. +24:1 knpf clothes made from camel hair 1 The hair of a camel is very coarse and strong. Clothes made of camel hair would not quickly wear out in the wilderness as other clothes would. +24:2 i3n5 Repent 1 To repent means to begin to think and act differently about something.In this case, it means to decide to change your behavior because it was wrong to sin. +24:2 ftny the kingdom of God is near 1 That means the kingdom of God is ready to appear. +24:3 dbv4 did not repent 1 That is, they did not turn away from their sins. +24:3 urr0 confess their sins 1 To confess is to acknowledge that something is true. These leaders did not want to acknowledge that they had sinned. +24:4 vjq5 You poisonous snakes 1 John was calling the religious leaders poisonous snakes because they were dangerous and deceptive. +24:4 y6g4 every tree that does not bear good fruit 1 John is not really talking about trees. This is an expression that compares good fruit to good actions and attitudes that come from God. +24:4 rfap God will cut down every tree that does not bear good fruit, and he will throw them into the fire 1 These phrases mean God will judge them and punish them. +24:4 w09h See 1 This word means that what follows is very important, and the one who hears should pay close attention to it. +24:4 hiij ahead of you 1 In this phrase, the word **you** refers to the Messiah. +24:4 o032 prepare your way 1 The prophets said that God’s messenger will prepare the people to listen to the Messiah. +24:5 ws2s not even worthy to untie his sandals 1 John meant that, compared to the Messiah, John was not important enough to do even the most menial task for him. Untying sandals was a very low job, something a slave would do. +24:6 qa8p the Lamb of God 1 Jesus was the perfect sacrifice for sin that God promised to provide. He fulfilled the image that was presented by the sacrifice of lambs in the Old Testament. +24:6 pkqm will take away 1 The sacrifice of Jesus causes God to look at our sin as if it never existed. +24:8 fntj This is my Son 1 God the Father called Jesus **my Son**. +24:9 ugqx God had told John 1 God had told John this before Jesus came to be baptized. +25:1 j549 During that time he fasted 1 Most scholars believe Jesus fasted during the entire 40 days and 40 nights. +25:1 nuoi tempted him to sin 1 Satan tried to convince Jesus to sin. +25:2 n684 turn these rocks into bread 1 Satan was reminding Jesus that, as the Son of God, Jesus had the power to supernaturally change the rocks into bread. +25:3 luqh It is written in God’s word 1 Jesus speaks the words that are written in Deuteronomy 8:3. +25:3 qmk8 People do not only need bread in order to live 1 Jesus knew that God had led him into the wilderness to fast. Therefore it would be wrong for Jesus to change the rocks into bread for him to eat. +25:3 csrd they need everything that God tells them 1 Jesus knew that hearing from God and obeying him was more important than eating food. By quoting this verse, Jesus showed that he was willing to follow it. +25:4 ako9 the highest point on the Temple 1 This part of the Temple in Jerusalem would have been about 150 meters from the ground. +25:4 gglp it is written 1 Satan spoke words from Psalm 91:11-12. +25:5 w02z Do not test the Lord your God 1 Jesus speaks the words that are written in Deuteronomy 6:16. Jesus wanted to say that it would be wrong to challenge God to take care of him while doing something that God did not want him to do. +25:6 bccu all the kingdoms of the world 1 This refers to all the greatest cities, countries, and other territories of the world. +25:6 av5l I will give you all this 1 It appears that Satan is able to give things of this world to people who obey him. +25:7 w4h4 Worship only the Lord your God. Honor only him as God 1 Jesus speaks the words that are written in Deuteronomy 6:16. We must worship and honor only the Lord God. +25:8 b1go did not give in to 1 Jesus did not do the things that Satan was tempting him to do. He did not sin. +26:1 vns1 After Jesus refused Satan’s temptations 1 Jesus did not do the wrong things Satan tried to get him to do, so Jesus defeated him. +26:2 fv93 the village where he had lived when he was a child 1 Jesus was born in Bethlehem, but Joseph and Mary were from Nazareth. They moved back to Nazareth when Jesus was a young boy and lived there after that. +26:2 pnm1 the place of worship 1 This was not the main Temple in Jerusalem where the Jews offered sacrifices. There were smaller buildings in many towns where the Jews worshiped and prayed together every week. This was one of those places. +26:2 lemg a scroll 1 A scroll was a long sheet of paper or leather that was rolled up and had writing on it. +26:2 nepe a scroll with the messages of the prophet Isaiah 1 This was a copy of the scroll that Isaiah had written hundreds of years before. +26:3 mhka proclaim good news to the poor 1 This means to tell poor and needy people the good message that God will help them. +26:3 fel1 to set prisoners free 1 This means to tell people who are wrongfully in prison that they will be released. +26:4 s685 The things I just read to you, they are happening right now 1 Jesus wanted to say that God was causing this passage about the Messiah to happen at that time. This meant that Jesus was the Messiah. +26:4 f07p Isn’t this the son of Joseph? 1 The people were not asking if he was Joseph’s son or not. They were wondering how he could be the Messiah since they thought he was only the son of an ordinary man. +26:5 l4j2 people never accept a prophet in the town he grew up in 1 Jesus was perhaps speaking a Jewish proverb. This proverb meant that people do not recognize the authority of a prophet who has grown up among them. Since Jesus grew up in Nazareth, the people there would not believe he was the Messiah. +26:5 xw6k he sent Elijah to a widow in a different nation 1 Jesus is referring to a story in the Old Testament about the prophet Elijah. God provided food for that widow during a famine so she could take care of Elijah. +26:6 mjuh Elisha 1 Elisha was God’s prophet who came after Elijah. Like Elijah, Elisha confronted Israelite kings who were sinning against God and he did miracles that God gave him power to do. +26:6 rz6x He only healed the skin disease of Naaman 1 Jesus is again referring to a story in the Old Testament. God healed Naaman because he obeyed what Elisha told him to do. +26:6 o8ir they were furious at him 1 The Jews did not want to hear that God had blessed any people besides themselves, so they were very angry at what Jesus said. +26:7 ay7n Jesus walked through the crowd 1 The crowd was trying to seize and kill Jesus. We do not know how Jesus was able to walk through the middle of them. Perhaps God confused them or prevented them from seeing Jesus. As a result, they were not able to do to Jesus what they had planned to do. +26:9 yvd1 who had demons in them 1 These people were controlled by evil spirits. +26:9 f202 You are the Son of God! 1 Even the demons knew that Jesus was the Son of God. +26:10 rtyu apostles 1 Jesus chose these 12 men from among his many disciples to be apostles. They spent more time with Jesus than his other disciples. And he later gave the apostles more authority than he gave his other disciples. +27:1 dcvk an expert in the Jewish law 1 This man studied and taught the laws God had given the Israelites, as well as other Jewish laws. +27:1 ry6z to inherit eternal life 1 The law expert was asking how he could be worthy to receive eternal life as an inheritance from God the Father. +27:1 a846 eternal life 1 This refers to life forever with God after the mortal body dies. +27:1 x8nr What is written in God’s law? 1 Jesus asked this question because he wanted the man to think about what God’s law really teaches. +27:2 ko5m Love the Lord your God 1 Jesus is quoting what God’s law commands people to do in Deuteronomy 6:5. +27:2 ipci with all your heart, soul, strength, and mind 1 This could mean ‘with your whole self’ or ‘with every part of yourself.’ +27:2 p5qu heart 1 The heart refers to the part of a person that has desires and emotions. +27:2 yg9t soul 1 The soul refers to the nonphysical, spiritual part of a person. +27:2 umjd strength 1 Here **strength** refers to the physical body and all of its abilities. +27:2 b43m mind 1 Here **mind** refers to the part of a person that thinks, plans, and has ideas. +27:2 h5e2 neighbor 1 Although the word **neighbor** normally refers to a person who lives near us,the Jews applied the term to everyone except close relatives, foreigners, and enemies. +27:2 emqy love your neighbor as yourself 1 This could mean ‘love your neighbor to the same extent that you love yourself.’ +27:3 gpmc who is my neighbor? 1 The law expert knew that he did not love everyone, and was asking which people he needed to love. +27:6 c3qe happened to walk down 1 The priest was not just walking on the road, but was traveling to get to another city. +27:6 eq11 ignored that man 1 The priest did not help that man or show any concern for him. +27:7 eeem Levites were a tribe of Jews 1 The Levites were from the Israelite tribe of Levi. +27:7 ptue ignored 1 This means he did not help the man. +27:9 jq13 an inn by the road 1 This was a place where travelers could get food and stay overnight. +27:11 i30d the three men 1 The three men were the priest, the Levite, and the Samaritan. +27:11 fcvr neighbor 1 Jesus is using the word **neighbor** in a broader sense than in [27:02](27/02). **Neighbor** here refers to anyone that we meet who needs our help. +27:11 m3as do the same 1 This could mean ‘love others, even your enemies.’ +28:1 m9em a rich young ruler 1 This man was already a rich and powerful political official, even though he was still young. +28:1 rnkj Good teacher 1 He meant to say that Jesus was a righteous teacher. He was not saying that Jesus was simply a skilled teacher. +28:1 psyp to have eternal life 1 This could mean ‘to live with God forever.’ +28:1 uekb Why do you call me ‘good’? 1 Jesus is not denying that he is good. Rather, he is asking if the ruler understands that Jesus is God. +28:2 uwyk as you love yourself 1 This could mean ‘as much as you love yourself.’ +28:4 yabf perfect 1 This could mean ‘completely righteous.’ +28:4 ywaw in heaven 1 Jesus is asking the man to give up wealth now in order to gain it later on when he will be with God. +28:6 bcff a camel 1 Camels are very large animals that are often used to carry heavy loads. +28:6 kfin the eye of a needle 1 This refers to the tiny hole in the end of a sewing needle. The idea of something as large as a camel going through the eye of a needle is intended to represent something that is impossible. +28:7 s6lw If it is like this, who will God save? 1 The disciples were surprised because many people believed that being rich was a sign of God’s favor. +28:7 ptyy save 1 This refers to God not judging or condemning them for their sin, and allowing them to be citizens in his kingdom. +28:10 l31f 100 times more 1 This could mean ‘very much more than he had before.’ +28:10 fojl many who are first will be last 1 This could mean ‘many people who are important now, will not be important then.’ +28:10 st9d many who are last will be first 1 This could mean ‘many people who are considered to not be very important on earth will be considered very important in heaven.’ +29:1 po42 my brother 1 This term sometimes included people who were not actually siblings, but who shared another very strong connection such as religion, ethnic background, etc. +29:1 oi9o Not seven times, but 70 times seven! 1 Jesus was not talking about an exact number. He was saying that we should forgive people every time they sin against us. +29:2 c8vd to settle accounts with his servants 1 That is, to collect the money his servants had borrowed from him. +29:4 jcuw fell on his knees 1 That is, he quickly knelt down on the ground. This was a way to show his humility and his desire for the king to help him. +29:4 nozy canceled all of his debt 1 The king said the servant did not need to pay back any of the money that he owed the king. +29:9 wpbf my heavenly Father 1 Jesus is expressing his unique, personal relationship to God the Father. +30:1 gx7x the lake 1 This refers to the Sea of Galilee. +30:1 p2ze to the other side of the lake 1 They went across the northern part of the lake. This would have been about 5-8 kilometers by boat. +30:2 zmmg to get to the other side 1 The distance around that part of the lake was about 8-10 kilometers. +30:3 q581 over 5,000 men in it, not counting the women and children 1 Some scholars think there may have been as many as 10,000 or 15,000 people. +30:3 z5s4 like sheep without a shepherd 1 This means the people were vulnerable and lost, just like sheep are when they have no shepherd to take care of them. +30:5 cxc1 How can we do that? 1 The disciples were not asking an actual question. Rather, they were strongly expressing that they did not think this was possible. +30:8 wvaa it never ran out! 1 This was a miracle. The small amount of food became enough for thousands of people as Jesus gave it to his disciples. +30:8 z9y2 were satisfied 1 That is, they were no longer hungry. +31:1 li7y to the other side of the lake 1 They went across the northern part of the Sea of Galilee. This would have been about 5-8 kilometers by boat. +31:2 zpe0 rowing their boat 1 The boat had a sail, but it would not have helped them much when the wind was against them. +31:3 dgdd walked on top of the water 1 This was a miracle. The average depth of the Sea of Galilee is 25 meters. +31:4 g8we they thought he was a ghost 1 The disciples thought Jesus was a spirit, because a human being cannot walk on water. +31:6 d6lr started walking to Jesus 1 Jesus enabled Peter to begin to actually walk on top of the water. +31:7 wujy Peter became afraid and began to sink 1 Peter sank into the water because he stopped looking at Jesus and became afraid of the waves instead. +31:8 w1dp They worshiped him 1 The disciples realized that Jesus could only do these miracles because he was the Son of God. +32:1 hnke the Gerasene people 1 The Gerasenes lived in an area along the eastern shore of the Sea of Galilee. They were descendants of the Jews, but we know few details about them. +32:2 c3fj was demon possessed 1 The man was controlled by evil spirits. +32:5 gmk5 knelt down in front of him 1 The man knelt down before Jesus as a sign of respect. He wanted Jesus to free him from the demons. +32:6 c7d1 What do you want with me 1 This expression means ‘What are you going to do to me?’ +32:6 mhvq the Most High God 1 This title means that God is the Supreme God who rules over everything. +32:6 jekt Legion 1 This was the name of the group of demons, but it also indicates that the evil spirits were very numerous. +32:10 cjoy begged to go along with Jesus 1 The man wanted to become one of Jesus’ disciples. +32:11 kzvt I want you to go home 1 Jesus told the man to serve him in his own town instead of traveling with Jesus to other places. +32:15 e5rk power had gone out from him 1 Jesus knew that his power had healed the woman. He asked who touched him because he wanted the woman to testify about what happened to her. +32:16 x1p3 shaking and very afraid 1 The woman was very afraid because she had tried to be healed secretly. She thought perhaps Jesus was angry with her for doing that. +32:16 q9k4 Your faith has healed you 1 Jesus did not heal the woman because she touched him, but because she believed that he was able to heal her. +32:16 as7v Go in peace 1 People spoke this traditional blessing when they left each other. Jesus may also have spoken these words because the woman was afraid. Now, however, she would know that Jesus had accepted her because of her faith in him. +33:1 fstt the lake 1 This refers to the Sea of Galilee. +33:2 w4an spreading the seed by hand 1 Farmers in the ancient Middle East typically planted grain-bearing crops by throwing the seed on the soil. +33:2 dx51 the path 1 The path was packed hard from people walking on it. The seed could not go down into the soil, so it was easy for the birds to eat all of it. +33:3 bdt5 very little soil 1 The rocky ground had enough soil to hide the seed from the birds, but not enough for the roots to grow well. +33:4 u4mb choked it out 1 The thorn bushes were so dense that the grain plants could not get enough sunlight to grow well. +33:6 vfkv This story confused the disciples 1 The disciples understood what happened to the seed, but they did not understand what it taught about God. +33:8 e8rl do not produce any grain 1 This could mean ‘do not produce spiritual fruit’ or ‘do not behave in a way that shows God’s Spirit is working in him.’ +33:9 d4cl produces fruit 1 This means he does the things that God wants him to do. +34:1 mdea stories 1 Jesus used these stories to teach truths about God’s kingdom. It is not clear if the events actually happened or not. +34:1 r18a a mustard seed 1 This probably refers to the seed of the black mustard plant, which has tiny seeds that rapidly grow into very large plants. +34:1 t0tu the smallest seed of all 1 That means the smallest of all the seeds that people planted at that time. +34:3 ogtk yeast 1 Yeast is added to bread dough to make it rise. A little bit of yeast mixed into a large amount of dough makes the whole batch of dough rise. +34:3 e1se bread dough 1 This is a mixture of flour and liquid that can be shaped and baked into bread. +34:3 oyxi it spreads throughout the dough 1 The yeast works its way into every part of the dough and causes it all to rise. +34:4 o0xa buried it again 1 He buried the treasure so that no one else would find it before he could buy the field. +34:4 i364 buy that field 1 After he bought the field, he could openly search for all of the treasure, and it would all be his. +34:5 arrz a perfect pearl 1 This refers to a pearl that does not have any defects, and is therefore very valuable. +34:5 g8dw a pearl merchant 1 This refers to a person whose business is buying and selling pearls. +34:6 kr1o despised others 1 This means they considered other people to be inferior to themselves. +34:6 bt9m the Temple 1 This refers to the Jewish Temple in Jerusalem. +34:7 r8o2 that tax collector 1 The Jews considered the tax collectors to be sinners because they worked for the Romans, collecting taxes from fellow Jews. +34:8 b9hl I fast 1 The religious ruler believed that doing this would earn favor with God. +34:9 f7v7 stood far away 1 He did not think he was worthy to come close to the religious leader. +34:9 t258 did not even look up to heaven 1 The word **up** indicates that people normally looked up to heaven when praying to God, but that this man did not because he was so ashamed of his sin. +34:9 l2vr he pounded on his chest with his fist 1 The tax collector pounded on his chest as a sign that he was very sorry that he had sinned. +34:10 e3jd declared him to be righteous 1 Even though the tax collector was a sinner, God was merciful to him because of his humility and repentance. +34:10 bb2z rather than the religious leader 1 God did not accept the prayer of the religious leader because he prayed in a proud way. The religious leader did not understand that he was also a sinner. +35:1 ujl7 tax collectors 1 The tax collectors were Jews who collected taxes for the Romans. The Jews hated them for that, and because they often collected higher taxes than the Romans required, keeping the difference for themselves. +35:2 usl8 religious leaders 1 This refers to the Jewish religious officials. +35:3 ql7b I want my inheritance now! 1 This was not normal. Sons received their inheritance when their fathers died. +35:3 wxx3 divided his property 1 The father was extremely generous to divide his property while he was still alive. An older son always received twice as much inheritance as a younger son. +35:5 zewc feeding pigs 1 The Law of Moses did not allow Jews to touch pigs. This was a shameful job for a Jewish man. +35:6 qopu one of his servants 1 The younger son assumed that his father would not accept him as his son, but might let him be a servant. +35:7 ugp1 He ran to his son 1 Older men did not run to meet people. The father was so excited to see his son that he ignored the culture and ran to kiss and hug his son. +35:8 m1eo I have sinned against God 1 The son had offended God, as well as his father by doing the things that he did (See: [35:03](35/03), [35:04](35/04)). +35:8 hucg I am not worthy to be your son 1 The younger son did not have time to ask to be a servant before his father interrupted him (See: [35:06](35/06)). +35:9 iy4c Put a ring on his finger and put sandals on his feet 1 A ring, sandals, and a fine clothes were symbols that showed the son was a member of the family and not a servant. +35:9 uvl0 kill the best calf 1 The Jews of that time often fed one of their calves special food so that it would be especially good to eat at a feast or other special occasion. +35:12 wmfv you did not give me even one small goat 1 A small goat was much less expensive than the best calf. The older brother was angry, and ignored the fact that his father had already given him twice the inheritance that he gave to the younger brother (See: [35:03](35/03)). +35:12 vp4r this son of yours 1 The older son was so angry that he did not speak of the younger son as his own brother. +35:13 l30h everything I have is yours 1 The father reminded his older son that he had already given him all of his possessions as an inheritance (See: [35:03](35/03)). +35:13 x5ze your brother 1 The father reminds his older son that his sons are also brothers. +35:13 x15h was dead, but now is alive 1 The younger son was so far away and separated from his family that it was as if he were dead. But now that he had returned, it was as if he were alive again (See: [35:09](35/09)). +36:1 f9j1 James 1 This is a different James than the one who wrote the Book of James in the Bible. +36:3 axzs Moses and the prophet Elijah 1 Moses gave the law to Israel, and Elijah was one of the most important prophets of Israel. These two men represented the way God spoke to Israel in the Old Testament. +36:4 xmte shelters 1 These were the small, individual, temporary shelters the Jews made from tree branches during an annual Jewish holiday. +36:4 vc1v did not know what he was saying 1 Peter spoke without thinking clearly because he was so excited. +36:5 kv9v a voice coming from the cloud 1 God spoke to them from the cloud. +36:5 j5pq This is my Son whom I love 1 This is the same thing that God had said about Jesus after John the Baptist baptized him in [24:08](24/08). +36:5 hula Listen to him 1 Moses and the prophets were important, but God told the disciples that Jesus was more important, and that they should honor what he said more than they honored Moses and the prophets. +36:6 loxb the only one still there was Jesus 1 Moses and Elijah had gone away, leaving only Jesus with the disciples. +36:7 eco9 Do not tell anyone yet 1 Jesus knew that the people would not yet believe who he was, but later, when he came back to life, many people would believe. +37:1 tp83 Mary 1 Jesus’ mother was also named Mary. This was a different woman. +37:1 ma7e This sickness will not end with Lazarus dying 1 Jesus’ disciples probably thought this meant that Lazarus would not die. But Jesus knew that, although Lazarus would die from his sickness, he would become alive again. +37:2 gp2d but he waited where he was for two days 1 Jesus stayed where he was for two days, even though they wanted him to go and heal Lazarus. He was waiting for Lazarus to die. +37:2 ahdt Judea 1 This refers to the southern section of Israel, which was settled by the tribe of Judah. +37:2 ofnu has fallen asleep, and I must wake him 1 When Jesus spoke about sleeping, he was talking about death. However, the disciples did not understand that yet. +37:3 necw he will get better 1 The disciples thought there was no reason for them to go to Lazarus now, since he was getting well. +37:3 arrm I am glad 1 This did not mean he was happy that Lazarus died, but rather that he was happy that God was going to show how great he is. +37:4 bnmi Martha 1 Martha was the sister of Lazarus and Mary (See: [37:01](37/01)). +37:4 ycq1 my brother would not have died 1 Martha believed that Jesus could have prevented her brother from dying. +37:5 xwkd I am the Resurrection and the Life 1 This is one of several very powerful **I am** statements in which Jesus says something about his essential nature. In this one, Jesus indicates that he is the provider or source of resurrection and life. +37:5 zcfs will never die 1 That means they will live forever, even if they die for a short time. +37:6 b44s Mary 1 This was the same woman as in [37:01](37/01), not the mother of Jesus. +37:6 uk76 fell at the feet of Jesus 1 Mary knelt down at Jesus’ feet as a sign of respect. +37:6 pzl3 my brother would not have died 1 Like Martha in [37:04](37/04), Mary also believed that Jesus could have kept her brother from dying. +37:7 p74o he told them 1 He was probably not telling Mary and Martha to roll the large stone away. He was speaking to the men who were with them. +37:7 zvga Martha 1 Martha was the sister of Lazarus and Mary (See: [37:01](37/01)). +37:8 l114 Did I not tell you 1 This could mean ‘Remember that I told you.’ Jesus is not asking this question in order to get an answer, so some languages should translate this as a command. +37:8 s6zz see God’s power 1 This could mean ‘see the power of God displayed’ or ‘see God show how powerful he is.’ +37:8 tuet rolled the stone away 1 Some languages should say: “rolled the stone away from the opening of the tomb.” +37:10 wqkk grave clothes 1 This refers to the strips of cloth that the Jews wrapped around dead bodies before they buried them. +37:11 qhlt envied 1 The religious leaders were jealous that the people were listening to Jesus instead of listening to them. +38:3 ovsa 30 silver coins 1 Each of these coins were worth about four days’ wages. +38:4 ahq4 broke it 1 Jesus tore the flat loaf of bread into small pieces in order to share it among the disciples. +38:4 w89v This is my body, which I will give for you 1 Jesus was referring to his death, which would happen soon. +38:5 kf9p my blood of the New Covenant 1 The shedding of Jesus’ blood made the New Covenant possible. +38:5 p1x9 I will pour out 1 Jesus would bleed as he was dying. +38:5 kgox remember me 1 When his followers ate this ceremonial meal in the future, it would remind them of how Jesus died for them. +38:7 oh3p Satan entered into him 1 At this time, Satan took control of Judas. +38:8 parl Mount of Olives 1 This is the name of a hill covered with olive trees, just outside the walls of the city of Jerusalem. +38:8 rc56 It is written 1 Jesus quoted a prophecy in the Old Testament that refers to Jesus’ death and his followers' desertion. +38:8 r43l the shepherd and all the sheep 1 Jesus is the shepherd in the prophecy, and his disciples who desert him are the sheep. +38:9 mjcz to have all of you 1 Satan wanted to cause all of the disciples to be so afraid of being killed that they would abandon Jesus. +38:9 qzo2 that your faith will not fail 1 Jesus prayed that Peter would not completely stop believing in Jesus. +38:9 pbv5 before the rooster crows 1 Roosters normally crow at the first light of the new day. +38:11 xara a place called Gethsemane 1 Gethsemane was a garden at the foot of the Mount of Olives. +38:11 d1yy they would not enter into temptation 1 This could mean ‘they would not be tempted’ or ‘Satan would not tempt them.’ +38:12 nmmj drink this cup of suffering 1 This is a figure of speech that means ‘Jesus would endure this suffering.’ +38:12 esp4 let your will be done 1 Jesus did not want to die, but he understood that he must die in order to make a way for God to forgive sinners as God wanted to do. +38:12 ilmz his sweat was like drops of blood 1 This may mean that Jesus’ grief was so intense that he started to bleed, and his blood mingled with his sweat. +38:15 ddm0 I could ask the Father for an army of angels to defend me, but I must obey my Father. 1 Jesus could have easily prevented the soldiers from arresting him. However, he allowed it because it was God’s will that he die in the place of sinners. +38:15 lb2f Jesus healed the man’s ear 1 Jesus was so gracious that he even healed the ear of the man who had come to arrest him. +38:15 t39i all the disciples ran away 1 The disciples fled as Jesus had said they would in [38:08](38/08). +39:1 rop3 the house of the high priest 1 The soldiers took Jesus there because the high priest was the one who ordered them to arrest Jesus. +39:3 pr2q are you the Messiah, the Son of the living God? 1 The religious leaders could not find any reason to condemn Jesus. Therefore, they asked him to tell them if he was the Son of God. They did not believe he was God’s Son. If he said that he was indeed the Messiah, they planned to condemn him for falsely stating that he was God. +39:4 dkt4 I am 1 **I am** is also the name of God (See: [09:14](09/14)). By saying simply “I am,” Jesus was also saying that he is God. +39:4 ee6p seated with God 1 Because God is the ruler over all, people talk about him as sitting on a throne in heaven. By saying that he would be seated with God, Jesus claimed that he had authority to rule with the Father. +39:4 gwqj tore his clothes because he was angry 1 The Jews would tear their clothes to show grief or anger. +39:4 q3tl What is your decision about him? 1 The chief priest wanted the religious leaders to condemn Jesus for claiming to be equal with God. +39:5 yklu He deserves to die! 1 The Jewish law said that any person who claimed to be God must be killed. Because the Jews did not believe that Jesus was God, they condemned him to die. +39:6 hy5a you both are from Galilee 1 The people could tell from the way Jesus and Peter talked that they both came from the region of Galilee. +39:7 xmnm a rooster crowed 1 **Crowing** is the loud sound that a rooster makes. Jesus had told him in [38:09](38/09) that Peter would deny Jesus before the rooster crowed. +39:8 zh9j Judas became full of sorrow 1 Although Judas was sorry for what he had done, he did not ask God to forgive him. Instead, he killed himself. +39:9 my2z He worked for Rome 1 The Roman government had appointed Pilate to govern the region of Judea in Israel. +39:9 bm9b condemn Jesus and kill him 1 As governor, Pilate had the authority to condemn Jesus to death and to give approval for his crucifixion, or he could set him free. The Jewish religious leaders did not have the authority to have someone killed. +39:10 bf8k my kingdom is not here on earth 1 Jesus’ kingdom is not like earthly kingdoms. +39:10 q5ys my servants would fight for me 1 An earthly king would ask his disciples to fight to protect him. But Jesus was not that kind of king. +39:10 sre4 listens to me 1 This includes not just hearing Jesus’ words, but also doing what he says. +39:10 vllp What is truth? 1 Pilate did not believe that anyone could know what is true. +39:11 fo88 Crucify him! 1 The Romans executed the worst criminals by nailing them to a cross and letting them hang on it until they died of exhaustion or asphyxiation. +39:11 ae4m He is not guilty! 1 Pilate correctly judged that Jesus was completely innocent. But the people would not accept his judgment. +39:12 avw7 he agreed to have 1 Pilate did not want to kill Jesus because he believed that Jesus was innocent. But he was forced to tell his soldiers to crucify Jesus because of his fear of the crowd. +39:12 jrq5 a royal robe 1 This robe had a bright color, so it looked like the kind of robe that a king would wear. +39:12 u009 a crown made of thorns 1 They tied thorn branches into a circle to look like a crown. A crown is an ornament that a king wears on his head to show his authority. But the crown that they put on Jesus’ head had sharp, dangerous thorns on it. +39:12 caqq the King of the Jews 1 The soldiers said this to mock Jesus. They did not believe that he was the King of the Jews. +40:1 es9a to crucify him 1 The soldiers crucified criminals by nailing them to a large cross and keeping them there until they died. +40:2 meg7 the Skull 1 This is a small escarpment near Jerusalem with a rocky, white face which looks somewhat like a skull. +40:2 n1lx forgive them, because they do not know what they are doing 1 Jesus knew that the soldiers thought Jesus was only a criminal who deserved to die. They did not understand that he was the Son of God. +40:2 rmia a sign on the cross above his head 1 The Romans often put a sign on a cross to state the crime that the person had committed. +40:3 y7rk gambled for Jesus’ clothing 1 The soldiers played a game of chance to win Jesus’ clothes. +40:3 b7vc they fulfilled a prophecy that said 1 King David wrote these words in Psalm 22 hundreds of years before this event. +40:4 fas5 two robbers 1 This refers to criminals who used force or violence to steal things. +40:4 t9m6 Paradise 1 This is another name for ‘heaven.’ +40:5 qwhl come down from the cross and save yourself! 1 These people did not understand that Jesus was able to come down from the cross and to save himself (See: [38:15](38/15)). However, it was God’s plan for him to die so that he could save other people (See: [38:12](38/12)). +40:6 fi1h the whole region became completely dark 1 God caused this darkness. Natural events such as an eclipse only last few minutes. This darkness lasted three hours. +40:7 mk6w It is finished! 1 This means that Jesus has completed his work to save people who had sinned against God. +40:7 nukf gave up his spirit 1 Jesus released his spirit back to God, and he died. +40:7 ivb3 the large curtain 1 This was a large, strong fabric hung in the Temple. It was like a wall separating one room from another. +40:7 s996 from the top to the bottom 1 The curtain was torn from the top to indicate that God was opening it from above, rather than men opening it from below. +40:8 m1xj opened the way for people to come to God 1 The tearing of the curtain showed that the barrier between God and people had been removed. +40:8 qm6m He was the Son of God 1 The soldier realized that Jesus did not die like an ordinary man, and that God had done the miraculous things that happened when he died. +40:9 ln1z Joseph 1 This was not Mary’s husband. It was another man named Joseph. +40:9 zck0 asked Pilate for Jesus’ body 1 The two men asked Pilate to permit them to take Jesus’ body down from the cross in order to bury it. +41:1 ltm4 That liar, Jesus, said 1 The Jewish leaders refused to believe that Jesus told the truth about being the Son of God. +41:1 jh0p rise from the dead 1 The Jewish leaders were well aware that Jesus promised to become alive again. +41:2 e10e a seal on the stone 1 They put a soft material like clay or wax between the stone and the tomb and marked it with an official seal. If anyone moved the stone, the material would break and show that someone had entered the tomb. +41:3 biod No one could work on the Sabbath day 1 The Sabbath day rules did not permit a Jew to walk very far or to do any other kind of work. +41:3 kmo8 spices 1 This refers to sweet-smelling spices that were placed on a dead body to cover the bad smell. +41:4 smj0 fell to the ground like dead men 1 They were not dead, but they did not move, just like dead men do not move. They probably had fainted from fright. +41:5 py8p Do not be afraid 1 The women were frightened because the angel shone like lightning. +41:6 w2u1 he will go to Galilee ahead of you 1 Jesus intended to meet his disciples in Galilee. +41:8 hyzr Do not be afraid 1 The women perhaps were afraid because they thought that Jesus was a ghost. +42:1 yk1f the women said he was alive again 1 The women told the disciples that Jesus was alive in [41:08](41/08). +42:2 lxty all the things that had happened 1 This refers to the teaching and miracles of Jesus, his death, and the reports of his resurrection. +42:3 tnm1 on the third day 1 This refers to the third day after his death. +42:6 yvlw Peace to you 1 This was a normal greeting among the Jews. However, Jesus may have said this here because the disciples thought he was a ghost and were frightened when he appeared. +42:6 jjya a ghost 1 This refers to the spirit of a dead person. +42:7 gw0e Jesus made them understand God’s word better 1 Jesus did something that enabled them to better understand the meaning of the scriptures. +42:8 nhk6 My disciples will proclaim this message starting in Jerusalem 1 The disciples would speak first in Jerusalem about Jesus rising from the dead, and then they would speak about it in other places. +42:10 q3nk make disciples in all people groups 1 The disciples would help people from every people group to also become disciples of Jesus. +42:10 mgy3 in the name of 1 This phrase means both ‘by the authority of’ and ‘under the authority of.’ +42:11 u2ty at the right hand of God 1 This was the position of the highest authority. +43:1 a6tb stayed in Jerusalem 1 Jesus had told them to stay in Jerusalem until the Holy Spirit came upon them (See: [42:11](42/11)). +43:2 c4bu celebrated the wheat harvest 1 The Jews would thank God for the wheat harvest by bringing offerings and celebrate by having special meals. This happened in May; other crops were harvested at other times of the year. +43:2 bggh This year 1 This refers to the year that Jesus died. +43:3 dztg filled with the Holy Spirit 1 The Holy Spirit entered into them and began to give them power to speak in other languages. +43:4 mknb this noise 1 This refers to the sound like a rushing wind that happened when the Holy Spirit filled the believers. +43:4 oa1c in their own native language 1 The people in the crowd were from different regions, and spoke different languages. They each heard the disciples speak to them in their own language. +43:5 kw6x Joel 1 Joel was a prophet in Israel who lived hundreds of years before this happened. +43:5 xu6d the last days 1 This refers to the final days before the end of the world. +43:5 y15d pour out my Spirit 1 This means that God will give his Spirit generously to people. +43:5 cgyi my Spirit 1 This refers to the Holy Spirit. +43:6 djjv you crucified him! 1 The Jews did not actually nail Jesus to the cross. However, the Jewish leaders caused him to be condemned and many of the people in the crowd had shouted for him to be crucified (See: [39:11](39/11)). +43:7 dfbk You will not let your 1 **You** and **your** refer to God the Father. +43:7 l5xn rot in the grave 1 This refers to the fact that Jesus did not remain in the tomb very long. It is another way of saying that he did not stay dead, but rather, came back to life again. +43:8 r1lz at his right hand 1 This is the place of highest honor. +43:8 b9nd as he promised he would do 1 Jesus promised to send the Holy Spirit to the disciples in [42:11](42/11). +43:8 l846 The Holy Spirit is causing 1 The Holy Spirit was the one who enabled the believers to speak the languages of all the people. +43:9 aqnt the Lord of everything 1 By saying this about Jesus, Peter was saying that Jesus is God. +43:10 r22j Brothers 1 This was a normal way for a Jew to address fellow Jews. +43:11 nz67 repent 1 To repent is to change one’s way of thinking about God. +43:11 ld3r in the name of 1 This phrase means both ‘by the authority of’ and ‘under the authority of.’ +43:11 onfh Christ 1 This is the same meaning as “Messiah.” +44:1 ev2q the Temple 1 This refers to the Jewish Temple in Jerusalem. +44:2 tdz5 In the name of Jesus 1 This expression here means ‘by the authority of Jesus.’ +44:3 ul6l the courtyard of the Temple 1 Only priests could enter the Temple, but ordinary Jews were allowed to come into this area that surrounded the Temple. +44:5 yw3g You are the ones who told the Roman governor to kill Jesus 1 The Jews did this in [39:11](39/11). +44:5 v2d7 turn to God 1 Peter is telling the Jews they must begin to obey God. +44:6 ysbc they were very upset 1 The leaders had Jesus killed because they were jealous that people listened to him. They were upset now that people were still talking about him. +44:6 ld6j The number of men 1 This was in addition to the women and children who believed. +44:8 dt57 rejected him 1 That is, they refused to believe that Jesus was the Messiah. +44:8 nqmc but there is no other way to be saved except through the power of Jesus 1 Jesus is the only one who has the power to save people. +44:8 vf48 to be saved 1 This means God will not condemn them for their sins. +44:9 wt2q ordinary 1 That means Peter and John were simple fishermen. +44:9 uqmd who were uneducated 1 That means they did not have a formal or religious education. +44:9 o2fm had been with Jesus 1 The disciples had spent time with Jesus and he had taught them. +45:1 nn7p followers of Jesus 1 This title refers to people who believe in Jesus Christ. +45:2 npl8 Moses 1 God used Moses to free the Israelites from being slaves in Egypt (See: [12:12](12/12)). God then gave his laws and commandments to Moses to give to the Israelites (See: [13:07](13/07)). +45:4 d1z9 covered their ears 1 They did this to show that they did not want to hear what Stephen said. +45:4 h092 They dragged Stephen out of the city 1 They did this as a sign that they did not think Stephen was worthy to live among them. +45:4 hdvl threw stones at him in order to kill him 1 This was the method that the Jews used to kill people who they believed had offended God. +45:5 tk0c Jesus, receive my spirit 1 Stephen prayed to Jesus, believing that when he died, his spirit would go to heaven, where Jesus is. +45:5 o3ix do not hold this sin against them 1 Stephen asked God to forgive the Jews for killing him. +45:6 xodp many people in Jerusalem started persecuting the followers of Jesus 1 The Jews were not satisfied to kill only Stephen. They also began to attack all of the other followers of Jesus who believed in him the same way Stephen did. +45:6 uye2 But in spite of opposition 1 The Jewish leaders thought they could stop the spread of Jesus’ teaching by persecuting his followers. Instead, this caused them to scatter and spread the message even more widely. +45:7 md15 Samaria 1 This region was located on the north side of Judea. The Jews hated the Samaritans, and rarely went there. +45:7 jhf0 chariot 1 A chariot was a type of cart with two wheels that was pulled by horses. A chariot had space for a few people to ride in it. It was used by soldiers and important officials. +45:7 jmob Ethiopia 1 Ethiopia is a country in Eastern Africa. +45:8 j4qc the Ethiopian 1 This refers to a person from the country of Ethiopia. +45:8 dax3 the prophet Isaiah 1 Isaiah lived many hundreds of years before Jesus. +45:8 oq1k as a lamb is silent 1 Lambs are so afraid that they are often silent when someone kills them. +45:9 dzax Was Isaiah writing about himself or someone else? 1 The Ethiopian was not able to understand the prophesy of Isaiah. He needed Philip to help him know whom Isaiah was writing about. This is why the Holy Spirit sent Philip to the Ethiopian. +45:11 prhn some water 1 This refers to a larger body of water such as a pond, lake, or stream. +45:11 picg May I be baptized? 1 Perhaps Philip told the Ethiopian that the disciples of Jesus were baptized, or perhaps when the Ethiopian was in Jerusalem, he heard that John the Baptist and Jesus baptized their disciples. He now decided that he wanted Philip to baptize him. +45:12 i67h carried Philip away 1 The Holy Spirit suddenly took Philip to a different place in a miraculous way. +46:1 vemc Saul 1 This was not the same man as King Saul in the Old Testament. Saul would later change his name to Paul (See: [47:01](47/01)). +46:1 xvy9 guarded the robes of the men who killed Stephen 1 See [45:06](45/06). +46:1 rj59 Damascus 1 Damascus is now the capital of the country of Syria. During Saul’s time, it was a city belonging to the Roman Empire. Most of the people there were not Jewish, but there were some Jews and also some followers of Jesus living there. +46:4 jzwv But Ananias said 1 Ananias did not want to go to Saul because he was afraid Saul would arrest him. +46:4 ki13 to declare my name 1 This could mean ‘to teach about me’ or ‘to make me known.’ +46:4 clnz for my name 1 Saul would suffer because he would be associated with Jesus and serve Jesus. +46:5 llyp placed his hands on him 1 This was a symbol that Ananias accepted Saul and gave God’s message to him. +46:6 e2pr argued with the Jews 1 Saul spoke persuasively with the Jews to convince them to believe in Jesus. +46:7 xpuc the city gates 1 The gates were the only normal way into or out of the walled cities. +46:7 mw12 lowered him over the city wall in a basket 1 The other believers helped Saul get into a large basket and lowered the basket with him in it over the city wall so he could leave the city without going through the gates where the Jews waited to kill him. +46:8 taxl accepted Saul 1 Barnabas convinced the apostles that Saul also was a believer in Jesus. +46:9 n2h1 the city of Antioch 1 This was an ancient city located in what is now the southernmost tip of the modern country of Turkey, near its border with Syria and close to the Mediterranean Sea. It was about 450 miles northwest of Jerusalem. +46:9 fe9e to strengthen the church 1 Barnabas and Saul helped the church to grow strong spiritually by teaching them about God and about Jesus. +46:9 vqla Christians 1 They were called Christians because they believe in Jesus Christ. +46:10 rqyb placed their hands on them 1 This was a symbol that they were sending Barnabas and Saul out to work for God on behalf of all the followers of Jesus. +47:1 fepu Philippi 1 Philippi was a major city and Roman colony located in Macedonia in the northern part of ancient Greece. +47:2 j3r4 She invited Paul and Silas to stay at her house 1 This was the normal custom of the day for people to provide hospitality to visitors in their homes. There were no immoral motives in this arrangement. +47:3 z4z7 as a fortuneteller 1 The masters of the slave girl charged people money for her to tell them what would happen to them in the future. +47:4 fu9w Paul became annoyed 1 Paul and Silas were indeed telling people how to be saved. But the demon who controlled the girl was the one who was actually saying these things. Paul did not want to accept praise from a demon. +47:5 nhy7 In the name of Jesus 1 Because of Jesus’ authority, Paul could command the demon to leave. +47:6 vqea without the demon 1 The owners of the slave girl knew that a demon gave her the power to tell what would happen in the future. They only thought of their own profit, and were not happy that the girl was now freed from the demon that had controlled her. +47:7 pau5 Paul and Silas to the Roman authorities 1 Paul and Silas had done nothing wrong, but they were strangers in Philippi. The Roman authorities believed the false accusations of the owners of the slave girl and punished Paul and Silas. +47:8 yn5o singing songs of praise to God 1 Paul and Silas were able to trust God even though the authorities beat them and put them in prison. Therefore, they were singing and praising God. +47:9 fmhh the chains of all the prisoners fell off 1 God caused this to happen. A natural earthquake would not release a person from the chains on their hands and feet. +47:10 gkjl the jailer 1 This could mean ‘the official in charge of the jail.’ +47:10 rupl he got ready to kill himself! 1 The jailer was so afraid, thinking that the prisoners had escaped, that he intended to kill himself rather than be punished for his failure to guard them. +47:11 lc51 What must I do to be saved? 1 The jailer knew that it was God who caused the earthquake and released the prisoners. He wanted to know how he could be saved from being punished by that powerful God. +47:11 hdr2 Believe in Jesus, the Master 1 This was addressed to both the jailer and his family, who all then believed and were baptized. +47:13 yxzc The good news about Jesus kept spreading 1 People in more and more places were hearing the good news about Jesus. +47:13 cn51 the Church kept growing 1 More and more people were becoming part of the Church by believing in Jesus. +48:1 txe9 God created the world 1 See [01:01](01/01). +48:1 olyg perfect 1 Everything was exactly as it should have been in order to accomplish all that God intended for it. +48:1 cj1i Adam and Eve 1 See [01:14](01/14). +48:1 g8rw There was no sin 1 See [02:01](02/01). +48:2 ffnt Satan 1 Satan is a spirit being that God created. He rebelled against God and became God’s enemy. +48:2 kl08 the garden 1 This refers to the garden created by God where he placed the first man and woman [01:10](01/10). +48:2 ithm deceive her 1 Satan lied to Eve by leading her to doubt what God had said. By doing this, he tricked her into disobeying God (See: [02:04](02/04)). +48:2 qw2t Because they sinned, everyone on earth dies 1 See [01:11](01/11). +48:4 fsp6 crush Satan’s head 1 God made this promise in [02:09](02/09). This (crushing the head) represents a person stepping on the head of a snake. The head is completely crushed, and the snake is dead and therefore harmless. +48:4 yj5h bite his heel 1 This represents a snake on the ground biting a person’s foot. In this case, Satan would cause the Messiah to suffer, but would not destroy him (See: [02:09](02/09)). +48:5 f5o7 God told Noah to build a boat 1 See [03:02](03/02). +48:6 kx2p priests kept on offering sacrifices 1 See [13:09](13/09). +48:6 fn6t He gave himself 1 That is, Jesus allowed himself to be killed. +48:7 ye53 I will bless all the people groups on the earth 1 See [04:04](04/04). +48:8 rmro sacrifice his own son, Isaac 1 See [05:06](05/06). +48:8 a4b2 the Lamb of God 1 See [24:06](24/06). +48:9 ppvs sent the last plague on Egypt 1 This was the tenth plague when God caused the firstborn sons of the Egyptians to die (See: [11:07](11/07)). +48:9 w6ud kill a lamb 1 See [11:02](11/02). +48:9 w1qp the Passover 1 The Passover is the name of a religious festival that the Jews celebrate every year to remember how God rescued their ancestors, the Israelites, from slavery in Egypt (See: [12:14](12/14)). +48:10 x285 blood of Jesus 1 This refers to the sacrifice of himself that Jesus made when he died for sinners. +48:11 y4pz a covenant 1 A covenant is a formal, binding agreement between two parties that one or both parties must fulfill. +48:12 vjxo call Jesus the Word of God 1 Jesus reveals God’s character. The other prophets preached the message God gave them, but Jesus revealed God in his preaching and his actions. +48:13 fh81 God promised King David 1 See [17:07](17/07). +49:1 nmdr the Holy Spirit came to her and made her become pregnant 1 Scholars cannot explain how the Holy Spirit caused Mary to become pregnant. However, the Holy Spirit does not have a physical body, so we know that the Holy Spirit did not have sexual relations with Mary (See: [22:05](22/05)). +49:2 v0yj He walked on water 1 See [31:03](31/03). +49:2 ordf drove demons out 1 See [26:09](26/09). +49:2 uc43 He raised dead people to life 1 See [37:10](37/10). +49:2 oeqz to feed over 5,000 people 1 See [30:08](30/08). +49:3 z8oh a great teacher 1 This could mean ‘a very important teacher’ or ‘an excellent teacher.’ +49:3 ezee the same way 1 This could mean ‘as much as’ or ‘the same amount that’ or ‘to the same degree that.’ +49:4 bz6k love God more than you love anything else 1 See [28:04](28/04). +49:5 f2oq better to be in God’s kingdom 1 See [34:04](34/04). +49:6 hkbl good soil 1 See [33:09](33/09). +49:6 j3it hard soil on a path 1 See [33:06](33/06). +49:8 zf9z Adam and Eve sinned 1 See [02:05](02/05). +49:9 xl6w gave his only Son 1 That is, he offered his only Son to the world as a sacrifice for sins. +49:10 gc3w Jesus took the punishment for sin in our place 1 Jesus willingly took the place of sinners and received the punishment that they deserved. +49:10 pfa6 killing him on a cross 1 See [42:02](42/02). +49:11 xy82 take away 1 The sacrifice of Jesus causes God to look at our sin as if it never existed. +49:14 hptr to believe in him 1 That means to believe that he is God and to trust in him to save you. +49:14 dlz1 to be baptized 1 Jesus wants people to be baptized in order to show others that they have believed in him. +49:15 rtla kingdom of darkness 1 **Darkness** is used here to refer to sin and everything that is evil. +49:15 es5u kingdom of light 1 **Light** here refers to God’s holiness and goodness. The Bible often compares evil to darkness, and goodness to light. +49:15 pu93 God has enabled you to no longer sin as you used to do. 1 Followers of Jesus still sin sometimes. But because the Holy Spirit lives in them, they can now resist sinning. Therefore, they do not sin easily or often, like they did before God saved them. +49:17 shb8 confess your sins 1 This could mean ‘admit to God what you have done wrong.’ +49:17 t5dd He will give you strength to fight against sin 1 God will give you spiritual strength to refuse to sin. +50:1 sk81 The Church has been growing 1 That is, the number of people who have believed in Jesus has been increasing. +50:1 c6q6 at the end of the world 1 This refers to the final days of this world. +50:3 n4zt make disciples 1 This has the meaning ‘help people to become my disciples.’ +50:3 qo1y The fields are ripe for harvest 1 That is, people in many places are ready to be gathered and brought to God like crops that are ripe in fields and ready to be gathered. +50:3 bn02 The fields 1 In this expression, **The fields** represents the people in the world. +50:3 b0u1 ripe 1 **Ripe** here represents being ready to believe in Jesus. +50:3 qalg harvest 1 **Harvest** here represents the work of bringing people to God by teaching them about Jesus. +50:4 q6w3 in this world 1 This could mean ‘in this lifetime.’ +50:4 p308 remain faithful to me 1 This could mean ‘Keep obeying me.’ +50:4 a7v3 to the end 1 This could mean ‘to the end of your life.’ +50:4 pzus will save you 1 This refers to spiritual salvation rather than physical deliverance from harm. It has already been stated that many believers will be killed or tortured. +50:5 a7kg good seed 1 This seed was wheat grain. +50:5 zref weed seeds 1 The weed seeds that were planted would grow up as tall grass but could not be eaten. They were useless. +50:5 m2p3 wheat seeds 1 Wheat is a kind of grain that grows like a tall grass. It has seeds that people use for food. +50:7 v0j0 you will pull out some of the wheat as well 1 It would be too difficult to distinguish young wheat from the weeds, and to pull the weeds without uprooting the wheat. +50:7 h0rw barn 1 This refers to the building where the harvested wheat grain was saved and stored. +50:8 xk0n the people of God’s kingdom 1 This refers to the people whom God has chosen to live in his kingdom. +50:9 ytlj who belong to the devil 1 This refers to the people who are ruled by the devil. +50:9 hzmd the devil 1 The devil is also called “Satan.” +50:9 l5r1 the evil one 1 This is another title for Satan. It describes his character. +50:9 iyhk the harvesters 1 This refers to the men who harvest the ripe grain. +50:10 mube who belong to the devil 1 This refers to those who do not believe in Jesus, but follow the evil ways of the devil. +50:10 kw2t the people who are righteous 1 This refers to the people who belong to the Messiah (See: [50:08](50/08)). +50:10 timc shine like the sun 1 This means everyone in heaven will see that they are good. +50:11 klcq he will have a real body 1 Jesus will still have his physical body, but it will be different than the body he had while he was on earth. He will never be able to die again. +50:11 x2dg will come on the clouds in the sky 1 The clouds in the sky will surround Jesus as he comes. +50:11 i7id meet him in the sky 1 Those who believe in Jesus will go up to be near Jesus while he is in the sky. +50:12 ppfq still alive 1 This refers to followers of Jesus who will still be alive when he returns to earth. +50:13 ftlv a crown 1 This crown represents our reward for believing in Jesus and serving him in this life. +50:14 r3pn hell 1 **Hell** is the place where God will punish forever all the people who do not believe in Jesus. +50:14 ed8x weep and grind their teeth 1 This is a symbol of their intense suffering (See: [50:10](50/10)). +50:14 e5b4 continually burn them 1 The fire will never completely destroy them. They will continue to suffer forever. +50:15 wba5 his kingdom 1 This refers to all the evil things Satan does and the evil people he controls. +50:16 eeuh God cursed it 1 See [02:11](02/11). +50:16 x2p3 a new heaven 1 This refers to a new set of stars and everything else in the sky. +50:16 fnsj a new earth 1 This current earth on which we live will be replaced by a new and improved one. +50:17 f7sw wipe away every tear 1 This means that Jesus will cause his people to never be sad again. +50:17 rgae They will not be sick or die 1 The people in the new earth will no longer suffer the effects of the curse that Adam and Eve brought upon the people of this earth. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sn/README.md b/src/__tests__/fixtures/unfoldingWord/en_sn/README.md new file mode 100644 index 000000000..582f716c1 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sn/README.md @@ -0,0 +1,3 @@ +# en_sn + +“Box 3” update to old UBN for Study Notes. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sn/TIT_sn.tsv b/src/__tests__/fixtures/unfoldingWord/en_sn/TIT_sn.tsv new file mode 100644 index 000000000..965c49c0b --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sn/TIT_sn.tsv @@ -0,0 +1,62 @@ +Reference ID Tags SupportReference Quote Occurrence Note +front:intro m2jl # Introduction to Titus\n\nThis is the introduction to the book of Titus +1:intro c7me # Introduction to Titus chapter 01\n\nPaul begins his letter by reminding Titus who Paul is to God, and who Titus is to Paul. He then instructs Titus about the kind of man that Titus must appoint as elders. These elders are necessary for the health of the new believers because there were so many people in Crete who are teaching things that were not true about God, and turning people away from God. +1:1 rtc9 δοῦλος Θεοῦ 1 Paul said that he was a servant or a slave of God because he did only what he knew that God, his master, wanted him to do. Other servants of God were Moses, David, and the other prophets. +1:1 xyz8 δοῦλος 1 People who speak some modern languages think that slave is different from servant, because slaves suffer in ways that servants do not. However, the Greek word **servant** means both slave and servant. It means anyone who must obey his master. This is why Paul said he was a slave or servant of God, because he wanted to obey God in every way. +1:1 abc8 ἐκλεκτῶν Θεοῦ 1 These people were the Christians. God chose them to know him. They did this by believing in Christ. This is why they were different from all other people. Paul became a servant and apostle of God so that they would trust in Christ and know God increasingly well. +1:1 fyf8 ἐκλεκτῶν Θεοῦ 1 Scholars debate whether or not the actions of people affected whether God chose them. They also debate whether God chose people as individuals or as groups. Here, Paul wrote that God is the one who chose them. +1:2 xyz9 ἐλπίδι ζωῆς αἰωνίου 1 God has promised that everyone who trusts in Christ will live forever. The Holy Spirit makes believers to be confident that God will do this for them. +1:2 r2gj ἣν ἐπηγγείλατο…πρὸ χρόνων αἰωνίων 1 Even before God created the earth, he planned to save his people so they would live with him forever. +1:3 b22h κατ’ ἐπιταγὴν…Θεοῦ 1 God commanded Paul to preach to everyone. This was what he should tell them: God has promised to make everyone live eternally if they believe in Jesus Christ. +1:4 swi9 Τίτῳ 1 Titus was a Gentile believer who traveled with Paul to Crete. Paul left him there so that he would choose elders for the churches and teach the believers. +1:4 abc9 γνησίῳ τέκνῳ, κατὰ κοινὴν πίστιν 1 Paul had enabled Titus to understand how to become a Christian. This is why Paul called him a son. +1:4 m41u χάρις καὶ εἰρήνη ἀπὸ Θεοῦ 1 This was a normal way that Christians greeted each other in letters during New Testament times. +1:5 dpn4 Κρήτῃ 1 Crete is a large island in the eastern part of the Mediterranean Sea. +1:5 xy18 πρεσβυτέρους 1 The word **elders** usually refers to old men. In groups of Christians, elders were men who served as the groups’ leaders. +1:5 gu55 πρεσβυτέρους 1 The leaders of Christians probably worked in much the same way as the leaders in Jewish synagogues. For example, Christian ***deacons*** were in charge of helping people in need. They were like certain synagogue leaders who worked in the same way. Synagogues also had their rabbis, whom the Jews often thought were prophets. Also, synagogues had leaders in charge of how the people worshiped on the Sabbath day. Christian groups had similar leaders. +1:6 wx6c μιᾶς γυναικὸς ἀνήρ 1 Paul wanted elders to have only one wife; he also wanted elders to be faithful to their wives. This was very different to many ethnic groups in the Roman Empire. Many of these peoples allowed men to have more than one wife. +1:6 h93t μιᾶς γυναικὸς ἀνήρ 1 Scholars do not agree about what Paul wanted to say when he wrote, **husband of one wife**. Some scholars think that Paul wanted every elder to have a wife. Others think that Paul wanted no elder to have more than one wives. Still other scholars think that Paul wanted all elders to be faithful to their wives. +1:7 s3yr δεῖ…τὸν ἐπίσκοπον…εἶναι 1 Leaders guide the people who belong to God, and they act in God’s place. Because of this, they must be the good kind of people that Paul described in verses 6-9. +1:7 xy17 ἐπίσκοπον 1 Paul continued here to write about elders. He wanted them to serve as **overseers** of the church. They must be overseers who care for God’s people. +1:9 lh9b τῇ διδασκαλίᾳ τῇ ὑγιαινούσῃ 1 Christian leaders teach believers correctly when they teach what the scriptures say. +1:10 ga62 οἱ ἐκ τῆς περιτομῆς 1 Some Jewish believers in Christ taught that all Gentile believers must become like themselves. They must be circumcised, and they must obey all the rules in the Law of Moses. Paul strongly opposed what this group taught, and he instructed Titus to do the same. +1:12 b52u Κρῆτες ἀεὶ ψεῦσται, κακὰ θηρία, γαστέρες ἀργαί 1 Paul repeated words written by Epimenides, who had been a Greek poet. Epimenides had been born in Crete six or seven hundred years before Jesus was born. The people of Crete thought that he was a philosopher and prophet. +1:14 p56w Ἰουδαϊκοῖς μύθοις 1 We do not know what these stories were. Perhaps they were stories or ideas that Jews had invented in order to explain events that had happened long ago. +1:15 wja4 πάντα καθαρὰ τοῖς καθαροῖς; τοῖς δὲ μεμιαμμένοις καὶ ἀπίστοις, οὐδὲν καθαρόν 1 Some Jewish teachers said that in order to be pure, a person must be careful not to eat certain foods, and that he must also avoid other things. But these teachers were wrong. However, believers are pure through faith in Jesus Christ, and do not need to follow those restrictions. +1:16 jen8 τοῖς…ἔργοις ἀρνοῦνται 1 When a person disobeys God, he shows by his actions that he does not believe God or his teachings. Paul was still writing here about the false teachers. +2:intro h3il # Introduction to Titus chapter 02\n\nIn this chapter, Paul instructs Titus on what to teach the Christian believers. Verses 1-10 have a list of duties. These are things that different kinds of people should do, for example, men, women, children, servants, and rulers. During Paul’s time, people often wrote down ways in which everyone should behave. In these verses, Paul told Titus what he should teach the Christian believers, about how they should behave. +2:1 lfu1 σὺ δὲ 1 In 1:1-10 Paul wrote about false teachers and said why they were bad. At the start of chapter 2, Paul wrote the words **But you** very strongly, in order tell Titus that he must teach very differently from how the false teachers were teaching. +2:3 tpi2 πρεσβύτιδας 1 The older women loved God, so they were well able to teach the younger women. +2:4 ph2j νέας 1 In verses 4-5, Paul told Titus that he must tell the older Christian women to show the younger women how to be good wives to their husbands, and good mothers to their children. In this way, the young women would show everyone that God’s Word is true and good. +2:6 xyz3 σωφρονεῖν 1 Paul summarized the responsibility of the younger men in a single phrase: **to be sensible**. This implies that the greatest weakness of the younger men was not thinking clearly and carefully, and acting in a way that was consistent with sound thinking. If the young men would learn to be sensible in their thoughts and actions, they would be honoring to God. +2:7 xy13 σεαυτὸν παρεχόμενος τύπον 1 In verses 7-8, Paul told Titus that he must live right, in order to be an example for others. This would make it difficult for unbelievers to speak against the Christian faith. +2:7 xc6t τύπον 1 Paul’s command Titus to set an example immediately follows the verse about young men. However, it is likely that Paul wanted Titus to be an example for all the people named in verses 2-6. +2:9 y3j2 δούλους 1 If Christian **slaves** acted well toward their masters, they could persuade other people to honor Jesus Christ. +2:11 abc1 σωτήριος πᾶσιν ἀνθρώποις 1 God has offered to save everyone. For that reason, believers should learn to live right, so that everyone will see that God works with power in believers. +2:12 m14y παιδεύουσα ἡμᾶς, ἵνα 1 The grace of God teaches us to live rightly and to control ourselves. He does this because he loves us and is powerful. This different from the Jewish stories and myths in chapter 1, because those things cannot help us. +2:12 z14y τῷ νῦν αἰῶνι 1 This present age is the time that we live in now, rather than the future when God removes all sin and evil from the world. The Bible shows that this age is different from the age that will come later. Everyone living in this age, which the Bible sometimes calls "this world," sins, does evil, and will die. Satan is the ruler of this age, but God has already started to save his people. In the age to come, God will rule the world completely. He will stop everyone from sinning and dying. He will save and his people and show them honor. God wants his people to honor him, as they wait for the age to come. +2:13 a14y τοῦ μεγάλου Θεοῦ καὶ Σωτῆρος ἡμῶν, Ἰησοῦ Χριστοῦ 1 Perhaps Paul was saying that Jesus is both **God** and **Savior**. Or perhaps he was writing about God the Father and about our Savior Jesus Christ. Or perhaps Paul was calling God the Father our Savior, and he was saying that Jesus is the glory that appeared to us. The sentence in Greek makes us think that Paul was saying that Jesus is both God and Savior. +2:14 gl8e ὃς ἔδωκεν ἑαυτὸν ὑπὲρ ἡμῶν 1 When Jesus died on the cross, he freed us from having to sin, just as someone frees slaves from their masters. This means that God will not punish us for having sinned, and that he also makes us able to refuse to sin, so that we can live rightly now and honor him. +2:15 v9cp μετὰ πάσης ἐπιταγῆς 1 Titus knew the truth about Jesus Christ, because the apostles had taught him well. So he should teach these same things well, because he knows they are true. Also, Titus should not let anyone stop him from leading the believers. +3:intro zh6x # Introduction to Titus chapter 03\n\nIn this chapter, Paul instructed Titus to tell the Christians how they should behave toward non-Christians so those non-Christians will understand some of the truth about God. He also reminds the believer that they themselves did not always believe in God, but God was gracious to them and save them. Therefore, they should focus on doing things that are worthwhile, and avoid things that bring strife and confict. Paul closes the letter with a several personal requests for Titus. +3:1 y9tr ἀρχαῖς, ἐξουσίαις, ὑποτάσσεσθαι 1 Christians should obey their rulers. But if a government requires them to do something that God forbids, Christians should not obey. +3:2 j2sa μηδένα βλασφημεῖν 1 Paul told believers that they should not say bad things about other people. Examples of bad things include falsely accusing someone to hurt their reputation, or telling lies or telling stories about people that may not even be true. +3:3 w3fy ἦμεν 1 When Paul wrote **we**, he was writing about Titus and himself. He wanted to show that even he himself and Titus did these sinful behaviors before they believed in Jesus. +3:4 wa9x ἡ φιλανθρωπία 1 God loves all people. The word for **love** refers to love for all people. Even if we behave badly, God loves us. When we sin, God forgives us because He loves us. +3:5 xy25 κατὰ τὸ αὐτοῦ ἔλεος 1 God decided to save people because He has mercy on them. He does not require us to do anything good before he saves us. +3:5 in7u λουτροῦ παλινγενεσίας καὶ ἀνακαινώσεως Πνεύματος Ἁγίου 1 Paul wrote here that the Holy Spirit washes believers and makes them new people. In Ephesians 5:26, Paul wrote that Jesus washes believers and makes them new people. The Holy Spirit and Jesus work together to make God’s people spiritually clean, to forgive their sins and make them want to obey God. +3:5 lug7 παλινγενεσίας καὶ ἀνακαινώσεως 1 Christians do not always agree about how the Holy Spirit makes people new. Some Christians believe the Holy Spirit does this when a new believer is baptized in water. Other Christians say that the Holy Spirit begins to remake someone after that person has started to believe in Christ. They say that baptism only shows that the Holy Spirit has already made the believer into a new person. +3:6 abc8 ἐξέχεεν 1 Paul wrote the word **poured** to show us that God generously provided the Holy Spirit for us through our Savior Jesus Christ. He wrote about the Holy Spirit as if he were a liquid that God pours out on us abundantly. +3:7 m9zd κληρονόμοι 1 The Bible tells us that believers are God’s children. Believers will permanently receive something from God as children receive land and possessions from their fathers. This is why the Bible says that God has an inheritance to give to his children. Like Christ, who always receives things from God, believers will possess the earth, God’s kingdom, and eternal life. +3:8 me7b πιστὸς ὁ λόγος 1 When Paul wrote **This message is trustworthy**, he was writing about what he said in verses 4-7. +3:9 bl8e μωρὰς…ζητήσεις, καὶ γενεαλογίας, καὶ ἔρεις, καὶ μάχας νομικὰς, περιΐστασο 1 Paul wrote that Christians should not get into arguments about Jewish rules and about things that happened in the past. Those kind of arguments do not do any good. Paul gave this same warning in chapter 1. +3:10 rrx9 αἱρετικὸν ἄνθρωπον…παραιτοῦ 1 In verses 10-11, Paul wrote that church leaders should warn people who quarrel. If the leaders do this, the believers will know that they must stop sinning. If these people repent, the leaders and the other believers must forgive them. If they do not repent, the leaders should reject them from the church so they will not cause more problems. +3:10 qt8f αἱρετικὸν ἄνθρωπον 1 Paul was talking about the kind of person who causes quarrels within the church. Such people say that non-Jewish believers must follow Jewish rules to make God happy. +3:12 xy27 Ἀρτεμᾶν 1 Artemas worked with Paul, but we do not know any other things about him. The New Testament does not say anything else about him. +3:12 tl5n Τυχικόν 1 Tychicus was a believer who worked with Paul. Paul trusted him. He was from the province of Asia, and he travelled with Paul on Paul’s third journey to make new believers. +3:12 dec4 ἐλθεῖν πρός με 1 When Paul wrote this letter, he was living in Nicopolis. Titus was living in Crete and working with the churches there. Artemus and Tychicus were going to Crete to replace Titus. When they arrived, Paul wanted Titus to leave Crete and come to Nicopolis, so they could be together. +3:12 y5lp Νικόπολιν 1 When Paul wrote this letter, he was living in Nicopolis. Titus was living in Crete and working with the churches there. Artemus and Tychicus were going to Crete to replace Titus. When they arrived, Paul wanted Titus to leave Crete and come to Nicopolis, so they could be together. +3:13 xy28 σπουδαίως πρόπεμψον 1 Paul wanted Titus and the believers in Crete to give Zenas and Apollos all they would need to do their missionary work. +3:13 ba5a Ζηνᾶν τὸν νομικὸν 1 Titus 3:13 is the only place where the New Testament says something about Zenas. He probably helped Paul in his work. There are two reasons he might have been called a lawyer. 1) If Zenas was a Jewish believer, he was probably an expert in the law of Moses. 2) If Zenas was a Gentile believer, he was probably an expert in the law of Rome. +3:13 abcg Ἀπολλῶν 1 Apollos was someone who worked with Paul. We do not know a lot about him. He was from Alexandria in Egypt. He was a Jewish believer who became a popular speaker and persuaded many people to believe in Jesus. +3:15 abch ἐν πίστει 1 Pauls called people who are in the faith "believers." This means that they believe in Jesus. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sn/manifest.yaml b/src/__tests__/fixtures/unfoldingWord/en_sn/manifest.yaml new file mode 100644 index 000000000..5e6d36f76 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sn/manifest.yaml @@ -0,0 +1,52 @@ +dublin_core: + conformsto: 'rc0.2' + contributor: + - 'Door43 World Missions Community' + - 'Larry Sallee (Th.M Dallas Theological Seminary, D.Min. Columbia Biblical Seminary)' + - 'Russ Perry' + creator: 'Door43 World Missions Community' + description: 'Open-licensed exegetical study notes that provide historical, cultural, and linguistic information for studying the Bible.' + format: 'text/tsv' + identifier: 'sn' + issued: '2020-09-24' + language: + direction: 'ltr' + identifier: 'en' + title: 'English' + modified: '2020-09-24' + publisher: 'unfoldingWord' + relation: + - 'en/ult' + - 'el-x-koine/ugnt?v=0.15' + - 'hbo/uhb?v=2.1.15' + rights: 'CC BY-SA 4.0' + source: + - identifier: 'sn' + language: 'en' + version: '0' + subject: 'TSV Study Notes' + title: 'unfoldingWord® Study Notes' + type: 'help' + version: '1' + +checking: + checking_entity: + - 'unfoldingWord' + checking_level: '3' + +projects: + - + title: 'unfoldingWord® Open Bible Stories' + versification: 'ufw' + identifier: 'obs' + sort: 0 + path: './OBS_sn.tsv' + categories: [ ] + + - + title: 'Titus' + versification: 'ufw' + identifier: 'tit' + sort: 56 + path: './TIT_sn.tsv' + categories: [ 'bible-nt' ] diff --git a/src/__tests__/fixtures/unfoldingWord/en_sq/LICENSE.md b/src/__tests__/fixtures/unfoldingWord/en_sq/LICENSE.md new file mode 100644 index 000000000..0e55b1209 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sq/LICENSE.md @@ -0,0 +1,29 @@ +*unfoldingWord® Study Questions* + +*Copyright © 2021 by unfoldingWord* + +# License + +## Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) + +This is a human-readable summary of (and not a substitute for) the full license found at http://creativecommons.org/licenses/by-sa/4.0/. + +### You are free to: + + * **Share**—copy and redistribute the material in any medium or format + * **Adapt**—remix, transform, and build upon the material for any purpose, even commercially. + +The licensor cannot revoke these freedoms as long as you follow the license terms. + +### Under the following conditions: + + * **Attribution**—You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. + * **ShareAlike**—If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. + +**No additional restrictions**—You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. + +### Notices: + +You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. + +No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sq/OBS_sq.tsv b/src/__tests__/fixtures/unfoldingWord/en_sq/OBS_sq.tsv new file mode 100644 index 000000000..70ac627e1 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sq/OBS_sq.tsv @@ -0,0 +1,736 @@ +Reference ID Tags Quote Occurrence Question Response +1:? qc8o meaning What all did God create? God made the universe and everything in it. He made light. He made the sun, moon, and stars. He made the earth with its sea and dry land. He made all the plants, birds, and animals. And he made the first man and woman, and a made a garden where they could live. +1:? j12p meaning What did God do in order to create everything except the first people? God only spoke, and the universe and everything in it appeared. In that way, he showed his great power. +1:9 qewx meaning In what way did God decide to make people to be different than the animals? God decided to make people in God’s image and to be like him. He also decided to give them power over all of the earth and over the animals (See: [01:09](01/09)). +1:11 q3is meaning What two special trees did God plant in the garden? God planted many trees in the garden, but he also planted two special trees. He planted the tree of life in the garden and told Adam that he could eat its fruit. He also planted the tree of the knowledge of good and evil there and told Adam he would die if he ate fruit from that tree (See: [01:11](01/11)). +1:12 fji9 meaning What did God do so that the man would not be alone? God wanted Adam to have a helper who would be like Adam. But none of the animals were like Adam, so they could not be his helper. Therefore, God took one of Adam’s ribs and made the woman from it to be a helper for Adam (See: [01:12](01/12), [01:13](01/13)). +1:16 xqwi meaning What did God do after he finished making everything? After God finished making everything in six days, he rested on the seventh day. God was not tired, but he had finished his work of making everything. He blessed the seventh day and made it a special day (See: [01:16](01/16)). +1:10 ivvc application Why do you think God made the man and the woman in a different way than he made the universe and the other things in the earth? God creates people in a more personal way than he created everything else. He formed the man from dust and breathed life into him. Then God formed the woman from one of the man’s ribs. In this way, he showed that people were very important to him, and that they have a special purpose in creation (See: [01:10](01/10), [01:13](01/13)). +1:9 jesg application In what way are people like God and made in his image? How are they different than God? God made people to be like God, but not the same as God. That is, people have some of the characteristics of God that the animals do not have. However, people are not equal to God. They are in God’s image because they are like God in some ways (See: [01:09](01/09)). +1:11 any4 application Why do you think God put the tree of the knowledge of good and evil in the garden when he did not want Adam to eat its fruit? God wanted Adam to be able to choose whether or not to obey God. Therefore, God planted the tree of the knowledge of good and evil in the garden where Adam was. However, he warned Adam clearly that he would die if he ate fruit from that tree. And God allowed Adam to eat fruit from every other tree, so there was no reason for Adam to disobey God (See: [01:11](01/11)). +1:13 g2i2 application Why do you think God made the woman from the man rather than from the soil? God wanted the man and the woman to become one. Therefore, he did not make the woman separately from Adam. Instead, God took part of Adam and made her from that. When Adam saw her, he understood that she was very much like Adam, and that God had made her especially for him (See: [01:13](01/13)). +1:14 ybo3 application How do you think a man becomes one with his wife? God wants a man and his wife to have a special bond that is closer than their connection to any other person. It is even closer than the bond with their parents. As they grow to know each other more, they begin to think in similar ways and value the same things. People who have been married a long time often seem to know what each other is thinking without even speaking (See: [01:14](01/14)). +1:15 w2so application Why did God say that everything he had made was very good? God created everything so that everything would work together to accomplish what he wanted to happen (See: [01:15](01/15)). +1:16 uf2u application What did God want people to do on the seventh day? God made the seventh day a special day. On that day, he wanted people to stop doing their normal work. Instead, they should remember that God created them and everything around them. Because they would not work on the seventh day, they would have more time to honor God and think about him than they did on the other days of the week (See: [01:16](01/16)). +2:1 enoi meaning What did Adam and Eve need that they did not have in the garden? Adam and Eve had everything they needed in the garden. There was no sin or shame, and they were able to walk with God and speak directly to him (See: [02:01](02/01)). +2:2 fshe meaning How did the snake convince the woman to eat the fruit of the tree of the knowledge of good and evil? The snake first questioned what God said (See: [02:02](02/02)). He next called God a liar (See: [02:04](02/04)). Finally, he told the woman that she could be like God (See: [02:04](02/04)). +2:2 qtor meaning Why did the woman eat the fruit? Eve thought the fruit looked good, and she wanted to be wise like God. Therefore, she decided to disobey God and to eat the fruit. +2:6 xj68 meaning What did Adam and Eve do after they ate the fruit? They were both ashamed, and tried to cover themselves with leaves. Then they tried to hide from God (See: [02:06](02/06), [02:07](02/07)). +2:6 fypk meaning What answer did Adam give when God asked if he had eaten the fruit? Adam did not admit that he had sinned. Instead, he blamed his wife. +2:6 k9il meaning What answer did Eve give when God asked her what she had done? Eve did not admit that she had sinned. Instead, she blamed the snake. +2:6 j5tr meaning What would the snake do to Eve’s descendant, and what would he do to the snake? Eve’s descendant would kill the snake by crushing its head. The snake would wound Eve’s descendant by biting him on the heel of his foot. +2:6 l06j meaning What did God use to cover Adam and Eve? God covered them with animal skins. Most scholars think this was the first animal sacrifice. God killed the animals and took their skins to cover Adam and Eve. +2:10 uzh9 meaning What did God want to say when he said that Adam’s body would return to the soil? God made Adam from the soil (See: [01:10](01/10)). When he died, he would become soil once again. +2:10 llzj meaning Why did God send Adam and Eve out of the garden? God did not want them to eat from the tree of life in the garden and live forever as sinners. +2:10 bift application How did the snake convince Eve to eat the fruit? The snake did not begin by telling Eve to disobey God. Instead, he asked questions that caused Eve to think about the one fruit that God had told her not to eat. Then the snake convinced her that God did not do the right thing when he told her not to eat the fruit. +2:10 wubs application Why do you think Eve forgot about all the things God had given her, and only focused on the one fruit that God told her not to eat? People often do not like someone telling them not to do something. They want to do whatever they want to do. Eve did not care that it was God who told her not to eat the fruit, or that God told her not to eat it in order to protect her. +2:10 fkf8 application Why do you think Adam and Eve tried to cover their shame and hid from God? When they disobeyed God by eating the fruit, they became sinners. They were so ashamed that they did not want God to see them. +2:10 s7z0 application How did Adam and Eve answer God when he asked them what they had done? Adam and Eve both blamed someone else for what they had done. Adam blamed Eve, and Eve blamed the snake. Neither of them was willing to tell God the truth about what they did. +2:10 m9ts application How did the curses match the way that Adam, Eve, and the snake disobeyed God? Adam ate the fruit, so God made it difficult for him to grow food. Eve caused Adam to sin, so God gave Adam power over Eve. The snake spoke as if he were wiser than God, so God made him crawl on his belly. +2:12 p99j application Why was it bad for Adam and Eve to know good and evil? Their knowledge of good and evil was knowledge gained by personal experience. That experience of making an evil choice caused them to be separated from God. Their fellowship with him was broken (See: [02:12](02/12)). +3:1 k858 meaning What did God decide to do about the wicked and violent people on the earth? He decided to destroy them with a huge flood (See: [03:01](03/01)). +3:2 p53i meaning How was Noah different than the other people? Noah was a righteous man even though he lived among wicked people (See: [03:02](03/02)). +3:3 xuuw meaning What was the purpose of the boat that God told Noah to build? The boat would keep Noah and his family safe during the flood (See: [03:03](03/03)). +3:4 v6uh meaning How many people entered into the boat? Eight people entered into the boat—Noah and his wife, and his three sons and their wives. No one else believed the flood would happen (See: [03:04](03/04), [03:05](03/05)). +3:6 b6qf meaning Why did the animals come to the boat? God sent some of each kind of the animals to the boat (See: [03:06](03/06)). +3:7 a3vr meaning How long did the rain last? The rain continued for 40 days and 40 nights (See: [03:07](03/07)). +3:8 uor8 meaning What happened to all the people and animals during the flood? Noah’s family and the animals that were inside the boat were safe. Every person and animal that was outside the boat died (See: [03:08](03/08)). +3:9 cnyf meaning How long did the flood continue on the earth? The boat floated on the water for five months, it took three more months for the mountains to be visible (See: [03:09](03/09)). It was several more months before the land was dry enough for Noah and his family to come out of the boat ([03:10](03/10) to [03:13](03/13)). +3:14 sn5i meaning What was the first thing Noah that did when he came out of the boat? Noah built and altar and sacrificed some of the animals to God (See: [03:14](03/14)). +3:15 lh9o meaning What promise did God make to Noah after the flood? God promised that he would not destroy the earth with a flood again. He put a rainbow in the sky as a sign of this promise (See: [03:15](03/15), [03:16](03/16)). +3:1 flty application Why did God decide to destroy the world? God created people to be with him. But God is good and cannot accept things that are evil. Because almost all the people became wicked and disobeyed him, he decided to destroy all those evil people (See: [03:01](03/01)). +3:1 uhvk application Why did God save Noah and his family? God did not want to destroy all that he had made. Therefore, he chose to save Noah and his family because Noah was a righteous person who honored God. God would allow Noah’s descendants to fill the earth after the wicked people died. +3:4 c9gm application Why was no one else besides Noah’s family ready when the flood came? The boat was very large, and it took Noah and his sons a very long time to build it. Many other people would have seen Noah building the boat and would have asked him about it. But none of them believed God would destroy them, so none of them were ready when the flood came (See: [03:04](03/04)). +3:6 p6in application Why did other people not come into the boat when the rain began? God himself closed the door of the boat before the rain began. After God did that, it was too late for people to enter into the boat and be saved from the flood (See: [03:06](03/06)). +3:14 l7tr application Why did Noah build an altar and offer a sacrifice to God? Noah was a righteous man who honored God both before and after the flood. He knew that God had saved him and his family. Therefore, the first thing he did when he left the boat was to honor God with a sacrifice (See: [03:14](03/14)). +3:14 noek application Why is the rainbow important? The rainbow that appears after a rain reminds God and people of God’s promise. He said he will never destroy the earth again with a flood. +4:13 c1a4 meaning Why was is wrong for the people to gather together in one city? God had commanded Noah and his descendants to fill the earth again after the flood (See: [03:13](03/13)). +4:2 d9mc meaning What was the purpose of the tower the people built in the city? They built the tower to be tall enough to reach heaven (See: [04:02](04/02)). Some scholars think they wanted to be able to go up to heaven. Other scholars think they wanted the gods to be able to come down from heaven. +4:3 xn52 meaning Why did God change their language? God changed their one language into many languages so they could not understand each other (See: [04:03](04/03)). As a result, they could not work together to continue building the tower or living together well. So they spread out over the earth in different language groups. +4:4 k6o2 meaning Who did God say he would bless through Abram? God would bless all the people groups on earth through Abram and his descendants (See: [04:04](04/04)). +4:5 sq7k meaning What land did God give to Abram? God gave the land of Canaan to Abram and his descendants (See: [04:05](04/05), [04:06](04/06)). He said they would always possess it. This is the land of Israel today. +4:7 uhah meaning Why did Abram give a tenth of his possessions to Melchizedek? Melchizedek was a priest of God (See: [04:07](04/07)). That is, he spoke for God and helped people worship God. Abram gave a tenth of his possessions to Melchizedek as an offering to God. In this way, Abram honored God. +4:8 cv28 meaning Why might it have been difficult for Abram to believe that he would have many descendants? Abram and Sarai did not yet have a son (See: [04:08](04/08)). Without a son, he could not have many descendants. +4:8 hntd meaning Why did God declare that Abram was righteous? God said Abram was righteous because Abram believed God (See: [04:08](04/08)). Abram believed he would have many descendants even though he did not yet have a son. +4:8 n62z application Noah was a righteous man. Why did his descendants begin to sin? God destroyed all the wicked people in the flood (See: [03:08](03/08)). So only the family of Noah survived to fill the earth. Although Noah obeyed God, he was not perfect. He received wicked desires from his ancestors, Adam and Eve. And he passed these on to his descendants. +4:1 ef3g application Why did the people want to live in one city? The descendants of Noah became proud and wanted other people to honor and remember them. Therefore, they decided they did not want to obey God. Instead, they settled in one place where they could honor each other (See: [04:01](04/01), [04:02](04/02)). +4:3 vtst application Why do people today speak different languages? People today speak different languages because God gave them different languages at Babel (See: [04:03](04/03)). He wanted each language group to spread out across the earth and learn to honor him. +4:3 m0py application Why did God send Abram to Canaan? Abram already honored God where he lived. But, God told him to go to Canaan, the land that God would give to him. God wanted Abram’s descendants to have a land where they could honor God. In this way, all the families of the earth could learn through them how to honor God. +4:3 dz7f application Why did Abram give his tenth to Melchizedek instead of directly to God? Melchizedek was the first priest of God. Before that, Noah and other righteous people offered their sacrifices directly to God. But now God was providing a priest to help people honor God and to speak to them for him. +4:3 cr9b application Why was God’s promise to Abram so surprising? God promised that Abram would have more descendants then the stars in the sky. No one is able to count all the stars! But Abram and Sarai did not yet have a son. It would not have seemed possible that they could have so many descendants. +5:1 h17h meaning Why did Sarai tell Abram to have a child with Hagar? Sarai was now too old to have children (See: [05:01](05/01)). The custom of that time allowed a woman to have a child through their servant. +5:2 uiy1 meaning What was the name of the son born to Abram through Hagar? Abram named the son that Hagar bore him Ishmael (See: [05:02](05/02)). +5:3 qwb9 meaning What did God tell Abram to do to show his covenant with God? As a sign of the covenant God made with Abram, God told Abram to circumcise every male in his family (See: [05:03](05/03)). +5:4 am7k meaning Who would be the **son of promise**? Sarai would bear a son for Abram. His name would be Isaac. He would be the **son of promise** (See: [05:04](05/04)). +5:4 tohr meaning What were the meanings of the new names that God gave to Abram and Sarai? Abraham means ‘father of many’ and Sarah means ‘princess’ (See: [05:04](05/04)). +5:5 pzrv meaning How old were Abraham and Sarah when Isaac was born? Abraham was 100 years old and Sarah was 90 years old (See: [05:05](05/05)). +5:6 p334 meaning What did God tell Abraham to do to his son Isaac? God told Abraham to kill Isaac as a sacrifice to God (See: [05:06](05/06)). +5:7 je2m meaning Where did Abraham tell Isaac that they would get the lamb for the sacrifice? Abraham told Isaac that God would provide the lamb for the sacrifice (See: [05:07](05/07)). +5:8 fcn7 meaning Did God want Abraham to actually kill Isaac as a sacrifice? No, God told Abraham not to kill Isaac. God was only testing Abraham to see if he would obey God. God provided a ram for the sacrifice instead of Isaac (See: [05:08](05/08), [05:09](05/09)). +5:8 ag66 meaning Why did God say that he would bless Abraham? God said he would bless Abraham because Abraham was willing to give God everything, even his only son ([05:10](05/10)). +5:8 vxvf application Should Sarai have told Abram to have a son with her servant Hagar? The custom of the day allowed Sarai to have a son through her servant. But perhaps Sarai did this because she did not believe God could give Abram a son in their old age. +5:4 vnvw application Why was Isaac called the **son of promise**? Isaac was the **son of promise** because God would fulfil his promise to bless all nations through him. Even though Ishmael was also Abram’s son, God had chosen to bless Abraham’s descendants through Isaac instead of through Ishmael (See: [05:04](05/04)). +5:4 rl5x application Why did God give new names to Abram and Sarai? In the Old Testament, people were often named according what kind of people they were, or what they would do. God gave Abram and Sarai new names to show that they would have many descendants and would be honored by them. +5:4 e178 application Why did God test Abraham by asking him to kill Isaac? God tested Abraham to show that Abraham would obey God no matter what God asked him to do. He would even sacrifice Isaac, his son of promise. +5:8 na5z application Was Abraham willing to kill Isaac as God asked? Yes, Abraham was willing to obey everything God told him to do. He was ready to kill Isaac when God told him to stop (See: [05:08](05/08)). +5:9 jd3i application Why did God provide a ram for the sacrifice? Abraham told Isaac that God would provide a lamb for the sacrifice. But at that time, God provided a ram instead (See: [05:09](05/09)). Abraham was speaking about a sacrifice in the future when God would provide a perfect lamb. +5:9 fhw5 application Why did God say that Isaac was Abraham’s only son? Ishmael was also the son of Abraham. But Isaac was the son of promise that God had chosen to bless. Isaac was the only son through whom God would keep his covenant. +6:1 qa2u meaning What did Abraham send his servant to do? Abraham sent him to get a wife for his son Isaac from among Abraham’s relatives (See: [06:01](06/01)). +6:2 bdeb meaning How did Abraham’s servant choose Rebekah as a wife for Isaac? God led him to Rebekah (See: [06:02](06/02)). +6:4 bki7 meaning Why did it seem as if Abraham would not have many descendants? Isaac’s wife, Rebekah, could not have children (See: [06:04](06/04)). +6:5 txo1 meaning What did Isaac do when Rebekah could not have children? Isaac prayed to God, and God allowed her to get pregnant (See: [06:05](06/05)). +6:6 vv5p meaning What did God tell Rebekah would happen to her two sons? God told her that her sons would become two nations who would struggle with each other. The nation from the older son would obey the nation from the younger son (See: [06:06](06/06)). +6:6 gqki meaning Who was Rebekah’s older son? Rebekah’s older son was Esau. +6:6 fxj6 meaning Who was Rebekah’s younger son? Rebekah’s younger son was Jacob. +6:6 id4n application Why did Abraham send his servant so far away to find a wife for Isaac? Abraham wanted Isaac to marry a woman who obeyed God. He did not want him to marry a woman from the tribes in Canaan who worshiped idols. +6:6 a3mb application Why did Rebekah agree to leave her family and marry Isaac, whom she did not know? Perhaps Rebekah believed that God had led Abraham’s servant to her. She trusted God to provide the right husband for her. +6:6 pkbj application Why could Rebekah not have children? We do not know why Rebekah could not have children. She had obeyed God to leave her family and marry Isaac. Perhaps God wanted Isaac to pray for Rebekah, so that they would understand that God enabled her to become pregnant. +6:6 gt0e application Why were the babies struggling with each other while they were still in Rebekah’s womb? While the babies were in Rebekah’s womb, God had already caused them to be the kind of people that he wanted them to be. They would continue to struggle with each other throughout their lives. Also, God had already decided that they would be large nations, and that the nation from the older brother would obey the nation from the younger brother. God decided this before they were born. +6:6 dr54 application Why was Jacob holding on to Esau’s heel? Later on, Jacob would take Esau’s place by receiving the honor and possessions that should belong to the firstborn son. Perhaps Jacob was holding on to Esau’s heel as a sign that he was already trying to hold Esau back and to take his place. +7:1 dfyu meaning How did Isaac and Rebekah treat their sons differently? Isaac loved Esau more than he loved Jacob. Rebekah loved Jacob more than she loved Esau (See: [07:01](07/01)). +7:2 ywtx meaning What did Esau give to Jacob in exchange for some food? Esau was the firstborn. As the firstborn, he deserved to receive more of his father’s possessions then Jacob, and to be honored more than Jacob. However, Esau traded all those things to Jacob in exchange for some food (See: [07:02](07/02)). +7:3 ifzv meaning Why did Rebekah and Jacob deceive Isaac by having Jacob pretend to be Esau? Rebekah and Jacob wanted Isaac to bless Jacob instead of blessing Esau (See: [07:03](07/03), [07:04](07/04)). +7:3 iq2y meaning Why did Jacob put goatskins on his neck and hands? Jacob wanted his hands and neck to be hairy like his brother Esau’s hands and neck. In that way, Isaac would feel the goat hair and think he was Esau (See: [07:03](07/03), [07:04](07/04)). +7:5 ymm3 meaning What did Esau plan to do to Jacob after Jacob stole his blessing? Esau planned to wait until Isaac died, and then to kill Jacob (See: [07:05](07/05)). +7:6 iq7p meaning What did Rebekah do to prevent Esau from killing Jacob? Rebekah and Isaac sent Jacob far away to her relatives so Esau would not kill him (See: [07:06](07/06)). +7:8 oaxo meaning How long did Jacob stay away from home? Jacob stayed with Rebekah’s relatives for twenty years. Then he returned home with the family God had given him while he was away (See: [07:08](07/08)). +7:9 ngqt meaning How did Jacob try to convince Esau not to kill him? He sent many herds of animals to Esau as a gift so that Esau would not still want to kill him (See: [07:09](07/09)). +7:10 cgni meaning Did Esau still want to kill Jacob? Esau was no longer angry with Jacob, and did not want to kill him. Esau and Jacob both lived in Canaan, and even buried their father together (See: [07:10](07/10)). +7:10 tsp1 application Why did Rebekah love Jacob more than she loved Esau? Jacob stayed around the home where Rebekah lived. Furthermore, God had told Rebekah that her older son would serve the younger. +7:10 rfk3 application Why did Isaac love Esau more than he loved Jacob? Esau loved to hunt. Perhaps Isaac also loved to hunt, and to eat the wild animals that they killed. This may be the reason he loved Esau more than he loved Jacob. +7:10 cxzz application What problems happened because Isaac and Rebekah each loved a different son? Jacob and Esau would have known that their parents did not love them equally. Perhaps this is why Jacob and Esau continually struggled with each other. They both tried to get what the other brother had. +7:10 m3wm application Why was Esau willing to trade what was his as the firstborn for some food? Esau did not care about the promises God made to Abraham. He was only interested in his food for that day. Later, he wanted to receive his father’s inheritance. But he was not interested in receiving anything from God. +7:10 jf3m application Jacob deceived Isaac to get his blessing. What does this tell us about Jacob? It was good that Jacob wanted to have his father’s blessing. But he was wrong to deceive his father in order to receive it. Because he did that, he had to flee from his brother and spend twenty years in another country. +7:10 qw1y application Was Jacob a good person? Jacob sometimes obeyed God, and he wanted God’s blessing. At the same time, Jacob had many faults. He often tried to trick people to get what he wanted. Nevertheless, God blessed Jacob because he had promised to Abraham that he would bless his descendants. +8:1 zl32 meaning How did Jacob feel about his son Joseph? Jacob loved Joseph more than he loved his other 11 sons (See: [08:01](08/01)). +8:2 a78u meaning Why did Joseph’s brothers hate him? They hated Joseph because Jacob loved Joseph more than he loved his other sons, and because Joseph dreamed he would rule over his brothers (See: [08:02](08/02)). +8:2 xxb7 meaning What did Joseph’s brothers do to get rid of Joseph? Joseph’s brothers sold him as a slave (See: [08:02](08/02)). Then they deceived their father into thinking that an animal had killed Joseph (See: [08:03](08/03)). +8:5 jbhy meaning Why did the Egyptians put Joseph in prison? The wife of Joseph’s Egyptian master lied and said Joseph tried to sleep with her. Her husband believed her and sent Joseph to prison (See: [08:05](08/05)). +8:5 wpqx meaning What did God do for Joseph while he was in prison? Joseph remained faithful to God, so God blessed him even in the prison (See: [08:05](08/05)). +8:6 aubb meaning How did Joseph get out of prison? Pharaoh had a dream that no one could interpret (See: [08:06](08/06)). When Joseph told him the meaning of the dream, Pharaoh made Joseph the second most powerful person in Egypt (See: [08:07](08/07), [08:08](08/08)). +8:10 prf6 meaning Why did Joseph’s brothers come to Egypt? There was a great famine and there was no food for them in Canaan (See: [08:10](08/10)). They came to Egypt to buy food (See: [08:11](08/11)). +8:12 urvp meaning How did Joseph treat his brothers when they came to him in Egypt? Joseph first tested them to see if they had changed. Then he told them who he was and promised to take care of them all in Egypt (See: [08:12](08/12)). +8:15 sffk meaning Who became the 12 tribes of Israel? God changed Jacob’s name to Israel. The descendants of each of his 12 sons then became the tribes of Israel (See: [08:15](08/15)). +8:15 m7pr application What mistake did Jacob make in the way he treated his sons? Jacob loved one of his sons more than he loved his other sons. This was the same mistake that his father Isaac made. As a result, Jacob’s sons hated Joseph and sold him as a slave. +8:15 fu7x application Why was God with Joseph even as a slave and as a prisoner? Joseph was always faithful to God, even when he suffered for doing the right thing. Therefore, God blessed Joseph and eventually restored him to his family. +8:15 r9zx application How did God make it possible for Joseph to go from prison to the palace in Egypt? God caused Pharaoh to have a dream that no one could interpret. He then revealed the meaning of the dream to Joseph. In that way, God provided a way for Joseph to be released from prison and to begin to rule over Egypt. +8:15 h80p application Why did Joseph not punish his brothers? Joseph’s brothers sold him as a slave. He could have been very angry with them. But Joseph saw that God was the one who sent Joseph to Egypt through his brothers’ evil actions. God did this to save Joseph’s entire family. Therefore, Joseph forgave his brothers and took care of them. +8:15 aar2 application Why did Jacob move his family to Egypt? God caused the famine so that Jacob would have to move his family to Egypt. God wanted them to grow into a large nation there. +9:2 oee7 meaning Why did the Egyptians make the Israelites slaves? They were afraid of the Israelites because there were so many of them (See: [09:02](09/02)). +9:3 gpsn meaning What did God do for the Israelites while they were slaves in Egypt? God blessed them so they had even more children (See: [09:03](09/03)). +9:4 fxbw meaning How did Pharaoh try to stop the Israelites from having larger families? Pharaoh ordered his people to kill all the Israelite baby boys (See: [09:04](09/04)). +9:6 q5et meaning Why did the Israelite woman put her baby boy in a basket in the river? She did not want him to be killed. Perhaps she hoped someone would find him floating in the basket and rescue him (See: [09:06](09/06)). +9:7 vasg meaning Who did Pharaoh’s daughter hire to nurse the baby boy? Pharaoh’s daughter hired the baby’s own mother to nurse him, although she did not know that she was his mother (See: [09:07](09/07)). +9:8 fd4d meaning Why did Moses kill the Egyptian? He was trying to save the Israelite whom the Egyptian was beating (See: [09:08](09/08), [09:09](09/09)). +9:12 dnvd meaning How did God appear to Moses? God appeared to Moses in a bush that was on fire, but which did not burn up (See: [09:12](09/12)). +9:13 cyz3 meaning Why did God send Moses to the Israelites? God told Moses to bring the Israelites out of slavery in Egypt and to lead them to the land of Canaan (See: [09:13](09/13)). +9:14 s648 meaning What did God say that his name was? God told Moses that his name was **I AM WHO I AM** or **I AM** (See: [09:14](09/14)). +9:15 zcim meaning Why did God send Aaron to help Moses? Moses said he did not speak well, so God sent his brother Aaron to help him (See: [09:15](09/15)). +9:12 e4w4 application God led the Israelites to Egypt. Why did they suffer there? God sent the Israelites to Egypt to protect them during the famine (See: [08:12](08/12)). However, the Egyptians later began to treat them badly and made them slaves. They suffered even though they had obeyed God. But God blessed them even while they suffered in Egypt. +9:12 qidu application Why did Moses’ mother defy Pharaoh’s order to kill all the Israelite baby boys? She knew that it was wrong to kill her son. Therefore, she did not obey Pharaoh. She hid Moses as long as she could, and then placed him a basket in the river so that someone might rescue him. By doing so, She made it possible for Moses to later rescue Israel from Egypt. +9:12 t58j application How was Moses’ mother able to care for Moses? God caused Pharaoh’s daughter to find Moses and want to keep him as her son. Then God caused her to hire Moses’ own mother to nurse him. In this way, God blessed Moses’ mother for refusing to obey Pharaoh and for doing what was right. +9:12 ml1r application What happened to Moses when he tried to rescue his fellow Israelite? Moses killed the Egyptian in order to save an Israelite. But then he had to flee from Egypt so Pharaoh would not kill him. It was not yet time for Moses to help the Israelites. And God did not want Moses to save them by his own power. Instead, God sent Moses into the wilderness until God was ready to send him to deliver the Israelites. +9:12 bkgd application What did God tell Moses his name was? God said he was **Yahweh**, which means ‘I AM WHO I AM.’ That means God always exists and does not depend on anyone else. He also said he was **the God of your ancestors Abraham, Isaac, and Jacob**. That means he is the same God that they worshiped hundreds of years before Moses. And he is the same God who made a lasting covenant with them. +9:12 gl49 application How did Moses respond when God told him to go to Pharaoh? Moses was afraid and did not want to go. Even though he was raised as part of the royal family of Egypt, he was not sure he could do what God told him to do. But God was kind to him and sent Aaron to help him. +10:1 jqvr meaning How did Pharaoh respond when Moses told him that God wanted him to let the Israelites go? Pharaoh not only refused to let the Israelites go, he also made work harder than before (See: [10:01](10/01)). +10:2 xn4u meaning What did God do to Egypt when Pharaoh refused to let the Israelites go? God sent ten terrible plagues that caused the people of Egypt to suffer greatly and to even die (See: [10:02](10/02)). +10:4 c4ob meaning How did Pharaoh respond to Moses when the frogs covered Egypt? Pharaoh begged Moses to take away the frogs. However, he still did not let the Israelites go (See: [10:04](10/04)). +10:5 q67x meaning How did Pharaoh act deceitfully about the plague of the flies? Pharaoh promised Moses that the Israelites could leave Egypt if Moses stopped the plague. But when Moses did that, Pharaoh changed his mind and did not let them go (See: [10:05](10/05)). +10:7 b0ro meaning How did God treat the Egyptians differently than the Israelites during the plague of the skin sores? God caused the sores on the Egyptians, but not on the Israelites (See: [10:07](10/07)). +10:8 lbpq meaning How did Pharaoh again act deceitfully about the plague of the hail? Pharaoh again promised Moses that the Israelites could leave Egypt if Moses stopped the plague of the hail (See: [10:08](10/08)). But after the hail stopped, Pharaoh again changed his mind and would not let them go (See: [10:09](10/09)). +10:11 rsa0 meaning How did God again treat the Egyptians differently than the Israelites during the plague of the darkness? God caused the darkness on the Egyptians, but there was light where the Israelites lived (See: [10:11](10/11)). +10:12 tfhk meaning What did God decide to do to the Egyptians since Pharaoh refused to obey God after the first nine plagues? God decided to send a final plague that would be worse than the other nine plagues. This one would cause Pharaoh to let the Israelites leave Egypt (See: [10:12](10/12)). +10:12 p2rd application Did God know that Pharaoh would not let the Israelites go when Moses asked him? God already knew that Pharaoh would be stubborn and would not agree to let the Israelites go at first. However, he expected Moses and Aaron to tell Pharaoh what God had said and to wait for God to change Pharaoh’s mind. +10:12 lqxr application Why did God send the ten plagues on Egypt? God wanted to show Pharaoh and all the people in Egypt that Yahweh is more powerful than Pharaoh and all the gods of Egypt. Even the other nations would hear about how God had forced Pharaoh to obey him and let the people go. +10:12 vv7q application What kinds of things did God cause to be plagues on the Egyptians? God used the normal things of Egypt to punish them. He turned the Nile River, animals, insects, and even the sun into plagues that caused them to suffer. The Egyptians used to worship all of these things as gods before the plagues happened. +10:12 e4w9 application Why did God cause some of the plagues to happen only to the Egyptians, and not to the Israelites? Through the plagues, God was showing the Egyptians and the Israelites that the Israelites belonged to him as his people. He protected the Israelites from many of the plagues so everyone would know that he was their God. +10:12 g91v application Why did God send ten plagues instead of sending only the last plague? God knew that the first nine plagues would not convince Pharaoh to obey him. However, those plagues showed all the people how powerful God was. When God had done that, he was ready to send the final plague to force Pharaoh to let the people go. +11:1 gt0s meaning Who was God going to kill in this final plague? He would kill the firstborn males of the Egyptian people and animals (See: [11:01](11/01)). +11:1 tbdk meaning God had already sent nine plagues on Egypt. Did Pharaoh now believe that God would send another plague? No, Pharaoh did not believe God would kill the firstborn males even though God had already sent nine plagues (See: [11:01](11/01)). +11:2 oodo meaning What did people in Egypt need to do to save their firstborn sons? To save their firstborn sons, they needed to kill a perfect lamb and put its blood around the door of their houses. Then they must roast the meat of the lamb and eat it with unleavened bread (See: [11:02](11/02), [11:03](11/03)). +11:5 d5jk meaning What happened to the Israelites with the lamb’s blood around their doors? God passed over the houses with the blood on the doors and did not kill the firstborn sons inside (See: [11:05](11/05)). +11:5 wfd7 meaning What happened to the Egyptians who did not put the blood on their doors? God killed the firstborn son of every Egyptian who did not put the blood on their doors. It did not matter if they were poor or rich. Every one of them died ([11:06](11/06), [11:07](11/07)). +11:8 zmjn meaning What did Pharaoh do after this plague? Pharaoh told Moses and Aaron to take the Israelites and to leave Egypt immediately. All the Egyptian people also asked them to go away (See: [11:08](11/08)). +11:8 nfzw application Why did Pharaoh not believe that God would kill the firstborn males in Egypt? Pharaoh had every reason to believe that God would do what he said. God had already sent nine plagues, just as he said he would. However, Pharaoh did not want to lose his power, so he choose not to believe God or to obey him, despite all the evidence that God has shown to him. +11:8 k67y application Why did each family need to kill a lamb in order to be saved from the plague? God could have simply spared all of the Israelites. Instead, he required that they kill a perfect lamb. God wanted each person to decide to obey him. +11:8 m43k application Why did God tell the Israelites to put the blood of the lamb around the door of their houses? When they put the blood of the lamb around their door, they showed God and other people that they believed God would save them from the plague. They trusted that the blood of the lamb would be enough to protect them from being killed. +11:8 coe8 application Why were the people to eat unleavened bread? God wanted the people to believe that he would take them out of Egypt immediately after the plague. They were to hurry to get ready to leave Egypt quickly. They would not have time to wait for bread to rise. Instead, they would prepare it without leaven, so they could eat soon. Unleavened bread was therefore a symbol that they were eating quickly. +11:8 pn0x application Did God really kill the firstborn sons? Even the children? God did exactly what he promised to do. He killed the firstborn son of any Egyptian family that did not kill the lamb and put its blood on the door. He did not spare the people who refused to believe and obey him. +11:8 bkgu application How did Pharaoh respond to this final plague? Pharaoh was forced to finally obey God. God knew how to cause Pharaoh to let the people go. He also knew how to show Pharaoh that he was more powerful than Pharaoh and all the gods of Egypt. When the firstborn sons of Egypt died, Pharaoh let the people go exactly as God had told Moses he would do. +12:1 acjy meaning Who also left Egypt along with the Israelites? Some people from other nations who believed in God also left Egypt along with the Israelites (See: [12:01](12/01)). +12:2 ix3t meaning How did God lead the Israelites? God sent a tall pillar of cloud during the day. It became a pillar of fire at night. It went ahead of the Israelites to show them where to go. God was in this pillar (See: [12:02](12/02)). +12:3 sn28 meaning Why did Pharaoh change his mind about letting the Israelites go? God caused Pharaoh to change his mind so that he could show everyone that he is more powerful than Pharaoh and all the gods of Egypt (See: [12:03](12/03)). +12:4 y4py meaning Why were the Israelites afraid when they saw the Egyptian army coming? They were trapped between the Egyptians and the Red Sea. They thought the Egyptians would kill them (See: [12:04](12/04)). +12:6 jie3 meaning What did God do to protect the Israelites from the Egyptians? God moved the pillar of cloud between the Israelites and the Egyptians so the Egyptians could not see the Israelites (See: [12:06](12/06)). +12:7 is5s meaning What happened when Moses raised his hand over the sea? God caused the wind to push the water to the left and to the right so that there was a path through the sea for the Israelites. The Israelites crossed the sea on dry ground (See: [12:07](12/07), [12:08](12/08)). +12:10 zd6j meaning What happened to the Egyptians when they followed the Israelites into the sea? God caused the Egyptians to panic and their chariots to get stuck. Then he closed the water over the Egyptians so that they all drowned (See: [12:10](12/10), [12:11](12/11)). +12:12 f7va meaning What did the Israelites believe about Moses? They believed that he was a prophet of God (See: [12:12](12/12)). +12:14 rw8n meaning How do the Israelites remember every year that God defeated the Egyptians? Every year, the Israelites celebrate the festival of the Passover by killing and eating a lamb with unleavened bread (See: [12:14](12/14)). +12:14 gnfv application Why do you think some people from other nations went with the Israelites from Egypt? They would have seen all the plagues that God did to the Egyptians. Perhaps that is why they believed that Yahweh is God. They decided to follow him instead of the gods of Egypt. +12:14 gk27 application God had already forced Pharaoh to let the Israelites leave Egypt. Why did he make Pharaoh chase after them again? Perhaps other nations would not know that God forced Pharaoh to let the Israelites go. God caused Pharaoh to chase after the Israelites so that he could completely destroy the Egyptians. In this way, people in every nation would hear about it and know that God was more powerful than Pharaoh and the gods of Egypt. +12:14 h8z1 application Why did God lead the Israelites to the Red Sea where they would be trapped, instead of leading them around it? God wanted to use the Red Sea to destroy the Egyptians and to show the Israelites how powerful he was. For this reason, God led them to the edge of the sea instead of around it. +12:14 tedt application Why were the Egyptians not able to immediately catch the Israelites before they finished crossing the sea? There were so many Israelites that it would have taken a long time for them to all cross the sea. However, God placed the pillar of cloud behind them so the Egyptians could attack them as they were crossing the sea. +12:14 b0f9 application What did the Israelites do when they realized the Egyptians were dead? The Israelites rejoiced and worshiped God. They realized that he had save them from dying and from being slaves. They were very happy and decided to obey God. They continued to celebrate the festival of the Passover every year as God commanded them to do. +13:2 smit meaning What did God say the Israelites would become if they kept his covenant with them? They would become his prized possession, a kingdom of priests, and a holy nation (See: [13:02](13/02)). +13:3 uhtz meaning What were the signs of God’s presence when he came down on the mountain? There was thunder, lightning, smoke, and sounds of loud trumpets (See: [13:03](13/03)). +13:4 fjle meaning What was the first command that God gave to the people? God told them not to worship any other god (See: [13:04](13/04)). +13:5 ei9t meaning What were the Israelites supposed to do on the seventh day of the week? They were supposed to keep the Sabbath day holy by resting and remembering God (See: [13:05](13/05)). +13:7 qf5j meaning What would God do to the people if they did not obey his commandments? God would punish them if they did not obey him (See: [13:07](13/07)). +13:8 ebas meaning Who was allowed to enter into the room in the Tent of Meeting where God was? Only the high priest was allowed to go into that room (See: [13:08](13/08)). +13:9 d7sn meaning What would the blood from an animal sacrifice do to the sin of the person who brought the animal? The blood of the animal would cover that person’s sin. He would become clean in God’s sight (See: [13:09](13/09)). +13:11 gyyk meaning Why did the people make an idol to worship? Moses remained on the mountain for a long time, and the people grew tired of waiting for him. Therefore, they asked Aaron to make an idol for them to worship (See: [13:11](13/11)). +13:13 wyx5 meaning What did Moses do when he came down the mountain and saw the people worshiping the idol? He smashed the two stone tablets on which God had written the Ten Commandments. He then destroyed the idol and made the people drink the dust of it in water (See: [13:13](13/13), [13:14](13/14)). +13:15 m18s meaning Why did God forgive the people? He forgave them because Moses prayed for them (See: [13:15](13/15)). +13:15 m8j7 application Why did God bring the people to Mount Sinai? This was the place where God had spoken to Moses from the burning bush. He promised Moses that he would bring the people out of Egypt to worship him there. God kept that promise and led them to that same place. +13:15 e788 application Why did God say the Israelites would be a kingdom of priests? Priests help other people worship God. They also teach people what God has said. All the people of Israel would be able to do these things for the other nations if they would obey God. +13:15 qoom application Why did God write the Ten Commandments on tablets of stone? God wanted the people to always remember his commandments. Perhaps that is why he wrote them on hard stone tablets with his own hand, instead of on clay, wood, or paper. +13:15 u82l application Why did God tell the Israelites to make a tent where he could meet them? The Israelites were traveling to the Promised Land. They could not build a temple which would be in one place. Instead, God told them to make a special tent that they could move with them and set up when they stopped in a place. +13:15 l2zh application Why do you think God said the blood of the sacrifice would cover a person’s sin? The sin of the person would still be there, but it would be covered. God would look at the blood instead of their sin, and would consider that person to be clean before him. +13:15 fd03 application Why was it especially evil that the people made an idol to worship? The first and most important command God gave them was not to worship any other god. +13:15 amm2 application What did God send on the people to punish them for worshiping the idol? God send a plague on them, which killed many of them. In Egypt, God sent plagues on the Egyptians. Now, God punished his own people with a plague because they sinned. +14:2 uozo meaning Why did God tell the people to get rid of the Canaanites completely? The Canaanites worshiped idols and did many evil things. God knew that if the Israelites lived with the Canaanites, they would marry them and start to worship idols also (See: [14:02](14/02), [14:03](14/03)). +14:5 wse4 meaning What did ten of the spies say about the land and people of Canaan? They said the land was good, but that the people were giants. They said the Israelites could not defeat them (See: [14:05](14/05)). +14:6 wohx meaning What did Joshua and Caleb say about the people of Canaan? They said the people were indeed strong, but that God would fight for the Israelites so they could defeat the Canaanites (See: [14:06](14/06)). +14:7 eiqh meaning How did the people respond to the bad report of the ten spies? They were angry that they had left Egypt. They wanted to choose a new leader to replace Moses and Aaron and to lead them back to Egypt (See: [14:07](14/07)). +14:8 mdz8 meaning How did God answer the people when they wanted to go back to Egypt? God was very angry with the people, and promised that they would wander in the wilderness until all the adults died. Only their children would enter into the Promised Land. Joshua and Caleb would also enter the land because they wanted to obey God (See: [14:08](14/08)). +14:9 q3sh meaning What did the people do when they heard that they would die in the wilderness? They attacked the Canaanites, but the Canaanites defeated them (See: [14:09](14/09), [14:10](14/10)). +14:11 m3e8 meaning How did God take care of the people in the wilderness? He gave them manna and quail to eat, and provided water for them. He also kept their clothes and sandals from wearing out for 40 years (See: [14:11](14/11), [14:12](14/12)). +14:13 k3y5 meaning Why could Moses not enter the Promised Land? God told Moses to speak to a rock so that it would give water to the people. But Moses disobeyed God and struck a rock with a stick instead. In this way, he dishonored God before the people. Therefore, God did not allow him to enter into the land. He went up to a high mountain and saw the land, and then he died (See: [14:13](14/13), [14:15](14/15)). +14:13 t8mo application What had the people of Canaan become like since Joseph and his family left? Joseph and his family had been in Egypt for 400 years. During that time, there was no one in Canaan who worshiped God. The people there had become very evil and worshiped many idols. +14:13 evrj application What often happens to people who live among people that worship other gods? God said the Israelites would begin to worship the idols of the Canaanites if they lived with them. People normally begin to worship the gods of the people around them. This is especially true if they marry people who believe in other gods. +14:13 issd application Why did Joshua give the people different advice than the other ten spies? All 12 of the spies saw the same land and people. However, ten of the spies only thought about how hard it would be to defeat the people. But Joshua and Caleb thought about the good land and about how God would help them. They believed he would enable them to defeat the Canaanites even though they were tall and strong. +14:13 puuf application Why did the people want to go back and be slaves in Egypt? The people were very afraid that the Canaanites would kill them. They thought it would be better to be enslaved in Egypt than to be killed. They did not trust God to protect them. +14:13 zsq9 application God made the Israelites wander in the wilderness for 40 years until all the adults died. Why did he take such good care of them during that time? God was angry with the people who would not go into the Promised Land. But he kept his promise to Abraham to make his descendants into a great nation. Therefore, he continued to care for the Israelites in the wilderness, and for their children who would enter into the Promised Land after their parents would die. +14:13 ppnw application Why did God punish Moses so harshly for striking the rock? Moses was the leader of Israel. He spoke to them for God. Because everyone watched what Moses did, God punished him harshly so the people would be afraid to disobey God. For this reason, Moses was not allowed to enter the Promised Land. +15:1 y0sf meaning Why did the two spies promise to protect Rahab the prostitute and her family? Rahab believed in God and helped the spies escape from Jericho (See: [15:01](15/01)). +15:2 yju9 meaning How did God enable the Israelites to cross the Jordan River? He caused the water upstream to stop flowing so the Israelites could walk across the river on dry ground (See: [15:02](15/02)). +15:3 es9j meaning How did God make it possible for the Israelites able to defeat the city of Jericho? They marched around Jericho, blew their trumpets, and shouted. When they did that, God caused the walls of the city to fall down so they could attack the people (See: [15:03](15/03), [15:04](15/04)). +15:5 e12l meaning What happened to Rahab and her family when the Israelites destroyed Jericho? Joshua spared Rahab and her family, and they became part of the Israelites (See: [15:05](15/05)). +15:6 h3kv meaning What did the Gibeonites do so that the Israelites would not destroy them? They pretended to be from a country far away so the Israelites would make a peace treaty with them (See: [15:06](15/06)). +15:7 jm4e meaning How did the Amorites respond when the Gibeonites made peace with the Israelites? They joined their armies together to attack the Gibeonites (See: [15:07](15/07)). +15:9 jqcw meaning What were the two miracles that God did to help the Israelites defeat the Amorites? God sent large hailstones to kill the Amorites, and made the sun stay in one place so the Israelites would have enough time to completely defeat them (See: [15:09](15/09), [15:10](15/10)). +15:12 tq24 meaning What did God give to each tribe after they finished fighting against the Canaanites? He gave each tribe of Israel its own section of the Promised Land (See: [15:12](15/12)). +15:13 rts8 meaning When Joshua called the Israelites together, what did they promise to do? They promised to be faithful to God and to obey his laws (See: [15:13](15/13)). +15:13 a1be application Rahab was a prostitute. But God accepted her and her entire family as part of Israel because she believed in God. What does that tell you about who God is? God is willing to accept any person who believes in him. It does not matter how much they have sinned. He will accept them even if other people do not think they deserve honor. +15:13 yp51 application God made a dry path through the Jordan River for Joshua and the Israelites. What had God done for Moses that was similar? God made a path through the Red Sea so Moses and the Israelites could escape the Egyptians. In a similar way, God made a path through the Jordan River for Joshua. Perhaps God wanted the Israelites to know that he would work through Joshua in the same powerful way as he worked through Moses. +15:13 q5es application Would you expect the walls of a great city to fall down because a group of people marched around it and shouted? This is not a normal way to attack a city with high walls. However, Joshua and all the Israelites obeyed God and did what he told them to do. As a result, God caused all the walls to fall down so they could destroy the city. +15:13 q8hq application Why do you think the Israelites did not ask God about the Gibeonites? People often neglect to ask God for help unless they know they need him. Perhaps Joshua and the Israelites thought they could decide how to answer the Gibeonites without God’s help. Because they did not ask God, they made a terrible mistake. The Gibeonites deceived them, and the Israelites could not break their peace treaty with them. +15:13 uvei application In what way did God show his power over creation when he helped the Israelites defeat the Amorites? God controlled the weather so that hailstones fell from the sky to kill the Amorites. He also caused the sun in the sky to stand still in order to make the day longer. Only Yahweh, who created all things, is able to do this. +16:1 t99o meaning How did the Israelites disobey God? They did not keep his laws, and they did not drive out the rest of the Canaanites from the land. Also, they began to worship Canaanite gods (See: [16:01](16/01)). +16:2 xdit meaning What pattern did the Israelites keep repeating? They would disobey God, so he would punish them by allowing their enemies to defeat them. When the Israelites repented, God would send a deliverer to rescue them (See: [16:02](16/02)). +16:5 df1z meaning Why was Gideon threshing grain in a hidden place? He was afraid the Midianites would find his grain and steal it (See: [16:05](16/05)). +16:6 c5r5 meaning What was the first thing that God told Gideon to do? God told him to tear down his father’s altar where his father worshiped an idol (See: [16:06](16/06)). +16:9 or8f meaning What two signs did God give to Gideon to prove that he would defeat the Midianites? God caused a sheepskin to be wet, but the ground around it to be dry. Then the next night, God caused the sheepskin to be dry, but the ground to be wet (See: [16:09](16/09)). +16:10 ukeu meaning What did God do when 32,000 men came to fight for Israel? God had Gideon send most of them home. He kept only 300 soldiers (See: [16:10](16/10)). +16:12 osx2 meaning How did Gideon’s 300 soldiers attack the Midianites? They put torches in clay pots. Then they blew their horns and all broke the pots at the same time, showing the torches (See: [16:12](16/12), [16:13](16/13)). +16:14 b0u9 meaning How did God help Gideon attack the Midianites? God confused the Midianites so that they attacked and killed each other (See: [16:14](16/14)). +16:16 lg74 meaning What did the people do with the special garment that Gideon made out of gold? The people began to worship it as an idol (See: [16:16](16/16)). +16:18 qubw meaning Why did the people ask God to give them a king? They wanted a king who was tall and strong, and who could lead them into battle against their enemies (See: [16:18](16/18)). +16:18 b55m application All of the Israelites did what they thought was right for themselves. Does this mean they obeyed God? The Israelites did not think about God in the right way. Therefore, they thought it was right to worship idols even though God had told them to worship only him. In this way, they disobeyed God. +16:18 j5yl application How many times did God send a deliverer to rescue the Israelites when they repented of their sin? Every time the Israelites repented of their sin and asked God to help them, he sent a deliverer to rescue them. This happened many times. +16:18 mcjv application Why did it take so long for the Israelites to ask God to save them from the Midianites? The Midianites stole all of the Israelites’ crops for seven years before they asked God to save them. Perhaps they forgot that he could rescue them. Or perhaps they asked their idols to save them for seven years before they finally decided to ask God for help. +16:18 k1h4 application What are some of the ways that Gideon showed that he was not very brave? Gideon was hiding from the Midianites as he threshed grain. He tore down his father’s altar at night because he was afraid of the people. God had to show him two signs to convince him to attack the Midianites. And God sent him to the Midianite camp to hear a soldier talk about his dream so Gideon would not be afraid. In spite of his fear, God used him to save Israel. +16:18 tprm application Why did God make Gideon send home all but 300 soldiers? God wanted everyone to know that the Israelites defeated the Midianites because God helped them. He did not want them to think their own strength saved them. For that reason, he did not want Gideon to attack with a lot of soldiers. +16:18 e5ga application Were the people thankful that God send deliverers to rescue them from their enemies? The people were not happy that God only sent them deliverers. Instead, they wanted a king like all the other nations had. +17:1 gsox meaning What kind of a man was Saul? Saul was tall and handsome, just like the people wanted. But he became a wicked man who did not obey God (See: [17:01](17/01)). +17:2 t82f meaning Who did God choose to become king after Saul? God chose a young shepherd from Bethlehem. He was humble and righteous, and he trusted and obeyed God (See: [17:02](17/02)). +17:3 dkvu meaning Who was Goliath, whom David killed? Goliath was a giant enemy soldier who was three meters tall (See: [17:03](17/03)). +17:4 q5hr meaning How did David prove to Saul that he was not trying to kill Saul? David cut off a piece of Saul’s clothing in a cave. He could have killed Saul at that time, but he did not harm him. When Saul found out about it, he knew that David was not trying to kill him (See: [17:04](17/04)). +17:6 sq19 meaning What did David want to build for God? David wanted to build a temple where the Israelites could worship God and bring him sacrifices (See: [17:06](17/06)). +17:7 klz1 meaning How did God respond to David’s plan to build a temple? God sent the prophet Nathan to tell David he would not be the one to build a temple. Instead, David’s son would build it (See: [17:07](17/07)). +17:8 ojld meaning Who did God say would rule forever? One of David’s descendants would rule forever. This person would be the Messiah. But the Messiah would not come for almost 1,000 years after David died (See: [17:08](17/08)). +17:10 heft meaning How did David sin against God? David slept with Bathsheba. Then he murdered her husband, Uriah, who was one of David’s best soldiers (See: [17:10](17/10), [17:11](17/11), [17:12](17/12)). +17:14 rsgb meaning How did God punish David for his sin? God caused Bathsheba’s baby to die. He also made David’s own family fight against him (See: [17:14](17/14)). +17:14 m594 application In what ways was David different than Saul? The people wanted Saul to be king because he was tall and handsome. But he was a wicked man. God chose David to be king because David was humble and trusted and obeyed God. +17:14 xo1p application How might David have learned to be the king of Israel while he was a shepherd? While he was a shepherd, David learned to be brave and to protect his father’s sheep. As a young man, he even killed a bear and a lion when they attacked the sheep. Because of this, he was able to protect the Israelites against their enemies. +17:14 x96y application Saul tried to kill David. Why did David not kill Saul when he found him in the cave? David did not want to sin in order to be king. He chose to wait until the time when God would make him king. Therefore, he did not kill Saul. Instead, he trusted God to protect him from Saul. +17:14 r1vn application Why did God not allow David to build a temple? David ruled Israel well, and God was pleased with David. God wanted David to be a good soldier for him. That was God’s plan for David. God wanted a different person to build a temple. David’s son would not be a soldier. He would be a builder. God would use him to build a temple. In this way, God would honor David by blessing his descendants. +17:14 llwy application What was the greatest blessing that God promised to David? God promised David that one of his descendants would be the Messiah. He would rule over God’s people forever. +17:14 co7x application Why did David cause Uriah to be killed? David tried to hide his sin by killing Uriah. If Uriah was dead, David thought no one would know the king was the father of Bathsheba’s baby. +17:14 ibgk application Why did God punish David after he repented? God forgave David when he repented. But because David had dishonored God before the people, God had to punish him. David accepted that punishment and obeyed God. +18:1 e9fk meaning What did Solomon ask God to do for him? He asked God to make him very wise (See: [18:01](18/01)). +18:2 stbc meaning Why did the people no longer offer sacrifices at the Tent of Meeting? Solomon build the Temple for which David had planned and prepared. People now offered sacrifices and worshiped God there instead of at the Tent of Meeting (See: [18:02](18/02)). +18:3 ubxs meaning Solomon married almost 1,000 women. How did that cause Solomon to sin? Many of the women Solomon married were foreign women. They brought their gods with them, and Solomon started to worship those false gods (See: [18:03](18/03)). +18:4 lwij meaning How did God say he would punish Solomon for worshiping other gods? God said he would punish Solomon by dividing the nation of Israel into two kingdoms after Solomon died (See: [18:04](18/04)). +18:5 wp78 meaning Why did the people rebel against Rehoboam? They asked him to make them work less than Solomon did. Instead, Rehoboam said he would make them work harder. This made them angry, so they refused to serve him (See: [18:05](18/05), [18:06](18/06)). +18:7 tvka meaning How many of the tribes of Israel remained with Rehoboam? Only two of the 12 tribes remained with Rehoboam (See: [18:07](18/07)). +18:9 bs9c meaning What did Jeroboam make so the people would no longer go to Jerusalem to worship? He made two idols for the people of the kingdom of Israel to worship (See: [18:09](18/09)). +18:11 weu7 meaning How many of the kings of the kingdom of Israel were evil? All of the kings of the kingdom of Israel were evil (See: [18:11](18/11)). +18:13 uw82 meaning Were most of the kings of Judah good or evil? Some of the kings of Judah were good men, but most of them were evil. They ruled badly, worshiped idols, and even sacrificed their children to false gods (See: [18:13](18/13)). +18:13 p3qe application Why did it please God when Solomon asked God to make him wise? Solomon did not ask for wealth for himself. Instead, he asked God to make him wise so that he could rule God’s people well. This pleased God, and so he also made him wealthy. +18:13 foqe application What problem happened because Solomon married women from foreign countries? Many people from other countries believed in God, and he accepted them. Solomon was not wrong to marry foreign women. But he was wrong to marry foreign women who still served other gods. Those women continued to worship those false gods. And eventually, they caused Solomon to worship those idols as well. This made God very angry. +18:13 af2i application Solomon was very wise. How was Rehoboam different than Solomon? Unlike his father Solomon, Rehoboam, was very foolish. The people were willing to follow him if he would treat them well. But instead, he answered the people so harshly that most of the tribes of Israel refused to follow him. +18:13 cy2m application Why did Jeroboam build idols for his people to worship? Jeroboam may have wanted to worship idols. But he also did not want his people to continue to go to Jerusalem to worship. Jerusalem was in the kingdom of Judah. Judah was now the enemy of the kingdom of Israel. Therefore, the main reason Jeroboam made the idols was so his people would stay away from the kingdom of Judah. They worshiped the idols in the kingdom of Israel instead. +18:13 l56s application The kings of Judah were descendants of David. How is it that many of them were evil? Even though David obeyed God, many of his children did not. Solomon obeyed God for a time, but then began to worship the idols of his foreign wives. Many of David’s other descendants also chose not to obey God. Each person had to decide for himself whether or not he would obey God. +19:2 smzy meaning Why did King Ahab try to kill the prophet Elijah? Ahab was angry with Elijah because Elijah said there would be no rain in the kingdom of Israel. Elijah said this because Ahab and the people of the kingdom of Israel worshiped an idol named Baal (See: [19:02](19/02)). +19:3 tkru meaning How did God provide for Elijah while he hid from Ahab at the stream? God sent birds to bring Elijah bread and meat to eat while he hid from Ahab (See: [19:03](19/03)). +19:4 ysj0 meaning How did God provide for Elijah while he lived with the widow and her son? God caused the widow’s jar of flour and bottle of oil to never become empty. For about three years, there was always enough food for them to eat even though there was no other food in the land (See: [19:04](19/04)). +19:6 a8ly meaning What did Elijah tell the people to decide about when they came with the prophets of Baal to Mount Carmel? Elijah told the people that they should stop changing their mind about God. If Yahweh is God, they should worship him, but if Baal is God, they should worship him instead (See: [19:06](19/06)). +19:7 nrdw meaning How did Elijah say the people could tell whether Yahweh or Baal was the true God? Elijah and the prophets of Baal would prepare a sacrifice on an altar. The people would know that the God who responded by sending fire onto the altar was the true God (See: [19:07](19/07)). +19:8 r0ug meaning What happened when the prophets of Baal asked Baal to send fire on the altar? Nothing happened when they asked Baal to send fire (See: [19:08](19/08)). +19:11 pwbo meaning What happened when Elijah asked Yahweh to send fire on the altar? Fire fell from the sky and burned up the altar and everything around it (See: [19:11](19/11)). +19:14 oequ meaning How did God heal Naaman of his skin disease? Elisha told Naaman to dip himself in the Jordan River seven times. At first, he refused. But then he changed his mind and did what Elisha told him to do. God healed him as soon as he obeyed (See: [19:14](19/14), [19:15](19/15)). +19:17 ijmo meaning How did the people try to kill the prophet Jeremiah? They put Jeremiah into a dry well and left him there to die. But later, the king sent his servants to pull him out (See: [19:17](19/17)). +19:18 l8m9 meaning Who did the prophets remind the people that God promised to send to them? The prophets reminded them that God would send the Messiah to them (See: [19:18](19/18)). +19:18 t2s3 application How did the people usually respond to the prophets whom God sent to them? The people did not believe what the prophets said. Instead, they hated the prophets and often tried to kill them. In spite of this, the prophets continued to speak to the people for God. +19:18 jtl4 application How did the prophet Elijah survive during the drought and the famine that it caused? When there was no rain in the kingdom of Israel, there was also very little food. During that time, God provided food for Elijah in special ways. For a while, he sent birds to bring food to Elijah. Then he caused the food of a poor widow to never end so she could feed Elijah. God took care of Elijah because Elijah obeyed God and spoke God’s messages to the people. +19:18 m8id application Why did Elijah tell the people to pour water on his sacrifice? Elijah told the people to pour water on his sacrifice in order to make it harder for it to burn. He wanted the people to know that Yahweh was truly the one who burned up the sacrifice. Therefore, he made the sacrifice so wet that only God could cause it to burn. He knew that nothing was too difficult for God. +19:18 z66m application Why did Naaman not go to the river immediately when Elisha told him to go? Perhaps Naaman thought what Elisha told him to do was too simple to cure his disease. At first, he thought he would have to do something more difficult in order to be healed. However, when he did the easy thing Elisha told him to do, he was healed! +19:18 wynu application What did the prophets say the people must do so that God would not destroy them? The prophets told the people they must repent. That is, they must change their mind about God and begin to think about him in a different way. They must understand that Yahweh is the true God and stop worshiping other gods. If they did not repent, God would destroy them because they sinned against him. +20:2 cg4d meaning What nation did God send to destroy the kingdom of Israel? God sent the Assyrians to destroy the kingdom of Israel. The Assyrians were very cruel. They killed many of the Israelites and took the rest of them to Assyria (See: [20:02](20/02), [20:03](20/03)). +20:4 t7j2 meaning Who did the Assyrians bring to live in the land of Israel? The Assyrians brought foreigners to live in the land of Israel. These foreigners married the Israelites who were left in the land. Their descendants were called Samaritans (See: [20:04](20/04)). +20:5 rar6 meaning What did the people in the kingdom of Judah do when they saw how God had punished the kingdom of Israel? The people in the kingdom of Judah continued to worship idols, including the gods of the Canaanites. They refused to believe the prophets whom God sent to warn them (See: [20:05](20/05)). +20:6 a80y meaning What nation did God send to attack the kingdom of Judah? God sent the Babylonians to attack the kingdom of Judah. As a result, the king of Judah promised to pay a lot of money each year to Nebuchadnezzar, the king of the Babylonians (See: [20:06](20/06)). +20:7 qeny meaning What did Nebuchadnezzar do to the kingdom of Judah when they rebelled against him? Nebuchadnezzar sent his army to destroy Jerusalem and the Temple. They took away all the treasures of the city. They also killed the king’s sons and made him blind. Then they led him away to Babylon (See: [20:07](20/07), [20:08](20/08)). +20:9 tcol meaning Who remained in the land of Judah during the Exile? The Exile is the time when many of the people of Judah were forced to go away to Babylon. During this time, Nebuchadnezzar left only the poorest people in the land (See: [20:09](20/09)). +20:10 zj7r meaning Did God forget his people after he punished them by sending them into exile? God did not forget his people as they were away from the land. He continued to send his prophets to speak to them for him. He promised that they would return to the land after 70 years in Babylon (See: [20:10](20/10)). +20:12 f2ed meaning How did the Jews return to the land of Judah? God caused the Persians to defeat the Babylonians. Cyrus, the Persian king, allowed the Jews to return to Jerusalem. He gave them money to rebuild the Temple. Many of the Jews returned to Jerusalem. They also rebuilt the walls of the city (See: [20:12](20/12), [20:13](20/13)). +20:12 l4nw application Does it seem right that God would send the cruel, evil Assyrians to destroy his people? God warned the kingdom of Israel that he would punish them, but they would not repent. Therefore, God sent the Assyrians to destroy them. Even though the Assyrians were a cruel people, God allowed them to defeat Israel in order to punish Israel. Later, however, he punished the Assyrians by allowing the Babylonians to defeat them. +20:12 cp4j application Why do you think the people in the kingdom of Judah refused to repent after the Assyrians destroyed the kingdom of Israel? People normally think they are not as bad as other people. Perhaps the people of the kingdom of Judah thought they were better than the people in the kingdom of Israel. They thought God would not punish them in the same way. But they were wrong. God sent his prophets to tell them that he would punish them if they did not repent. And he punished them just as he said that he would. +20:12 xt63 application Why do you think the Babylonians were able to destroy the Temple in Jerusalem? The Temple was the place where God stayed with the Israelites. However, God did not stay with them because they sinned against him and worshiped other gods. Therefore, God left the Temple and allowed the Babylonians to destroy it. +20:12 fxnu application Why did the prophets say that the Israelites would only be in exile for 70 years? God decided to allow the Jews to return to Judah after 70 years in exile in Babylon. He also decided to cause Cyrus and the Persians to defeat Babylon in order to let the Jews leave and go home to Judah. Since God knew beforehand that he was going to do this, he sent his prophets to tell the Jews that he would do these things. +20:12 h5hi application How were the Jews able to rebuild the Temple? God provided everything the Jews needed to rebuild the Temple. He even caused Cyrus, the king of the Persians, to give them the money they needed to rebuild the Temple. God wanted to live with his people there again. So he made it possible for them to rebuild the Temple where he would live with them. +21:1 zb64 meaning Who would crush the snake’s head? The Messiah, a descendant of Eve, would crush the snake’s head (See: [21:01](21/01)). +21:2 ztgz meaning Who were the people whom the Messiah would save? The Messiah would save people out of every people group in the world (See: [21:02](21/02)). +21:5 l88a meaning How would the New Covenant be different than the old covenant? In the New Covenant, people would know God personally. They would love him and want to obey his laws. His law would be written on their hearts (See: [21:05](21/05)). +21:7 fz0q meaning What perfect sacrifice would the Messiah offer to God? The Messiah would offer himself as a perfect sacrifice to God (See: [21:07](21/07)). +21:9 l651 meaning What did the prophets say about the birth of the Messiah? The prophets said the Messiah would be born of a virgin in the town of Bethlehem (See: [21:09](21/09)). +21:11 k356 meaning According to the prophet Isaiah, how would people receive the Messiah? The prophet Isaiah said people would hate the Messiah and refuse to accept him. His friend would turn against him, and the people would kill him (See: [21:11](21/11)). +21:13 qga5 meaning According to the prophets, why would the Messiah die? The Messiah would die because God would punish him for other people’s sins. He would die so they could have peace with God (See: [21:13](21/13)). +21:14 hneq meaning What would God do for the Messiah after he died? The prophets said God would raise the Messiah from the dead (See: [21:14](21/14)). +21:15 h4i4 meaning After the prophets finished speaking about the Messiah, how much time passed before God send him into the world? God sent the Messiah into the world 400 years after the prophets last spoke about him (See: [21:15](21/15)). +21:15 q9xm application Why do you think God spoke about the Messiah to Adam and Eve, even though God would not send the Messiah for a very long time? When he first created the world, God already planned to send the Messiah to save us from our sins. Therefore, he began to tell people about the Messiah from the very beginning. +21:15 y126 application Abraham’s descendants were the Jews, who are God’s chosen people. Why is it significant that God told Abraham that he would bless all the people groups of the world through him? God never planned to save only the Jews. Rather, from the very beginning, his plan was to save people from every people group in the world. However, God told Abraham that God would bless all these people through a Jewish descendant of Abraham. This descendant would be the Messiah. +21:15 cfs0 application The New Covenant will be written on people’s hearts. Why is this important? The old covenant was written on tables of stone and paper. Even the Jews who received it often forgot about it and did not obey it. But God will write the New Covenant within people so they cannot forget it. Because God will change their hearts, people will obey the New Covenant. They will willingly worship and serve God. +21:15 uu6h application Why should we be encouraged that the Messiah never has to make another sacrifice for sin? The Messiah offered himself as a perfect sacrifice to God. God accepted his sacrifice in place of punishing us. Since his sacrifice was perfect, he never has to offer it again. That means God will never punish believers for their sins, since the sacrifice of the Messiah will always be enough to please God. +21:15 s2rq application The Messiah never sinned. Why did God allow people to kill him? God wanted the Messiah to die because that was the only way God could forgive people’s sins. God is holy and cannot ignore when people sin. But God punished the Messiah in the place of other people so God would not have to punish them. +22:1 c1gi meaning How many years went by when God did not speak to his people through a prophet? God did not speak to his people through a prophet for 400 years (See: [22:01](22/01)). +22:1 t021 meaning What problem did Zechariah and Elizabeth have? They were very old, and Elizabeth had not been able to have children (See: [22:01](22/01)). +22:2 upjd meaning What would John get the people ready to do? John would get the people ready to accept the Messiah (See: [22:02](22/02)). +22:3 xns6 meaning Why did Zechariah become unable to speak? Zechariah became unable to speak because he did not believe the angel when the angel said Zechariah would have a son (See: [22:03](22/03)). +22:4 dv20 meaning To whom was Mary engaged to be married? Mary was engaged to be married to a man named Joseph (See: [22:04](22/04)). +22:4 qw5l meaning Who did the angel tell Mary that her son would be? The angel said she should name her son Jesus, and he would be the Son of the Most High God who would rule forever (See: [22:04](22/04)). +22:5 jmz3 meaning Why was Mary confused about how she could have a son? Mary was a virgin. Therefore, she did not understand how she could have a son (See: [22:05](22/05)). +22:5 cuju meaning How did Mary respond when the angel told her that God and the Holy Spirit would come to her so that she would be pregnant? Mary believed that what the angel said would happen to her (See: [22:05](22/05)). +22:6 h59u meaning What did Elizabeth’s baby do when Mary arrived to visit Elizabeth? Elizabeth’s baby jumped inside her when Mary arrived to visit (See: [22:06](22/06)). +22:6 w0k9 meaning Why did Zechariah and Elizabeth name their baby John? The angel has commanded them to name their baby John. +22:6 glzd application Why were Zechariah and Elizabeth unable to have children before this time? Zechariah and Elizabeth were unable to have children, but this did not mean that they had done anything wrong. They honored God, and he was pleased with them. Therefore, God did a miracle through them, allowing them to become the parents of John in their old age. +22:6 q00d application Was Zechariah being reasonable when he doubted the message of the angel? It would certainly seem reasonable that Zechariah doubted the angel, because God had not spoken to his people for 400 years. However, God did not merely send a prophet to Zechariah. Instead, he sent one of his mighty angels. The presence of the angel should have convinced Zechariah to believe the message. +22:6 k416 application Mary was a virgin. Therefore, her son did not have a human father. Why do you think this was important? Every descendant of Adam and Eve is born with a desire to sin. Mary’s son, however, is the Son of God, conceived by the Holy Spirit. For that reason, he is holy and has never sinned. He is the only person who has ever been born who does not have this desire to sin. God did not need to punish him for his sins. Instead, he could be punished in the place of other people who sinned. +22:6 p8gm application How was baby John able to know when Mary came to Elizabeth, and to jump in Elizabeth’s womb? John was already a person who could think and act even while he was in Elizabeth’s womb. He was already able to worship God by jumping inside Elizabeth when Mary came near with the baby Son of God inside her. +22:6 xa0j application Why did God send John ahead of the Messiah? The Messiah is the most important person who ever came to earth. When important people traveled somewhere in that time, someone went ahead of them to make preparations for their arrival and to tell people that they were coming. This is what John did for the Messiah. He told them that the Messiah was coming, and prepared people to accept him. +23:1 t3o7 meaning Why did Joseph decide to divorce Mary quietly? Mary was pregnant, and Joseph knew it was not his baby. Therefore, he decided to divorce her. However, he decided to have mercy on her and not to shame her. Therefore, he was going to divorce her quietly (See: [23:01](23/01)). +23:2 lqvg meaning The angel told Joseph how Mary became pregnant. How did he say this happened? The angel told Joseph that the Holy Spirit placed the baby in her (See: [23:02](23/02)). +23:2 a6z9 meaning What does the name **Jesus** mean? It means ‘Yahweh saves’ (See: [23:02](23/02)). +23:3 rmtq meaning How long did Mary remain a virgin? Joseph did not sleep with her until after she had given birth (See: [23:03](23/03)). +23:4 xnk0 meaning Why did Joseph and Mary need to travel to Bethlehem? Their ancestor, King David, was born in Bethlehem. The Roman officials told everyone to travel back to where their ancestors lived. Therefore, Joseph and Mary went to Bethlehem (See: [23:04](23/04)). +23:6 mtbz meaning Who told the shepherds that the Messiah was born? An angel told the shepherds that the Messiah was born. Then many other angels also appeared to the shepherds, praising God for what he had done (See: [23:06](23/06)), (See: [23:07](23/07)). +23:8 ew6d meaning What did the shepherds do after the angel told them about the Messiah? The shepherds went to Bethlehem and found the baby in the feeding trough, just as the angel had told them (See: [23:08](23/08)). +23:9 pxci meaning Why did men come from the east to see the baby? They studied the stars and saw an unusual star in the sky. They knew this meant the king of the Jews had been born. Therefore, they came to see him (See: [23:09](23/09)). +23:10 b11x meaning What did the wise men do when they saw the child? They bowed down and worshiped him, and they gave him expensive gifts (See: [23:10](23/10)). +23:10 szqg application Joseph learned that Mary was pregnant, and knew he was not the father of the baby. Why do you think he decided to have mercy on Mary? Joseph believed that Mary was pregnant because she had been unfaithful to him and had slept with another man. Joseph could have been angry with Mary and wanted to punish her. Joseph was a righteous man, and did not want to marry an adulteress. However, he was a good man, and it appears that he loved Mary. Therefore, he decided to have mercy on her instead of punishing her. +23:10 s7g6 application How might Mary have felt when people learned that she was pregnant? Mary must have been very sad when people learned that she was pregnant, because they did not believe that her baby was from the Holy Spirit. Everyone thought she was an adulteress. Even Joseph thought she had sinned, and did not want to marry her. However, Mary knew that she had obeyed God and was still a virgin. She waited patiently until God told Joseph that she was faithful, and that he should marry her. +23:10 qvcg application Why did Joseph not sleep with Mary until the baby was born? God told Joseph that Mary was a virgin and that the baby inside her was from God. Perhaps Joseph was so amazed that the Son of God was in Mary’s womb that he kept her a virgin. Or perhaps he wanted to be able to tell everyone that Mary’s baby could not possibly be the result of a human father. Therefore, he did not sleep with her until Jesus was born. +23:10 vc21 application How was the location of Jesus’ birth different than where you would expect the Son of God to be born? Joseph and Mary were forced to travel far away to another city while she was pregnant. She gave birth to Jesus in a place where animals were kept. They were too poor to be able to find a proper room to stay in. None of their family or friends were with them. Joseph and Mary honored and obeyed God. And Jesus was the Messiah, the Son of God. However, they still faced many difficult situations. But God took care of them during that time. +23:10 an2l application What did God do to encourage Joseph and Mary after Jesus was born? God sent the shepherds to tell Joseph and Mary about the angels that visited them. He also sent the wise men who brought expensive gifts and worshiped Jesus. +24:1 mxwn meaning Where did John live? He lived in the wilderness, apart from other people (See: [24:01](24/01)). +24:2 wg04 meaning What was the message that John preached to the people? John told the people to repent, for the kingdom of God is near (See: [24:02](24/02)). +24:3 ldh0 meaning How did people respond when they heard John’s message? Some of the people repented from their sins and John baptized them. However, many of the religious leaders who came to John did not repent (See: [24:03](24/03)). +24:4 jtl8 meaning To what did John compare the religious leaders who did not repent? He compared them to poisonous snakes (See: [24:04](24/04)). +24:5 lvpw meaning How did John respond when the religious leaders asked him if he was the Messiah? John told them that he was not the Messiah, but that the Messiah was coming after him (See: [24:05](24/05)). +24:6 avjv meaning What was the title that John called Jesus when Jesus came to John? John called Jesus the Lamb of God who will take away the sin of the world (See: [24:06](24/06)). +24:7 egqv meaning Why did John not want to baptize Jesus? John said he was not worthy to baptize Jesus, but that Jesus should baptize John instead (See: [24:07](24/07)). +24:8 b01n meaning What came down and landed on Jesus after John baptized him? After John baptized Jesus, the Spirit of God came down in the form of a dove and rested on Jesus (See: [24:08](24/08)). +24:8 om9v meaning What did God say about Jesus when he spoke from heaven? God said that Jesus was his Son, and that he was very pleased with Jesus (See: [24:08](24/08)). +24:9 plni meaning What had God told John about the person on whom the Holy Spirit would stay? God told John that the person on whom the Holy Spirit would stay would be the Son of God (See: [24:09](24/09)). +24:9 f4ir application Why do you think John preached in the wilderness instead of in a city? Perhaps John wanted to preach God’s message to people who wanted to listen. Few people lived in the wilderness, so people had to make an effort to go there in order to hear John. Most of the people who came to John were serious about listening to his message. +24:9 mhqx application John told people to repent, for the kingdom of God was near. Why was his message so simple? John’s message was indeed very simple. However, he told the people everything they needed to know at that time. That is, the Messiah was coming soon to establish his kingdom. People had to repent of their sins if they wanted to participate in that kingdom. +24:9 wpkv application Why do you think the religious rulers came to John? The religious rulers did not come to John to repent of their sins. Perhaps they were curious about why other people were coming to see him. Or perhaps they were jealous that people were coming to John instead of coming to them. We know John did not think the leaders came for good reasons, because he called them poisonous snakes. Even today, some people come to hear preaching for evil reasons. +24:9 l0mj application How did John show that he was a humble man? John openly said that he was not the Messiah, and that he was not worthy to untie the sandals of the Messiah. He also told Jesus that he was not worthy to baptize him. John is an example for us. He was a great prophet, but he knew the Messiah was greater than he was. +24:9 o3p4 application How can Jesus be both the Messiah and the Lamb of God? The Messiah is the only person who did not sin. Therefore, he was the only one who could be a perfect sacrifice to God. In that way, he was punished for the sins of everyone in the world who believes in him. +24:9 yxkn application Why did the Father, the Son, and the Holy Spirit appear together when Jesus was baptized? By appearing together, they demonstrated that the Father, the Son, and the Holy Spirit are all working together to save people from their sins, and to enable them to enter into the kingdom of God. When Jesus was baptized, he was doing what God the Father wanted him to do. The Holy Spirit guided Jesus to prepare him to do the work of the Messiah and to become the Lamb of God. +25:1 ynt4 meaning Why did Jesus go out into the wilderness? The Holy Spirit led him into the wilderness (See: [25:01](25/01)). +25:1 zt67 meaning What did Jesus do in the wilderness before Satan came to tempt him? Jesus had fasted for 40 days and 40 nights before Satan came to tempt him (See: [25:01](25/01)). +25:2 zorc meaning What did Satan tell Jesus to do the first time he tempted him? Satan told Jesus to turn the rocks into bread so he could eat. (See: [25:02](25/02)). +25:3 oyxm meaning What did Jesus say was more important than eating bread? Jesus said it was more important to obey God than to eat bread (See: [25:03](25/03)). +25:4 vz9v meaning Why did Satan say that Jesus would not be hurt if he jumped off the top of the Temple? Satan said the angels of God would catch Jesus so that he would not hit the ground (See: [25:04](25/04)). +25:5 j36h meaning Why did Jesus refuse to jump off the top of the Temple? Jesus did not want to test God, and God had not told him to jump off the Temple (See: [25:05](25/05)). +25:6 my9c meaning What was the only thing Satan told Jesus to do in order to receive all the kingdoms of the world? Satan told Jesus he would give him all the kingdoms of the world if he would bow down and worship Satan (See: [25:06](25/06)). +25:8 ch59 meaning Did Jesus do any of the sinful things that Satan tempted him to do? No, Jesus refused to do any of the things that Satan told him to do (See: [25:08](25/08)). +25:8 nnxq application Why do you think Satan tempted Jesus to turn a stone into bread? Satan knew that Jesus was very hungry after he had fasted for 40 days and nights. Satan often uses a person’s weakness when he tries to tempt them. +25:8 m7u3 application Why do you think the Holy Spirit led Jesus into the wilderness to fast for 40 days? God wanted to prove that Jesus would not sin. To show this, he caused Jesus to be weak and hungry. Yet, even though Jesus was weak, he did not sin. He did not do what Satan told him to do. +25:8 lef4 application Why did Satan quote from the scripture when he told Jesus to jump off the top of the Temple? Satan knows the scripture and can quote it. However, he does not use the scripture in the correct way. He tries to give the scripture meanings that God did not intend for it to have. Satan only uses the scripture to deceive people. +25:8 y4di application Did Satan really have the authority to offer all the kingdoms of the world to Jesus? Jesus did not contradict Satan when. There is no reason to believe that Satan cannot give people wealth and power in this world. +25:8 tydy application How was Satan trying to deceive Jesus by offering him all the kingdoms of the world? The things in this world will end. However, only God can give wealth and power that lasts forever in heaven. Jesus correctly chose to wait until God gave him all the kingdoms of the world so that he could rule forever in heaven. +25:8 ucyq application Why was it impossible for Jesus to worship Satan even for a short time in order to receive the kingdoms of this world from Satan? God demands that people serve him alone. It is never right to serve Satan or anyone else—not even for a short time. We are to worship God only. We sin if we worship anyone or anything other than God. +26:1 ik7c meaning How did Jesus receive power to do the things that he did? The Holy Spirit was giving him power (See: [26:01](26/01)). +26:2 rsqk meaning Why did the people of Nazareth know Jesus well? Jesus lived in Nazareth when he was a child (See: [26:02](26/02)). +26:2 mi7q meaning Who wrote the scroll that the leaders asked Jesus to read? The leaders asked Jesus to read the scroll that the prophet Isaiah wrote (See: [26:02](26/02)). +26:4 j8k2 meaning Who was the scripture about that Jesus read? The scripture that Jesus read was about the Messiah (See: [26:04](26/04)). +26:4 j9ra meaning Why were the people amazed? Jesus said the things he had read were happening right then. He wanted to say that the Messiah was doing those things right then. This amazed the people (See: [26:04](26/04)). +26:5 dwzt meaning Who did the prophet Elijah go to help? Elijah went to help a widow from another nation (See: [26:05](26/05)). +26:6 gzjl meaning Who did the prophet Elisha heal? Elisha healed a commander of Israel’s enemies (See: [26:06](26/06)). +26:7 pbvv meaning Why did the people of Nazareth take Jesus out of the place of worship? The people wanted to throw Jesus off a cliff to kill him because he said that the prophets helped Israel’s enemies (See: [26:07](26/07)). +26:8 it5x meaning What did Jesus do when the people in Galilee brought many sick people and people with demons to him? Jesus healed them all (See: [26:08](26/08), [26:09](26/09)). +26:10 wtli meaning What did Jesus call the 12 men whom he called to travel with him and learn from him? Jesus called these 12 men his apostles (See: [26:10](26/10)). +26:10 yddv application Jesus grew up in Nazareth. Did that influence how the people responded to him when he claimed to be the Messiah? Because the people of Nazareth knew Jesus when he was a little boy, they continued to think of him as an unimportant person. Therefore, it was hard for them to believe that he was the Messiah. For this reason, Jesus said that people do not accept a prophet in the town where he grew up. Have you seen this happen? +26:10 wscu application Jesus did not directly tell the people of Nazareth that he was the Messiah. Instead, he read the scripture and said it was happening right then. Why do you think Jesus revealed himself in this way? Jesus knew that the people of Nazareth did not want to accept that he was the Messiah. Therefore, instead of stating that as a fact, he read the scripture and said that it was talking about him. If the people of Nazareth wanted to know who he was, they could see that he was doing all the things that the scripture said the Messiah would do. If they were willing to believe in him, they could figure out for themselves from the scripture that he was the Messiah. +26:10 sst1 application Why were the Jews so angry when Jesus told them what Elijah and Elisha did? The Jews believed that God loved only Jews, and would not help people from other nations. They were wrong. Jesus spoke about Elijah and Elisha to show that God also loved people of other nations. God send the prophets to help the people who would believe in him. But he did not send them to help the Jews when the Jews did not serve him. +26:10 tkaf application Why did Jesus choose 12 men to be his apostles? Jesus knew that he would die for our sins. After he would die, someone would have to be able to tell everyone what Jesus had done for us. Therefore, Jesus chose 12 men to prepare them to teach about him. They traveled with him and he taught them so they would be ready to be witnesses for him when he went back to heaven. +27:1 qs4m meaning Did the expert in the Jewish law really want to know how to have eternal life? No, he only wanted to show that Jesus was teaching wrongly (See: [27:01](27/01)). +27:1 kfy1 meaning Where did Jesus tell the man to find the answer to his question? Jesus asked the man to see what was written in God’s law (See: [27:01](27/01)). +27:2 blgs meaning What did Jesus say would happen to the man if he did what God’s law told him to do? Jesus said the man would have eternal life if he did what God’s law told him to do (See: [27:02](27/02)). +27:3 jmsb meaning Why did the man ask Jesus who his neighbor was? The man wanted to show people that he was living correctly (See: [27:03](27/03)). +27:4 sbr4 meaning Why did Jesus tell a story to the man? Jesus told the man a story in order to answer his question about who was his neighbor (See: [27:04](27/04)). +27:6 ogi3 meaning What did the priest and the Levite do when they saw the injured man? The priest and the Levite both ignored the injured man and did not help him (See: [27:06](27/06), [27:07](27/07)). +27:8 rwmh meaning Why was it surprising that the Samaritan helped the injured Jewish man? The Samaritans and the Jews hated each other (See: [27:08](27/08)). +27:11 fqsr meaning Which of the men was merciful to the injured man? The Samaritan was the only one who was merciful to the injured man (See: [27:11](27/11)). +27:11 m2u9 meaning What did Jesus tell the expert in the Jewish law to do? Jesus told the expert in the Jewish law to be merciful to people in need, just as the Samaritan in the story did to the injured Jewish man (See: [27:11](27/11)). +27:11 ryj6 application Why was it surprising that Jesus asked the expert in the Jewish law about what was written in God’s law? The man knew far more about the Jewish law than any other person in Israel. He continually studied it and taught it to others. However, he did not really understand what the law meant. Therefore, Jesus started questioning him about the law so that he could show the man that he did not really know what God’s law taught. +27:11 o71u application Why do you think the man asked Jesus who his neighbor was? The man knew God’s law said to love his neighbor as himself. But he also knew that he did not love other people as he should. Therefore, he asked about his neighbor because he was hoping that he only needed to love a few specific people in order to obey the law. +27:11 obx3 application Why might Jesus have chosen to talk to this man about a priest and a Levite? The Jews considered the priests and Levites to be the most spiritual people in Israel. They also considered the experts in the law to be very much like the priests and the Levites. Because the experts studied and taught God’s law, people assumed they knew more about God than other people did. +27:11 fjdh application Why might the expert in the Jewish law have been offended when Jesus compared the actions of the priest and the Levite to the actions of the Samaritan? The expert in the Jewish law considered the priests and the Levites to be good people, but he hated the Samaritan. He thought all Samaritans were sinners. However, in the story that Jesus told him, the Samaritan was the only person who acted kindly to the injured Jewish man. +27:11 vmjd application How much did the Samaritan show mercy to the injured man? The Samaritan did not merely help the injured man a little bit. Instead, he did more for the injured man than anyone would expect him to do. He bandaged him, took him to the inn, and paid all of the expenses for the man. +27:11 e233 application What does the story tell us about loving our neighbor? The Samaritan saw another person who had a serious need. Although the man was a stranger from a people that the Samaritans hated, he felt compassion for him. He took care of the man, doing more than was necessary or expected to help him. He treated the injured man as he would like to be treated himself if he was in need. This is what it means to be a neighbor to someone. +28:1 adzp meaning What did the rich young ruler want Jesus to tell him? The rich young ruler wanted Jesus to tell him how he could have eternal life. He wanted to live forever with God (See: [28:01](28/01)). +28:1 oa6f meaning How did Jesus respond when the man called him **good**? Jesus asked the young man what he meant to say when he called Jesus **good**. Jesus did not wait for the man to answer. He reminded the man that only God is truly good. Perhaps Jesus was asking the man if he believed that Jesus was God (See: [28:01](28/01)). +28:1 m7lo meaning What did Jesus tell the young man he should do in order to have eternal life? Jesus told him to obey God’s laws in order to have eternal life (See: [28:01](28/01)). +28:3 xd98 meaning How well did the young man think he had obeyed the law? The young man thought he had always fully obeyed God’s law. Of course, no one can do that. But he honestly believed that he had done everything that God asked him to do (See: [28:03](28/03)). +28:4 hje9 meaning What did Jesus tell the young man to give up? Jesus told the young man to give up all of his possessions (See: [28:04](28/04)). +28:4 qcf9 meaning What did Jesus tell the young man to do after he gave up his possessions? Jesus told the young man to follow him as his disciple (See: [28:04](28/04)). +28:5 va9d meaning Why did the young man go away sad? The young man went away sad because he had many possessions, and he did not want to give them up (See: [28:05](28/05)). +28:6 t0es meaning According to Jesus, how do riches affect whether a person enters heaven? Jesus said that it was almost impossible for a rich man to enter into the kingdom of heaven (See: [28:06](28/06)). +28:10 pift meaning If disciples give up things for Jesus’ sake, how much more will they receive from him? Disciples who give up things for Jesus will receive 100 times as much from him as a reward (See: [28:10](28/10)). +28:10 epnc application Why did the young man ask which laws he must obey? The young man did not understand that people must obey all of God’s laws. God considers that we sin if we fail to obey even one of his laws. The young man wrongly thought that God would accept him if he faithfully obeyed some of God’s most important laws. +28:10 y703 application Why did Jesus talk to the young man about being perfect? The young man wrongly thought he could be ‘good enough’ to have eternal life. Jesus wanted him to know that he had to be perfect—that is, without any sin—in order to have eternal life. He could not keep God’s law perfectly. The only way for him to be perfect was to follow Jesus and trust that Jesus would save him from his sin. +28:10 bpag application If the young man wanted to have eternal life, why was he not willing to give up his possessions? Jesus promised that the young man would have treasure in heaven if he followed Jesus. However, the young man could not yet see and touch that treasure. He had to believe that Jesus would reward him. However, he could easily see and touch the possessions that he already had in this world. Therefore, it was hard for him to give up his current treasure to gain something that he could not yet see. +28:10 xni8 application Why were the disciples so shocked to hear that it was almost impossible for a rich man to enter the kingdom of heaven? The people of that day believed that if God loved someone, he made them wealthy. The more possessions a person had, the more people thought God loved them. The disciples were shocked to hear that God does not necessarily accept a person who is rich. +28:10 ehqb application When will Jesus reward his disciples for giving up things for his sake? Jesus does not say when he will reward his disciples. He may give them some things in this life, but most of their reward will be in heaven. Jesus clearly told his disciples that he would give them 100 times as much as they give up for him in this life. Other people may think they are poor in this life, but Jesus will richly reward them in his kingdom. +29:1 rjkk meaning What did Jesus mean when he told Peter to forgive his brother 70 times seven? When Jesus told Peter to forgive his brother 70 times seven, he wanted to say that Peter should forgive his brother as many times as necessary without stopping (See: [29:01](29/01)). +29:3 rp6j meaning How would the king get his money back by selling the servant and his family as slaves? The king would take the money that he would receive from selling the man and his family as slaves. This money would be a partial payment toward what the servant owed the king (See: [29:03](29/03)). +29:2 e2a5 meaning Would the servant ever be able to repay the money he owed to the king? Since the servant owed 200,000 years’ wages, he would not be able to repay the king in his lifetime (See: [29:02](29/02), [29:04](29/04)). +29:5 j5p7 meaning Would the servant who owed four months’ wages be able to repay the other servant? The servant who owed four months’ wages might have been able to repay the other servant if he had time to earn the money (See: [29:05](29/05), [29:06](29/06)). +29:7 rz1w meaning Why were the other servants disturbed by what happened? The other servants thought the servant whom the king forgave had treated the other servant unfairly. He should have forgiven the other servant (See: [29:07](29/07)). +29:8 rjyg meaning Why was the king so angry? The king was angry because he had forgiven the debt of the servant, but now he saw that the servant was a wicked man. He was not willing to forgive other people as the king had forgiven him (See: [29:08](29/08)). +29:8 ykn2 meaning For how long did the king put the wicked servant into prison? The king put the servant into the prison until he could repay his debt. However, his debt was so large that he would never be able to repay it. Therefore, he would be in prison for the rest of his life (See: [29:08](29/08)). +29:9 tugk meaning Why did Jesus tell this story? Jesus wanted his disciples to know that God had forgiven them, and that he expected them to forgive each other in the same way (See: [29:09](29/09)). +29:9 nlj9 application Why do you think Peter offered to forgive his brother seven times? Peter apparently thought that he was being merciful if he forgave his brother seven times. That seemed like a lot to Peter. However, Jesus answered that seven times was not enough. Disciples of Jesus should forgive 70 times more than that. That is, they should forgive their brothers without limit. +29:9 k9a8 application How did the debts of the two servants compare to each other? The debt of the first servant was so large that it would be impossible to repay. The debt of the second servant was significant, but not impossible to pay. +29:9 jrqw application Who do you think the king and the servants represent in this story? In this story, the king represents God. The servants represent the disciples of Jesus. Every disciple owed God a payment for his sin that was impossible to pay, just as the servant owed the king a huge debt. However, God forgave their sin because Jesus died in their places. Therefore, God expects his disciples to forgive each other. +29:9 q8fk application How will God respond to disciples who do not forgive other disciples? God will be very angry with disciples who are not willing to forgive other disciples. He will judge them severely. +30:1 p07m meaning Why did Jesus invite his disciples to go to a quiet place to rest? His disciples had been preaching and teaching about Jesus in many different villages, and they were tired (See: [30:01](30/01)). +30:2 sngd meaning What did the people do in order to see Jesus? The people ran along the shore of the lake in order to get to the other side to be there when the boat carrying Jesus and his disciples would arrive there (See: [30:02](30/02)). +30:3 zavy meaning How many people were in the crowd that waited for Jesus? There were over 5,000 men in the crowd, but there were also many woman and children. We do not know the total number of people who were there (See: [30:03](30/03)). +30:3 mx83 meaning How did Jesus respond to the crowds that waited for him? Jesus had compassion on the people, because they were like sheep without a shepherd (See: [30:03](30/03)). +30:5 vo1n meaning How much food did the disciples have with them? The disciples only had five loaves of bread and two small fish (See: [30:05](30/05)). +30:7 iteg meaning What did Jesus do with the loaves and the fish? Jesus thanked God for the loaves and fish, broke them into pieces, and gave them to his disciples to give to the people (See: [30:07](30/07), [30:08](30/08)). +30:8 boco meaning What happened when the crowd ate the five loaves of bread and the two small fish? The bread and the fish never ran out. The crowd ate as much as they wanted and they were satisfied (See: [30:08](30/08)). +30:9 s7sc meaning How much food was left over after the crowd ate what they wanted? The disciples picked up 12 baskets full of food that was left over (See: [30:09](30/09)). +30:9 q2p1 application Should disciples rest even when there is a lot of work to do? Rest is a good thing. When God created the earth, he commanded people to rest on the seventh day of the week. When the disciples finished preaching and teaching, Jesus took them away to rest. People need to rest occasionally in order to do their work well. +30:9 e185 application How did Jesus respond to the crowd when they interrupted him and the disciples as they were going to a place to rest? Even though Jesus wanted the disciples to rest, he was not angry with the crowds that followed them. Instead, he felt compassion on the people. Even though he and his disciples needed to rest, they taught and healed the people in the crowd. +30:9 r5q8 application Why did Jesus tell the disciples to give the crowd something to eat? Jesus knew that they did not have enough food to feed the crowd. He told the disciples to feed them so that the disciples would understand that it was impossible to do that. Then, when Jesus caused the bread and the fish to increase and feed them all, the disciples would understand that he had done what was impossible. They would know that God had worked through him in a mighty way. +30:9 blf5 application Who caused the food to increase? Jesus was the one who caused the food to increase and satisfy all the people. The disciples passed out the food to the people, but Jesus was the one who continually gave them the food. When everyone had finished eating, the disciples knew that Jesus was the one who had done this miracle. +30:9 e4s0 application Why do you think the disciples collected the leftover food? Jesus wanted the disciples to see how much he had multiplied the food. The leftover food was more than the five loaves of bread and two fish that they had at the beginning. Those would fit into a single basket. But now there were 12 full baskets. Each of the 12 disciples had a full basket of leftover food. +31:1 u6t4 meaning What did Jesus do after he sent his disciples across the lake in a boat? Jesus sent away the crowd and then went up on a mountainside to pray alone (See: [31:01](31/01)). +31:2 q30w meaning What difficulty did the disciples have on the lake? The wind was blowing hard, so the disciples were having difficulty crossing the lake in the boat (See: [31:02](31/02)). +31:3 ada5 meaning How did Jesus come to the disciples? Jesus walked on top of the water to the boat in the middle of the lake (See: [31:03](31/03)). +31:4 kirv meaning Why were the disciples afraid of Jesus when he came to them? The disciples were afraid when they saw Jesus walking on top of the water because they thought Jesus was a ghost (See: [31:04](31/04)). +31:5 kcaz meaning What did Peter ask Jesus to do in order to prove that Jesus was not a ghost? Peter asked Jesus to command him to walk to Jesus on the water (See: [31:05](31/05)). +31:6 yt4z meaning What happened when Peter stepped onto the water? Peter was also able to walk on the water for a short distance (See: [31:06](31/06)). +31:6 qsz3 meaning Why did Peter begin to sink in the water? Peter began to sink when he took his eyes away from Jesus and looked at the waves instead (See: [31:06](31/06), [31:07](31/07)). +31:7 a260 meaning What did Peter do to save himself as he was sinking in the water? Peter shouted for Jesus to save him. Jesus reached out and grabbed Peter (See: [31:07](31/07)). +31:8 o8rn meaning What happened to the storm? The storm stopped as soon as Peter and Jesus stepped into the boat (See: [31:08](31/08)). +31:8 vl4u meaning How did the disciples respond when Jesus entered the boat? The disciples were amazed. They all bowed down and worshiped Jesus as the Son of God (See: [31:08](31/08)). +31:8 af5j application Why did Jesus remain on the mountainside and pray until late at night? Jesus believed that prayer was important even for him. He often spent time talking to his Father. Even when he was very busy, he took time to pray. He became an example for all of his disciples, and for us. +31:8 u12v application Why do you think the disciples had difficulty crossing the lake? Jesus had sent them there. A disciple who follows Jesus will still experience difficult times. Jesus did not say it was easy to be his disciple. In this situation, Jesus sent the wind against the disciples so he could show them that he had authority over the storm. God often causes difficult times in our lives so that he can show us his power. +31:8 vx2m application Why do you think it was wise for Peter to try to walk on the water to Jesus? Peter often did not think carefully about things before he did them. Perhaps this occasion is an example. It may have been a foolish thing to do. But at the same time, it was also very brave. None of the other disciples tried to go to Jesus. They all remained in the boat and waited for Jesus to come to them. +31:8 afzn application Why did Jesus say that Peter had little faith? Peter began to trust Jesus. He asked to Jesus to cause him to walk on the water. That shows that Peter believed in Jesus. However, when Peter saw the wind and the waves, he began to fear that Jesus could not keep him safe on the water. His faith began to waver. At that point, he began to sink. His faith was not strong enough to trust Jesus for very long. +31:8 axs9 application Why did the disciples worship Jesus? The disciples saw that he had walked across the water of the lake during the storm, and that he had calmed the wind. Many of the disciples were fishermen. They knew that no mere man could walk on the water. They understood clearly that Jesus was doing things that only God could do. Therefore, they bowed down and worshiped him. +32:3 xzwy meaning How did the demon affect the man he possessed? The demon made the man so strong that no one could control him. But it also made him scream all day and night, go around without clothes, and cut himself with stones (See: [32:03](32/03), [32:04](32/04)). +32:6 inzn meaning What was the name of the demon in the man? The name of the demon was Legion because he was actually a group of many demons (See: [32:06](32/06)). +32:7 s9rp meaning The demons asked Jesus for permission to do what? The demons asked Jesus for permission to go into the pigs instead of leaving the region (See: [32:07](32/07)). +32:8 wvih meaning What happened when the demons entered into the pigs? All 2,000 pigs ran into the lake and drowned (See: [32:08](32/08)). +32:10 bich meaning What did the people of the region ask Jesus to do when they saw the man who was healed and heard that the pigs were dead? Because the people of the region were afraid of Jesus, they asked him to leave them (See: [32:10](32/10)). +32:13 lj9h meaning What problem did the woman in the crowd have? The woman had been bleeding for 12 years. She spent all of her money on doctors and none of them could heal her. Instead, she got worse (See: [32:13](32/13)). +32:14 cyez meaning What did the woman think would heal her? The woman thought she would be healed if she could only touch Jesus’ clothes (See: [32:14](32/14)). +32:14 pj8w meaning What happened when the woman touched Jesus? The woman immediately stopped bleeding when she touched Jesus. But Jesus knew that power had gone out from him, and asked who had touched him (See: [32:14](32/14), [32:15](32/15)). +32:16 x7lp meaning What did Jesus say was the reason the woman was healed? Jesus told the woman that her faith had healed her. She was well because she believed that Jesus could heal her (See: [32:16](32/16)). +32:16 xaak application How did the demons treat the man they possessed? The demons caused the man they possessed to suffer and to bring shame upon himself. They caused him to harm even his own body. He would scream in pain all day and all night. Demons want to destroy the people whom God created. +32:16 dcbt application This story show that Jesus had which power over the demons? Jesus had the power to command the demons to come out of the man. He also had the power to decide where they could go after they left him. Jesus could send them into eternal punishment. The demons were afraid Jesus would do that. That is why they asked to go into the pigs instead. +32:16 pgr2 application Why did the people ask Jesus to leave their region? The people were very concerned about the money they lost when their pigs drowned, but they did not care that the man was released from the demons. They asked Jesus to leave because they valued their possessions more than they valued other people. +32:16 dw7n application Why did Jesus tell the man who was freed from the demons to go to his home? The man wanted to follow Jesus as his disciple. But Jesus told the man to stay and to be his disciple among his own people. The people sent Jesus away. So Jesus told the man to stay at his home so that he could tell the people there about Jesus after Jesus went away. +32:16 lf77 application Why did Jesus ask the woman to tell what had happened to her? Jesus healed the woman because she believed in him. But Jesus also wanted other people to believe in him. For that reason, he did not allow the woman to be healed in secret. Instead, he caused her to tell everyone how he had healed her. In this way, she acted as his disciple. +33:1 u9d0 meaning Why did Jesus get into a boat to teach the people? The people were crowding too tightly around him. So Jesus got into the boat so that he would have room to speak to all the people (See: [33:01](33/01)). +33:2 kbl4 meaning What happened to the seed that fell on the path? The birds ate the seed that fell on the path (See: [33:02](33/02)). +33:3 fhhd meaning What happened to the seed that fell on rocky ground? The seed that fell on rocky ground did not have enough soil for its roots, so it withered and died (See: [33:03](33/03)). +33:4 n8fc meaning What happened to the seed that fell among the thorns? The thorns choked out the seed that fell among them so that it did not produce any grain (See: [33:04](33/04)). +33:5 oiec meaning What happened to the seed that fell on the good soil? The seed that fell on the good soil produced 30, 60 or even 100 times as much grain as the seed that was planted (See: [33:05](33/05)). +33:6 f4sy meaning What does the seed in the story represent? The seed in the story represents the word of God that goes out to different people (See: [33:06](33/06)). +33:6 pgtl meaning What does the seed on the path represent? The seed on the path represents people who do not understand the word of God. Then the devil takes it away from them (See: [33:06](33/06)). +33:7 r2xl meaning What does the seed on the rocky ground represent? The seed on the rocky ground represents people who hear the word of God, but then hardship causes them to stop trusting in God (See: [33:07](33/07)). +33:7 nz1b meaning What does the seed on the thorny ground represent? The seed on the thorny ground represents people who allow money and other things to distract them from their love for God (See: [33:07](33/07)). +33:9 aysc meaning What does the seed in the good soil represent? The seed in the good soil is the person who hears and believes the word of God (See: [33:09](33/09)). +33:9 fweh application Why do you think Jesus told this story to the large crowd? There would be many kinds of people in the large crowd. They would respond to the words of Jesus in different ways. This story described how they would respond. They would all hear the words of Jesus, but only a few would believe his words and do what God wanted them to do. The other people would fail to love God for different reasons. +33:9 w2k4 application How can hardship and suffering cause a person to stop trusting in God? Many people wrongly think that God will only allow good things to happen to them. Therefore, when they suffer, they think that God has deceived them or that he does not care about them. They stop trusting in him and following him. But God promised that people would treat his disciples badly. +33:9 bxhv application How do worries about money and other things cause people to stop loving God? Jesus said that people cannot love both God and money. They must choose to serve either God or possessions. Many people try do both, but they cannot. If they do not stop loving their possessions, they stop loving God. God is not pleased with these people. +33:9 ovtk application How does a person produce 30, 60 or 100 times as much fruit? A single person can cause many other people to hear about Jesus and to love God. This may not happen all at once. But if they obey God throughout their lives and tell others about him, many people will respond to their testimony. The people may be their family, their friends, or even total strangers. +34:1 yx94 meaning What was Jesus talking about when he told his stories? He was talking about the kingdom of God (See: [34:01](34/01)). +34:1 rtat meaning How did Jesus discribe the mustard seed? The mustard seed was the smallest of all the seeds that people planted at that time (See: [34:01](34/01)). +34:2 mjs6 meaning What happens to the mustard seed when it grows? The mustard seed becomes bigger than other garden plants, so that even birds nest in its branches (See: [34:02](34/02)). +34:3 d5of meaning What happens to the yeast that a woman mixes into bread dough? It spreads throughout the dough (See: [34:03](34/03)). +34:4 ciu2 meaning What did the man do when he found the treasure in a field? He was filled with joy, and went and sold everything he had so he could buy that field (See: [34:04](34/04)). +34:5 i07o meaning What did the merchant do when he found a perfect pearl? He sold all that he had so he could buy that pearl (See: [34:05](34/05)). +34:7 kb1p meaning How did the religious leader pray? He thanked God that he was not a sinner like other men (See: [34:07](34/07)). +34:9 q8re meaning How did the tax collector pray? He asked God to be merciful to him because he was a sinner (See: [34:09](34/09)). +34:10 ekca meaning Which man did God declare to be righteous? Jesus said that God declared the tax collector to be righteous (See: [34:10](34/10)). +34:10 la35 application In what way is the kingdom of God like a mustard seed? The kingdom of God will be small when it begins, but it will grow to become larger than all other kingdoms of the world. +34:10 i7zt application In what way is the kingdom of God like yeast? The kingdom of God will spread throughout the world. +34:10 k5rq application In what way is the kingdom of God like a treasure hidden in a field? The kingdom of God is so valuable that a person should be willing to sell everything they own in order to obtain it, and then rejoice. +34:10 c9sy application What wrong understanding did some people have about who God would accept? Some people thought God would accept them because they did good things. Jesus told the story of the two men in order to correct their wrong understanding. +34:10 a0om application Why might the people who heard the story of the two men be surprised about who God accepted? The people of that time thought tax collectors were evil and religious rulers were good. They did not understand that everyone is a sinner, and that God only accepts the people who humble themselves and confess that they are sinners. +35:2 zre8 meaning Why did the religious leaders criticize Jesus? The religious leaders criticized Jesus because he treated the tax collectors and sinners as friends (See: [35:02](35/02)). +35:5 dkc4 meaning Why did the man’s younger son decide to return to his father? The younger son had no money, and was so hungry that he wanted to eat the food he gave to the pigs. He realized that the servants of his father lived better than that (See: [35:05](35/05), [35:06](35/06)). +35:6 d4bq meaning What did the man’s younger son want his father to do for him when he returned home? The man’s younger son wanted his father to treat him as a servant, and not as a son (See: [35:06](35/06), [35:08](35/08)). +35:7 qdjd meaning What did the father do when he saw his younger son? The father was so happy that he ran to his younger son and hugged and kissed him (See: [35:07](35/07)). +35:8 nvgs meaning What did the man’s younger son tell his father after his father greeted him? The man’s younger son told his father that he had sinned against his father and against God, and that he was not worthy to be his father’s son (See: [35:08](35/08)). +35:11 zts4 meaning Why did the father need to go out to his older son? The father went out to his older son because the older son would not come into the house where they were celebrating that his younger brother had returned (See: [35:11](35/11)). +35:12 eikh meaning Why was the man’s older son angry with his father? The man’s older son was angry with his father because he thought his father treated his younger son better than he treated his older son. The man’s older son thought his father should treat him better because he stayed home and worked while his younger brother went away and wasted his money (See: [35:12](35/12)). +35:13 ac9d meaning Why should the father and his older son celebrate? The father told his older son that they should celebrate because his younger brother had returned to them alive. This was a time to rejoice, rather than a time to be angry about the past (See: [35:13](35/13)). +35:3 quwr application Why did the man’s younger son demand that his father give him his inheritance while his father was still alive? Perhaps the man’s younger son only wanted his father’s possessions, and was not interested in honoring his father (See: [35:03](35/03)). +35:3 w4w6 application Why do you think the father agreed to give his inheritance to his sons while he was still alive? It seems that the father loved his sons more than he loved his possessions (See: [35:03](35/03)). +35:3 y4tw application How is the younger son an example of people who run away from God and live according to their desires? Many people are like the younger son. They want to live according to their own desires rather than to be friends with God the Father. +35:3 mymh application Do you think the father should have treated his younger son well when he returned? Many people would think the father should have rejected his younger son since that son abandoned him. However, the father in the story was merciful, just as God the Father is merciful. He continued to love his son and accepted him with joy when he returned. +35:3 omy9 application How should people who have sinned, but who now want to come to God, expect God to treat them? Jesus told this story to people who had sinned, but who were then coming to God. He wanted them to know that God will accept them when they come to him. +35:3 gkcx application Why do you think some believers want to make it difficult for people who have sinned to come to God? Some believers do not think it is fair that God accepts people who have sinned without punishing them. In this story, Jesus showed that God will not punish people who have sinned when they come to him and ask him to forgive them. +36:1 g3t5 meaning Who did Jesus take with him when he went up the mountain to pray? He took Peter, James, and John (See: [36:01](36/01)). +36:2 jt44 meaning In what way did Jesus’ face change as he was praying? His face became as bright as the sun (See: [36:02](36/02)). +36:2 zjr1 meaning In what way did Jesus’ clothes change as he was praying? His clothes became as white as light, whiter than anyone on earth could make them (See: [36:02](36/02)). +36:3 ufvi meaning Who appeared with Jesus on the mountain? Moses and the prophet Elijah appeared with him (See: [36:03](36/03)). +36:3 wa4t meaning What were Jesus, Moses, and Elijah talking about? They were talking about Jesus’ death, which would soon happen in Jerusalem (See: [36:03](36/03)). +36:4 boj4 meaning What did Peter offer to do for Jesus, Moses, and Elijah? Peter offered to build three shelters for them (See: [36:04](36/04)). +36:5 mr0l meaning Who answered Peter? God the Father answered as a voice from heaven (See: [36:05](36/05)). +36:5 ywk1 meaning What did God the Father tell Peter do to? God said that Peter should listen to Jesus, because he was God’s Son whom he loved, and God was pleased with him (See: [36:05](36/05)). +36:5 k6sc meaning What did the disciples do when they heard God’s voice? The disciples fell down on the ground in fear (See: [36:05](36/05)). +36:6 tkzj meaning What did the disciples see when Jesus told them to get up? They no longer saw anyone there except Jesus (See: [36:06](36/06)). +36:7 vhci meaning When would Jesus allow the disciples to tell people what had happened on the mountain? Jesus told the disciples that after he would die and come back to life, they could then tell people what had happened on the mountain (See: [36:07](36/07)). +36:7 ixzy application Why do you think Jesus took only Peter, James, and John with him up the mountain, and not the other disciples? Jesus allowed Peter, James, and John to see and hear more things than the other disciples. This may have been because they would become the highest leaders of the early church. +36:7 qipl application Why do you think the appearance of Jesus changed? While Jesus was on earth, he appeared as a normal person. However, he was also God. On the mountain, he allowed the disciples to see a glimpse of his divine nature. Both his face and his clothes changed to the form they have in heaven. +36:7 rqqg application Why is it significant that Moses and Elijah were the two men who were talking with Jesus? Moses represents all the law of God, and Elijah represents all the Old Testament prophets who prophesied that the Messiah would come and die in order to save people. When they appeared with Jesus, that showed that Jesus was the Messiah. +36:7 x5eh application Why was it not proper for Peter to make shelters for Jesus, Moses, and Elijah? Peter wanted to make three shelters in order to honor Jesus, Moses, and Elijah as equals. But they were not equal. Jesus was the Messiah and the Son of God. He was greater than Moses and Elijah. Therefore, God the Father spoke from heaven and told Peter to listen only to Jesus. +36:7 lhx8 application Why do you think Jesus did not allow the disciples to tell anyone what had happened on the mountain right away? The disciples did not yet understand what these thing meant. They would not be able to explain them properly at that time. However, after Jesus would die and come back to life again, they would understand these things, and could explain to other people what these things meant. +37:1 f08p meaning What did Jesus say would be the result of Lazarus being sick? He said that Lazarus’ illness would cause people to honor God (See: [37:01](37/01)). +37:2 uk2l meaning How long did Jesus wait before he went to see Lazarus? Jesus waited two days in the place where he was (See: [37:02](37/02)). +37:2 ali4 meaning What did Jesus mean when he said that Lazarus was sleeping? When Jesus said Lazarus was sleeping, he was using a polite way to say that Lazarus was dead (See: [37:02](37/02), [37:03](37/03)). +37:4 p7se meaning How long had Lazarus been dead when Jesus finally arrived at his home? Lazarus had already been dead for four days by that time (See: [37:04](37/04)). +37:5 effk meaning What title did Jesus give to himself when he spoke to Martha? Jesus said that he was the Resurrection and the Life (See: [37:05](37/05)). +37:5 v5yc meaning Who did Martha say that Jesus was? She said he was the Messiah, the Son of God (See: [37:05](37/05)). +37:7 oi6u meaning Why was Martha afraid to open the tomb? She was afraid that the body of Lazarus would smell bad because he had been dead for four days (See: [37:07](37/07)). +37:8 oyld meaning What did Jesus say to his Father was the reason that he was praying to his Father? Jesus said he was praying to his Father so that the people standing around would believe that God had sent Jesus into the world (See: [37:08](37/08)). +37:10 dh21 meaning What did Lazarus do when Jesus told him to come out of the tomb? Lazarus became alive again and came out of the tomb, still wrapped in the grave clothes (See: [37:10](37/10)). +37:11 obry meaning Why did the religious leaders of the Jews plan to kill Jesus and Lazarus? They envied Jesus, because the people believed in him (See: [37:11](37/11)). +37:11 jy0c application Why do you think Jesus spoke about Lazarus’ death as if Lazarus were asleep? Lazarus had died, but he would not remain dead. Jesus knew that he would make Lazarus alive again. Jesus perhaps said Lazarus was asleep in order to show that his death was temporary. In the same way, God speaks of all believers who die as being asleep. This encourages followers of Jesus when a fellow believer dies. +37:11 vze3 application Why did Jesus wait for two days before he went to Lazarus? Jesus did not want his friend Lazarus to suffer, or his sisters to grieve. But the most important thing to Jesus was to honor God. Therefore, Jesus allowed Lazarus, Martha, and Mary to suffer so that God would be honored when Jesus made Lazarus alive again. For followers of Jesus, suffering is temporary, and can bring glory to God. +37:11 ffwv application Why were the disciples surprised that Jesus wanted to go to Lazarus in Judea? The Jewish leaders in Judea wanted to kill Jesus. However, Jesus was not afraid to die. In fact, he came to earth in order to die for sinners. Therefore, he was willing to go to Judea even though he knew they wanted to kill him there. +37:11 tmju application In what way was the faith of Martha and Mary limited? Martha and Mary both believed that Jesus was able to prevent Lazarus from dying. However, neither of them understood that Jesus could raise Lazarus to life even after he had died. +37:11 s81h application Why do you think the religious leaders did not believe in Jesus even after he raised Lazarus from the dead? The religious leaders hated Jesus because people listened to Jesus instead of to them. They wanted power over people so badly that they would not even believe in him when he performed a miracle that only God can do. Their sin kept them from seeing that Jesus was God. +38:1 ws1e meaning What does the Passover celebrate? It celebrates how God saved the Jews from slavery in Egypt (See: [38:01](38/01)). +38:1 vz53 meaning What did Jesus tell the disciples would happen to him in Jerusalem after the Passover? He told them that he would be killed there (See: [38:01](38/01)). +38:2 ndxd meaning What did Judas offer to do for the Jewish leaders in exchange for money? He offered to betray Jesus to them so they could kill Jesus (See: [38:02](38/02)). +38:4 uxxe meaning What did Jesus say the bread he broke represented? Jesus said the bread was his body, which he would give for the disciples (See: [38:04](38/04)). +38:5 git2 meaning What did Jesus say the cup of wine he drank represented? Jesus said the cup of wine was the New Covenant in his blood, which he would pour out for the disciples (See: [38:05](38/05)). +38:8 wuyw meaning As Jesus and the disciples walked to the Mount of Olives, what did Jesus say the disciples would all do that night? Jesus said the disciples would all abandon him, like sheep scattering when their shepherd is struck (See: [38:08](38/08)). +38:9 gcut meaning What did Jesus say that Peter would do before the rooster crowed that night? He said Peter would deny three times that he even knew Jesus (See: [38:09](38/09)). +38:12 vztd meaning What did Jesus ask his Father to do when he prayed in the garden? Jesus asked his Father not to make him drink the cup of suffering. But he also asked his Father to do his will even if there was no other way except for Jesus to die (See: [38:12](38/12)). +38:13 h0pz meaning What did the disciples do instead of watching with Jesus? They fell asleep, because they were very tired (See: [38:13](38/13)). +38:14 g465 meaning How did Judas betray Jesus to the crowd? He pretended to honor Jesus by greeting him with a kiss (See: [38:14](38/14)). +38:15 r2hg meaning What did Jesus do for the servant of the high priest? Jesus healed the servant after Peter cut off his ear with a sword (See: [38:15](38/15)). +38:15 qmv7 application Why did the disciples not suspect that Judas would betray Jesus? Judas appeared to be just like the other disciples. In fact, they trusted him so much that they put him in charge of their shared money bag. Judas fooled all of the disciples. Jesus alone knew that he would betray Jesus. +38:15 klwg application What new meaning did Jesus reveal about the Passover meal? Jesus said the bread and the cup of wine at the Passover meal would remind the disciples that Jesus gave his body and shed his blood in order to save them. +38:15 kn5o application Why do you think the disciples did not believe that they would abandon Jesus? The disciples thought they were brave enough to stand with Jesus. They were offended when he warned them that they would flee. Therefore, they fell asleep instead of watching and praying as Jesus had asked them. As a result, they were not able to stand with him when Judas and the crowd came for Jesus. +38:15 cucp application What does Jesus prayer to his Father in the garden teach us about doing God’s will? Jesus did not want to suffer and die, and asked his Father to spare him. However, Jesus was also willing to suffer in order to do his Father’s will. He knew that there was no other way for sinners to be saved if he did not die for them. Therefore, he was willing to be arrested and killed. +38:15 athx application Why did the Jewish leaders need Judas to betray Jesus? Jesus taught publicly every day, but the Jewish leaders were afraid to arrest him in front of the crowds who came to listen to him. They needed Judas to tell them when Jesus would be in a secluded place so they could arrest him in secret. +38:15 kdmi application Why do you think Peter struck the servant of the high priest with his sword? Peter did not understand that Jesus must die for sinners. He had not listened each time Jesus told him this would happen. Therefore, he wrongly tried to save Jesus by force. But Jesus rebuked Peter and even healed the servant that Peter struck. He did not want his servants to prevent his arrest. +39:1 j4c3 meaning Where did the soldiers first take Jesus after they arrested him? They took him to the house of the high priest (See: [39:01](39/01)). +39:2 mffj meaning What did the Jewish leaders do to try and prove that Jesus was guilty? They brought many false witnesses who lied about Jesus. However, the witnesses did not agree with each other, so they could not prove that Jesus was guilty of anything (See: [39:02](39/02)). +39:3 q27l meaning What question did the high priest ask Jesus, and how did Jesus answer? The high priest asked if Jesus was the Messiah, and the Son of the living God. Jesus told the high priest that this was who he was (See: [39:03](39/03), [39:04](39/04)). +39:5 g2ik meaning How did the Jewish leaders react when Jesus said he was the Messiah and the Son of God? They all became angry and shouted that Jesus deserved to die. They blindfolded him, spit on him, hit him, and mocked him (See: [39:05](39/05)). +39:7 jepb meaning What did Peter say when people outside the high priest’s house said he had been with Jesus? Peter swore and said he did not know Jesus (See: [39:07](39/07)). +39:8 m8et meaning What did Judas do to himself after Jesus was arrested? Judas went away and killed himself (See: [39:08](39/08)). +39:9 nmxo meaning What question did Pilate ask Jesus? Pilate asked Jesus if he was the king of the Jews (See: [39:09](39/09)). +39:10 r92z meaning Why did Jesus say his servants would not fight to defend him? Jesus’ kingdom was not on earth, so his servants did not fight on earth to save him (See: [39:10](39/10)). +39:11 z49r meaning What did Pilate decide about whether Jesus was guilty? Pilate decided that Jesus was not guilty of anything, and told this to the crowd three times (See: [39:11](39/11)). +39:12 relk meaning Why did Pilate tell his soldiers to crucify Jesus? Pilate was afraid the crowd would riot, so he ordered his soldiers to crucify Jesus in order to satisfy the crowd. Therefore, they whipped Jesus and prepared to kill him (See: [39:12](39/12)). +39:12 kljc application What was the only charge the high priest was able to bring against Jesus? Jesus had not done anything wrong, so the high priest could not find true witnesses against him. Finally, he accused Jesus of pretending to be the Messiah and the Son of God. Jesus really was God’s Son, so he was not pretending. He was innocent, but the high priest would not believe him. Therefore, the whole group of religious leaders condemned Jesus. +39:12 lidb application How is it encouraging to followers of Jesus that Peter denied Jesus? Peter was one of Jesus’ closest disciples. He truly believed in Jesus, and became a leader in the church. However, even Peter denied Jesus when the people accused him. No believer is perfect. Jesus does not expect us to always do the right thing. Just as Jesus loved Peter in spite of his failure, followers of Jesus know he will forgive them when they repent of their sin. +39:12 q1o2 application Why do you think God allowed Jesus to be falsely accused and condemned? God knows that our fallen nature causes us to sin. His Holy Spirit enables people to do his will. By dying, Jesus took the place of sinners, accepting God's judgment of sin on himself, even though he was without sin. Paying the penalty for our sin, he made it possible for God to forgive sinners. So God allowed the Jewish leaders and the Romans to convict Jesus even though they knew he was innocent. Evil actions do not stop God’s plan or his will from happening. +40:2 h6mb meaning What did the soldiers force Jesus to carry? They forced him to carry the cross on which he would die (See: [40:02](40/02)). +40:2 jptp meaning What did Jesus ask his Father to do for the soldiers who crucified him? He asked his Father to forgive them, for they did not understand what they were doing (See: [40:02](40/02)). +40:2 dqe8 meaning What did the sign above Jesus’ head say? The sign said **King of the Jews** (See: [40:02](40/02)). +40:4 e4ak meaning What did Jesus promise to the robber who asked Jesus to remember him? Jesus promised him that he would be with Jesus that very day in Paradise (See: [40:04](40/04)). +40:5 zwn7 meaning What did the Jewish leaders and people in the crowd tell Jesus to do so that they might believe in him? They told Jesus to come down from the cross and to save himself (See: [40:05](40/05)). +40:6 bisq meaning What happened to the sky as Jesus was on the cross? The sky became completely dark for three hours in the middle of the day (See: [40:06](40/06)). +40:7 rscr meaning What did Jesus cry out to his Father as he died? He said that it was finished, and gave his spirit into his Father’s hands (See: [40:07](40/07)). +40:7 w6t7 meaning What happened to the curtain in the Temple when Jesus died? The curtain was torn in two from the top to the bottom (See: [40:07](40/07)). +40:8 n28y meaning What did the the Roman soldier say about Jesus when he died? The soldier said the Jesus was certainly innocent, and that he was the Son of God (See: [40:08](40/08)). +40:9 likl meaning Who buried Jesus? Two Jewish leaders named Joseph and Nicodemus buried Jesus (See: [40:09](40/09)). +40:9 jdq9 meaning How did Joseph close the tomb? He rolled a large stone in front of the tomb to block the entrance (See: [40:09](40/09)). +40:9 y7co application Why do you think Jesus said the soldiers did not know what they were doing? The soldiers were Romans who did not know very much about the Jewish religion. They probably thought Jesus was an ordinary criminal, and they treated him as one. +40:9 a2fe application They soldiers gambled for Jesus’ clothing. Why does that help us believe Jesus was the Messiah? This action was one of many things that the scriptures, written hundreds of years before, said they would do to the Messiah. All these prophesies were fulfilled in Jesus. +40:9 bthj application Jesus told the robber who repented that he would be with Jesus in Paradise that day. What does that tell us about the way to enter into heaven? The robber did not perform a single good deed. Instead, he simply confessed that he was a sinner, and asked Jesus to remember him in the kingdom. As a result, Jesus promised that he would be in Paradise (that is, heaven) that same day. The way to enter into heaven is to believe in Jesus. +40:9 n9ji application Why do you think Jesus did not come down from the cross and save himself when the people asked him to? The people who told Jesus to come down from the cross did not want to believe in him. They were only mocking him. They did not realize that he had the power to come down from the cross. But he came to earth to die for sinners. That was the will of his Father. He had to stay on the cross and give up his own life in order to make it possible for God to forgive other people who believed in Jesus. +40:9 bcq9 application What was finished when Jesus cried out? When Jesus cried out, “It is finished!” he wanted to say that he had finished paying the penalty for the sins of everyone in the world. It was now possible for God to forgive those who repented and trusted in Jesus. People no longer needed to die for their own sins. +40:9 pecl application Why was the curtain of the Temple torn from top to bottom? The curtain of the Temple prevented people from seeing or entering into the most holy place in the Temple where God was. God in heaven above tore the curtain from the top to the bottom when Jesus died. He did this to show that Jesus had opened a way for man to approach God through the sacrifice of Jesus. +40:9 pgyz application Why did the soldier say that Jesus was innocent, and the Son of God? The Roman soldier had probably executed hundreds of criminals. He recognized that Jesus did not act like a criminal. Instead, he was a good man who asked his Father to forgive the soldiers, and who spoke kindly to the robber who repented. Furthermore, the miraculous signs that happened when Jesus died convinced the soldier that Jesus was not just a man—he was the Son of God. +41:1 rfb2 meaning What were the Jewish leaders afraid the disciples would do with the body of Jesus? They were afraid the disciples would steal Jesus’ body and say he had risen from the dead (See: [41:01](41/01)). +41:2 gx10 meaning How did Pilate make sure the disciples could not steal Jesus’ body? Pilate let them placed a seal on the entrance of the tomb, and also stationed some soliders there to guard it. (See: [41:02](41/02)). +41:3 mda0 meaning When did the women come to the tomb? The women came to the tomb after the Sabbath day was over (See: [41:03](41/03)). +41:3 xtdw meaning What did the woman plan to do at the tomb? The women wanted to put more spices on Jesus’ body (See: [41:03](41/03)). +41:4 elsx meaning Who rolled the stone away from the tomb? An angel from heaven rolled the stone away from the tomb (See: [41:04](41/04)). +41:4 z6k5 meaning What did the soldiers do when they saw the angel? The soldiers were so afraid that they fell to the ground like dead men (See: [41:04](41/04)). +41:5 n4g9 meaning What did the angel tell the women had happened to Jesus? The angel told them that Jesus was not there, but that he had risen from the dead (See: [41:05](41/05)). +41:6 nbrx meaning What did the angel tell the women to say to the disciples? He told them to tell the disciples that Jesus had risen from the dead, and would go ahead of them to Galilee (See: [41:06](41/06)). +41:8 qx83 meaning What did the women do when Jesus appeared to them as they were on their way? The woman fell down and worshiped Jesus (See: [41:08](41/08)). +41:8 bp9n application Who was it that remembered Jesus’ promise to rise from the dead in three days? It is surprising that the disciples did not remember the Jesus said he would rise from the dead in three days. Instead, it was the unbelieving Jewish leaders who remembered what he said. They did not believe him, but they did remember his words. The disciples should have remembered. +41:8 ee23 application Were the soldiers able to prevent the tomb from opening? The Roman soldiers were the best soldiers of that time. However, they could not stand against the single angel that God sent to open the tomb. The strongest military force could not stop God from doing what he planned to do. When the angel appeared, they fell down like dead men. +41:8 xeex application How did the angel treat the women who came to the tomb? The angel knew that the women had come to honor Jesus by putting spices on his body. Therefore, the angel spoke kindly to them and told them not to be afraid. He showed them the empty tomb, and told them that Jesus would meet them in Galilee. +41:8 ul9s application Why do you think Jesus met the women, when he told them the same thing as the angel? Jesus did not need to appear to the women. The angel had already told them that he was alive and would meet the disciples in Galilee. But Jesus also knew that the women had come to honor him. Perhaps he appears to them for that reason, so he could honor them for coming to serve him. The women were therefore the first people to see Jesus after he became alive again. +42:1 evqi meaning What were the two disciples talking about as they went to a nearby town? They were talking about what had happened to Jesus. The women had said Jesus was alive, so they did not know what to believe (See: [42:01](42/01)). +42:2 us3a meaning Who did the disciples think Jesus was? They thought he was a foreigner who did not know what had happened in Jerusalem (See: [42:02](42/02)). +42:3 qcjs meaning What did Jesus explain to the two disciples? Jesus explained what God’s word said about the Messiah—how he would suffer and die, and then rise again on the third day (See: [42:03](42/03)). +42:4 ceym meaning When did the two disciples to recognize Jesus? They recognized him when he broke the bread with them (See: [42:04](42/04)). +42:5 wies meaning How did Jesus convince the disciples in Jerusalem that he was not a ghost? He showed them his hands and feet, and then ate a piece of fish before them (See: [42:05](42/05)). +42:8 zjel meaning What is the message that the prophets said Jesus’ disciples would proclaim? They would tell everyone to repent so God will forgive their sins. They would tell this to people everywhere, starting in Jerusalem (See: [42:08](42/08)). +42:9 y2fv meaning How many people saw Jesus at one time after he rose from the dead? More than 500 people saw him at the same time (See: [42:09](42/09)). +42:10 lhax meaning What did Jesus command his disciples to do? He told them to make disciples in all people groups, and to baptize them and to teach them to obey everything that he had commanded them (See: [42:10](42/10)). +42:11 c6pq meaning Where did Jesus go 40 days after he rose from the dead? Jesus went up to heaven and sat down at the right hand of God to rule over all things (See: [42:11](42/11)). +42:11 z0vv application Why do you think the two disciples on the road did not believe that Jesus had risen from the dead? They had thought Jesus was the Messiah, so it was very difficult and discouraging for them when he died. Perhaps they did not want to believe the report from the women so that they would not be disappointed again if Jesus was not really alive. +42:11 dnav application Why do you think the two disciples did not recognize Jesus? It seems as if Jesus prevented the two disciples from recognizing him. Perhaps he wanted them to believe the things the prophets had written about him in God’s word before he revealed himself to them. From the time Jesus went back to heaven, people have not been able to see him, and must believe in him because of what God’s word says about him. +42:11 ykyt application Why did the disciples in Jerusalem not believe Jesus was alive when he first appeared to them? Jesus had told the disciples that he would become alive again after three days. The woman had also seen him alive at the tomb and told the disciples. And the two disciples who saw Jesus on the road told them that Jesus was alive. Even so, when Jesus appeared among them in the room, they thought he was a ghost. It is amazing that they did not believe he was alive even with so much proof. They only understood clearly after Jesus explained to them the things written about him in God’s word. +42:11 iryw application What must people do in order for God to forgive them? People must repent in order for God to forgive them. That is, they must change their minds about themselves and confess that they are sinners, and change their minds about God and confess that Jesus died to pay for their sins. +42:11 r5ia application To whom are Jesus’ disciples to speak his message? We are to proclaim God’s message about Jesus to all people groups everywhere. +42:11 wxrt application How long are Jesus’ disciples to proclaim his message? We are to continue to proclaim his message until there are disciples among all people groups who obey everything that Jesus commanded us. +42:11 dcfd application How does Jesus help his disciples to proclaim his message? Jesus sent the Holy Spirit to give power to his disciples so they can proclaim his message to everyone everywhere. +42:11 ils6 application What is Jesus doing as his disciples proclaim his message? Jesus is in heaven ruling over all things at the right hand of God. This encourages his disciples, as they know that he will enable them to do what he has commanded us. He will cause disciples to believe in him in every people group. +43:1 lhel meaning Why did the believers constantly gather together in Jerusalem? They continually gathered together to pray (See: [43:01](43/01)). +43:3 h5pf meaning What happened to the believers as they were gathered together during Pentecost? As the believers were gathered together, the house was filled with the sound of a strong wind and something like flames of fire appeared over their heads. They were all filled with the Holy Spirit and began to speak in other languages (See: [43:03](43/03)). +43:4 ovbo meaning What astonished the crowd when they came to see the believers? They heard the believers speaking in the native language of each person in the crowd (See: [43:04](43/04)). +43:5 htrn meaning How did Peter reply when the crowd said the believers were drunk? Peter told the crowd that they were not drunk, but that this was the Spirit of God poured out on the believers as the prophet Joel had said long ago (See: [43:05](43/05)). +43:6 jtdw meaning According to Peter, how did God the Father honor Jesus? God the Father honored Jesus by making him sit at his right hand, and by making him both Lord over everything and the Messiah (See: [43:06](43/06), [43:07](43/07)). +43:11 nud9 meaning When the people asked Peter what they should do, how did he reply? Peter told them to repent so that God would forgive them and to be baptized in the name of Jesus Christ (See: [43:11](43/11)). +43:12 ge4s meaning How many people believed what Peter preached and became disciples of Jesus that day? About 3,000 people believed Peter and became disciples of Jesus (See: [43:12](43/12)). +43:13 pb7s meaning What did the new believers do together in Jerusalem? They continued to listen to the teaching of the apostles. They also met, ate, and prayed together. And they continually praised God together and shared everything they had with each other (See: [43:13](43/13)). +43:13 m4n8 application What was the main thing the believers continually did when they gathered together? Prayer was very important to the believers. They continually gathered together to pray to God as a group, in addition to praying individually. Perhaps that is why God did such powerful works among them. +43:13 vrnt application How did the gift of speaking in other languages help the believers proclaim the message of Jesus? The people in Jerusalem knew the believers could not speak the native languages of everyone in the crowd. When they heard and saw them do this, they knew it was a miracle. Therefore, they were ready to listen to Peter as he preached to them. They could also speak to any person from any language group about Jesus, and that person would understand completely what they said. +43:13 dhs7 application What did Peter tell the crowd about Jesus? Peter told them that they had crucified Jesus, but that God had raised him from the dead just as the prophets had said he would. Peter and the believers were eyewitnesses of this. Peter also said that God had honored Jesus by making him sit at his right hand in heaven, and that it was Jesus who was sending the Holy Spirit. +43:13 uxw6 application How did people respond to Peter’s message? God caused the people to be deeply moved so that they asked Peter what they should do. God will not always cause people to respond in this way, but on that occasion, 3,000 people believed the message and repented. +43:13 bpxp application How did the people of Jerusalem react when they saw that the believers continually met together to pray, praise God, and share with each other? When everyone in Jerusalem saw how the believers treated each other and praised God, they thought well of them, and many more people became believers. +44:1 vquv meaning Why was the crippled man sitting at the gate of the Temple? He was begging for money from the people who were coming to the Temple (See: [44:01](44/01)). +44:2 vbex meaning What did Peter give the crippled man instead of money? Peter told him to get up and walk in the name of Jesus (See: [44:02](44/02)). +44:4 ig8g meaning According to Peter, whose power healed the crippled man? Peter said the man was not healed by the power of Peter and John, but by the power of Jesus (See: [44:04](44/04)). +44:5 mex0 meaning What did Peter tell the people to do? He told them to repent and turn to God so that God would wash away their sins (See: [44:05](44/05)). +44:6 xplc meaning How many believers were there in Jerusalem after this message by Peter? The number of believers grew to about 5,000 (See: [44:06](44/06)). +44:7 wpqb meaning What did the Jewish leaders do to Peter and John after they healed the man? The leaders arrested them and brought them before the high priest and the other leaders (See: [44:07](44/07)). +44:8 gw3c meaning According to Peter, what was the only way to be saved? Peter said there is no other way to be saved except through the power of Jesus Christ (See: [44:08](44/08)). +44:9 gvin meaning Why were the leaders shocked that Peter and John spoke so boldly? Peter and John were ordinary, uneducated men. They should not have been able to speak so powerfully (See: [44:09](44/09)). +44:9 dwmc meaning What did the leaders tell Peter and John before they let them go? The leaders threatened to punish them if they continued to speak to the people about Jesus (See: [44:09](44/09)). +44:9 xrn4 application What did the crippled man have to do in order to be healed? It appears that the crippled man did not have to do anything to be healed. We do not even know if he believed in Jesus before he was healed. Instead, Peter believed that Jesus would heal the man, and God healed him. +44:9 wqsb application How did the healing of the crippled man happen? The crippled man was immediately and completely healed. One minute, he could not stand, and the next minute, he was able to walk and jump around. The change was so obvious to everyone that the people who saw it were amazed and responded to Peter’s message. +44:9 kuav application Who gave the power to heal the crippled man? Peter was very careful to tell the people that the power to heal the man did not come from Peter and John. Instead, Jesus healed the man because Peter and John believed in Jesus. Peter and John were very humble about the way God used them. +44:9 i5j9 application Why did Peter tell the crowd that they killed Jesus? People cannot be saved if they do not repent. Therefore, Peter clearly explained how they had sinned by rejecting Jesus. Although they did not personally kill Jesus, they wanted Pilate to kill him, and so they were guilty of his death. They needed to confess that sin before God would save them, so Peter was not afraid to confront them. +44:9 if0n application Is there any other way to be saved other than through Jesus? Peter very clearly told the religious leaders that there is no other way to be saved except through Jesus. The works of the leaders would not save them. No other god could save them. Jesus is the only way. +44:9 odoo application What did the leaders decide was the reason that Peter and John spoke so boldly? The leaders realized that they spoke so boldly because they had been with Jesus. It did not matter that they were not educated, and that they did not have important positions among their people. They followed Jesus and learned from him. Therefore, they were able to speak boldly and accurately for him. +45:2 mw2k meaning What lie did the unbelieving Jews tell about Stephen? They lied and said he was speaking evil things about Moses and God (See: [45:02](45/02)). +45:3 g6sj meaning What evil things did Stephen say the people of Israel had done? In the past, the people of Israel had always disobeyed God, rejected the Holy Spirit, and killed God’s prophets. But Stephen said that they had now done something even worse—they had killed the Messiah (See: [45:03](45/03)). +45:4 av6l meaning What did the religious leaders do to Stephen when they heard what he said about them? They dragged Stephen out of the city and threw stones at him to kill him (See: [45:04](45/04)). +45:5 nkhc meaning What did Stephen ask God to do for the religious leaders? Stephen asked God not to hold it against them that they were stoning him (See: [45:05](45/05)). +45:6 o6zv meaning What did the believers do when the persecution forced them to leave Jerusalem? They fled to other places and continued to preach about Jesus everywhere they went (See: [45:06](45/06)). +45:7 pj1y meaning Who did the Holy Spirit tell Philip to go and meet on the road? He told Philip to meet an important official from Ethiopia, who was riding in his chariot (See: [45:07](45/07)). +45:8 oy5u meaning What was the official reading when Philip approached him? He was reading what the prophet Isaiah wrote about a man who was silent as a lamb when he was killed (See: [45:08](45/08)). +45:10 p3ep meaning Who did Philip say Isaiah had written about? Philip said Isaiah had written about Jesus (See: [45:10](45/10)). +45:11 q2lo meaning What did the Ethiopian ask to do when they came to some water? The Ethiopian asked Philip if he could be baptized (See: [45:11](45/11)). +45:12 eim9 meaning What happened to Philip after he baptized the Ethiopian? The Holy Spirit took Philip away to another place where he continued to tell people about Jesus (See: [45:12](45/12)). +45:12 abkl application How did Stephen respond when he was arrested and brought before the high priest and other leaders? Even though people had lied about Stephen, he boldly proclaimed the message about Jesus. He was not afraid to tell the leaders that they had sinned and disobeyed God. +45:12 jhyu application What was Stephen’s attitude toward the Jews who killed him? Stephen did not condemn the people who killed him. Instead, he was gracious to them and asked God not to punish them for killing him. He loved his enemies even as he was dying. +45:12 u31f application Did the persecution of the believers stop the message about Jesus? God used the persecution of the believers to spread the message about Jesus even further than Jerusalem. Before the persecution, the believers only preached in Jerusalem. But after the persecution started, they scattered everywhere and preached the message wherever they went. +45:12 d0hq application What was Philip doing when the Holy Spirit told him to go to the wilderness to meet the Ethiopian? Philip was preaching in Samaria, and many people were believing in Jesus as a result. However, the Holy Spirit sent Philip away from Samaria to meet only the Ethiopian. It seems that it was so important that the Ethiopian believed that God took Philip away from speaking to many other people. Philip obeyed God and went. +45:12 w4i5 application When Philip approached the Ethiopian, how was it exactly the right time for the Ethiopian to hear about Jesus? The Ethiopian was reading about the Messiah in the book of the prophet Isaiah, but did not know that Isaiah was writing about Jesus. The Holy Spirit brought Philip to the Ethiopian at exactly the right time when he was willing to listen to God’s message. Because Philip came to him then, the Ethiopian quickly believed and was baptized. +45:12 tg1v application Who suggested that the Ethiopian be baptized? The Ethiopian himself knew that he should honor Jesus by being baptized in his name. Therefore, he asked Philip to baptize him. Philip did that, and the Ethiopian continued on to his home, happy to know Jesus. +46:1 bz0i meaning What did Saul do to the believers in Jerusalem? He persecuted them by going from house to house to arrest both men and women and put them in prison (See: [46:01](46/01)). +46:1 zh5g meaning Why did Saul go to the city of Damascus? The high priest gave Saul permission to go to Damascus to arrest the followers of Jesus there and bring them back to Jerusalem (See: [46:01](46/01)). +46:3 mp8q meaning What happened to Saul as he was traveling to Damascus? A bright light shone around him and he heard someone say, “Saul! Saul! Why are you persecuting me?” (See: [46:03](46/03)). +46:4 xvnr meaning Who did God send to Saul so that he could see again? God sent a disciple in Damascus named Ananias to Saul to make him see again (See: [46:04](46/04)). +46:5 x3d8 meaning Who did Saul tell the Jews in Damascus that Jesus was? Saul told them that Jesus was the Son of God and the Messiah (See: [46:05](46/05)). +46:7 bx60 meaning How did Saul escape from the Jews in Damascus when they wanted to kill him? Saul’s friends lowered him over the city wall in a basket at night so he could escape (See: [46:07](46/07)). +46:8 n77y meaning What happened when Saul tried to meet with the apostles in Jerusalem? The apostles were afraid of Saul until Barnabas took him to them and explained how Saul had boldly preached about Jesus in Damascus (See: [46:08](46/08)). +46:9 cvxd meaning How were the believers in Antioch different from the believers in Jerusalem? The believers in Antioch were not Jews (See: [46:09](46/09)). +46:10 sn4f meaning Who did the Holy Spirit tell the followers of Jesus in Antioch to set apart to do God’s work in other places? The Holy Spirit told them to set apart Barnabas and Saul to do God’s work, so they sent them out (See: [46:10](46/10)). +46:10 m3zc application What was Saul’s attitude about the believers before the Lord appeared to him? Saul hated the believers and tried to destroy them. He guarded the robes of the people who killed Stephen. Later, he arrested believers throughout Jerusalem, and planned to do the same thing in Damascus. He was perhaps the least likely person we would expect God to save and use for his glory. +46:10 w51o application Why do you think Jesus told Saul that he was persecuting Jesus? Jesus was already in heaven when Saul began to persecute the believers. But the believers represented Jesus on earth, so when Saul persecuted them, it was as if he was persecuting Jesus himself. Jesus cares about what happens to the believers. +46:10 m2pm application What did God tell Ananias that he had chosen Saul to do? God told Ananias that he had chosen Saul to declare his name to the Jews and to people from other people groups, and to suffer in God’s name. Even though Saul had hated the believers and persecuted them, God had a plan to use Saul to spread the good news about Jesus throughout the world of that day. +46:10 lo7n application What happened in Damascus when Saul preached about Jesus? Saul argued boldly with the Jews to prove that Jesus was the Son of God. However, it is not clear if many people believed. Perhaps arguing about Jesus is not the best way to convince people to repent of their sin. After a time, the Jews tried to kill Saul, and he had to escape at night. +46:10 bhhf application Who went to Antioch to teach the new believers there? The two people who went to teach the believers at Antioch were Barnabas and Saul. Saul was the one who God said he would send to people of other nations, such as the people at Antioch. And Barnabas was the one who spoke for Saul and convinced the apostles in Jerusalem to accept him. Both men were uniquely prepared to teach people who were not Jews. +46:10 xe6e application How did the Holy Spirit send out Barnabas and Saul? The Holy Spirit spoke to the believers in the church at Antioch in order to send out Barnabas and Saul. The church then prayed for them, placed their hands on them, and supported them as they went out to preach among the other people groups. God did not send them out alone. Instead, he worked through the church so the believers were deeply involved in the work of Barnabas and Saul. +47:1 enhd meaning Who was Paul? **Paul** was Saul using his Roman name as he traveled through the Roman Empire (See: [47:01](47/01)). +47:2 cq09 meaning Where did Paul and Silas meet Lydia? Paul and Silas met Lydia in Philippi when they went to a place by the river outside the city where people gathered to pray (See: [47:02](47/02)). +47:3 uf8n meaning What did the demon enable the slave girl to do for her masters? The demon enabled her to predict the future for people. They paid her masters a lot of money for that (See: [47:03](47/03)). +47:4 jz27 meaning Why was Paul annoyed with the slave girl? The demon caused her to keep telling people that Paul and Silas were servants of the Most High God (See: [47:04](47/04)). +47:6 sidb meaning What did the owners of the slave girl do when Paul forced the demon to leave her? They became very angry with Paul and Silas, for they realized the girl could no longer tell the future, and people would no longer pay them. So they took Paul and Silas to the authorities, who beat them and put them into jail (See: [47:06](47/06), [47:07](47/07)). +47:9 nkcx meaning What happened when the earthquake shook the jail during the night? All the prison doors opened wide, and the chains of all the prisoners fell off. As a result, the jailer thought the prisoners had escaped, and planned to kill himself (See: [47:09](47/09), [47:10](47/10)). +47:11 eo1r meaning What did the jailer ask Paul and Silas when they stopped him from killing himself? The jailer asked them what he must do in order to be saved (See: [47:11](47/11)). +47:12 cdtl meaning Why did Paul and Silas baptize the jailer and his whole family? Paul and Silas baptized them because they all believed in Jesus (See: [47:12](47/12)). +47:13 sbyw meaning What did Paul do after he and Silas were released from jail in Philippi? Paul traveled to many cities to preach the good news about Jesus. He also wrote many letters to teach and encourage the believers in the churches. Some of his letters became books of the Bible (See: [47:13](47/13), [47:14](47/14)). +47:13 zdrw application Why did Paul and Silas go to the river in Philippi? When Paul and Silas arrived in Philippi, they looked for a place where people would be willing to hear about Jesus. They went to the river because that was the place where people went to pray to God. +47:13 zkvb application Why did Lydia need to believe in Jesus if she already loved and worshiped God? Lydia perhaps followed the Jewish religion. She knew about God, but she did not know about Jesus. When Paul and Silas told her about Jesus, she believed in him and was baptized. It is not enough for a person to believe in God. They must also believe in Jesus, whom God sent, in order to be saved from their sins. +47:13 tiwg application Why was Paul so annoyed by the demon that was speaking the truth about Paul and Silas? Demons are evil, and the enemies of God. Therefore, Paul was not willing to have them speak about God—even if what they said at that time was true. There can be no friendship between demons and the servants of God. +47:13 exms application What were Paul and Silas doing in the middle of the night while they were in jail? Even though the authorities beat Paul and Silas and threw them into jail, they were singing songs of praise to God. They trusted God completely, and were able to praise him in the most difficult situations. +47:13 zktx application Why did Paul stop the jailer from killing himself? Paul had mercy on the jailer. Because he thought the prisoners had escaped, the jailer was so afraid that he planned to kill himself. But Paul and Silas remained in the prison instead of escaping so that they could tell the jailer about Jesus. As a result, the jailer and his whole family believed. +47:13 ur8k application To whom did Paul write the letters that became books of the Bible? Paul wrote all of his letters to the believers in the churches of that time. However, the Holy Spirit guided Paul so that some of his books are also written to us today to encourage and teach us. Therefore, each book of the Bible has both an ancient and a modern audience. +48:1 s00r meaning What was the world like when God rested from its creation? Everything was perfect, and there was no sin, sickness, or death. Adam and Eve loved each other and they loved God (See: [48:01](48/01)). +48:2 ypha meaning Why do people die? Everyone dies because Adam and Eve sinned against God (See: [48:02](48/02)). +48:4 nc1a meaning What did God promise that the Messiah would do to Satan? God promised that the Messiah would take away Satan’s power forever (See: [48:04](48/04)). +48:6 vsbt meaning What did the sacrifices that the priest offered to God accomplish? These sacrifices showed people that they had sinned, and that they deserved God's punishment (See: [48:06](48/06)). +48:7 or3j meaning Who did God say he would bless through Abraham? God said he would bless all the people groups on earth through Abraham (See: [48:07](48/07)). +48:8 om9o meaning Why do we call Jesus the “Lamb of God?” God gave Abraham a lamb to sacrifice instead of his son, Isaac. In the same way, Jesus died in our place as a sacrifice for our sins. That is why he is called the “Lamb of God” (See: [48:08](48/08)). +48:9 ucjh meaning How is Jesus like the Passover lamb? Just as God spared the Jews who put the blood of the lamb on their doors, he will not punish the person for whom Jesus shed his blood (See: [48:09](48/09), [48:10](48/10)). +48:12 b3af meaning Why is Jesus a greater prophet than Moses? Everything Jesus did and said were the actions and words of God (See: [48:12](48/12)). +48:13 hu8h meaning Why is Jesus able to rule forever? Jesus is the descendant of King David and also the Messiah. Therefore, he will rule forever (See: [48:13](48/13)). +48:13 e9cn application Why is there evil, suffering, and death in the world? People do evil things, suffer, and die because Adam and Eve sinned against God. They became sinners because of that, and so did all of their descendants. As a result, every person in the world is a sinner. +48:13 j45l application Why is there no peace between God and people? When Adam and Eve sinned, they and their descendants became enemies of God. Therefore, there is no peace between God and people. +48:13 t4rm application Why did God require sacrifices if they cannot save people from their sins? God required sacrifices in order to show them that only Jesus, the perfect high priest, could offer a sacrifice that would take away their sins. Any other sacrifice does not save us, but only shows us that we need to believe in Jesus. +48:13 tkm6 application Who does God want to save from their sins? God wants to save people from every people group from their sins. Therefore, we must proclaim the message about Jesus to every people group so they can believe in Jesus and be saved. +48:13 swn1 application How does the Lamb of God keep God from punishing those who believe in him? Jesus was perfect, and never sinned. Therefore, when he shed his blood, he died to pay the penalty for our sins, and not for his own. We can be confident, then, that God will not punish us, since Jesus has already paid for our sins. +48:13 p87z application How does a person accept the New Covenant? The New Covenant that God made with us means that anyone who believes in Jesus belongs to God. It is no longer necessary to obey the Law (that is, the Old Covenant) in order to be saved. Jesus already completely fulfilled the Law. We only need to believe in him in order to be saved. +48:13 k3g0 application How is Jesus a greater king than King David? King David ruled over Israel. But Jesus will rule over the entire universe. Therefore, he is a greater king than his ancestor, King David. +49:1 sizf meaning How did Mary become pregnant with Jesus? She was a virgin, but the Holy Spirit came to her and made her become pregnant (See: [49:01](49/01)). +49:5 lfhu meaning What did Jesus say was better than anything else in the world? He said to be in the kingdom of God was better than anything else in the world (See: [49:05](49/05)). +49:6 a1xd meaning Who did Jesus say were like good soil? People who receive the good news about Jesus are like good soil, and God will save them (See: [49:06](49/06)). +49:7 d2z8 meaning What does God want to do for sinners because he loves them very much? He wants to forgive them and to make them his children (See: [49:07](49/07)). +49:9 thi1 meaning How did God show that he loves everyone in the world? He gave his only Son to receive the punishment due to sinners so that those who believe in him will escape the punishment and live with him forever (See: [49:09](49/09)). +49:11 sk9k meaning How is Jesus the perfect sacrifice to take away your sins? Jesus never sinned, but he took the place of all sinners, receiving the punishment for sin (See: [49:11](49/11)). +49:15 wkex meaning What do you need to do in order to become a follower of Jesus? If you believe in Jesus and confess what he has done for you, you are a follower of Jesus (See: [49:15](49/15)). +49:17 moqq meaning Does Satan tempt followers of Jesus to sin? Yes, Satan will still tempt followers of Jesus to sin. But if you confess your sins, God will forgive you (See: [49:17](49/17)). +49:18 w35a meaning How can you become a strong friend of Jesus? You will be a strong friend of Jesus if you pray and study his word, worship together with other followers of Jesus, and tell other people what Jesus has done for you (See: [49:18](49/18)). +49:18 c7j9 application Why is it important to us that Jesus is human as well as God? Because Jesus is human as well as divine he can understand our struggles and weaknesses and will help us to serve God. +49:18 w37t application Why can we be confident that Jesus is God? He did many powerful miracles for many people that proved he was God. He walked on water, calmed storms, healed sick people, drove out demons, and even raised dead people to life. If he were only a man, he would not have been able to do these things. +49:18 ja8c application How can you know that you will be in God’s kingdom? If you believe in Jesus and ask him to forgive your sins, God will save you and invite you into his kingdom. +49:18 wkqi application What kind of soil are you—good soil, or hard soil on a path? Only you can answer that question. +49:18 ei8n application Have you become a friend of God and a child of God, or are you still an enemy of God? Only you can answer that question. +49:18 dhmi application Will you pay for your own sins against God, or have you asked Jesus to pay for your sins? Only you can answer that question. +49:18 ssmt application What are you doing to become a strong friend of God? Only you can answer that question. +50:2 lzit meaning When did Jesus say the end of the world would happen? He said his disciples would preach the good news about the kingdom of God to people everywhere in the world, and then the end would come (See: [50:02](50/02)). +50:3 qaag meaning Will Jesus’ servants be treated well in the world? No, Jesus said the important people in this world would torture and kill them because of him (See: [50:03](50/03)). +50:5 orkx meaning What did an enemy do to the field where a man planted good seed? His enemy planted weeds in the field to ruin his crop (See: [50:05](50/05)). +50:10 kc4j meaning When the world ends, what will God’s angels do to all the people who belong to the devil and not to God? His angels will gather the people who belong to the devil together and throw them into a very hot fire where they will suffer terribly (See: [50:10](50/10)). +50:10 oory meaning When the world ends, what will happen to the people who are righteous and have followed God? They will shine like the sun in the kingdom of God their Father (See: [50:10](50/10)). +50:11 hkqd meaning When Jesus returns, what will happen to every follower of Jesus who has died? They will rise from the dead and meet him in the sky (See: [50:11](50/11)). +50:13 tfga meaning What will Jesus give to everyone who believes in him? He will give them a crown, and they will rule with God forever and have perfect peace (See: [50:13](50/13)). +50:14 u1lo meaning Where will God throw everyone who does not believe in Jesus? He will throw them into hell, where they will suffer forever and burn continually in a fire that never goes out (See: [50:14](50/14)). +50:15 ljw1 meaning What will happen to Satan when Jesus returns? Jesus will completely destroy Satan and his kingdom and throw him into hell, where he will burn there forever (See: [50:15](50/15)). +50:15 x9pf meaning What will happen to this earth when Jesus returns? God will destroy the present heaven and earth and create a new heaven and earth that will be perfect. +50:15 rz1h application Should we be concerned that Jesus has not come back to earth for almost 2,000 years? No, we should not be worried. Jesus promised to return at the end of the world, and he will keep his promise. +50:15 xk4h application What should followers of Jesus be doing as we wait for him to return? We should be living in a holy way that honors Jesus, and telling other people about his kingdom. +50:15 qkzj application What did Jesus want to say when he said, “The fields are ripe for harvest”? He wanted to say that at any time, there are many people in the world who are ready to believe in Jesus. +50:15 bbxw application Should we let persecution stop us from telling people about Jesus? No, people killed Jesus, and he said they will also torture and kill his servants. Jesus expects us to be faithful just as he was faithful to God. +50:15 bnq3 application Why are there so many evil people in the world? Jesus said Satan places evil people in the world just as an enemy placed weeds in a man’s field. These people will grow up together with believers, but God’s angels will separate them out at the judgement. +50:15 mw5c application Why will Jesus give us a crown? He will give a crown to everyone who believes in him as a sign that they will rule with him forever. This should encourage us in this life. +50:15 d4pc application Will God always allow evil and Satan to be in the world? No, God will throw Satan and every evil person into hell where they will suffer forever. He will even destroy this earth where sin has been, and create a new heaven and earth that will be perfect. That is where believers will live forever with God. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sq/README.md b/src/__tests__/fixtures/unfoldingWord/en_sq/README.md new file mode 100644 index 000000000..7f5d44440 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sq/README.md @@ -0,0 +1,3 @@ +# en_sq + +“Box 3” test of study questions for Bible Book Packages. diff --git a/src/__tests__/fixtures/unfoldingWord/en_sq/TIT_sq.tsv b/src/__tests__/fixtures/unfoldingWord/en_sq/TIT_sq.tsv new file mode 100644 index 000000000..b2669eb51 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sq/TIT_sq.tsv @@ -0,0 +1,188 @@ +Reference ID Tags Quote Occurrence Question Response +front:intro gtn1 # Titus Study Questions\n\nThe Apostle Paul left Titus in Crete and gave him the responsibility to teach the new believers there, and to appoint elders in the local churches. Titus was a godly man, but he was not have as much experience as Paul did in guiding the formation of the new churches. In this letter, therefore, Paul counsels Titus concerning:\n\n* How Titus should fulfil his task\n* The kind of men he should appoint as elders\n* The type of threats that existed that could damage the new believers\n* How believers should act in their daily lifes\n* What is the hope that the believers look forward to\n* How believers should interact with secular authorities and those who do not believe in Jesus\n* The precise message that we should believe and teach\n* How to deal with division within the church\n\nYou can discover Paul’s teaching concerning each of these things by carefully reading each chapter of the letter. Ask yourself questions about what you read, and pray to God that he will open your eyes to see clearly. +1:1 x3em How did Paul describe himself to Titus? +1:1 v5b9 δοῦλος & ἀπόστολος 1 Why do you think Paul described himself as a **servant** before he described himself as an **apostle**? +1:1 sg88 δοῦλος Θεοῦ 1 In what ways was Paul **a servant of God**? +1:1 r5x7 δοῦλος & ἀπόστολος 1 Would you prefer to be a servant or an apostle? Why? +1:1 lab1 δοῦλος 1 The word Paul used for **servant** is also the word for “slave.” Does that change your understanding of how Paul described himself? How? +1:1 lk5q δοῦλος 1 What do people in your culture think about servants or slaves? +1:1 rj9f δοῦλος Θεοῦ, ἀπόστολος δὲ Ἰησοῦ Χριστοῦ 1 In this verse, for what two purposes did Paul say he was **a servant of God and an an apostle of Jesus Christ**? +1:1 z3yq πίστιν 1 What **faith** do you think Paul wanted the chosen people of God to have? +1:1 at5s ἐκλεκτῶν Θεοῦ 1 Why did Paul call the believers **the chosen people of God**? +1:1 h97z ἐκλεκτῶν 1 From among whom did God choose the believers? Why did he choose them? +1:1 m89w ἐκλεκτῶν 1 How might it change your life if you truly believed that God chose you? +1:1 ww9a ἐπίγνωσιν ἀληθείας 1 Why do you think it was so important for Paul that God’s chosen people had **the knowledge of the truth**? +1:1 sxc7 ἀληθείας 1 What do you think is **the truth** that believers must know? +1:1 z85a εὐσέβειαν 1 What do you think Paul was referring to when he spoke of **godliness**? +1:1 v8bl ἐπίγνωσιν & κατ’ εὐσέβειαν 1 Why is it important that **the knowledge** of the believers **agrees with godliness**? +1:1 d8pa ἀληθείας & εὐσέβειαν 1 What things can you think of that are true, but that are not godly? +1:1 e6el ἀληθείας & εὐσέβειαν 1 Paul speaks of both **truth** and **godliness** together. What problems happen when someone or some group has one of these without the other? +1:2 c7pa ἐλπίδι ζωῆς αἰωνίου 1 Paul referred to the **certain hope of everlasting life**. Why is this hope **certain** for believers? +1:2 dx6p What do we learn about God’s character in this verse? +1:2 rnp6 ζωῆς αἰωνίου 1 When did God make the promise everlasting life to believers? +1:3 r2l5 καιροῖς ἰδίοις 1 Why was it **the right time** when God revealed his word? +1:3 f9p2 ἐν κηρύγματι, ὃ ἐπιστεύθην ἐγὼ 1 How did God reveal his word? +1:3 mdc8 ἐπιστεύθην 1 What does it mean to **entrust** something to another person? +1:3 zfp4 ἐπιστεύθην 1 What effect do you think it had on Paul to be entrusted to proclaim God’s word? +1:3 is3p τοῦ Σωτῆρος ἡμῶν 1 What title does Paul use for God in this verse, and why would it be important? +1:4 b5wy γνησίῳ τέκνῳ, κατὰ κοινὴν πίστιν 1 What does Paul mean when he calls Titus **a true son in our common faith**? +1:4 n5ql χάρις καὶ εἰρήνη ἀπὸ Θεοῦ 1 Paul greeted Titus with **Grace and peace from God**. How does this compare to the way people in your culture greet one another? +1:4 ki6h χάρις καὶ εἰρήνη ἀπὸ Θεοῦ Πατρὸς καὶ Χριστοῦ Ἰησοῦ τοῦ Σωτῆρος ἡμῶν 1 Why would Paul expect grace and peace to come from God the Father and Christ Jesus our Savior? +1:4 f3g1 τοῦ Σωτῆρος ἡμῶν 1 What title does Paul use for Jesus in this verse? How does that affect your understanding of the title for God in verse 3? +1:5 ux1x ἵνα τὰ λείποντα ἐπιδιορθώσῃ, καὶ καταστήσῃς κατὰ πόλιν πρεσβυτέρους 1 Why did Paul leave Titus in Crete? +1:5 yi1f ἐπιδιορθώσῃ 1 What does it mean to set things in order? +1:5 u1cq τὰ λείποντα 1 What do you think might have been **not yet complete** in Crete? +1:5 ru3x κατὰ πόλιν 1 Where was Titus to ordain elders? +1:6 gnu7 ἀνέγκλητος 1 How would you describe a person who is **blameless**? +1:6 j96v μιᾶς γυναικὸς ἀνήρ 1 What does Paul mean when he says an elder must be **the husband of one wife**? Who would qualify? +1:6 s4bm πιστά 1 What does it mean for children to be **faithful**? +1:6 mm2f ἐν κατηγορίᾳ ἀσωτίας ἢ ἀνυπότακτα 1 Why might it be important that the children of an elder not be **accused of reckless behavior or rebellion**? How might those things hinder his ministry? +1:6 h7nu If you have a family, would it meet these conditions for you to be an elder? Why or why not? +1:7 f5x9 ἀνέγκλητον 1 Why is it important that Paul says for a second time (see verse 6) that an overseer must be **blameless**? +1:7 sz5b ἐπίσκοπον 1 Paul here refers to an elder as an **overseer**? Is there any difference in the meaning of these words? +1:7 ii3m Θεοῦ οἰκονόμον 1 Paul describes an elder as **the household manager of God**. How does that influence your understanding of the role of an elder? +1:7 h38h μὴ αὐθάδη, μὴ ὀργίλον, μὴ πάροινον, μὴ πλήκτην, μὴ αἰσχροκερδῆ 1 Paul says an elder should not be **arrogant**, **easily angered**, **addicted to wine**, **a brawler**, or **a greedy man**. How might each of those bad character traits hinder a man from being a good elder in the church? +1:7 igg9 Do you have any of these weaknesses that Paul listed? If so what do you plan do about that? +1:8 hbv6 Would you be willing to receive counsel of teaching from a man with the characteristics listed in this verse? Why? +1:8 gqv3 φιλόξενον 1 Why would it be important for an elder to be **hospitable**? +1:8 r15v Do these characteristics of an elder also describe you? Why or why not? How could you do better? +1:9 c69s ἀντεχόμενον 1 What does it mean to **hold tightly** to a message? +1:9 wzy3 πιστοῦ 1 What kind of message would be **trustworthy**? +1:9 rn72 τοῦ κατὰ τὴν διδαχὴν πιστοῦ λόγου 1 Paul said **the trustworthy message** must be in accordance with **the teaching**. What **teaching** do you think Paul was referring to? +1:9 tbu2 ἀντεχόμενον τοῦ & πιστοῦ λόγου 1 According to Paul in this verse, what two things will an elder be qualified to do if he **holds tightly to the trustworthy message**? +1:9 u8z3 ἀντεχόμενον τοῦ & πιστοῦ λόγου 1 Are you **holding tightly to the trustworthy message**? In what way? How can you improve? +1:9 szu6 τῇ ὑγιαινούσῃ 1 The word **sound** can also be translated as “healthy.” How might teaching be “healthy?” +1:9 wk7u τοὺς ἀντιλέγοντας ἐλέγχειν 1 Why would it be important for an elder to **rebuke those who oppose him**? (See verses 10-11) +1:9 uvc1 παρακαλεῖν ἐν τῇ διδασκαλίᾳ τῇ ὑγιαινούσῃ, καὶ τοὺς ἀντιλέγοντας ἐλέγχειν 1 Do you understand the message of the gospel well enough to teach and rebuke others? If not, what might you do to improve? +1:10 c7hp γὰρ 1 How does the word **For** connect this verse to the previous one? +1:10 dxr6 ματαιολόγοι 1 What is an **empty talker**? +1:10 xm6i οἱ ἐκ τῆς περιτομῆς 1 Who was Paul referring to when he spoke of **those of the circumcision**? +1:10 gw8y Do you listen to anyone who is like the people Paul described in this verse? If so, what should you do about that? +1:11 ddr2 οὓς δεῖ ἐπιστομίζειν 1 What did Paul say the elders must do to these false teachers who opposed them? +1:11 ly68 οἵτινες ὅλους οἴκους ἀνατρέπουσιν 1 Why did Paul speak so forcefully about stopping these men who opposed the elders of the church? +1:11 k9xu οἵτινες ὅλους οἴκους ἀνατρέπουσιν 1 In what way do you think these false teachers were **upsetting whole households**? +1:11 x2wl οἴκους 1 Why are **households** important for the growth and spiritual life of the church? +1:11 r14e αἰσχροῦ κέρδους χάριν 1 What did Paul say was the reason these false teachers were teaching their false doctrine? +1:12 u971 τις ἐξ αὐτῶν, ἴδιος αὐτῶν προφήτης 1 Why is it significant that the person quotes here was one of the Cretans? +1:12 fvv6 Κρῆτες ἀεὶ ψεῦσται, κακὰ θηρία, γαστέρες ἀργαί 1 Why would one of the Cretans speak so harshly about his own people? +1:12 ec9q γαστέρες ἀργαί 1 What do you think this man meant when he said they were **lazy bellies**? +1:12 tlv5 ἴδιος αὐτῶν προφήτης 1 If a **prophet** from your own people group described a character weakness or sin that is common among your people, what would it be? How might elders prevent believers from continuing to act that way? +1:13 n8ac ἡ μαρτυρία αὕτη ἐστὶν ἀληθής 1 What did Paul say about the words of this Cretan prophet? +1:13 a8pm δι’ ἣν αἰτίαν ἔλεγχε αὐτοὺς ἀποτόμως 1 When Paul tells Titus and the elders, "**For this reason, rebuke them severely**", how does that relate to verse 9? +1:13 dv6h ἔλεγχε αὐτοὺς ἀποτόμως, ἵνα ὑγιαίνωσιν ἐν τῇ πίστει 1 Why were the Titus and the elders supposed to **rebuke** the Cretan false teachers **severely**? +1:13 e9pj ἵνα ὑγιαίνωσιν ἐν τῇ πίστει 1 What result did Paul want to happen after Titus and the elders rebuked the false teachers? +1:13 v89u ὑγιαίνωσιν 1 The word **sound** can also be translated as “healthy.” How might they be “healthy” **in the faith**? +1:13 jb2g ὑγιαίνωσιν ἐν τῇ πίστει 1 Would you describe yourself as **sound in the faith**? Why or why not? +1:14 pil3 What does Paul in this verse say is one way people can be sound in the faith? +1:14 hw81 τὴν ἀλήθειαν 1 What is Paul referring to when he says **the truth**? +1:14 j4ni How should this verse affect the way we interact with false teachers or people who teach things that are not according to the gospel? +1:15 vs4a πάντα καθαρὰ τοῖς καθαροῖς; τοῖς δὲ μεμιαμμένοις καὶ ἀπίστοις, οὐδὲν καθαρόν 1 Which is true: pure things make people pure, or pure people make things pure? What is the difference? +1:15 g3ja πάντα καθαρὰ τοῖς καθαροῖς; τοῖς δὲ μεμιαμμένοις καὶ ἀπίστοις, οὐδὲν καθαρόν 1 Which is true: corrupt things make people corrupt, or corrupt people make things corrupt? What is the difference? +1:15 c7ja μεμιαμμένοις καὶ ἀπίστοις 1 Paul says these people are both **corrupt** and **unbelieving**. How might those two traits be connected? +1:15 gn3f ὁ νοῦς 1 What is Paul referring to when he says **their minds** have been corrupted? +1:15 qvi3 μεμίανται αὐτῶν & ἡ συνείδησις 1 In what way can a person’s conscience be corrupted? +1:16 yvm1 Θεὸν ὁμολογοῦσιν εἰδέναι 1 What do these false teachers say about God? +1:16 cx7y τοῖς δὲ ἔργοις ἀρνοῦνται 1 How do people know that these people do not really know God? +1:16 bt7u Why do you think Paul speaks so harshly about these false teachers? +1:16 yy1c Are these people able to do **good work**? Why or why not? +1:16 p8z2 πρὸς πᾶν ἔργον ἀγαθὸν ἀδόκιμοι 1 Do you know God? How would other people know if you do? +1:16 c2e2 πρὸς πᾶν ἔργον ἀγαθὸν ἀδόκιμοι 1 Are you fit for any good work? If not, how would you become fit? +2:1 t4qm σὺ δὲ 1 Who is Paul contrasting Titus against when he says **But you**? +2:1 f4tt πρέπει τῇ ὑγιαινούσῃ διδασκαλίᾳ 1 How did the rebellious people speak what did not **fit with sound teaching**? +2:1 th8q ὑγιαινούσῃ 1 The word **sound** used here normally refers to good health. What kind of **teaching** would you say is “healthy”? +2:2 cxx8 πρεσβύτας 1 Who would be an **Older man** in your culture? +2:2 ytu6 πρεσβύτας 1 Are the qualities of an older man that Paul lists here attractive in your culture? Why or why not? +2:2 iqg1 πρεσβύτας 1 What would be the opposite of the qualities Paul lists here? Why would those not be good older men to do? +2:2 z12q ὑγιαίνοντας τῇ πίστει 1 The phrase **sound in faith** here uses the same word **sound** as verse 1 does for "teaching." How do you think faith can be “healthy”? +2:3 ama2 πρεσβύτιδας 1 Who would be an **Older woman** in your culture? +2:3 dse2 ἐν καταστήματι ἱεροπρεπεῖς 1 Paul says older women are to be **reverent in behavior**. Is this quality of an older woman attractive in your culture? Why or why not? +2:3 y6ts διαβόλους & οἴνῳ πολλῷ δεδουλωμένας 1 Paul here says older women are not to be **slanders** or **slaves to much wine**. Do some older women in your culture have those problems? +2:3 d7pj καλοδιδασκάλους 1 Older women are to be **teachers of what is good**. What does this mean, and how is it different that the things Paul says not to do? +2:4 x3mi σωφρονίζωσι 1 How does "they may train** in this verse connect back to the older women being **teachers of what is good** in verse 3? +2:4 md5e νέας 1 Who are **younger women** in your culture? +2:4 jt4b τὰς νέας, φιλάνδρους εἶναι, φιλοτέκνους 1 Who are the younger women to **love**? +2:4 ybp2 φιλάνδρους & φιλοτέκνους 1 Why is **love** so important for the younger women to do? +2:4 jr4i Must younger women already have husbands and children before the older women can train them? Why or why not? +2:4 kfy1 Why do you think Paul focuses his commands to younger women on how they love their families (husbands and children)? +2:5 rgw4 ἵνα 1 The phrase **so that** expresses the result of younger women following Paul’s commands. What is that result, and why would following these commands make it possible? +2:5 wg1h μὴ ὁ λόγος τοῦ Θεοῦ βλασφημῆται 1 Why might people insult the word of God is young believing women did not treat their families well? +2:6 ijd6 νεωτέρους 1 Who would be the **younger men** in your culture? +2:6 zwg7 σωφρονεῖν 1 Instead of a list of commands, Paul only tells Titus to exhort the younger men to be **sensible**. How might that single trait cause them to live well? +2:6 rk75 σωφρονεῖν 1 Do you think younger men struggle with being **sensible**? Why or why not? +2:7 p7mw σεαυτὸν παρεχόμενος 1 To whom is Paul directly speaking in verses 7-8? +2:7 pex3 τύπον καλῶν ἔργων 1 Why is it important that Titus be **an example of good works**? How might that affect the purpose for which Paul sent Titus to Crete? +2:7 w537 ἐν τῇ διδασκαλίᾳ ἀφθορίαν 1 How might a person be corrupted in his teaching? Why is it so important not to do that? +2:7 swj9 σεμνότητα 1 How can a person teach **with dignity**? Why is that important? +2:8 t8pv λόγον ὑγιῆ 1 In the phrase **sound message** Paul uses the same word **sound** that he uses in verses 1-2 for **teaching** and **faith**. How might a message be “healthy”? +2:8 agl8 ὁ ἐξ ἐναντίας 1 What kind of opponents might want to criticize the message of the gospel today? Why would they do that? +2:8 f52g μηδὲν ἔχων λέγειν περὶ ἡμῶν φαῦλον 1 Why would an opponent of the gospel have nothing bad to say about believers if they did what Paul commanded in verses 1-7? +2:8 fv4k ἡμῶν 1 Why does Paul include himself by saying **us**? Why would people say bad things about Paul if the Cretan church did not obey what Titus told them to do? +2:9 h8cp About whom is Paul speaking in verses 9-10? +2:9 c4dn δούλους 1 The Greek language has a single word for **slave** that also means “servant”. Does it make any difference if you apply Paul’s commands to both slaves and hired servants? +2:9 gj1q δούλους ἰδίοις δεσπόταις ὑποτάσσεσθαι 1 Why do you think Paul commands believing **slaves to be **subject to their own masters** instead of trying to free themselves? +2:9 gec6 εὐαρέστους εἶναι 1 How might a slave **be pleasing** to his master? +2:10 ub51 πᾶσαν πίστιν ἐνδεικνυμένους ἀγαθήν 1 What does it mean to **demonstrate all good faith** and how is that different from arguing and stealing? +2:10 m341 ἵνα 1 The phrase **so that** introduces the reason slaves should submit to their masters. What is that reason? +2:10 guq1 τὴν διδασκαλίαν τὴν τοῦ Σωτῆρος ἡμῶν, Θεοῦ, κοσμῶσιν 1 How do believing slaves ** bring credit to the teaching that is about God our Savior** when they submit to their masters? +2:10 wa6f τοῦ Σωτῆρος ἡμῶν, Θεοῦ 1 Compare **God our Savior** to the similar title in verse 13. To whom does this title refer? +2:11 fcb4 γὰρ 1 The word **For** which begins this verse introduces the reason why slaves should submit to their masters. What is that reason? +2:11 j1e6 ἡ χάρις τοῦ Θεοῦ 1 For what purpose did **the grace of God** appear? +2:11 c2n3 σωτήριος πᾶσιν ἀνθρώποις 1 Who is the grace of God able to save? +2:11 u8f7 σωτήριος πᾶσιν ἀνθρώποις 1 The grace of God makes possible the salvation of all people. Does that mean that all people are saved? In other words, are the rebellious people and deceivers and corrupt people in chapter 1 also saved? +2:12 ck9i ἀρνησάμενοι τὴν ἀσέβειαν καὶ τὰς κοσμικὰς ἐπιθυμίας 1 What does the grace of God train us to reject? +2:12 n7q4 τὰς κοσμικὰς ἐπιθυμίας 1 What are the **worldly passions** that we are to reject? +2:12 a9s5 σωφρόνως καὶ δικαίως, καὶ εὐσεβῶς, ζήσωμεν 1 How does the grace of God train us to live? +2:12 n5ev τῷ νῦν αἰῶνι 1 What is **the present age** and why should we live in a sensible, righteous, and godly way during it? +2:13 vt1f προσδεχόμενοι 1 What is it that believers are looking forward to as they live in this present age? +2:13 i9tg τὴν μακαρίαν ἐλπίδα, καὶ ἐπιφάνειαν τῆς δόξης τοῦ μεγάλου Θεοῦ καὶ Σωτῆρος ἡμῶν, Ἰησοῦ Χριστοῦ 1 Paul speaks of **the blessed hope** and the **appearing of the glory of our great God and Savior Jesus Christ** as two names for the same event. What do these titles tell you about that event? +2:13 zg3s μακαρίαν 1 What does Paul mean when he says our hope is **blessed**? +2:13 ib56 τῆς δόξης 1 Why does Paul not simply refer to the appearance of Christ, but instead to the appearing **of the glory** of Christ? +2:13 s7a6 τοῦ μεγάλου Θεοῦ καὶ Σωτῆρος ἡμῶν, Ἰησοῦ Χριστοῦ 1 It is not clear in the text if **our great God and Savior Jesus Christ** refers to both God and Father and Jesus, or if it is one title referring to Jesus. How do you understand this verse? What difference does it make? +2:14 wkx8 ὃς 1 Considering your answer to the last question in verse 13, to whom does **He** refer in this verse? +2:14 ml3k ἔδωκεν ἑαυτὸν 1 What does Paul mean when he says that Christ **gave himself**? +2:14 m6cy ἵνα 1 The phrase **in order to** introduces the reason Jesus gave himself. What is that reason? +2:14 y3bu λυτρώσηται 1 The word **redeem** is used for slaves who are bought back from the slave market. How can **lawlessness** cause people to be like slaves? +2:14 sw8x ζηλωτὴν καλῶν ἔργων 1 What specifically does Jesus want believers to be zealous to do? +2:15 k32u To whom is Paul again speaking directly in verse 15? +2:15 t28w λάλει, καὶ παρακάλει, καὶ ἔλεγχε, μετὰ πάσης ἐπιταγῆς 1 What does it mean to **speak**, **exhort**, and **rebuke with all authority**? +2:15 eg4h ἔλεγχε 1 In 1:9 Paul tells Titus to rebuke those who oppose him. Would there ever be a reason to also rebuke believers? +2:15 s4na μηδείς σου περιφρονείτω 1 Paul tells Titus not to let people disregard him. Why was that necessary? Who might do that, and why? +3:1 c1bu To whom is Paul again speaking directly in verse 1? +3:1 tn5f αὐτοὺς 1 Who are the **them** who must submit to rulers and authorities? +3:1 q2id ἀρχαῖς, ἐξουσίαις 1 Who are the **rulers and authorities** to whom they should submit? +3:1 xl6v ὑποτάσσεσθαι, πειθαρχεῖν 1 Is there any difference between **submit** and **obey**? Why did Paul use both terms? +3:1 x35c πρὸς πᾶν ἔργον ἀγαθὸν ἑτοίμους εἶναι 1 How might obeying authorities prepare us to do good works? +3:2 z28q πρὸς πάντας ἀνθρώπους 1 To whom are believers to show humility? +3:3 cnq7 καὶ ἡμεῖς 1 by saying **we also**, Paul includes himself along with Titus and the believers in Crete. When did they live as this verse describes? When did you live this way? +3:3 c5fp πλανώμενοι, δουλεύοντες ἐπιθυμίαις καὶ ἡδοναῖς ποικίλαις 1 Paul uses the image of a person being led astray and made a slave, What does that teach you about the way passion and pleasure can affect a person? +3:3 lc6m ἐπιθυμίαις καὶ ἡδοναῖς ποικίλαις 1 What are some of the passions and pleasures that enslave people? +3:4 gz6j ἡ χρηστότης καὶ ἡ φιλανθρωπία ἐπεφάνη τοῦ Σωτῆρος ἡμῶν, Θεοῦ 1 How did God respond to the evil way in which we formerly lived? +3:4 l3we τοῦ Σωτῆρος ἡμῶν, Θεοῦ 1 What title does Paul again use for God in this verse? +3:5 xn6w οὐκ ἐξ ἔργων τῶν ἐν δικαιοσύνῃ, ἃ ἐποιήσαμεν ἡμεῖς 1 What was it that Paul says did not save us? +3:5 wi7z κατὰ τὸ αὐτοῦ ἔλεος 1 What was it that Paul says did save us? +3:5 p7qq λουτροῦ παλινγενεσίας 1 What image did Paul use for the **washing** through which God saved us? +3:5 ar5a ἀνακαινώσεως Πνεύματος Ἁγίου 1 Who was it that renewed us in order to save us? +3:6 gh9s οὗ ἐξέχεεν ἐφ’ ἡμᾶς πλουσίως 1 Who was it that gave the Holy Spirit to us? +3:6 uq9y οὗ ἐξέχεεν ἐφ’ ἡμᾶς πλουσίως 1 What does the image of the Holy Spirit being **richly poured on us** tell you about your relationship to the Holy Spirit? +3:6 hl38 οὗ ἐξέχεεν ἐφ’ ἡμᾶς πλουσίως, διὰ Ἰησοῦ Χριστοῦ, τοῦ Σωτῆρος ἡμῶν 1 In verses 5-6, Paul states that the Holy Spirit, God, and Jesus were all active in saving us. Why is it important that he listed all three? +3:6 vb45 Ἰησοῦ Χριστοῦ, τοῦ Σωτῆρος ἡμῶν 1 How does the title Paul here uses for Jesus compare to verse 4? Why is that important? +3:7 qn68 δικαιωθέντες 1 What does it mean to be **justified** by God? Why is that important? +3:7 mv4d δικαιωθέντες τῇ ἐκείνου χάριτι 1 What is it that caused God to justify us? +3:7 grr3 κληρονόμοι γενηθῶμεν 1 What does it mean to become an heir? To whom have we become heirs? +3:7 q13d ἐλπίδα ζωῆς αἰωνίου 1 What **certain hope** do we have because God saved us? +3:8 xq7q πιστὸς ὁ λόγος 1 **This message** may refer back to verses 4-7, or to the entire book. What does it mean when Paul says it is **trustworthy**? Why should that be important to you? +3:8 i497 φροντίζωσιν καλῶν ἔργων 1 Paul said in verse 5 that **works of righteousness** do not cause our salvation, but he says in 2:6, 2:14, and 3:8 that we should do them. For what other reason are they important? +3:9 jg8q μωρὰς & ζητήσεις, καὶ γενεαλογίας, καὶ ἔρεις, καὶ μάχας νομικὰς 1 What are some examples of foolish things people talk about, or things that cause strife between people? +3:9 sbm3 εἰσὶν γὰρ ἀνωφελεῖς καὶ μάταιοι 1 What does Paul say is the value of these debates and conflicts? +3:10 xq62 αἱρετικὸν ἄνθρωπον 1 What is an example of a **divisive person**? +3:10 vt7f μετὰ μίαν καὶ δευτέραν νουθεσίαν 1 Why should we warn a divisive person once or twice instead of rejecting him immediately? +3:11 nf3j ἐξέστραπται ὁ τοιοῦτος 1 Why does Paul describe being divisive as turning **from the right way**? +3:11 be71 ὢν αὐτοκατάκριτος 1 Why would Paul say that a divisive person is **self-condemned**? +3:12 lqz2 σπούδασον ἐλθεῖν πρός με εἰς Νικόπολιν 1 What did Paul want Titus to do when Artemas or Tychicus arrive in Crete? +3:13 g2vh σπουδαίως πρόπεμψον, ἵνα μηδὲν αὐτοῖς λείπῃ 1 What exactly did Paul want Titus and the believers in Crete to do for Zenas and Apollos **so that they lack nothing**? +3:14 bl6h καλῶν ἔργων προΐστασθαι εἰς τὰς ἀναγκαίας χρείας 1 What did Paul want the believers in Crete to learn to do? +3:14 s44m ἀναγκαίας χρείας 1 What are some examples of **essential needs**? +3:14 hkk4 ὦσιν ἄκαρποι 1 What image did Paul use to describe a believer who does not do good works? +3:15 v149 ἀσπάζονταί σε οἱ μετ’ ἐμοῦ πάντες. ἄσπασαι τοὺς φιλοῦντας ἡμᾶς ἐν πίστει 1 Paul always passed greetings between the believers and churches. Why is that so important to do? +3:15 dk8q τοὺς φιλοῦντας ἡμᾶς ἐν πίστει 1 What does it mean to **love** another believer **in faith**? +3:15 dd3p ἡ χάρις μετὰ πάντων ὑμῶν 1 As Paul’s closing desire in this letter, what did he want all the believers in Crete to receive? diff --git a/src/__tests__/fixtures/unfoldingWord/en_sq/manifest.yaml b/src/__tests__/fixtures/unfoldingWord/en_sq/manifest.yaml new file mode 100644 index 000000000..dcf9c51f7 --- /dev/null +++ b/src/__tests__/fixtures/unfoldingWord/en_sq/manifest.yaml @@ -0,0 +1,53 @@ +--- + +dublin_core: + conformsto: 'rc0.2' + contributor: + - 'Door43 World Missions Community' + - 'Larry Sallee (Th.M Dallas Theological Seminary, D.Min. Columbia Biblical Seminary)' + creator: 'Door43 World Missions Community' + description: 'Comprehension and theological questions for each chapter of the Bible.' + format: 'text/markdown' + identifier: 'tq' + issued: '2020-09-25' + language: + direction: 'ltr' + identifier: 'en' + title: 'English' + modified: '2020-09-25' + publisher: 'unfoldingWord' + relation: + - 'en/ult' + - 'en/ust' + rights: 'CC BY-SA 4.0' + source: + - + identifier: 'sq' + language: 'en' + version: '0' + subject: 'TSV Study Questions' + title: 'unfoldingWord® Study Questions' + type: 'help' + version: '1' + +checking: + checking_entity: + - 'unfoldingWord' + checking_level: '3' + +projects: + - + title: 'unfoldingWord® Open Bible Stories' + versification: 'ufw' + identifier: 'obs' + sort: 0 + path: './OBS_sq.tsv' + categories: [ ] + + - + title: 'Titus' + versification: 'ufw' + identifier: 'tit' + sort: 56 + path: './TIT_sq.tsv' + categories: [ 'bible-nt' ] diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index a0d2c8c0e..feb876b9b 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -8,7 +8,7 @@ import { checkRepo } from '../repo-check/checkRepo'; // const BP_VALIDATOR_VERSION_STRING = '0.6.0'; -const MANIFEST_FILENAME = 'manifest.yaml'; +const STANDARD_MANIFEST_FILENAME = 'manifest.yaml'; /* @@ -16,8 +16,8 @@ const MANIFEST_FILENAME = 'manifest.yaml'; */ /** * - * @param {string} username - * @param {string} languageCode + * @param {string} username, e.g., 'unfoldingWord' + * @param {string} languageCode, e.g., 'en' * @param {string} bookID -- 3-character USFM book ID or 'OBS' * @param {Function} setResultValue function * @param {Object} checkingOptions -- can contain: getFile (function), originalLanguageRepoUsername, taRepoUsername, checkManifestFlag @@ -148,44 +148,45 @@ export async function checkBookPackage(username, languageCode, bookID, setResult /** * - * @param {string} repoCode, e.g., TA - * @param {string} repoName, e.g., en_ta + * @param {string} repoCode, e.g., 'TA' + * @param {string} repoName, e.g., 'en_ta' + * @param {string} repoBranch, e.g., 'master' * @param {string} manifestLocation * @param {Object} checkingOptions */ - async function ourCheckManifest(repoCode, repoName, repoBranch, manifestLocation, checkingOptions) { + async function ourCheckManifestFile(repoCode, repoName, repoBranch, manifestLocation, checkingOptions) { // Updates the global list of notices - // functionLog(`checkBookPackage ourCheckManifest(${repoCode}, ${repoName}, ${repoBranch}, ${manifestLocation}, ${JSON.stringify(checkingOptions)})…`); - parameterAssert(repoCode !== undefined, "cBP ourCheckManifest: 'repoCode' parameter should be defined"); - parameterAssert(typeof repoCode === 'string', `cBP ourCheckManifest: 'repoCode' parameter should be a string not a '${typeof repoCode}' : ${repoCode}`); - parameterAssert(repoName !== undefined, "cBP ourCheckManifest: 'repoName' parameter should be defined"); - parameterAssert(typeof repoName === 'string', `cBP ourCheckManifest: 'repoName' parameter should be a string not a '${typeof repoName}': ${repoName}`); - parameterAssert(repoBranch !== undefined, "cBP ourCheckManifest: 'repoBranch' parameter should be defined"); - parameterAssert(typeof repoBranch === 'string', `cBP ourCheckManifest: 'repoBranch' parameter should be a string not a '${typeof repoBranch}': ${repoBranch}`); - parameterAssert(manifestLocation !== undefined, "cBP ourCheckManifest: 'manifestLocation' parameter should be defined"); - parameterAssert(typeof manifestLocation === 'string', `cBP ourCheckManifest: 'manifestLocation' parameter should be a string not a '${typeof manifestLocation}'`); + // functionLog(`checkBookPackage ourCheckManifestFile(${repoCode}, ${repoName}, ${repoBranch}, ${manifestLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(repoCode !== undefined, "cBP ourCheckManifestFile: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `cBP ourCheckManifestFile: 'repoCode' parameter should be a string not a '${typeof repoCode}' : ${repoCode}`); + parameterAssert(repoName !== undefined, "cBP ourCheckManifestFile: 'repoName' parameter should be defined"); + parameterAssert(typeof repoName === 'string', `cBP ourCheckManifestFile: 'repoName' parameter should be a string not a '${typeof repoName}': ${repoName}`); + parameterAssert(repoBranch !== undefined, "cBP ourCheckManifestFile: 'repoBranch' parameter should be defined"); + parameterAssert(typeof repoBranch === 'string', `cBP ourCheckManifestFile: 'repoBranch' parameter should be a string not a '${typeof repoBranch}': ${repoBranch}`); + parameterAssert(manifestLocation !== undefined, "cBP ourCheckManifestFile: 'manifestLocation' parameter should be defined"); + parameterAssert(typeof manifestLocation === 'string', `cBP ourCheckManifestFile: 'manifestLocation' parameter should be a string not a '${typeof manifestLocation}'`); let manifestFileContent; try { - // debugLog("checkBookPackage ourCheckManifest about to fetch manifest", username, repoName, repoBranch); - manifestFileContent = await getFile_({ username, repository: repoName, path: MANIFEST_FILENAME, branch: repoBranch }); - // debugLog("checkBookPackage ourCheckManifest fetched content for manifest", username, repoName, repoBranch, typeof manifestFileContent, manifestFileContent.length); + // debugLog("checkBookPackage ourCheckManifestFile about to fetch manifest", username, repoName, repoBranch); + manifestFileContent = await getFile_({ username, repository: repoName, path: STANDARD_MANIFEST_FILENAME, branch: repoBranch }); + // debugLog("checkBookPackage ourCheckManifestFile fetched content for manifest", username, repoName, repoBranch, typeof manifestFileContent, manifestFileContent.length); // debugLog(manifestFileContent); } catch (cBPgfError) { - console.error(`checkBookPackage ourCheckManifest(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load manifest`, username, repoName, repoBranch, cBPgfError + ''); + console.error(`checkBookPackage ourCheckManifestFile(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load manifest`, username, repoName, repoBranch, cBPgfError + ''); let details = `username=${username}`; if (! await repositoryExistsOnDoor43({ username, repository: repoName })) checkBookPackageResult.noticeList.push({ priority: 997, message: "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode }); else { // eslint-disable-next-line eqeqeq if (cBPgfError != 'TypeError: repoFileContent is null') details += ` error=${cBPgfError}`; - addNoticePartial({ priority: 996, message: "Unable to load", details: `username=${username} error=${cBPgfError}`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode }); + addNoticePartial({ priority: 996, message: "Unable to load", details: `username=${username} error=${cBPgfError}`, repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: repoCode }); } } if (manifestFileContent) { const cmtResultObject = await checkManifestText(languageCode, repoCode, username, repoName, repoBranch, manifestFileContent, manifestLocation, checkingOptions); - // debugLog(`ourCheckManifest checkManifestText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); - // debugLog(`ourCheckManifest checkManifestText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); + // debugLog(`ourCheckManifestFile checkManifestText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); + // debugLog(`ourCheckManifestFile checkManifestText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); // NOTE: We ignore the returned success messages here // for (const successEntry of cfResultObject.successList) userLog(" ourCheckBPFileContents:", successEntry); // debugLog("cfcResultObject", JSON.stringify(cfcResultObject)); @@ -193,47 +194,50 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // Process noticeList line by line, appending the repoCode as an extra field as we go for (const cfcNoticeEntry of cmtResultObject.noticeList) { // NOTE: We don’t use addNoticePartial, because it adds a misleading BookID - // addNoticePartial({ ...cfcNoticeEntry, filename: MANIFEST_FILENAME, extra: `${repoCode} MANIFEST` }); - checkBookPackageResult.noticeList.push({ ...cfcNoticeEntry, username, repoCode, repoName, filename: MANIFEST_FILENAME, extra: `${repoCode} MANIFEST` }); + // addNoticePartial({ ...cfcNoticeEntry, filename: STANDARD_MANIFEST_FILENAME, extra: `${repoCode} MANIFEST` }); + checkBookPackageResult.noticeList.push({ ...cfcNoticeEntry, username, repoCode, repoName, filename: STANDARD_MANIFEST_FILENAME, extra: `${repoCode} MANIFEST` }); } return manifestFileContent.length; } // NOTE: We don’t use addNoticePartial, because it adds a misleading BookID - // addNoticePartial({ priority: 956, message: "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `${repoCode} MANIFEST` }); - checkBookPackageResult.noticeList.push({ priority: 956, message: "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `${repoCode} MANIFEST` }); + // addNoticePartial({ priority: 956, message: "Got empty manifest file", repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: `${repoCode} MANIFEST` }); + checkBookPackageResult.noticeList.push({ priority: 956, message: "Got empty manifest file", repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: `${repoCode} MANIFEST` }); return 0; } - // end of ourCheckManifest function + // end of ourCheckManifestFile function /** * - * @param {string} repoCode, e.g., TA - * @param {string} repoName, e.g., en_ta - * @param {string} filename, e.g., README.md + * @param {string} repoCode, e.g., 'TA' + * @param {string} repoName, e.g., 'en_ta' + * @param {string} repoBranch, e.g., 'master' + * @param {string} filename, e.g., 'README.md' * @param {string} markdownLocation * @param {Object} checkingOptions */ - async function ourCheckMarkdown(repoCode, repoName, repoBranch, filename, markdownLocation, checkingOptions) { + async function ourCheckMarkdownFile(repoCode, repoName, repoBranch, filename, markdownLocation, checkingOptions) { // Updates the global list of notices - // functionLog(`checkBookPackage ourCheckMarkdown(${repoCode}, ${repoName}, #{repoBranch}, ${markdownLocation}, ${JSON.stringify(checkingOptions)})…`); - parameterAssert(repoCode !== undefined, "cBP ourCheckMarkdown: 'repoCode' parameter should be defined"); - parameterAssert(typeof repoCode === 'string', `cBP ourCheckMarkdown: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); - parameterAssert(repoName !== undefined, "cBP ourCheckMarkdown: 'repoName' parameter should be defined"); - parameterAssert(typeof repoName === 'string', `cBP ourCheckMarkdown: 'repoName' parameter should be a string not a '${typeof repoName}'`); - parameterAssert(repoBranch !== undefined, "cBP ourCheckMarkdown: 'repoBranch' parameter should be defined"); - parameterAssert(typeof repoBranch === 'string', `cBP ourCheckMarkdown: 'repoBranch' parameter should be a string not a '${typeof repoBranch}'`); - parameterAssert(markdownLocation !== undefined, "cBP ourCheckMarkdown: 'markdownLocation' parameter should be defined"); - parameterAssert(typeof markdownLocation === 'string', `cBP ourCheckMarkdown: 'markdownLocation' parameter should be a string not a '${typeof markdownLocation}'`); + // functionLog(`checkBookPackage ourCheckMarkdownFile(${repoCode}, ${repoName}, ${filename}, ${repoBranch}, ${markdownLocation}, ${JSON.stringify(checkingOptions)})…`); + parameterAssert(repoCode !== undefined, "cBP ourCheckMarkdownFile: 'repoCode' parameter should be defined"); + parameterAssert(typeof repoCode === 'string', `cBP ourCheckMarkdownFile: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + parameterAssert(repoName !== undefined, "cBP ourCheckMarkdownFile: 'repoName' parameter should be defined"); + parameterAssert(typeof repoName === 'string', `cBP ourCheckMarkdownFile: 'repoName' parameter should be a string not a '${typeof repoName}'`); + parameterAssert(repoBranch !== undefined, "cBP ourCheckMarkdownFile: 'repoBranch' parameter should be defined"); + parameterAssert(typeof repoBranch === 'string', `cBP ourCheckMarkdownFile: 'repoBranch' parameter should be a string not a '${typeof repoBranch}'`); + parameterAssert(filename !== undefined, "cBP ourCheckMarkdownFile: 'filename' parameter should be defined"); + parameterAssert(typeof filename === 'string', `cBP ourCheckMarkdownFile: 'filename' parameter should be a string not a '${typeof filename}': ${filename}`); + parameterAssert(markdownLocation !== undefined, "cBP ourCheckMarkdownFile: 'markdownLocation' parameter should be defined"); + parameterAssert(typeof markdownLocation === 'string', `cBP ourCheckMarkdownFile: 'markdownLocation' parameter should be a string not a '${typeof markdownLocation}'`); let markdownFileContent; try { - // debugLog("checkBookPackage ourCheckMarkdown about to fetch markdown file", username, repoName, repoBranch, filename); + // debugLog("checkBookPackage ourCheckMarkdownFile about to fetch markdown file", username, repoName, repoBranch, filename); markdownFileContent = await getFile_({ username, repository: repoName, path: filename, branch: repoBranch }); - // debugLog("checkBookPackage ourCheckMarkdown fetched markdown content", username, repoName, repoBranch, filename, typeof markdownFileContent, markdownFileContent.length); + // debugLog("checkBookPackage ourCheckMarkdownFile fetched markdown content", username, repoName, repoBranch, filename, typeof markdownFileContent, markdownFileContent.length); // debugLog(markdownFileContent); } catch (cBPgfError) { - console.error(`checkBookPackage ourCheckMarkdown(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load markdown`, username, repoName, filename, originalBranch, cBPgfError + ''); + console.error(`checkBookPackage ourCheckMarkdownFile(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load markdown`, username, repoName, filename, originalBranch, cBPgfError + ''); let details = `username=${username}`; if (! await repositoryExistsOnDoor43({ username, repository: repoName })) checkBookPackageResult.noticeList.push({ priority: 997, message: "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode }); @@ -245,8 +249,8 @@ export async function checkBookPackage(username, languageCode, bookID, setResult } if (markdownFileContent) { const cmtResultObject = await checkMarkdownText(languageCode, repoCode, repoName, markdownFileContent, markdownLocation, checkingOptions); - // debugLog(`ourCheckMarkdown checkMarkdownText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); - // debugLog(`ourCheckMarkdown checkMarkdownText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); + // debugLog(`ourCheckMarkdownFile checkMarkdownText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); + // debugLog(`ourCheckMarkdownFile checkMarkdownText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); // NOTE: We ignore the returned success messages here // for (const successEntry of cfResultObject.successList) userLog(" ourCheckBPFileContents:", successEntry); // debugLog("cfcResultObject", JSON.stringify(cfcResultObject)); @@ -273,7 +277,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult checkBookPackageResult.noticeList.push({ priority: 956, message: "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode }); return 0; } - // end of ourCheckMarkdown function + // end of ourCheckMarkdownFile function // Main code for checkBookPackage() @@ -304,7 +308,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult addNoticePartial({ priority: 902, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${generalLocation}` }); return checkBookPackageResult; } } - // functionLog(`checkBookPackage: bookNumberAndName='${bookNumberAndName}' (${whichTestament} testament)`); + // debugLog(`checkBookPackage: bookNumberAndName='${bookNumberAndName}' (${whichTestament} testament)`); // So now we want to work through checking this one specified Bible book in various repos const origLangRepoCode = whichTestament === 'old' ? 'UHB' : 'UGNT'; @@ -323,6 +327,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult const checkedManifestDetails = []; let numCheckedRepos = 0; for (const repoCode of repoCodeList) { + // debugLog(`checkBookPackage for ${bookID} got repoCode=${repoCode} abortFlag=${abortFlag} from ${repoCodeList}`); if (abortFlag) break; const repoLocation = ` in ${repoCode}${generalLocation}`; let adjustedRepoCode = repoCode, adjustedBranch = originalBranch; @@ -379,17 +384,18 @@ export async function checkBookPackage(username, languageCode, bookID, setResult } else { // For repos other than OBS and TQ, we only have one file to check let repoFileContent; try { - // debugLog("checkBookPackage about to fetch fileContent for", username, repoName, adjustedBranch, filename); + // debugLog(`checkBookPackage about to fetch fileContent for ${username}, ${repoName}, ${adjustedBranch}, ${filename}`); repoFileContent = await getFile_({ username, repository: repoName, path: filename, branch: adjustedBranch }); - // debugLog("checkBookPackage fetched fileContent for", username, repoName, adjustedBranch, filename, typeof repoFileContent, repoFileContent.length); + // debugLog(`checkBookPackage fetched fileContent for ${username}, ${repoName}, ${adjustedBranch}, ${filename}, ${typeof repoFileContent}, ${repoFileContent.length}`); checkedFilenames.push(filename); totalCheckedSize += repoFileContent.length; checkedRepoNames.add(repoName); } catch (cBPgfError) { - // console.error(`checkBookPackage(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load`, username, repoName, filename, branch, cBPgfError + ''); - // debugLog(`cBPgfError=${cBPgfError} or ${JSON.stringify(cBPgfError)} or2 ${cBPgfError == 'TypeError: repoFileContent is null'} or3 ${cBPgfError.message == 'TypeError: repoFileContent is null'} or4 ${cBPgfError.message === 'TypeError: repoFileContent is null'}`); + // debugLog(`checkBookPackage(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load ${repoName}, ${filename}, ${adjustedBranch}, ${cBPgfError}`); + // debugLog(`cBPgfError=${cBPgfError} or ${JSON.stringify(cBPgfError)} or2 ${cBPgfError === 'TypeError: repoFileContent is null'} or3 ${cBPgfError.message === 'TypeError: repoFileContent is null'} or4 ${cBPgfError.message === 'TypeError: repoFileContent is null'}`); let details = `username=${username}`; - if (! await repositoryExistsOnDoor43({ username, repository: repoName })) + // Next line has special code to handle book-package-check.test.js tests [so we don't call repositoryExistsOnDoor43()] + if (cBPgfError.startsWith('Tests could not find') || ! await repositoryExistsOnDoor43({ username, repository: repoName })) checkBookPackageResult.noticeList.push({ priority: 997, message: "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode }); else { // eslint-disable-next-line eqeqeq @@ -416,7 +422,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (newCheckingOptions?.checkManifestFlag) { // debugLog(`Checking MANIFEST for ${repoName}`); - const numCheckedCharacters = await ourCheckManifest(repoCode, repoName, adjustedBranch, generalLocation, newCheckingOptions); + const numCheckedCharacters = await ourCheckManifestFile(repoCode, repoName, adjustedBranch, generalLocation, newCheckingOptions); if (numCheckedCharacters > 0) { checkedFileCount += 1; checkedFilenames.push('manifest.yaml'); @@ -431,7 +437,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (newCheckingOptions?.checkReadmeFlag) { // debugLog(`Checking README for ${repoName}`); const filename = 'README.md'; - const numCheckedCharacters = await ourCheckMarkdown(repoCode, repoName, adjustedBranch, filename, generalLocation, newCheckingOptions); + const numCheckedCharacters = await ourCheckMarkdownFile(repoCode, repoName, adjustedBranch, filename, generalLocation, newCheckingOptions); if (numCheckedCharacters > 0) { checkedFileCount += 1; checkedFilenames.push(filename); @@ -446,7 +452,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult if (newCheckingOptions?.checkLicenseFlag) { // debugLog(`Checking LICENSE for ${repoName}`); const filename = 'LICENSE.md'; - const numCheckedCharacters = await ourCheckMarkdown(repoCode, repoName, adjustedBranch, filename, generalLocation, newCheckingOptions); + const numCheckedCharacters = await ourCheckMarkdownFile(repoCode, repoName, adjustedBranch, filename, generalLocation, newCheckingOptions); if (numCheckedCharacters > 0) { checkedFileCount += 1; checkedFilenames.push(filename); From 56c806c397dbfb50e3a39a8278aff1bcdd8e2ba8 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Sat, 20 Feb 2021 08:26:29 +1300 Subject: [PATCH 09/16] Check for adjacent \w fields in USFM --- noticeList.txt | 167 +++++----- package.json | 2 +- .../book-package-check.test.js.snap | 248 +++++++-------- src/core/manifest-text-check.js | 28 +- src/core/markdown-text-check.js | 4 +- src/core/twl-tsv6-row-check.js | 4 +- src/core/usfm-text-check.js | 40 ++- src/core/utilities.js | 8 +- src/demos/repo-check/checkRepo.js | 4 +- yarn.lock | 293 +++++++++--------- 10 files changed, 406 insertions(+), 392 deletions(-) diff --git a/noticeList.txt b/noticeList.txt index a16e030fd..c42eafe50 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,10 +1,10 @@ -Last updated 2021-02-17 20:41:30.385127 by makeNoticeList.py -Got 469 notices: +Last updated 2021-02-20 08:26:26.258391 by makeNoticeList.py +Got 470 notices: checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 256 - languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 927 - marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 955 - `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,034 - C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,127 + languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 941 + marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 969 + `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,048 + C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,141 const notice = 95, "Unexpected trailing space(s)", excerpt, location: ourLocation ; from field-text-check.js line 193 notice from field-text-check.js line 196 notice = 124, "Unexpected double spaces", excerpt, location: ourLocation ; from field-text-check.js line 227 @@ -58,9 +58,9 @@ Got 469 notices: 988, "Bad TSV header", details: `expected '$EXPECTED_TWL_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from twl-tsv6-table-check.js line 117 988, "Bad TSV header", details: `expected '$EXPECTED_NOTES_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from notes-tsv7-table-check.js line 117 988, "Bad TSV header", details: `expected '$EXPECTED_QUESTIONS_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from questions-tsv7-table-check.js line 117 - 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,111 + 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,125 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 - 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 691 + 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 697 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 561 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv7-row-check.js line 502 @@ -90,13 +90,13 @@ Got 469 notices: 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 283 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 943, `USFM3 toJSON Check doesn’t pass`, location: ourLocation from usfm-js-check.js line 91 - 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,161 - 939, "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 703 - 938, `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 720 - 937, `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 722 - 936, `Error loading manifest project link`, details: trcGCerror, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 724 - 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 656 - 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 654 + 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,175 + 939, "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 709 + 938, `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 726 + 937, `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 728 + 936, `Error loading manifest project link`, details: trcGCerror, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 730 + 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 662 + 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 660 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 174 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 364 919, "Missing Quote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 487 @@ -114,11 +114,11 @@ Got 469 notices: 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 405 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 326 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 323 - 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 660 - 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 716 + 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 674 + 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 730 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 361 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 370 - 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 976 + 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ourLocation from usfm-text-check.js line 990 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 308 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 76 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 105 @@ -132,41 +132,41 @@ Got 469 notices: 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 303 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 309 879, `Badly formatted Resource Container link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 - 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 763 - 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 567 - 869, "Chapter number out of range", C: chapterNumberString, excerpt: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 417 - 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, excerpt: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 456 - 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 470 - 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 475 - 857, "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 808 - 856, "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 811 - 855, "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 814 - 854, "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 817 - 854, "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 820 - 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 823 - 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 - 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 829 + 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 777 + 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 569 + 869, "Chapter number out of range", C: chapterNumberString, excerpt: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 419 + 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, excerpt: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 458 + 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 472 + 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 477 + 857, "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 822 + 856, "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 + 855, "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 828 + 854, "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 831 + 854, "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 834 + 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 837 + 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 839 + 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 843 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 295 849, `Unexpected '$badCharCombination' character combination`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 371 - 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 - 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 - 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 838 + 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 847 + 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 850 + 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 852 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 805 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 809 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 816 - 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 857 - 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 859 - 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 843 - 836, "Seems too few translation \\w attributes", details: `Expected two attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 845 - 835, "Seems too few original \\k-s attributes", details: `Expected one attribute but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 862 - 834, "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 894 - 833, "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 891 - 830, "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 874 - 829, "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 877 - 828, "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 880 - 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 883 - 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 886 - 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 889 + 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 871 + 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 873 + 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 857 + 836, "Seems too few translation \\w attributes", details: `Expected two attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 859 + 835, "Seems too few original \\k-s attributes", details: `Expected one attribute but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 876 + 834, "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 908 + 833, "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 905 + 830, "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 888 + 829, "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 891 + 828, "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 894 + 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 897 + 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 900 + 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 903 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 281 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 386 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 334 @@ -176,8 +176,8 @@ Got 469 notices: 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 339 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 369 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 299 - 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 919 - 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 923 + 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 933 + 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 937 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 401 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 352 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 382 @@ -189,7 +189,7 @@ Got 469 notices: 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 409 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv7-row-check.js line 361 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 391 - 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 597 + 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 599 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 317 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 418 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 370 @@ -211,8 +211,8 @@ Got 469 notices: 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv7-row-check.js line 383 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 413 799, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 412 - 798, "Field doesn't contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 396 - 797, "Field doesn't contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation from twl-tsv6-row-check.js line 403 + 798, "Field doesn’t contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 396 + 797, "Field doesn’t contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation from twl-tsv6-row-check.js line 403 796, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 393 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 378 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 501 @@ -241,22 +241,22 @@ Got 469 notices: 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 389 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 419 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 203 - 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 750 - 775, "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 755 + 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 764 + 775, "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 769 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 210 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 171 772, `Unexpected trailing word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 166 771, `Unexpected leading zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 149 770, `Unexpected leading word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 145 - 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,087 + 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,101 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation from plain-text-check.js line 228 - 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,089 + 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,103 765, "Unexpected link", characterIndex, excerpt, location: ourLocation from field-text-check.js line 444 - 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,060 - 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,073 - 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 444 - 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 - 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,104 + 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,074 + 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,087 + 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 446 + 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,097 + 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,118 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 762 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 369 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 492 @@ -333,12 +333,12 @@ Got 469 notices: 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 224 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 223 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 223 - 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,056 - 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,069 - 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,100 + 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,070 + 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 + 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,114 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 425 - 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 952 - 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,020 + 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 966 + 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,034 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 778 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 384 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 421 @@ -358,10 +358,10 @@ Got 469 notices: 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 727 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 797 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 791 - 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 254 + 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 256 638, "Only found whitespace", location: ourLocation from field-text-check.js line 111 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 131 - 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 990 + 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,004 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 117 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 150 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 158 @@ -380,15 +380,16 @@ Got 469 notices: 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 181 539, "File starts with empty line", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 153 538, "File ends without newline character", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 158 - 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 601 - 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 609 - 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 605 + 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 603 + 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 611 + 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 607 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 229 + 444, "Shouldn’t have consecutive word fields without a space", details: badCount> 1? details+`$badCount occurrences found in line`: details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 645 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 149 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 121 - 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 950 - 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,124 + 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 964 + 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,138 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 332 375, "Divider without surrounding snippet", location: ourLocation from orig-quote-check.js line 332 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 390 @@ -409,15 +410,15 @@ Got 469 notices: 349, "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 144 349, "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 163 348, "Markdown image link has no title text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 165 - 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 684 - 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 948 + 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 698 + 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 962 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 163 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 547 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 463 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 488 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 522 256, "Possibly missing current copyright year", details: `possibly expecting '$fullYearString'`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 270 - 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 612 + 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 614 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 322 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 267 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 273 @@ -440,7 +441,7 @@ Got 469 notices: 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 256 158, `Unexpected space(s) beside divider $discontiguousDivider`, characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 265 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 279 - 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 658 + 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 664 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 747 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 346 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 483 @@ -454,14 +455,14 @@ Got 469 notices: 109, `Unexpected leading space`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 142 107, "Unexpected leading line break", characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 181 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, excerpt, location: ourLocation from field-text-check.js line 214 - 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,165 - 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 248 + 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,179 + 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 250 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 184 94, "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 201 93, "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 206 - 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,117 - 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,119 - 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 468 + 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,131 + 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,133 + 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 470 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 155 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 160 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 305 diff --git a/package.json b/package.json index 07ea95be5..07e27a4f0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha4", + "version": "2.0.0_alpha5", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/__snapshots__/book-package-check.test.js.snap b/src/__tests__/__snapshots__/book-package-check.test.js.snap index 2b0b02750..93d2ec842 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -302,7 +302,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "it,'", "extra": "LT", "filename": "08-RUT.usfm", @@ -429,7 +429,7 @@ Object { "V": "3", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Naomi's", "extra": "ST", "filename": "08-RUT.usfm", @@ -446,7 +446,7 @@ Object { "V": "8", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…n-law,␣\\"Each", "extra": "ST", "filename": "08-RUT.usfm", @@ -498,7 +498,7 @@ Object { "V": "8", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "mother's", "extra": "ST", "filename": "08-RUT.usfm", @@ -515,7 +515,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "home.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -532,7 +532,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "said,␣\\"No!", "extra": "ST", "filename": "08-RUT.usfm", @@ -584,7 +584,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…atives.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -601,7 +601,7 @@ Object { "V": "11", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "said,␣\\"No,", "extra": "ST", "filename": "08-RUT.usfm", @@ -653,7 +653,7 @@ Object { "V": "13", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "mine.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -670,7 +670,7 @@ Object { "V": "15", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "her,␣\\"Look!", "extra": "ST", "filename": "08-RUT.usfm", @@ -722,7 +722,7 @@ Object { "V": "15", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "her!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -739,7 +739,7 @@ Object { "V": "16", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…plied,␣\\"No!", "extra": "ST", "filename": "08-RUT.usfm", @@ -791,7 +791,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "die.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -808,7 +808,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…aimed,␣\\"It", "extra": "ST", "filename": "08-RUT.usfm", @@ -860,7 +860,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Naomi!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -877,7 +877,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "them,␣\\"You", "extra": "ST", "filename": "08-RUT.usfm", @@ -929,7 +929,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "means␣'pleasan…", "extra": "ST", "filename": "08-RUT.usfm", @@ -981,7 +981,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "means␣'bitter.…", "extra": "ST", "filename": "08-RUT.usfm", @@ -1033,7 +1033,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "badly.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1050,7 +1050,7 @@ Object { "V": "1", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Naomi's", "extra": "ST", "filename": "08-RUT.usfm", @@ -1067,7 +1067,7 @@ Object { "V": "1", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…limelek's", "extra": "ST", "filename": "08-RUT.usfm", @@ -1084,7 +1084,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Naomi,␣\\"Let", "extra": "ST", "filename": "08-RUT.usfm", @@ -1136,7 +1136,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…ission.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1153,7 +1153,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"Go", "extra": "ST", "filename": "08-RUT.usfm", @@ -1205,7 +1205,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…ughter.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1222,7 +1222,7 @@ Object { "V": "3", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…limelek's", "extra": "ST", "filename": "08-RUT.usfm", @@ -1239,7 +1239,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…aying,␣\\"May", "extra": "ST", "filename": "08-RUT.usfm", @@ -1291,7 +1291,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "you!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1308,7 +1308,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"May", "extra": "ST", "filename": "08-RUT.usfm", @@ -1360,7 +1360,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "you!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1377,7 +1377,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…reman,␣\\"Who", "extra": "ST", "filename": "08-RUT.usfm", @@ -1429,7 +1429,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "to?\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1446,7 +1446,7 @@ Object { "V": "6", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"She", "extra": "ST", "filename": "08-RUT.usfm", @@ -1498,7 +1498,7 @@ Object { "V": "7", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "me,␣'Please", "extra": "ST", "filename": "08-RUT.usfm", @@ -1550,7 +1550,7 @@ Object { "V": "7", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "behind.'", "extra": "ST", "filename": "08-RUT.usfm", @@ -1567,7 +1567,7 @@ Object { "V": "7", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…helter.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1584,7 +1584,7 @@ Object { "V": "8", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Ruth,␣\\"Young", "extra": "ST", "filename": "08-RUT.usfm", @@ -1636,7 +1636,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "filled.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1653,7 +1653,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…aimed,␣\\"Why", "extra": "ST", "filename": "08-RUT.usfm", @@ -1705,7 +1705,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…eigner!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1722,7 +1722,7 @@ Object { "V": "11", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"People", "extra": "ST", "filename": "08-RUT.usfm", @@ -1774,7 +1774,7 @@ Object { "V": "12", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "full.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1791,7 +1791,7 @@ Object { "V": "13", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"Sir,", "extra": "ST", "filename": "08-RUT.usfm", @@ -1843,7 +1843,7 @@ Object { "V": "13", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "girls!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1860,7 +1860,7 @@ Object { "V": "14", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "her,␣\\"Come", "extra": "ST", "filename": "08-RUT.usfm", @@ -1912,7 +1912,7 @@ Object { "V": "14", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "it.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1929,7 +1929,7 @@ Object { "V": "15", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…rkers,␣\\"Even", "extra": "ST", "filename": "08-RUT.usfm", @@ -1981,7 +1981,7 @@ Object { "V": "16", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "her.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -1998,7 +1998,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "her,␣\\"Where", "extra": "ST", "filename": "08-RUT.usfm", @@ -2050,7 +2050,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "you.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2067,7 +2067,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "said,␣\\"The", "extra": "ST", "filename": "08-RUT.usfm", @@ -2119,7 +2119,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Boaz.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2136,7 +2136,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…n-law,␣\\"May", "extra": "ST", "filename": "08-RUT.usfm", @@ -2188,7 +2188,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "died.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2205,7 +2205,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "added,␣\\"That", "extra": "ST", "filename": "08-RUT.usfm", @@ -2257,7 +2257,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "family.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2274,7 +2274,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "said,␣\\"He", "extra": "ST", "filename": "08-RUT.usfm", @@ -2326,7 +2326,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "me,␣'Stay", "extra": "ST", "filename": "08-RUT.usfm", @@ -2378,7 +2378,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "field.'\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2395,7 +2395,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "field.'\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2412,7 +2412,7 @@ Object { "V": "22", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Ruth,␣\\"My", "extra": "ST", "filename": "08-RUT.usfm", @@ -2464,7 +2464,7 @@ Object { "V": "22", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "else's", "extra": "ST", "filename": "08-RUT.usfm", @@ -2481,7 +2481,7 @@ Object { "V": "22", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "you.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2498,7 +2498,7 @@ Object { "V": "23", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Boaz's", "extra": "ST", "filename": "08-RUT.usfm", @@ -2515,7 +2515,7 @@ Object { "V": "1", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Ruth,␣\\"My", "extra": "ST", "filename": "08-RUT.usfm", @@ -2567,7 +2567,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Boaz's", "extra": "ST", "filename": "08-RUT.usfm", @@ -2584,7 +2584,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "do.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2601,7 +2601,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"I", "extra": "ST", "filename": "08-RUT.usfm", @@ -2653,7 +2653,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "do.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2670,7 +2670,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "her,␣\\"Who", "extra": "ST", "filename": "08-RUT.usfm", @@ -2722,7 +2722,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "you?\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2739,7 +2739,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"I", "extra": "ST", "filename": "08-RUT.usfm", @@ -2791,7 +2791,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "husband's", "extra": "ST", "filename": "08-RUT.usfm", @@ -2808,7 +2808,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "me.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2825,7 +2825,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"May", "extra": "ST", "filename": "08-RUT.usfm", @@ -2877,7 +2877,7 @@ Object { "V": "12", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Naomi's", "extra": "ST", "filename": "08-RUT.usfm", @@ -2894,7 +2894,7 @@ Object { "V": "13", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…orning.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2911,7 +2911,7 @@ Object { "V": "14", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "added,␣\\"It", "extra": "ST", "filename": "08-RUT.usfm", @@ -2963,7 +2963,7 @@ Object { "V": "14", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "here.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -2980,7 +2980,7 @@ Object { "V": "15", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "her,␣\\"Bring", "extra": "ST", "filename": "08-RUT.usfm", @@ -3032,7 +3032,7 @@ Object { "V": "15", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "out.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3049,7 +3049,7 @@ Object { "V": "16", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "her,␣\\"Is", "extra": "ST", "filename": "08-RUT.usfm", @@ -3101,7 +3101,7 @@ Object { "V": "16", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…ughter?\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3118,7 +3118,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Naomi,␣\\"He", "extra": "ST", "filename": "08-RUT.usfm", @@ -3170,7 +3170,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…aying,␣'I", "extra": "ST", "filename": "08-RUT.usfm", @@ -3222,7 +3222,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…thing.'\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3239,7 +3239,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…othing.'\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3256,7 +3256,7 @@ Object { "V": "18", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "said,␣\\"My", "extra": "ST", "filename": "08-RUT.usfm", @@ -3308,7 +3308,7 @@ Object { "V": "18", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "today.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3325,7 +3325,7 @@ Object { "V": "1", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "said,␣\\"Come", "extra": "ST", "filename": "08-RUT.usfm", @@ -3377,7 +3377,7 @@ Object { "V": "1", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "down.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3394,7 +3394,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "them,␣\\"Please", "extra": "ST", "filename": "08-RUT.usfm", @@ -3446,7 +3446,7 @@ Object { "V": "2", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…siness.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3463,7 +3463,7 @@ Object { "V": "3", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…ative,␣\\"Did", "extra": "ST", "filename": "08-RUT.usfm", @@ -3515,7 +3515,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "you.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3532,7 +3532,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…plied,␣\\"I", "extra": "ST", "filename": "08-RUT.usfm", @@ -3584,7 +3584,7 @@ Object { "V": "4", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "it!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3601,7 +3601,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "him,␣\\"When", "extra": "ST", "filename": "08-RUT.usfm", @@ -3653,7 +3653,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…elative's", "extra": "ST", "filename": "08-RUT.usfm", @@ -3670,7 +3670,7 @@ Object { "V": "5", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "…usband.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3687,7 +3687,7 @@ Object { "V": "6", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "said,␣\\"Then", "extra": "ST", "filename": "08-RUT.usfm", @@ -3739,7 +3739,7 @@ Object { "V": "6", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "son's", "extra": "ST", "filename": "08-RUT.usfm", @@ -3756,7 +3756,7 @@ Object { "V": "6", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "it.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3773,7 +3773,7 @@ Object { "V": "8", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Boaz,␣\\"You", "extra": "ST", "filename": "08-RUT.usfm", @@ -3825,7 +3825,7 @@ Object { "V": "8", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "…urself!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3842,7 +3842,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "there,␣\\"Today", "extra": "ST", "filename": "08-RUT.usfm", @@ -3894,7 +3894,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Mahlon's", "extra": "ST", "filename": "08-RUT.usfm", @@ -3911,7 +3911,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "Mahlon's", "extra": "ST", "filename": "08-RUT.usfm", @@ -3928,7 +3928,7 @@ Object { "V": "10", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "them.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -3945,7 +3945,7 @@ Object { "V": "11", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "said,␣\\"Yes,", "extra": "ST", "filename": "08-RUT.usfm", @@ -3997,7 +3997,7 @@ Object { "V": "12", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "woman.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -4014,7 +4014,7 @@ Object { "V": "14", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Naomi,␣\\"Praise", "extra": "ST", "filename": "08-RUT.usfm", @@ -4066,7 +4066,7 @@ Object { "V": "15", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "old.\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -4083,7 +4083,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "said,␣\\"It", "extra": "ST", "filename": "08-RUT.usfm", @@ -4135,7 +4135,7 @@ Object { "V": "17", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\w)", + "details": "line marker='\\\\w'", "excerpt": "son!\\"", "extra": "ST", "filename": "08-RUT.usfm", @@ -4152,7 +4152,7 @@ Object { "V": "18", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Perez's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4169,7 +4169,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\v)", + "details": "line marker='\\\\v'", "excerpt": "…␣Hezron's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4186,7 +4186,7 @@ Object { "V": "19", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Ram's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4203,7 +4203,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\v)", + "details": "line marker='\\\\v'", "excerpt": "…minadab's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4220,7 +4220,7 @@ Object { "V": "20", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Nahshon's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4237,7 +4237,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\v)", + "details": "line marker='\\\\v'", "excerpt": "…␣Salmon's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4254,7 +4254,7 @@ Object { "V": "21", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Boaz's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4271,7 +4271,7 @@ Object { "V": "22", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\v)", + "details": "line marker='\\\\v'", "excerpt": "22␣Obed's", "extra": "ST", "filename": "08-RUT.usfm", @@ -4288,7 +4288,7 @@ Object { "V": "22", "bookID": "RUT", "branch": "master", - "details": "(line marker=\\\\zaln-s)", + "details": "line marker='\\\\zaln-s'", "excerpt": "Jesse's", "extra": "ST", "filename": "08-RUT.usfm", diff --git a/src/core/manifest-text-check.js b/src/core/manifest-text-check.js index cb9ca38b3..bf5f71d25 100644 --- a/src/core/manifest-text-check.js +++ b/src/core/manifest-text-check.js @@ -7,15 +7,16 @@ import { removeDisabledNotices } from './disabled-notices'; import { parameterAssert } from './utilities'; -const MANIFEST_VALIDATOR_VERSION_STRING = '0.4.0'; +const MANIFEST_VALIDATOR_VERSION_STRING = '0.4.1'; // Pasted in 2020-10-02 from https://raw.githubusercontent.com/unfoldingWord/dcs/master/options/schema/rc.schema.json +// Updated 2021-02-19 const MANIFEST_SCHEMA = { "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://resource-container.readthedocs.io/schema/rc.schema.json", "$$target": [ - "rc.schema.json#/definitions/languageTag", - "rc.schema.json#/definitions/localizedText" + "rc.schema.json#/definitions/languageTag", + "rc.schema.json#/definitions/localizedText" ], "title": "Root", "type": "object", @@ -63,7 +64,7 @@ const MANIFEST_SCHEMA = { "title": "Contributor", "type": "array", "default": [], - "items": { + "items":{ "$id": "#root/dublin_core/contributor/items", "title": "Items", "type": "string", @@ -172,7 +173,7 @@ const MANIFEST_SCHEMA = { "title": "Relation", "type": "array", "default": [], - "items": { + "items":{ "$id": "#root/dublin_core/relation/items", "$ref": "#/definitions/relationItem", "title": "Items", @@ -200,7 +201,7 @@ const MANIFEST_SCHEMA = { "title": "Source", "type": "array", "default": [], - "items": { + "items":{ "$id": "#root/dublin_core/source/items", "title": "Items", "type": "object", @@ -257,9 +258,14 @@ const MANIFEST_SCHEMA = { "OBS Translation Notes", "OBS Translation Questions", "Open Bible Stories", + "Study Notes", + "Study Questions", "Translation Academy", "Translation Notes", "Translation Questions", + "TSV Study Notes", + "TSV Study Questions", + "TSV Translation Questions", "Translation Words", "TSV Translation Notes" ] @@ -308,7 +314,7 @@ const MANIFEST_SCHEMA = { "title": "Checking_entity", "type": "array", "default": [], - "items": { + "items":{ "$id": "#root/checking/checking_entity/items", "title": "Items", "type": "string", @@ -336,7 +342,7 @@ const MANIFEST_SCHEMA = { "title": "Projects", "type": "array", "default": [], - "items": { + "items":{ "$id": "#root/projects/items", "title": "Items", "type": "object", @@ -390,7 +396,7 @@ const MANIFEST_SCHEMA = { "title": "Categories", "type": ["array", "null"], "default": [], - "items": { + "items":{ "$id": "#root/projects/items/categories/items", "title": "Items", "type": "string", @@ -415,10 +421,10 @@ const MANIFEST_SCHEMA = { "localizedText": { "type": "object", "additionalProperties": { - "$ref": "#/definitions/trimmedText" + "$ref": "#/definitions/trimmedText" }, "propertyNames": { - "$ref": "#/definitions/languageTag" + "$ref": "#/definitions/languageTag" }, "minProperties": 1, "description": "A textual string specified in one or multiple languages, indexed by IETF language tag." diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index c34346c6c..95ddc4830 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -2,7 +2,7 @@ import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTextField } from './field-text-check'; import { cachedGetFileUsingFullURL } from '../core/getApi'; import { removeDisabledNotices } from './disabled-notices'; -import { userLog, parameterAssert, dataAssert } from './utilities'; +import { parameterAssert, dataAssert } from './utilities'; const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.6.0'; @@ -352,8 +352,6 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, else addSuccessMessage(`No errors or warnings found by checkMarkdownText v${MARKDOWN_TEXT_VALIDATOR_VERSION_STRING}`) // debugLog(` checkMarkdownText returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); - if (textOrFileName.endsWith('walk.md')) - userLog("checkMarkdownText result is", JSON.stringify(result)); return result; } // end of checkMarkdownText function diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index 541afdb54..86a41df07 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -393,14 +393,14 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, addNoticePartial({ priority: 796, message: "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation }); else { // More than just whitespace if (!TWLink.startsWith('rc://*/tw/dict/bible/')) - addNoticePartial({ priority: 798, message: "Field doesn't contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation }); + addNoticePartial({ priority: 798, message: "Field doesn’t contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation }); else { // it starts correctly const bits = TWLink.substring('rc://*/tw/dict/bible/'.length).split('/'); // debugLog(`checkTWL_TSV6DataRow checking ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); if (bits[0] !== 'kt' && bits[0] !== 'names' && bits[0] !== 'other') { const characterIndex = 'rc://*/tw/dict/bible/'.length; const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + TWLink.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < TWLink.length ? '…' : '') - addNoticePartial({ priority: 797, message: "Field doesn't contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); + addNoticePartial({ priority: 797, message: "Field doesn’t contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); } else { // all good so far // debugLog(`checkTWL_TSV6DataRow looking up ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); await ourcheckNotesLinksToOutside(rowID, 'TWLink', TWLink, ourRowLocation, linkCheckingOptions); diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 627597b6c..64f21ce3f 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -8,7 +8,7 @@ import { userLog, parameterAssert, dataAssert, ourParseInt } from './utilities'; import { removeDisabledNotices } from './disabled-notices'; -// const USFM_VALIDATOR_VERSION_STRING = '0.8.3'; +// const USFM_VALIDATOR_VERSION_STRING = '0.8.5'; const VALID_LINE_START_CHARACTERS = `([“‘`; // '{' gets added for STs @@ -208,7 +208,9 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex parameterAssert(typeof noticeObject.location === 'string', `cUSFM addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); // Doublecheck -- we don’t want "Mismatched {}" per line, only per file - parameterAssert(noticeObject.message.indexOf("Mismatched {}") < 0 || noticeObject.lineNumber === undefined, `checkUSFMText addNoticePartial: got bad notice: ${JSON.stringify(noticeObject)}`); + const noticeObjectString = JSON.stringify(noticeObject); + parameterAssert(noticeObject.message.indexOf("Mismatched {}") === -1 || noticeObject.lineNumber === undefined, `checkUSFMText addNoticePartial: got bad notice: ${noticeObjectString}`); + parameterAssert(noticeObjectString.indexOf('NONE') === -1 && noticeObjectString.indexOf('SPECIAL') === -1, `'NONE' & 'SPECIAL' shouldn't make it thru to end user: ${noticeObjectString}`) if (noticeObject.debugChain) noticeObject.debugChain = `checkUSFMText ${noticeObject.debugChain}`; result.noticeList.push({ ...noticeObject, bookID, filename }); } @@ -629,7 +631,19 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // functionLog(`checkUSFMLineText(${lineNumber}, ${C}:${V}, ${marker}='${rest}', ${lineLocation}, ${JSON.stringify(checkingOptions)})…`); // functionLog(`checkUSFMLineText(${lineNumber}, ${C}:${V}, ${marker}=${rest.length} chars, ${lineLocation}, ${JSON.stringify(checkingOptions)})…`); - const details = `(line marker=\\${marker})` + const details = `line marker='\\${marker}'` + + // Check that no \w markers touch, i.e., shouldn't have '\w*\w' in file + let characterIndex; + if ((characterIndex = rest.indexOf('\\w*\\w')) >= 0) { + // NOTE: There's one example of this in ULT 1 Kings 6:1 "480th" + // \w 480|x-occurrence="1" x-occurrences="1"\w*\w th|x-occurrence="1" x-occurrences="1"\w* + // Also UST Ezra 6:19 "14th" and Ezra 10:9 "20th" + // TODO: Do we want to disable this particular case, or to look for ordinal numbers??? + const badCount = countOccurrences(rest, '\\w*\\w'); + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + rest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < rest.length ? '…' : '') + addNoticePartial({ priority: 444, message: "Shouldn’t have consecutive word fields without a space", details: badCount> 1? details+`${badCount} occurrences found in line`: details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); + } // Remove any self-closed milestones and internal \v markers // NOTE: replaceAll() is not generally available in browsers yet, so need to use RegExps @@ -785,7 +799,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // functionLog(`checkUSFMLineAttributes(${lineNumber}, ${C}:${V}, ${marker}='${rest}', ${lineLocation}, ${JSON.stringify(checkingOptions)})…`); // functionLog(`checkUSFMLineAttributes(${lineNumber}, ${C}:${V}, ${marker}=${rest.length} chars, ${lineLocation}, ${JSON.stringify(checkingOptions)})…`); - const details = `(line marker=\\${marker})` + const details = `line marker='\\${marker}'` // Put marker inside string so easy to do RegExp searches const adjustedRest = `\\${marker} ${rest}`; @@ -909,7 +923,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex */ function checkUSFMLineContents(lineNumber, C, V, marker, rest, lineLocation, checkingOptions) { // Looks at the marker and determines what content is allowed/expected on the rest of the line - // 'SPECIAL1' is used internally here when a character other than a backslash starts a line + // 'SPECIAL' is used internally here when a character other than a backslash starts a line function checkUSFMLineInternals(lineNumber, C, V, marker, rest, lineLocation, checkingOptions) { // Handles character formatting within the line contents @@ -932,8 +946,8 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (rest.indexOf('=') >= 0 || rest.indexOf('"') >= 0) checkUSFMLineAttributes(lineNumber, C, V, marker, rest, lineLocation, checkingOptions); - const allowedLinks = (marker === 'w' || marker === 'k-s' || marker === 'f' || marker === 'SPECIAL1') - // (because we don’t know what marker SPECIAL1 is, so default to "no false alarms") + const allowedLinks = (marker === 'w' || marker === 'k-s' || marker === 'f' || marker === 'SPECIAL') + // (because we don’t know what marker SPECIAL is, so default to "no false alarms") && rest.indexOf('x-tw') >= 0; ourCheckTextField(lineNumber, C, V, 'USFM', `\\${marker}`, rest, allowedLinks, lineLocation, checkingOptions); } @@ -942,7 +956,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // Main code for checkUSFMLineContents() - if (ALLOWED_LINE_START_MARKERS.indexOf(marker) >= 0 || marker === 'SPECIAL1') { + if (ALLOWED_LINE_START_MARKERS.indexOf(marker) >= 0 || marker === 'SPECIAL' || marker === 'NONE') { if (rest && MARKERS_WITHOUT_CONTENT.indexOf(marker) >= 0) if (isWhitespace(rest)) addNoticePartial({ priority: 301, message: `Unexpected whitespace after \\${marker} marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation }); @@ -973,7 +987,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticePartial({ priority: 903, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '${bookID}')${ourLocation}` }); + addNoticePartial({ priority: 903, message: "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ourLocation }); } function findStartMarker(C, V, lineNumber, USFMline) { @@ -1029,7 +1043,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // NOTE: Some unfoldingWord USFM Bibles commonly have this // so it’s not necessarily either an error or a warning rest = line; - if (validLineStartCharacters.indexOf(line[0]) < 0) { // These are the often expected characters + if (validLineStartCharacters.indexOf(line[0]) === -1) { // These are the often expected characters // Drop the priority if it’s a "half-likely" character addNoticePartial({ priority: `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, message: "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation }); if (line[1] === '\\') { // Let’s drop the leading punctuation and try to check the rest of the line @@ -1038,10 +1052,10 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // debugLog(`USFM after ${line[0]} got '\\${marker}': '${rest}'`); } else - marker = 'rem'; // to try to avoid consequential errors, but the rest of the line won’t be checked + marker = 'NONE'; // to try to avoid consequential errors, but the rest of the line won’t be checked } else { // How do we handle an allowed line that doesn’t start with a backslash? - // Can’t use 'rem' because we want the rest of the line checked - marker = 'SPECIAL1'; // Handle as a special case + // Can’t use 'NONE' because we want the rest of the line checked + marker = 'SPECIAL'; // Handle as a special case } } markerSet.add(marker); // Keep track of all line markers diff --git a/src/core/utilities.js b/src/core/utilities.js index b0a37493e..d9edd1a84 100644 --- a/src/core/utilities.js +++ b/src/core/utilities.js @@ -1,4 +1,4 @@ -// utilities +// utilities.js /** @@ -7,9 +7,9 @@ * @param {string} optionalParameter2 */ export function userLog(logString, optionalParameter2) { - if (optionalParameter2) userLog(`userLog note: we have a 2nd parameter: '${optionalParameter2}' after '${logString}'`); // We can remove them all by disabling the next line console.log(`uw-content-validation: ${logString}`); + if (optionalParameter2) userLog(`userLog note: we have a 2nd parameter: '${optionalParameter2}'`); } @@ -19,9 +19,9 @@ export function userLog(logString, optionalParameter2) { * @param {string} optionalParameter2 */ export function debugLog(logString, optionalParameter2) { - if (optionalParameter2) debugLog(`debugLog note: we have a 2nd parameter: '${optionalParameter2}' after '${logString}'`); // We can remove them all by disabling the next line console.log(`uw-content-validation debug: ${logString}`); + if (optionalParameter2) debugLog(`debugLog note: we have a 2nd parameter: '${optionalParameter2}'`); } @@ -31,9 +31,9 @@ export function debugLog(logString, optionalParameter2) { * @param {string} optionalParameter2 */ export function functionLog(logString, optionalParameter2) { - if (optionalParameter2) functionLog(`functionLog note: we have a 2nd parameter: '${optionalParameter2}' after '${logString}'`); // We can remove them all by disabling the next line console.log(`uw-content-validation function call: ${logString}`); + if (optionalParameter2) functionLog(`functionLog note: we have a 2nd parameter: '${optionalParameter2}'`); } diff --git a/src/demos/repo-check/checkRepo.js b/src/demos/repo-check/checkRepo.js index eefd5ab4d..317b555ba 100644 --- a/src/demos/repo-check/checkRepo.js +++ b/src/demos/repo-check/checkRepo.js @@ -4,7 +4,7 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { logicAssert, parameterAssert, repositoryExistsOnDoor43, getFileListFromZip, cachedGetFile, cachedGetRepositoryZipFile } from '../../core'; -// const REPO_VALIDATOR_VERSION_STRING = '0.4.6'; +// const REPO_VALIDATOR_VERSION_STRING = '0.4.7'; /** @@ -231,7 +231,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe bookID = (bookOrFileCode.length === 6 || bookOrFileCode.length === 7) ? bookOrFileCode.substring(0, 3) : bookOrFileCode.slice(-3).toUpperCase(); logicAssert(bookID !== 'twl' && bookID !== 'TWL', `Should get a valid bookID here, not '${bookID}'`) // debugLog(`Have TSV bookcode(${bookID.length})='${bookID}'`); - if (repoCode === 'TWL') + if (repoCode === 'TWL' || repoCode === 'SN' || repoCode === 'SQ' || repoCode === 'TN2' || repoCode === 'TQ2') // new repos parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for TSV)`); else parameterAssert(bookID !== 'OBS' && books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for TSV)`); diff --git a/yarn.lock b/yarn.lock index 822a475c1..5549043a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@babel/cli@^7.12.1": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.16.tgz#bde5bc5118d90e539603abcd37938c5f0fd6c87a" - integrity sha512-cKWkNCxbpjSuYLbdeJs4kOnyW1E2D65pu7SodXDOkzahIN/wSgT8geIqf6+pJTgCo47zrOMGcJTmjSFe5WKYwQ== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.17.tgz#2db13a0f2ba9c05bed78b8aad9669b473dd7f267" + integrity sha512-R9dQbDshWvAp3x5XjANsfthqka+ToEdDUonKgtALNgzQxgiUg2Xa4ZwKIcE84wnoiobIJFXF+TCM4ylJvUuW5w== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -68,18 +68,18 @@ source-map "^0.5.0" "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.16.tgz#8c6ba456b23b680a6493ddcfcd9d3c3ad51cab7c" - integrity sha512-t/hHIB504wWceOeaOoONOhu+gX+hpjfeN6YRBT209X/4sibZQfSF1I0HFRRlBe97UZZosGx5XwUg1ZgNbelmNw== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.17.tgz#993c5e893333107a2815d8e0d73a2c3755e280b2" + integrity sha512-V3CuX1aBywbJvV2yzJScRxeiiw0v2KZZYYE3giywxzFJL13RiyPjaaDwhDnxmgFTTS7FgvM2ijr4QmKNIu0AtQ== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.15" - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helpers" "^7.12.13" - "@babel/parser" "^7.12.16" + "@babel/generator" "^7.12.17" + "@babel/helper-module-transforms" "^7.12.17" + "@babel/helpers" "^7.12.17" + "@babel/parser" "^7.12.17" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.12.17" + "@babel/types" "^7.12.17" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -88,12 +88,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.13", "@babel/generator@^7.12.15", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" - integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== +"@babel/generator@^7.12.17", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.17.tgz#9ef1dd792d778b32284411df63f4f668a9957287" + integrity sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.12.17" jsesc "^2.5.1" source-map "^0.5.0" @@ -112,31 +112,31 @@ "@babel/helper-explode-assignable-expression" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.12.16", "@babel/helper-compilation-targets@^7.8.7": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.16.tgz#6905238b4a5e02ba2d032c1a49dd1820fe8ce61b" - integrity sha512-dBHNEEaZx7F3KoUYqagIhRIeqyyuI65xMndMZ3WwGwEBI609I4TleYQHcrS627vbKyNTXqShoN+fvYD9HuQxAg== +"@babel/helper-compilation-targets@^7.12.17", "@babel/helper-compilation-targets@^7.8.7": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.17.tgz#91d83fae61ef390d39c3f0507cb83979bab837c7" + integrity sha512-5EkibqLVYOuZ89BSg2lv+GG8feywLuvMXNYgf0Im4MssE0mFWPztSpJbildNnUgw0bLI2EsIN4MpSHC2iUJkQA== dependencies: "@babel/compat-data" "^7.12.13" - "@babel/helper-validator-option" "^7.12.16" + "@babel/helper-validator-option" "^7.12.17" browserslist "^4.14.5" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.12.13", "@babel/helper-create-class-features-plugin@^7.12.16", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.16.tgz#955d5099fd093e5afb05542190f8022105082c61" - integrity sha512-KbSEj8l9zYkMVHpQqM3wJNxS1d9h3U9vm/uE5tpjMbaj3lTp+0noe3KPsV5dSD9jxKnf9jO9Ip9FX5PKNZCKow== +"@babel/helper-create-class-features-plugin@^7.12.13", "@babel/helper-create-class-features-plugin@^7.12.17", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.17.tgz#704b69c8a78d03fb1c5fcc2e7b593f8a65628944" + integrity sha512-I/nurmTxIxHV0M+rIpfQBF1oN342+yvl2kwZUrQuOClMamHF1w5tknfZubgNOLRoA73SzBFAdFcpb4M9HwOeWQ== dependencies: "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.12.16" + "@babel/helper-member-expression-to-functions" "^7.12.17" "@babel/helper-optimise-call-expression" "^7.12.13" "@babel/helper-replace-supers" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-create-regexp-features-plugin@^7.12.13": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.16.tgz#3b31d13f39f930fad975e151163b7df7d4ffe9d3" - integrity sha512-jAcQ1biDYZBdaAxB4yg46/XirgX7jBDiMHDbwYQOgtViLBXGxJpZQ24jutmBqAIB/q+AwB6j+NbBXjKxEY8vqg== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz#a2ac87e9e319269ac655b8d4415e94d38d663cb7" + integrity sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg== dependencies: "@babel/helper-annotate-as-pure" "^7.12.13" regexpu-core "^4.7.1" @@ -171,12 +171,12 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-member-expression-to-functions@^7.12.13", "@babel/helper-member-expression-to-functions@^7.12.16": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.16.tgz#41e0916b99f8d5f43da4f05d85f4930fa3d62b22" - integrity sha512-zYoZC1uvebBFmj1wFAlXwt35JLEgecefATtKp20xalwEK8vHAixLBXTGxNrVGEmTT+gzOThUgr8UEdgtalc1BQ== +"@babel/helper-member-expression-to-functions@^7.12.13", "@babel/helper-member-expression-to-functions@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.17.tgz#f82838eb06e1235307b6d71457b6670ff71ee5ac" + integrity sha512-Bzv4p3ODgS/qpBE0DiJ9qf5WxSmrQ8gVTe8ClMfwwsY2x/rhykxxy3bXzG7AGTnPB2ij37zGJ/Q/6FruxHxsxg== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.12.17" "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.8.3": version "7.12.13" @@ -185,10 +185,10 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-module-transforms@^7.12.13", "@babel/helper-module-transforms@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz#01afb052dcad2044289b7b20beb3fa8bd0265bea" - integrity sha512-acKF7EjqOR67ASIlDTupwkKM1eUisNAjaSduo5Cz+793ikfnpe7p4Q7B7EWU2PCoSTPWsQkR7hRUWEIZPiVLGA== +"@babel/helper-module-transforms@^7.12.13", "@babel/helper-module-transforms@^7.12.17", "@babel/helper-module-transforms@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.17.tgz#7c75b987d6dfd5b48e575648f81eaac891539509" + integrity sha512-sFL+p6zOCQMm9vilo06M4VHuTxUAwa6IxgL56Tq1DVtA0ziAGTH1ThmJq7xwPqdQlgAbKX3fb0oZNbtRIyA5KQ== dependencies: "@babel/helper-module-imports" "^7.12.13" "@babel/helper-replace-supers" "^7.12.13" @@ -196,8 +196,8 @@ "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-validator-identifier" "^7.12.11" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.12.17" + "@babel/types" "^7.12.17" lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.12.13": @@ -257,10 +257,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== -"@babel/helper-validator-option@^7.12.16": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.16.tgz#f73cbd3bbba51915216c5dea908e9b206bb10051" - integrity sha512-uCgsDBPUQDvzr11ePPo4TVEocxj8RXjUVSC/Y8N1YpVAI/XDdUwGJu78xmlGhTxj2ntaWM7n9LQdRtyhOzT2YQ== +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== "@babel/helper-wrap-function@^7.12.13": version "7.12.13" @@ -272,14 +272,14 @@ "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helpers@^7.12.13", "@babel/helpers@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.13.tgz#3c75e993632e4dadc0274eae219c73eb7645ba47" - integrity sha512-oohVzLRZ3GQEk4Cjhfs9YkJA4TdIDTObdBEZGrd6F/T0GPSnuV6l22eMcxlvcvzVIPH3VTtxbseudM1zIE+rPQ== +"@babel/helpers@^7.12.17", "@babel/helpers@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.17.tgz#71e03d2981a6b5ee16899964f4101dc8471d60bc" + integrity sha512-tEpjqSBGt/SFEsFikKds1sLNChKKGGR17flIgQKXH4fG6m9gTgl3gnOC1giHNyaBCSKuTfxaSzHi7UnvqiVKxg== dependencies: "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.12.17" + "@babel/types" "^7.12.17" "@babel/highlight@^7.0.0", "@babel/highlight@^7.12.13", "@babel/highlight@^7.8.3": version "7.12.13" @@ -290,10 +290,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.16", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" - integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.17", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.17.tgz#bc85d2d47db38094e5bb268fc761716e7d693848" + integrity sha512-r1yKkiUTYMQ8LiEI0UcQx5ETw5dpTLn9wijn9hk6KkTtOK95FndDN10M+8/s6k/Ymlbivw0Av9q4SlgF80PtHg== "@babel/plugin-proposal-async-generator-functions@^7.12.13", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.12.13" @@ -329,10 +329,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-decorators" "^7.8.3" -"@babel/plugin-proposal-dynamic-import@^7.12.16", "@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.16.tgz#b9f33b252e3406d492a15a799c9d45a9a9613473" - integrity sha512-yiDkYFapVxNOCcBfLnsb/qdsliroM+vc3LHiZwS4gh7pFjo5Xq3BDhYBNn3H3ao+hWPvqeeTdU+s+FIvokov+w== +"@babel/plugin-proposal-dynamic-import@^7.12.17", "@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.17.tgz#e0ebd8db65acc37eac518fa17bead2174e224512" + integrity sha512-ZNGoFZqrnuy9H2izB2jLlnNDAfVPlGl5NhFEiFe4D84ix9GQGygF+CWMGHKuE+bpyS/AOuDQCnkiRNqW2IzS1Q== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-dynamic-import" "^7.8.0" @@ -418,10 +418,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.16", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.16.tgz#600c7531f754186b0f2096e495a92da7d88aa139" - integrity sha512-O3ohPwOhkwji5Mckb7F/PJpJVJY3DpPsrt/F0Bk40+QMk9QpAIqeGusHWqu/mYqsM8oBa6TziL/2mbERWsUZjg== +"@babel/plugin-proposal-optional-chaining@^7.12.17", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.17.tgz#e382becadc2cb16b7913b6c672d92e4b33385b5c" + integrity sha512-TvxwI80pWftrGPKHNfkvX/HnoeSTR7gC4ezWnAL39PuktYUe6r8kEpOLTYnkBTsaoeazXm2jHJ22EQ81sdgfcA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" @@ -782,11 +782,11 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-transform-react-jsx-development@^7.12.12", "@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.16.tgz#af187e749d123b54ae49bc7e034057a0c1d4d568" - integrity sha512-GOp5SkMC4zhHwLbOSYhF+WpIZSf5bGzaKQTT9jWkemJRDM/CE6FtPydXjEYO3pHcna2Zjvg4mQ1lfjOR/4jsaQ== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.17.tgz#f510c0fa7cd7234153539f9a362ced41a5ca1447" + integrity sha512-BPjYV86SVuOaudFhsJR1zjgxxOhJDt6JHNoD48DxWEIxUCAMjV1ys6DYw4SDYZh0b1QsS2vfIA9t/ZsQGsDOUQ== dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.16" + "@babel/plugin-transform-react-jsx" "^7.12.17" "@babel/plugin-transform-react-jsx-self@^7.9.0": version "7.12.13" @@ -802,16 +802,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-react-jsx@^7.12.13", "@babel/plugin-transform-react-jsx@^7.12.16", "@babel/plugin-transform-react-jsx@^7.9.1": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.16.tgz#07c341e02a3e4066b00413534f30c42519923230" - integrity sha512-dNu0vAbIk8OkqJfGtYF6ADk6jagoyAl+Ks5aoltbAlfoKv8d6yooi3j+kObeSQaCj9PgN6KMZPB90wWyek5TmQ== +"@babel/plugin-transform-react-jsx@^7.12.13", "@babel/plugin-transform-react-jsx@^7.12.17", "@babel/plugin-transform-react-jsx@^7.9.1": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.17.tgz#dd2c1299f5e26de584939892de3cfc1807a38f24" + integrity sha512-mwaVNcXV+l6qJOuRhpdTEj8sT/Z0owAVWf9QujTZ0d2ye9X/K+MTOTSizcgKOj18PGnTc/7g1I4+cIUjsKhBcw== dependencies: "@babel/helper-annotate-as-pure" "^7.12.13" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/types" "^7.12.17" "@babel/plugin-transform-react-pure-annotations@^7.12.1": version "7.12.1" @@ -846,9 +846,9 @@ semver "^5.5.1" "@babel/plugin-transform-runtime@^7.12.1": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.15.tgz#4337b2507288007c2b197059301aa0af8d90c085" - integrity sha512-OwptMSRnRWJo+tJ9v9wgAf72ydXWfYSXWhnQjZing8nGZSDFqU1MBleKM3+DriKkcbv7RagA8gVeB0A1PNlNow== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.17.tgz#329cb61d293b7e60a7685b91dda7c300668cee18" + integrity sha512-s+kIJxnaTj+E9Q3XxQZ5jOo+xcogSe3V78/iFQ5RmoT0jROdpcdxhfGdq/VLqW1hFSzw6VjqN8aQqTaAMixWsw== dependencies: "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.12.13" @@ -891,11 +891,11 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-transform-typescript@^7.9.0": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.16.tgz#3f30b829bdd15683f71c32fa31330c2af8c1b732" - integrity sha512-88hep+B6dtDOiEqtRzwHp2TYO+CN8nbAV3eh5OpBGPsedug9J6y1JwLKzXRIGGQZDC8NlpxpQMIIxcfIW96Wgw== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.17.tgz#4aa6a5041888dd2e5d316ec39212b0cf855211bb" + integrity sha512-1bIYwnhRoetxkFonuZRtDZPFEjl1l5r+3ITkxLC3mlMaFja+GQFo94b/WHEPjqWLU9Bc+W4oFZbvCGe9eYMu1g== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.16" + "@babel/helper-create-class-features-plugin" "^7.12.17" "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-typescript" "^7.12.13" @@ -981,18 +981,18 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.4.5": - version "7.12.16" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.16.tgz#16710e3490e37764b2f41886de0a33bc4ae91082" - integrity sha512-BXCAXy8RE/TzX416pD2hsVdkWo0G+tYd16pwnRV4Sc0fRwTLRS/Ssv8G5RLXUGQv7g4FG7TXkdDJxCjQ5I+Zjg== + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.17.tgz#94a3793ff089c32ee74d76a3c03a7597693ebaaa" + integrity sha512-9PMijx8zFbCwTHrd2P4PJR5nWGH3zWebx2OcpTjqQrHhCiL2ssSR2Sc9ko2BsI2VmVBfoaQmPrlMTCui4LmXQg== dependencies: "@babel/compat-data" "^7.12.13" - "@babel/helper-compilation-targets" "^7.12.16" + "@babel/helper-compilation-targets" "^7.12.17" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-validator-option" "^7.12.16" + "@babel/helper-validator-option" "^7.12.17" "@babel/plugin-proposal-async-generator-functions" "^7.12.13" "@babel/plugin-proposal-class-properties" "^7.12.13" - "@babel/plugin-proposal-dynamic-import" "^7.12.16" + "@babel/plugin-proposal-dynamic-import" "^7.12.17" "@babel/plugin-proposal-export-namespace-from" "^7.12.13" "@babel/plugin-proposal-json-strings" "^7.12.13" "@babel/plugin-proposal-logical-assignment-operators" "^7.12.13" @@ -1000,7 +1000,7 @@ "@babel/plugin-proposal-numeric-separator" "^7.12.13" "@babel/plugin-proposal-object-rest-spread" "^7.12.13" "@babel/plugin-proposal-optional-catch-binding" "^7.12.13" - "@babel/plugin-proposal-optional-chaining" "^7.12.16" + "@babel/plugin-proposal-optional-chaining" "^7.12.17" "@babel/plugin-proposal-private-methods" "^7.12.13" "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" "@babel/plugin-syntax-async-generators" "^7.8.0" @@ -1048,7 +1048,7 @@ "@babel/plugin-transform-unicode-escapes" "^7.12.13" "@babel/plugin-transform-unicode-regex" "^7.12.13" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.13" + "@babel/types" "^7.12.17" core-js-compat "^3.8.0" semver "^5.5.0" @@ -1095,9 +1095,9 @@ "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.12.1", "@babel/runtime-corejs3@^7.9.6": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.13.tgz#53d09813b7c20d616caf258e9325550ff701c039" - integrity sha512-8fSpqYRETHATtNitsCXq8QQbKJP31/KnDl2Wz2Vtui9nKzjss2ysuZtyVsWjBtvkeEFo346gkwjYPab1hvrXkQ== + version "7.12.18" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.18.tgz#e5663237e5658e4c09586995d2dd6d2c8cfd6fc0" + integrity sha512-ngR7yhNTjDxxe1VYmhqQqqXZWujGb6g0IoA4qeG6MxNGRnIw2Zo8ImY8HfaQ7l3T6GklWhdNfyhWk0C0iocdVA== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1110,9 +1110,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d" - integrity sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw== + version "7.12.18" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b" + integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg== dependencies: regenerator-runtime "^0.13.4" @@ -1125,25 +1125,25 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.13", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0" - integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.13", "@babel/traverse@^7.12.17", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.17.tgz#40ec8c7ffb502c4e54c7f95492dc11b88d718619" + integrity sha512-LGkTqDqdiwC6Q7fWSwQoas/oyiEYw6Hqjve5KOSykXkmFJFqzvGMb9niaUEag3Rlve492Mkye3gLw9FTv94fdQ== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.13" + "@babel/generator" "^7.12.17" "@babel/helper-function-name" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/parser" "^7.12.17" + "@babel/types" "^7.12.17" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611" - integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ== +"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.17.tgz#9d711eb807e0934c90b8b1ca0eb1f7230d150963" + integrity sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ== dependencies: "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" @@ -1901,9 +1901,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.14.28" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b" - integrity sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g== + version "14.14.31" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055" + integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1936,9 +1936,9 @@ integrity sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw== "@types/react-transition-group@^4.2.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d" - integrity sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w== + version "4.4.1" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.1.tgz#e1a3cb278df7f47f17b5082b1b3da17170bd44b1" + integrity sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ== dependencies: "@types/react" "*" @@ -3271,7 +3271,7 @@ browserslist@4.7.0: electron-to-chromium "^1.3.247" node-releases "^1.1.29" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.1, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.9.1: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.3, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.9.1: version "4.16.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== @@ -3497,9 +3497,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: - version "1.0.30001187" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001187.tgz#5706942631f83baa5a0218b7dfa6ced29f845438" - integrity sha512-w7/EP1JRZ9552CyrThUnay2RkZ1DXxKe/Q2swTC4+LElLh9RRYrL1Z+27LlakB8kzY0fSmHw9mc7XYDUKAKWMA== + version "1.0.30001189" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001189.tgz#f8547299b9db78d3882b0dea1cae891fed1651e8" + integrity sha512-BSfxClP/UWCD0RX1h1L+vLDexNSJY7SfOtbJtW10bcnatfj3BcoietUFYNwWreOCk+SNvGUaNapGqUNPiGAiSA== canvg@^3.0.6: version "3.0.7" @@ -4051,17 +4051,17 @@ copy-webpack-plugin@^4.6.0: serialize-javascript "^1.4.0" core-js-compat@^3.6.2, core-js-compat@^3.8.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" - integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== + version "3.9.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.9.0.tgz#29da39385f16b71e1915565aa0385c4e0963ad56" + integrity sha512-YK6fwFjCOKWwGnjFUR3c544YsnA/7DoLL0ysncuOJ4pwbriAtOpvM2bygdlcXbvQCQZ7bBU9CL4t7tGl7ETRpQ== dependencies: - browserslist "^4.16.1" + browserslist "^4.16.3" semver "7.0.0" core-js-pure@^3.0.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.8.3.tgz#10e9e3b2592ecaede4283e8f3ad7020811587c02" - integrity sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA== + version "3.9.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.9.0.tgz#326cc74e1fef8b7443a6a793ddb0adfcd81f9efb" + integrity sha512-3pEcmMZC9Cq0D4ZBh3pe2HLtqxpGNJBLXF/kZ2YzK17RbKp94w0HFbdbSx8H8kAlZG5k76hvLrkPm57Uyef+kg== core-js@^2.4.0: version "2.6.12" @@ -4069,9 +4069,9 @@ core-js@^2.4.0: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.0.0, core-js@^3.5.0, core-js@^3.6.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" - integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== + version "3.9.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.0.tgz#790b1bb11553a2272b36e2625c7179db345492f8" + integrity sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -4895,9 +4895,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.666" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.666.tgz#59f3ce1e45b860a0ebe439b72664354efbb8bc62" - integrity sha512-/mP4HFQ0fKIX4sXltG6kfcoGrfNDZwCIyWbH2SIcVaa9u7Rm0HKjambiHNg5OEruicTl9s1EwbERLwxZwk19aw== + version "1.3.670" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.670.tgz#b1560b9ab212ff77fc8197002e735b72882c31be" + integrity sha512-iiHQa72+3wbkPR0O8InsNbRwKcV6gBEKiUqPaJ4+TOwQkJQY4ku1sBNC+0ZSfANQ0nqr0SyRO3/Qr6S7Lct/IA== elliptic@^6.5.3: version "6.5.4" @@ -5158,9 +5158,9 @@ eslint-plugin-flowtype@4.6.0: lodash "^4.17.15" eslint-plugin-flowtype@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.0.tgz#a4bef5dc18f9b2bdb41569a4ab05d73805a3d261" - integrity sha512-z7ULdTxuhlRJcEe1MVljePXricuPOrsWfScRXFhNzVD5dmTHWjIF57AxD0e7AbEoLSbjSsaA5S+hCg43WvpXJQ== + version "5.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.2.tgz#c6e5dd2fad4e757a1c63e652da6cff597659554f" + integrity sha512-C4PlPYpszr9h1cBfUbTNRI1IdxUCF0qrXAHkXS2+bESp7WUUCnvb3UBBnYlaQLvJYJ2lRz+2SPQQ/WyV7p/Tow== dependencies: lodash "^4.17.15" string-natural-compare "^3.0.1" @@ -9032,22 +9032,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== - -"mime-db@>= 1.43.0 < 2": +mime-db@1.46.0, "mime-db@>= 1.43.0 < 2": version "1.46.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== + version "2.1.29" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" + integrity sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ== dependencies: - mime-db "1.45.0" + mime-db "1.46.0" mime@1.6.0: version "1.6.0" @@ -9055,9 +9050,9 @@ mime@1.6.0: integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.4.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.0.tgz#2b4af934401779806ee98026bb42e8c1ae1876b1" - integrity sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag== + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== mimic-fn@^1.0.0: version "1.2.0" @@ -13439,9 +13434,9 @@ url-loader@2.3.0: schema-utils "^2.5.0" url-parse@^1.4.3, url-parse@^1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + version "1.5.1" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" + integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" @@ -13931,9 +13926,9 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5: iconv-lite "0.4.24" whatwg-fetch@^3.0.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz#605a2cd0a7146e5db141e29d1c62ab84c0c4c868" - integrity sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A== + version "3.6.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.1.tgz#93bc4005af6c2cc30ba3e42ec3125947c8f54ed3" + integrity sha512-IEmN/ZfmMw6G1hgZpVd0LuZXOQDisrMOZrzYd5x3RAK4bMPlJohKUZWZ9t/QsTvH0dV9TbPDcc2OSuIDcihnHA== whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: version "2.3.0" From eaab3c6fbe0a4ab2d6f25e6f4260fb1460a0c6ad Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Tue, 23 Feb 2021 07:33:31 +1300 Subject: [PATCH 10/16] Trying to figure out why not finding missing tW links --- package.json | 8 +- src/__tests__/tn-table-row-check.test.js | 4 +- src/core/notes-links-check.js | 62 +++++----- src/core/tn-tsv9-row-check.js | 4 +- src/core/twl-tsv6-row-check.js | 19 ++- src/core/twl-tsv6-table-check.js | 1 - src/core/usfm-text-check.js | 97 +++++++++++---- .../book-package-check/BookPackageCheck.js | 8 +- src/demos/book-package-check/README.md | 4 +- .../book-package-check/checkBookPackage.js | 1 + src/demos/file-check/FileCheck.js | 4 +- src/demos/file-check/README.md | 4 +- src/demos/file-check/checkFileContents.js | 2 +- src/demos/repo-check/RepoCheck.js | 4 +- src/demos/repo-check/checkRepo.js | 2 +- yarn.lock | 111 ++++++++---------- 16 files changed, 185 insertions(+), 150 deletions(-) diff --git a/package.json b/package.json index 07e27a4f0..ab098ad43 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha5", + "version": "2.0.0_alpha6", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { @@ -53,7 +53,7 @@ "@babel/preset-react": "^7.12.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", - "@types/jest": "24.0.22", + "@types/jest": "^24.0.22", "babel-eslint": "^10.1.0", "coveralls": "^3.1.0", "eslint-config-google": "^0.12.0", @@ -69,13 +69,13 @@ "jest": "^26.6.3", "material-table": "^1.69.1", "react": "^17.0.0", - "react-docgen": "4.1.1", + "react-docgen": "^4.1.1", "react-dom": "^17.0.1", "react-markdown": "^4.0.6", "react-scripts": "^3.0.1", "react-styleguidist": "^9.2.0", "react-test-renderer": "^16.12.0", - "webpack": "4.44.2" + "webpack": "^4.44.2" }, "browserslist": [ ">0.2%", diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index 636d4f3cc..f165b372d 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -7,8 +7,8 @@ import fs from 'fs-extra'; const optionalCheckingOptions = { originalLanguageRepoUsername: 'unfoldingWord', taRepoUsername: 'unfoldingWord', - checkLinkedTAArticleFlag: false, - checkLinkedTWArticleFlag: false, + disableLinkedTAArticlesCheckFlag: true, + disableLinkedTWArticlesCheckFlag: true, getFile: params => { const { username, repository, path } = params; // console.log(`tn-table-row-check.test getFile(${username}, ${repository}, ${path})`) diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index ce12ac2bb..c76a921c7 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -15,9 +15,9 @@ const DEFAULT_BRANCH = 'master'; const GENERAL_LINK1_REGEX = new RegExp('\\[[^\\]]+?\\]\\([^\\)]+?\\)', 'g'); // [displayLink](URL) const GENERAL_LINK2_REGEX = new RegExp('\\[\\[[^\\]]+?\\]\\]', 'g'); // [[combinedDisplayLink]] -const TA_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] -const TW_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] -const TWL_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g'); // Just a raw link +const TA_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TW_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TWL_RAW_LINK_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g'); // Just a raw link // TODO: Do we need to normalise Bible links, i.e., make sure that the link itself // (we don't care about the displayed text) doesn't specify superfluous levels/information @@ -25,7 +25,7 @@ const TWL_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g') // TODO: Test to see if "[2:23](../02/03.md)" is found by more than one regex below const BIBLE_REGEX_OTHER_BOOK_ABSOLUTE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](rev/03/11.md) const BIBLE_REGEX_OTHER_BOOK_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(\\.{2}/\\.{2}/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](../../rev/03/11.md) -const BIBLE_REGEX_THIS_BOOK_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](../03/11.md) +const BIBLE_REGEX_THIS_BOOK_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Revelation 3:11](../03/11.md) const BCV_V_TO_THIS_BOOK_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})[–-](\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); // [Genesis 26:12-14](../26/12.md) or [4:11–16](../04/11.md) NOTE en-dash const BIBLE_REGEX_THIS_CHAPTER_RELATIVE = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(?:(\\d{1,3}):)?(\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); const THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g');// [27](../11/27.md) @@ -103,16 +103,16 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // -- you can control this with: // checkingOptions?.taRepoUsername // checkingOptions?.taRepoBranch (or tag) - // checkingOptions?.checkLinkedTAArticleFlag + // checkingOptions?.disableLinkedTAArticlesCheckFlag // We attempt to fetch any TW links to test that the destination is really there // -- you can control this with: // checkingOptions.twRepoUsername // checkingOptions.twRepoBranch (or tag) - // checkingOptions.checkLinkedTWArticleFlag + // checkingOptions.disableLinkedTWArticlesCheckFlag */ - // functionLog(`checkNotesLinksToOutside v${NOTES_LINKS_VALIDATOR_VERSION_STRING} ${repoCode} ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, …)…`); + // if (fieldText.indexOf('brother') !== -1) functionLog(`checkNotesLinksToOutside v${NOTES_LINKS_VALIDATOR_VERSION_STRING} ${repoCode} ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkNotesLinksToOutside: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkNotesLinksToOutside: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode !== undefined, "checkNotesLinksToOutside: 'repoCode' parameter should be defined"); @@ -156,10 +156,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // Main code for checkNotesLinksToOutside // Get any options that were suppplied, or else set default values - let excerptLength; - try { - excerptLength = checkingOptions?.excerptLength; - } catch (trcELerror) { } + let excerptLength = checkingOptions?.excerptLength; if (typeof excerptLength !== 'number' || isNaN(excerptLength)) { excerptLength = DEFAULT_EXCERPT_LENGTH; // debugLog(`Using default excerptLength=${excerptLength}`); @@ -171,22 +168,17 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // debugLog(`Using excerptHalfLength=${excerptHalfLength}`, `excerptHalfLengthPlus=${excerptHalfLengthPlus}`); const getFile_ = (checkingOptions && checkingOptions?.getFile) ? checkingOptions?.getFile : cachedGetFile; - let defaultLanguageCode; - try { defaultLanguageCode = checkingOptions?.defaultLanguageCode; } catch (trcLCerror) { } + let defaultLanguageCode = checkingOptions?.defaultLanguageCode; if (!defaultLanguageCode) defaultLanguageCode = DEFAULT_LANGUAGE_CODE; // debugLog("checkNotesLinksToOutside defaultLanguageCode", defaultLanguageCode); - let taRepoUsername; - try { taRepoUsername = checkingOptions?.taRepoUsername; } catch (trcUNerror) { } + let taRepoUsername = checkingOptions?.taRepoUsername; if (!taRepoUsername) taRepoUsername = defaultLanguageCode === 'en' ? 'unfoldingWord' : 'Door43-Catalog'; - let taRepoBranch; - try { taRepoBranch = checkingOptions?.taRepoBranch; } catch (trcBRerror) { } + let taRepoBranch = checkingOptions?.taRepoBranch; if (!taRepoBranch) taRepoBranch = DEFAULT_BRANCH; - let twRepoUsername; - try { twRepoUsername = checkingOptions?.twRepoUsername; } catch (trcUNerror) { } + let twRepoUsername = checkingOptions?.twRepoUsername; if (!twRepoUsername) twRepoUsername = defaultLanguageCode === 'en' ? 'unfoldingWord' : 'Door43-Catalog'; - let twRepoBranch; - try { twRepoBranch = checkingOptions?.twRepoBranch; } catch (trcBRerror) { } + let twRepoBranch = checkingOptions?.twRepoBranch; if (!twRepoBranch) twRepoBranch = DEFAULT_BRANCH; // Convert our given C:V strings to integers @@ -216,20 +208,20 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g let processedLinkList = []; // Check for TA links like [[rc://en/ta/man/translate/figs-metaphor]] - // debugLog("checkNotesLinksToOutside: Search for TA links") - while ((regexResultArray = TA_REGEX.exec(fieldText))) { + // if (fieldText.indexOf('brother') !== -1) debugLog("checkNotesLinksToOutside: Search for TA links") + while ((regexResultArray = TA_DOUBLE_BRACKETED_LINK_REGEX.exec(fieldText))) { // debugLog(` checkNotesLinksToOutside TA resultArray=${JSON.stringify(regexResultArray)}`); taLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 4, `TA_REGEX expected 4 fields (not ${regexResultArray.length})`) let languageCode = regexResultArray[1]; if (languageCode !== '*') { - const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found + const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); } else if (repoCode === 'TN') { // but not TN2 // At the moment, tC can’t handle these links with * so we have to ensure that they're not there - const characterIndex = TA_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found + const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); } @@ -256,8 +248,8 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); else if (taFileContent.length < 10) addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.checkLinkedTAArticleFlag === true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); + else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); if (await alreadyChecked(taPathParameters) !== true) { // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); @@ -277,10 +269,10 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // Check for TW links like [[rc://en/tw/dict/bible/other/death]] in TN or rc://en/tw/dict/bible/other/death in TWLinks // (These are not nearly as many as TA links.) - // debugLog("checkNotesLinksToOutside: Search for TW links") - const ourTWRegex = (fieldName === 'TWLink') ? TWL_REGEX : TW_REGEX + const ourTWRegex = (fieldName === 'TWLink') ? TWL_RAW_LINK_REGEX : TW_DOUBLE_BRACKETED_LINK_REGEX; + // if (fieldText.indexOf('brother') !== -1) debugLog(`checkNotesLinksToOutside: ${bookID} ${givenC}:${givenV} Search for TW links with ${ourTWRegex}`) while ((regexResultArray = ourTWRegex.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside TW resultArray=${JSON.stringify(regexResultArray)}`); + // if (fieldText.indexOf('brother') !== -1) debugLog(` checkNotesLinksToOutside ${givenC}:${givenV} found TW resultArray=${JSON.stringify(regexResultArray)}`); twLinkCount += 1; processedLinkList.push(regexResultArray[0]); // Save the full link parameterAssert(regexResultArray.length === 4, `TW_REGEX expected 4 fields (not ${regexResultArray.length})`) @@ -292,12 +284,12 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // debugLog(`Got tW filepath=${filepath}`); if (!checkingOptions?.disableAllLinkFetchingFlag) { - // debugLog(`Need to check TW link against ${twRepoName}`); + // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; let twFileContent; try { twFileContent = await getFile_(twPathParameters); - // debugLog(`Fetched fileContent for ${twRepoName} ${filepath} ${typeof fileContent} ${twFileContent.length}`); + // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); } catch (trcGCerror) { console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); @@ -307,8 +299,8 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g else { // we got the content of the TW article if (twFileContent.length < 10) addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.checkLinkedTWArticleFlag === true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); + else if (checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); if (await alreadyChecked(twPathParameters) !== true) { // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); @@ -322,8 +314,10 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g markAsChecked(twPathParameters); // don’t bother waiting for the result } } + else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); } } + else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } // debugLog("checkNotesLinksToOutside: Search for Bible links") diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index fb678cc31..7aec2612b 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -30,7 +30,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] * @param {string} givenC - chapter number or (for OBS) story number string * @param {string} givenV - verse number or (for OBS) frame number string * @param {string} givenRowLocation - description of where the line is located - * @param {Object} checkingOptions - may contain excerptLength, twRepoUsername, twRepoBranch (or tag), checkLinkedTWArticleFlag parameters + * @param {Object} checkingOptions - may contain excerptLength, twRepoUsername, twRepoBranch (or tag), disableLinkedTWArticlesCheckFlag parameters * @return {Object} - containing noticeList */ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, givenC, givenV, givenRowLocation, checkingOptions) { @@ -284,7 +284,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // Uses // checkingOptions.twRepoUsername // checkingOptions.twRepoBranch (or tag) - // checkingOptions.checkLinkedTWArticleFlag + // checkingOptions.disableLinkedTWArticlesCheckFlag // Updates the global list of notices diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index 86a41df07..4ad6e0150 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -180,21 +180,19 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, // end of ourCheckTNOriginalLanguageQuote function - async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + async function ourcheckNotesLinksToOutside(rowID, fieldName, twLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Updates the global list of notices - // functionLog(`checkTWL_TSV6DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + // functionLog(`checkTWL_TSV6DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${twLinkText.length}) '${twLinkText}', ${rowLocation}, ${JSON.stringify(checkingOptions)})`); parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); parameterAssert(fieldName === 'TWLink', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'TWLink' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + parameterAssert(twLinkText !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'twLinkText' parameter should be defined"); + parameterAssert(typeof twLinkText === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'twLinkText' parameter should be a string not a '${typeof twLinkText}'`); - const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, twLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); // Choose only ONE of the following @@ -385,6 +383,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, } if (TWLink.length) { + // debugLog(`checkTWL_TSV6DataRow checking ${bookID} ${rowID} TWLink='${TWLink}'`); if (TWLink.indexOf('\u200B') >= 0) { const charCount = countOccurrences(TWLink, '\u200B'); addNoticePartial({ priority: 374, message: "Field contains zero-width space(s)", details: `${charCount} occurrence${charCount === 1 ? '' : 's'} found`, fieldName: 'TWLink', rowID, location: ourRowLocation }); @@ -395,14 +394,14 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, if (!TWLink.startsWith('rc://*/tw/dict/bible/')) addNoticePartial({ priority: 798, message: "Field doesn’t contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation }); else { // it starts correctly - const bits = TWLink.substring('rc://*/tw/dict/bible/'.length).split('/'); - // debugLog(`checkTWL_TSV6DataRow checking ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); + const bits = TWLink.substring('rc://*/tw/dict/bible/'.length).split('/'); // Get the last two bits of the link path + // debugLog(`checkTWL_TSV6DataRow checking ${bookID} ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); if (bits[0] !== 'kt' && bits[0] !== 'names' && bits[0] !== 'other') { const characterIndex = 'rc://*/tw/dict/bible/'.length; const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + TWLink.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < TWLink.length ? '…' : '') addNoticePartial({ priority: 797, message: "Field doesn’t contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); } else { // all good so far - // debugLog(`checkTWL_TSV6DataRow looking up ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); + // debugLog(`checkTWL_TSV6DataRow looking up ${bookID} ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); await ourcheckNotesLinksToOutside(rowID, 'TWLink', TWLink, ourRowLocation, linkCheckingOptions); } } diff --git a/src/core/twl-tsv6-table-check.js b/src/core/twl-tsv6-table-check.js index 9d2a6e77c..4fa25a07e 100644 --- a/src/core/twl-tsv6-table-check.js +++ b/src/core/twl-tsv6-table-check.js @@ -123,7 +123,6 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam // eslint-disable-next-line no-unused-vars const [reference, rowID, tags, quote, occurrence, TWLLink] = fields; const [C, V] = reference.split(':') - if (V === '3') break; // Use the row check to do most basic checks const drResultObject = await checkTWL_TSV6DataRow(languageCode, repoCode, lines[n], bookID, C, V, ourLocation, checkingOptions); diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 64f21ce3f..5c1d4d9cf 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -4,11 +4,12 @@ import { checkTextField } from './field-text-check'; import { checkTextfileContents } from './file-text-check'; import { runUsfmJsCheck } from './usfm-js-check'; import { runBCSGrammarCheck } from './BCS-usfm-grammar-check'; -import { userLog, parameterAssert, dataAssert, ourParseInt } from './utilities'; +import { checkNotesLinksToOutside } from './notes-links-check'; +import { userLog, parameterAssert, logicAssert, dataAssert, ourParseInt } from './utilities'; import { removeDisabledNotices } from './disabled-notices'; -// const USFM_VALIDATOR_VERSION_STRING = '0.8.5'; +// const USFM_VALIDATOR_VERSION_STRING = '0.8.6'; const VALID_LINE_START_CHARACTERS = `([“‘`; // '{' gets added for STs @@ -145,7 +146,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex Returns a result object containing a successList and a noticeList */ - // functionLog(`checkUSFMText(${languageCode}, ${bookID}, ${givenText.length.toLocaleString()} chars, '${givenLocation}', ${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkUSFMText(${languageCode}, ${repoCode}, ${bookID}, ${filename}, ${givenText.length.toLocaleString()} chars, '${givenLocation}', ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkUSFMText: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkUSFMText: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode !== undefined, "checkUSFMText: 'repoCode' parameter should be defined"); @@ -383,7 +384,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } } } - if (gotDeep) parameterAssert(false, `We need to add more depth levels to hasText() for ${bookID} ${chapterNumberString}:${verseNumberString}`); + if (gotDeep) logicAssert(false, `We need to add more depth levels to hasText() for ${bookID} ${chapterNumberString}:${verseNumberString}`); // debugLog(`hasText() for ${chapterNumberString}:${verseNumberString} returning false with ${typeof verseObjects} (${verseObjects.length}): ${JSON.stringify(verseObjects)}`); return false; } @@ -394,7 +395,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // const lowercaseBookID = bookID.toLowerCase(); let expectedVersesPerChapterList = []; try { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in usfm-text-check1"); + logicAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in usfm-text-check1"); expectedVersesPerChapterList = books.chaptersInBook(lowercaseBookID); // A list of integers -- numVerses for each chapter // debugLog("Got chapterList", JSON.stringify(expectedVersesPerChapterList)); } @@ -527,7 +528,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // for this particular kind of text field for (const noticeEntry of dbtcResultObject.noticeList) { // debugLog("Notice keys", JSON.stringify(Object.keys(noticeEntry))); - parameterAssert(Object.keys(noticeEntry).length >= 4, `USFM ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); + logicAssert(Object.keys(noticeEntry).length >= 4, `USFM ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); addNoticePartial({ ...noticeEntry, lineNumber, C, V }); // } } @@ -552,7 +553,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line for (const noticeEntry of resultObject.noticeList) { - parameterAssert(Object.keys(noticeEntry).length >= 5, `USFM ourBasicFileChecks notice length=${Object.keys(noticeEntry).length}`); + logicAssert(Object.keys(noticeEntry).length >= 5, `USFM ourBasicFileChecks notice length=${Object.keys(noticeEntry).length}`); addNoticePartial(noticeEntry); } } @@ -635,14 +636,15 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // Check that no \w markers touch, i.e., shouldn't have '\w*\w' in file let characterIndex; - if ((characterIndex = rest.indexOf('\\w*\\w')) >= 0) { + if ((characterIndex = rest.indexOf('\\w*\\w')) !== -1) { // NOTE: There's one example of this in ULT 1 Kings 6:1 "480th" // \w 480|x-occurrence="1" x-occurrences="1"\w*\w th|x-occurrence="1" x-occurrences="1"\w* // Also UST Ezra 6:19 "14th" and Ezra 10:9 "20th" - // TODO: Do we want to disable this particular case, or to look for ordinal numbers??? const badCount = countOccurrences(rest, '\\w*\\w'); - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + rest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < rest.length ? '…' : '') - addNoticePartial({ priority: 444, message: "Shouldn’t have consecutive word fields without a space", details: badCount> 1? details+`${badCount} occurrences found in line`: details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); + if (badCount > 1 || rest.indexOf('\\w*\\w th|') === -1) { // there's multiple cases or it's not an ordinal + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + rest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < rest.length ? '…' : '') + addNoticePartial({ priority: 444, message: "Shouldn’t have consecutive word fields without a space", details: badCount > 1 ? details + `${badCount} occurrences found in line` : details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); + } } // Remove any self-closed milestones and internal \v markers @@ -673,28 +675,28 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + adjustedRest.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus).replace(/ /g, '␣') + (characterIndex + excerptHalfLengthPlus < adjustedRest.length ? '…' : '') addNoticePartial({ priority: 912, message: 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation }); } - parameterAssert(ixWordEnd >= 1, `Why1 is w| = ${ixWordEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); + dataAssert(ixWordEnd >= 1, `Why1 is w| = ${ixWordEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); ixEnd = adjustedRest.indexOf('\\w*'); if (ixEnd >= 0) adjustedRest = adjustedRest.substring(0, ixWordEnd) + adjustedRest.substring(ixEnd + 3, adjustedRest.length); - else parameterAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); + else dataAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); } else if (marker === 'zaln-s') { // Remove first \zaln-s milestone (if marker == zaln-s) ixEnd = adjustedRest.indexOf('\\*'); if (ixEnd >= 0) adjustedRest = adjustedRest.substring(ixEnd + 2, adjustedRest.length); - else parameterAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); + else dataAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); } else if (marker === 'k-s') { // Remove first \k-s milestone (if marker == k-s) ixEnd = adjustedRest.indexOf('\\*'); if (ixEnd >= 0) adjustedRest = adjustedRest.substring(ixEnd + 2, adjustedRest.length); - else parameterAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); + else dataAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); } else if (marker === 'f') { // Handle first footnote (if marker == f) ixEnd = adjustedRest.indexOf('\\f*'); const startIndex = adjustedRest.startsWith('+ ') ? 2 : 0; if (ixEnd >= 0) adjustedRest = adjustedRest.substring(startIndex, ixEnd) + adjustedRest.substring(ixEnd + 3, adjustedRest.length); else { - // parameterAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); + // dataAssert(false, `Why is ixEnd = ${ixEnd}? ${languageCode} ${bookID} ${C}:${V} ${lineNumber} '\\${marker}'`); addNoticePartial({ priority: 312, message: 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation }); } // debugLog(`After removing f field: '${adjustedRest}' from '${rest}'`); @@ -712,7 +714,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex const ixZEnd = adjustedRest.indexOf('\\*'); // debugLog(` ${nextZIndex} and ${ixZEnd}`); if (ixZEnd >= 0) { - // parameterAssert(ixZEnd > nextZIndex, `Exected closure at ${ixZEnd} to be AFTER \\zaln-s (${nextZIndex})`); + // dataAssert(ixZEnd > nextZIndex, `Exected closure at ${ixZEnd} to be AFTER \\zaln-s (${nextZIndex})`); adjustedRest = adjustedRest.substring(0, nextZIndex) + adjustedRest.substring(ixZEnd + 2, adjustedRest.length); // debugLog(` Now '${adjustedRest}'`); } else { @@ -731,10 +733,10 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex adjustedRest = ''; // Avoid follow-on errors break; } - parameterAssert(ixWordEnd > nextWIndex + 3, `Why2 is w| = ${ixWordEnd}? nextWIndex=${nextWIndex} ${languageCode} ${bookID} ${C}:${V} ${lineNumber}`); + dataAssert(ixWordEnd > nextWIndex + 3, `Why2 is w| = ${ixWordEnd}? nextWIndex=${nextWIndex} ${languageCode} ${bookID} ${C}:${V} ${lineNumber}`); const ixWEnd = adjustedRest.indexOf('\\w*'); if (ixWEnd >= 0) { - parameterAssert(ixWEnd > nextWIndex, `Exected closure at ${ixWEnd} to be AFTER \\w (${nextWIndex})`); + dataAssert(ixWEnd > nextWIndex, `Exected closure at ${ixWEnd} to be AFTER \\w (${nextWIndex})`); adjustedRest = adjustedRest.substring(0, nextWIndex) + adjustedRest.substring(nextWIndex + 3, ixWordEnd) + adjustedRest.substring(ixWEnd + 3, adjustedRest.length); // debugLog(`After removing w field, got '${adjustedRest}'`); } else { @@ -747,7 +749,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex while ((nextFIndex = adjustedRest.indexOf('\\f + ')) >= 0) { const ixFEnd = adjustedRest.indexOf('\\f*'); if (ixFEnd >= 0) { - parameterAssert(ixFEnd > nextWIndex, `Exected closure at ${ixFEnd} to be AFTER \\w (${nextFIndex})`); + dataAssert(ixFEnd > nextWIndex, `Exected closure at ${ixFEnd} to be AFTER \\w (${nextFIndex})`); adjustedRest = adjustedRest.substring(0, nextFIndex) + adjustedRest.substring(nextFIndex + 5, ixFEnd) + adjustedRest.substring(ixFEnd + 3, adjustedRest.length); // functionLog(`checkUSFMLineText(${lineNumber}, ${C}:${V}, ${marker}='${rest}', ${lineLocation}, ${JSON.stringify(checkingOptions)})…`); // debugLog(`After removing footnote: '${adjustedRest}'`); @@ -840,7 +842,9 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex if (attributeName === 'x-morph' && ((repoCode === 'UHB' && !attributeValue.startsWith('He,') && !attributeValue.startsWith('Ar,')) || (repoCode === 'UGNT' && !attributeValue.startsWith('Gr,')))) - addNoticePartial({ priority: 852, message: "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); + addNoticePartial({ priority: 852, message: "Unexpected original \\w x-morph language prefix", details: "Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); + else if (attributeName === 'x-tw') + ourcheckNotesLinksToOutside(lineNumber, C, V, marker, attributeValue, lineLocation, checkingOptions); } else { // a translation -- not UHB or UGNT if (attributeCounter === 1) { if (attributeName !== 'x-occurrence') @@ -972,6 +976,51 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // end of checkUSFMLineContents function + async function ourcheckNotesLinksToOutside(lineNumber, C, V, marker, twLinkText, location, checkingOptions) { + // Checks that the TA/TW/Bible reference can be found + + // Updates the global list of notices + + // functionLog(`checkUSFMText ourcheckNotesLinksToOutside(${lineNumber}, ${C}:${V}, ${marker}, (${twLinkText.length}) '${twLinkText}', ${location}, ${JSON.stringify(checkingOptions)})`); + parameterAssert(marker !== undefined, "checkUSFMText ourcheckNotesLinksToOutside: 'marker' parameter should be defined"); + parameterAssert(typeof marker === 'string', `checkUSFMText ourcheckNotesLinksToOutside: 'marker' parameter should be a string not a '${typeof marker}': ${marker}`); + parameterAssert(twLinkText !== undefined, "checkUSFMText ourcheckNotesLinksToOutside: 'twLinkText' parameter should be defined"); + parameterAssert(typeof twLinkText === 'string', `checkUSFMText ourcheckNotesLinksToOutside: 'twLinkText' parameter should be a string not a '${typeof twLinkText}': ${twLinkText}`); + + const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, C, V, 'TWLink', twLinkText, location, { ...checkingOptions, defaultLanguageCode: languageCode }); + // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coTNlResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const coqNoticeEntry of coTNlResultObject.noticeList) { + if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + result.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is + else // For our direct checks, we add the repoCode as an extra value + addNoticePartial({ ...coqNoticeEntry, lineNumber, C, V, fieldName: marker }); + } + // The following is needed coz we might be checking the linked TA and/or TW articles + if (coTNlResultObject.checkedFileCount && coTNlResultObject.checkedFileCount > 0) + if (typeof result.checkedFileCount === 'number') result.checkedFileCount += coTNlResultObject.checkedFileCount; + else result.checkedFileCount = coTNlResultObject.checkedFileCount; + if (coTNlResultObject.checkedFilesizes && coTNlResultObject.checkedFilesizes > 0) + if (typeof result.checkedFilesizes === 'number') result.checkedFilesizes += coTNlResultObject.checkedFilesizes; + else result.checkedFilesizes = coTNlResultObject.checkedFilesizes; + if (coTNlResultObject.checkedRepoNames && coTNlResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of coTNlResultObject.checkedRepoNames) + try { if (result.checkedRepoNames.indexOf(checkedRepoName) < 0) result.checkedRepoNames.push(checkedRepoName); } + catch { result.checkedRepoNames = [checkedRepoName]; } + if (coTNlResultObject.checkedFilenameExtensions && coTNlResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of coTNlResultObject.checkedFilenameExtensions) + try { if (result.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) result.checkedFilenameExtensions.push(checkedFilenameExtension); } + catch { result.checkedFilenameExtensions = [checkedFilenameExtension]; } + // if (result.checkedFilenameExtensions) userLog("result", JSON.stringify(result)); + } + // end of ourcheckNotesLinksToOutside function + + function mainUSFMCheck(bookID, filename, givenText, location) { // debugLog("Running mainUSFMCheck() (can take quite a while for a large book)…"); @@ -982,7 +1031,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // eslint-disable-next-line no-unused-vars let numChaptersThisBook = 0; try { - parameterAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in usfm-text-check2"); + logicAssert(lowercaseBookID !== 'obs', "Shouldn’t happen in usfm-text-check2"); numChaptersThisBook = books.chaptersInBook(lowercaseBookID).length; } catch { @@ -993,7 +1042,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex function findStartMarker(C, V, lineNumber, USFMline) { // Returns the USFM marker at the start of the line // (without the leading backslash but including full self-closing milestones) - parameterAssert(USFMline && USFMline[0] === '\\', `Programming error in findStartMarker(${C}:${V}, ${lineNumber}, ${USFMline})`); + logicAssert(USFMline && USFMline[0] === '\\', `Programming error in findStartMarker(${C}:${V}, ${lineNumber}, ${USFMline})`); let foundMarker = ''; for (let characterIndex = 1; characterIndex < USFMline.length; characterIndex++) { const char = USFMline[characterIndex]; @@ -1186,7 +1235,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex allResults.push(CVCheck(bookID, givenText, ourLocation)); if (!books.isExtraBookID(bookID)) allResults.push(ourRunBCSGrammarCheck(filename, givenText, ourLocation)); - // parameterAssert(allResults.length === 2); + // logicAssert(allResults.length === 2); // debugLog("allResults", JSON.stringify(allResults)); // if (!allResults[1].isValidUSFM) // addNoticePartial({priority: 941, "USFM Grammar check fails", location}); diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 12215fd2a..2e3c679e2 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -45,10 +45,10 @@ function BookPackageCheck(/*username, languageCode, bookID,*/ props) { if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); if (props.disableAllLinkFetchingFlag) checkingOptions.disableAllLinkFetchingFlag = props.disableAllLinkFetchingFlag.toLowerCase() === 'true'; - if (props.checkLinkedTAArticleFlag) checkingOptions.checkLinkedTAArticleFlag = props.checkLinkedTAArticleFlag.toLowerCase() === 'true'; - if (props.checkLinkedTWArticleFlag) checkingOptions.checkLinkedTWArticleFlag = props.checkLinkedTWArticleFlag.toLowerCase() === 'true'; - // functionLog(`checkingOptions.checkLinkedTAArticleFlag ${checkingOptions.checkLinkedTAArticleFlag} from '${props.checkLinkedTAArticleFlag}'`); - // functionLog(`checkingOptions.checkLinkedTWArticleFlag ${checkingOptions.checkLinkedTWArticleFlag} from '${props.checkLinkedTWArticleFlag}'`); + if (props.disableLinkedTAArticlesCheckFlag) checkingOptions.disableLinkedTAArticlesCheckFlag = props.disableLinkedTAArticlesCheckFlag.toLowerCase() === 'true'; + if (props.disableLinkedTWArticlesCheckFlag) checkingOptions.disableLinkedTWArticlesCheckFlag = props.disableLinkedTWArticlesCheckFlag.toLowerCase() === 'true'; + // functionLog(`checkingOptions.disableLinkedTAArticlesCheckFlag ${checkingOptions.disableLinkedTAArticlesCheckFlag} from '${props.disableLinkedTAArticlesCheckFlag}'`); + // functionLog(`checkingOptions.disableLinkedTWArticlesCheckFlag ${checkingOptions.disableLinkedTWArticlesCheckFlag} from '${props.disableLinkedTWArticlesCheckFlag}'`); useEffect(() => { // const newProps = { bookID, branch, checkingOptions, languageCode, cutoffPriorityLevel: props.cutoffPriorityLevel, displayType: props.displayType, errorPriorityLevel: props.errorPriorityLevel, maximumSimilarMessages: props.maximumSimilarMessages, sortBy: props.sortBy, username}; diff --git a/src/demos/book-package-check/README.md b/src/demos/book-package-check/README.md index 142591253..4143d3408 100644 --- a/src/demos/book-package-check/README.md +++ b/src/demos/book-package-check/README.md @@ -41,8 +41,8 @@ import BookPackageCheck from './BookPackageCheck'; // Normally links in files are downloaded to check that they really exist disableAllLinkFetchingFlag='false' // 'true' or 'false' // The next two are only relevant if the above is 'false' - checkLinkedTAArticleFlag='true' // 'true' or 'false' - checkLinkedTWArticleFlag='true' // 'true' or 'false' + disableLinkedTAArticlesCheckFlag='false' // 'true' or 'false' + disableLinkedTWArticlesCheckFlag='false' // 'true' or 'false' // Lines starting with // are ignored -- you can add or remove // as desired // Specifying excerptLength and maximumSimilarMessages is just to show off options diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index feb876b9b..c069a6a47 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -55,6 +55,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult newCheckingOptions.getFile = getFile_; // use same getFile_ when we call core functions if (!newCheckingOptions.originalLanguageRepoUsername) newCheckingOptions.originalLanguageRepoUsername = username; if (!newCheckingOptions.taRepoUsername) newCheckingOptions.taRepoUsername = username; + if (!newCheckingOptions.twRepoUsername) newCheckingOptions.twRepoUsername = username; // No point in passing the branch through as a parameter // coz if it’s not 'master', it’s unlikely to be common for all the repos diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 782330e8b..664926862 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -206,8 +206,8 @@ function FileCheck(props) { if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); if (props.cutoffPriorityLevel) checkingOptions.cutoffPriorityLevel = ourParseInt(props.cutoffPriorityLevel); if (props.disableAllLinkFetchingFlag) checkingOptions.disableAllLinkFetchingFlag = props.disableAllLinkFetchingFlag.toLowerCase() === 'true'; - if (props.checkLinkedTAArticleFlag) checkingOptions.checkLinkedTAArticleFlag = props.checkLinkedTAArticleFlag.toLowerCase() === 'true'; - if (props.checkLinkedTWArticleFlag) checkingOptions.checkLinkedTWArticleFlag = props.checkLinkedTWArticleFlag.toLowerCase() === 'true'; + if (props.disableLinkedTAArticlesCheckFlag) checkingOptions.disableLinkedTAArticlesCheckFlag = props.disableLinkedTAArticlesCheckFlag.toLowerCase() === 'true'; + if (props.disableLinkedTWArticlesCheckFlag) checkingOptions.disableLinkedTWArticlesCheckFlag = props.disableLinkedTWArticlesCheckFlag.toLowerCase() === 'true'; // {/* <div className={classes.root}> */} return ( diff --git a/src/demos/file-check/README.md b/src/demos/file-check/README.md index d711e06d3..824322edd 100644 --- a/src/demos/file-check/README.md +++ b/src/demos/file-check/README.md @@ -60,8 +60,8 @@ and then validates the content of one file selected from the repo. // Normally links in files are downloaded to check that they really exist disableAllLinkFetchingFlag='true' // 'true' or 'false' // The next two are only relevant if the above is 'false' - checkLinkedTAArticleFlag='true' // 'true' or 'false' - checkLinkedTWArticleFlag='true' // 'true' or 'false' + disableLinkedTAArticlesCheckFlag='false' // 'true' or 'false' + disableLinkedTWArticlesCheckFlag='false' // 'true' or 'false' // Default displayType is 'ErrorsWarnings' // Alternatives are `SevereMediumLow', 'SingleList' diff --git a/src/demos/file-check/checkFileContents.js b/src/demos/file-check/checkFileContents.js index 48cc3c459..299d01afa 100644 --- a/src/demos/file-check/checkFileContents.js +++ b/src/demos/file-check/checkFileContents.js @@ -24,7 +24,7 @@ import { export async function checkFileContents(username, languageCode, repoCode, branch, filename, fileContent, givenLocation, checkingOptions) { // Determine the file type from the filename extension // and return the results of checking that kind of file text - // functionLog(`checkFileContents(${username}, ${languageCode}, ${repoCode}, ${branch}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + // if (repoCode !== 'TQ') functionLog(`checkFileContents(${username}, ${languageCode}, ${repoCode}, ${branch}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(username !== undefined, "checkFileContents: 'username' parameter should be defined"); parameterAssert(typeof username === 'string', `checkFileContents: 'username' parameter should be a string not a '${typeof username}': ${username}`); parameterAssert(languageCode !== undefined, "checkFileContents: 'languageCode' parameter should be defined"); diff --git a/src/demos/repo-check/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index d3c3b60e8..731238428 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -38,8 +38,8 @@ function RepoCheck(/*username, languageCode,*/ props) { // Also, I don’t think the results were getting returned correctly yet // if (repoName && repoName.endsWith('_tn')) { // // TODO: Should the user be able to turn this off and on ???? - // checkingOptions.checkLinkedTAArticleFlag = true; - // checkingOptions.checkLinkedTWArticleFlag = true; + // checkingOptions.disableLinkedTAArticlesCheckFlag = false; + // checkingOptions.disableLinkedTWArticlesCheckFlag = false; // } // Or this allows the parameters to be specified as a RepoCheck property if (props.excerptLength) checkingOptions.excerptLength = ourParseInt(props.excerptLength); diff --git a/src/demos/repo-check/checkRepo.js b/src/demos/repo-check/checkRepo.js index 317b555ba..4354b2626 100644 --- a/src/demos/repo-check/checkRepo.js +++ b/src/demos/repo-check/checkRepo.js @@ -231,7 +231,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe bookID = (bookOrFileCode.length === 6 || bookOrFileCode.length === 7) ? bookOrFileCode.substring(0, 3) : bookOrFileCode.slice(-3).toUpperCase(); logicAssert(bookID !== 'twl' && bookID !== 'TWL', `Should get a valid bookID here, not '${bookID}'`) // debugLog(`Have TSV bookcode(${bookID.length})='${bookID}'`); - if (repoCode === 'TWL' || repoCode === 'SN' || repoCode === 'SQ' || repoCode === 'TN2' || repoCode === 'TQ2') // new repos + if (repoCode === 'TWL' || repoCode === 'SN' || repoCode === 'SQ' || repoCode === 'TN2' || repoCode === 'TQ2') // new repos allow `OBS` parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for TSV)`); else parameterAssert(bookID !== 'OBS' && books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for TSV)`); diff --git a/yarn.lock b/yarn.lock index 5549043a3..ecb9a4b84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1871,19 +1871,12 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest-diff@*": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-24.3.0.tgz#29e237a3d954babfe6e23cc59b57ecd8ca8d858d" - integrity sha512-vx1CRDeDUwQ0Pc7v+hS61O1ETA81kD04IMEC0hS1kPyVtHDdZrokAvpF7MT9VI/fVSzicelUZNCepDvhRV1PeA== +"@types/jest@^24.0.22": + version "24.9.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.9.1.tgz#02baf9573c78f1b9974a5f36778b366aa77bd534" + integrity sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q== dependencies: - jest-diff "*" - -"@types/jest@24.0.22": - version "24.0.22" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.22.tgz#08a50be08e78aba850a1185626e71d31e2336145" - integrity sha512-t2OvhNZnrNjlzi2i0/cxbLVM59WN15I2r1Qtb7wDv28PnV9IzrPtagFRey/S9ezdLD0zyh1XGMQIEQND2YEfrw== - dependencies: - "@types/jest-diff" "*" + jest-diff "^24.3.0" "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5": version "7.0.7" @@ -2626,14 +2619,14 @@ array-flatten@^2.1.0: integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== array-includes@^3.0.3, array-includes@^3.1.1, array-includes@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" - integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" + integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - get-intrinsic "^1.0.1" + es-abstract "^1.18.0-next.2" + get-intrinsic "^1.1.1" is-string "^1.0.5" array-union@^1.0.1: @@ -3497,9 +3490,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: - version "1.0.30001189" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001189.tgz#f8547299b9db78d3882b0dea1cae891fed1651e8" - integrity sha512-BSfxClP/UWCD0RX1h1L+vLDexNSJY7SfOtbJtW10bcnatfj3BcoietUFYNwWreOCk+SNvGUaNapGqUNPiGAiSA== + version "1.0.30001190" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001190.tgz#acc6d4a53c68be16cfc314d55c9cab637e558cba" + integrity sha512-62KVw474IK8E+bACBYhRS0/L6o/1oeAVkpF2WetjV58S5vkzNh0/Rz3lD8D4YCbOTqi0/aD4X3LtoP7V5xnuAg== canvg@^3.0.6: version "3.0.7" @@ -4895,9 +4888,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.670" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.670.tgz#b1560b9ab212ff77fc8197002e735b72882c31be" - integrity sha512-iiHQa72+3wbkPR0O8InsNbRwKcV6gBEKiUqPaJ4+TOwQkJQY4ku1sBNC+0ZSfANQ0nqr0SyRO3/Qr6S7Lct/IA== + version "1.3.671" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.671.tgz#8feaed6eae42d279fa4611f58c42a5a1eb81b2a0" + integrity sha512-RTD97QkdrJKaKwRv9h/wGAaoR2lGxNXEcBXS31vjitgTPwTWAbLdS7cEsBK68eEQy7p6YyT8D5BxBEYHu2SuwQ== elliptic@^6.5.3: version "6.5.4" @@ -4964,7 +4957,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^4.1.0, enhanced-resolve@^4.3.0: +enhanced-resolve@^4.1.0, enhanced-resolve@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== @@ -5014,7 +5007,7 @@ es-abstract@^1.17.2: string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.18.0-next.1: +es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: version "1.18.0-next.2" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== @@ -6071,7 +6064,7 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -7439,17 +7432,7 @@ jest-config@^26.6.3: micromatch "^4.0.2" pretty-format "^26.6.2" -jest-diff@*, jest-diff@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" - integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== - dependencies: - chalk "^4.0.0" - diff-sequences "^26.6.2" - jest-get-type "^26.3.0" - pretty-format "^26.6.2" - -jest-diff@^24.9.0: +jest-diff@^24.3.0, jest-diff@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== @@ -7459,6 +7442,16 @@ jest-diff@^24.9.0: jest-get-type "^24.9.0" pretty-format "^24.9.0" +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + jest-docblock@^24.3.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" @@ -8739,9 +8732,9 @@ lodash.uniq@^4.5.0: integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= "lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-driver@^1.2.7: version "1.2.7" @@ -9483,11 +9476,11 @@ object-inspect@^1.8.0, object-inspect@^1.9.0: integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== object-is@^1.0.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.4.tgz#63d6c83c00a43f4cbc9434eb9757c8a5b8565068" - integrity sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg== + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" object-keys@^1.0.12, object-keys@^1.1.1: @@ -9533,13 +9526,13 @@ object.fromentries@^2.0.2: has "^1.0.3" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0, object.getownpropertydescriptors@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" - integrity sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng== + version "2.1.2" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" + integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.18.0-next.2" object.pick@^1.3.0: version "1.3.0" @@ -10755,9 +10748,9 @@ prepend-http@^1.0.0: integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= pretty-bytes@^5.1.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.5.0.tgz#0cecda50a74a941589498011cf23275aa82b339e" - integrity sha512-p+T744ZyjjiaFlMUZZv6YPC5JrkNj8maRmPaQCWFJFplUAzpIUTRaTcS+7wmZtUoFXHtESJb23ISliaWyz3SHA== + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== pretty-error@^2.1.1: version "2.1.2" @@ -11123,7 +11116,7 @@ react-docgen-displayname-handler@^2.1.1: dependencies: ast-types "0.13.2" -react-docgen@4.1.1, react-docgen@^4.1.0: +react-docgen@^4.1.0, react-docgen@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-4.1.1.tgz#8fef0212dbf14733e09edecef1de6b224d87219e" integrity sha512-o1wdswIxbgJRI4pckskE7qumiFyqkbvCO++TylEDOo2RbMiueIOg8YzKU4X9++r0DjrbXePw/LHnh81GRBTWRw== @@ -13868,10 +13861,10 @@ webpack@4.42.0: watchpack "^1.6.0" webpack-sources "^1.4.1" -webpack@4.44.2: - version "4.44.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" - integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== +webpack@^4.44.2: + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -13881,7 +13874,7 @@ webpack@4.44.2: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" + enhanced-resolve "^4.5.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" From c19bc340a068cc488b4a068d7be7b48296adadcf Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Tue, 23 Feb 2021 19:25:05 +1300 Subject: [PATCH 11/16] WIP checking md links more thoroughly --- package.json | 2 +- src/__tests__/book-package-check.test.js | 2 + src/core/manifest-text-check.js | 2 +- src/core/markdown-file-contents-check.js | 40 +- src/core/markdown-text-check.js | 151 ++- src/core/notes-links-check.js | 1156 ++++++++++------- src/core/notes-tsv7-row-check.js | 22 +- src/core/notes-tsv7-table-check.js | 2 +- src/core/plain-text-check.js | 2 +- src/core/questions-tsv7-row-check.js | 24 +- src/core/questions-tsv7-table-check.js | 2 +- src/core/tn-tsv9-row-check.js | 22 +- src/core/tn-tsv9-table-check.js | 2 +- src/core/twl-tsv6-row-check.js | 18 +- src/core/twl-tsv6-table-check.js | 2 +- src/core/usfm-text-check.js | 16 +- src/core/utilities.js | 2 +- src/core/yaml-text-check.js | 2 +- .../book-package-check/checkBookPackage.js | 3 +- src/demos/file-check/FileCheck.js | 9 +- src/demos/file-check/README.md | 8 +- src/demos/file-check/checkFileContents.js | 13 +- yarn.lock | 38 +- 23 files changed, 915 insertions(+), 625 deletions(-) diff --git a/package.json b/package.json index ab098ad43..8eeda739f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha6", + "version": "2.0.0_alpha7", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/book-package-check.test.js b/src/__tests__/book-package-check.test.js index 65aeefe5b..57776af26 100644 --- a/src/__tests__/book-package-check.test.js +++ b/src/__tests__/book-package-check.test.js @@ -7,6 +7,8 @@ import fs from 'fs-extra'; let testFiles = {}; const optionalCheckingOptions = { + disableLinkedTAArticlesCheckFlag: true, + disableLinkedTWArticlesCheckFlag: true, getFile: params => { const { username, repository, path } = params; // console.log(`book-package-check.test getFile(${username}, ${repository}, ${path})`) diff --git a/src/core/manifest-text-check.js b/src/core/manifest-text-check.js index bf5f71d25..187b95b83 100644 --- a/src/core/manifest-text-check.js +++ b/src/core/manifest-text-check.js @@ -740,7 +740,7 @@ export async function checkManifestText(languageCode, repoCode, username, repoNa } // addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length==1?'':'s'}${ourLocation}.`); - if (cmtResult.noticeList) + if (cmtResult.noticeList.length) addSuccessMessage(`checkManifestText v${MANIFEST_VALIDATOR_VERSION_STRING} finished with ${cmtResult.noticeList.length ? cmtResult.noticeList.length.toLocaleString() : "zero"} notice${cmtResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkManifestText v${MANIFEST_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/markdown-file-contents-check.js b/src/core/markdown-file-contents-check.js index 32fbc6912..6c4820fa5 100644 --- a/src/core/markdown-file-contents-check.js +++ b/src/core/markdown-file-contents-check.js @@ -1,7 +1,8 @@ import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkMarkdownText } from './markdown-text-check'; import { checkTextfileContents } from './file-text-check'; -import { userLog, parameterAssert } from './utilities'; +// eslint-disable-next-line no-unused-vars +import { userLog, functionLog, debugLog, parameterAssert } from './utilities'; const MARKDOWN_FILE_VALIDATOR_VERSION_STRING = '0.4.0'; @@ -10,25 +11,22 @@ const MARKDOWN_FILE_VALIDATOR_VERSION_STRING = '0.4.0'; /** * * @param {string} languageCode - * @param {string} repoCode -- e.g., 'TN' or 'TQ2', etc. + * @param {string} repoCode -- e.g., 'TW' or 'TQ', etc. * @param {string} markdownFilename -- used for identification * @param {string} markdownText -- the actual text to be checked * @param {string} givenLocation * @param {Object} checkingOptions */ -export function checkMarkdownFileContents(languageCode, repoCode, markdownFilename, markdownText, givenLocation, checkingOptions) { +export async function checkMarkdownFileContents(languageCode, repoCode, markdownFilename, markdownText, givenLocation, checkingOptions) { /* This function is optimised for checking the entire markdown file, i.e., all lines. - Note: This function does not check that any link targets in the markdown are valid links. - Returns a result object containing a successList and a noticeList */ - // functionLog(`checkMarkdownFileContents(${languageCode}, ${markdownFilename}, ${markdownText.length}, ${givenLocation})…`); + // functionLog(`checkMarkdownFileContents(${languageCode}, ${repoCode}, ${markdownFilename}, ${markdownText.length}, ${givenLocation})…`); parameterAssert(languageCode !== undefined, "checkMarkdownFileContents: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkMarkdownFileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); - parameterAssert(repoCode !== undefined, "checkMarkdownFileContents: 'repoCode' parameter should be defined"); - parameterAssert(typeof repoCode === 'string', `checkMarkdownFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}': ${repoCode}`); -parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'markdownFilename' parameter should be defined"); + parameterAssert(repoCode === 'TW' || repoCode === 'TQ', `checkMarkdownFileContents: 'repoCode' parameter should be a 'TW' or 'TQ' not '${repoCode}'`); + parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'markdownFilename' parameter should be defined"); parameterAssert(typeof markdownFilename === 'string', `checkMarkdownFileContents: 'markdownFilename' parameter should be a string not a '${typeof markdownFilename}': ${markdownFilename}`); parameterAssert(markdownText !== undefined, "checkMarkdownFileContents: 'markdownText' parameter should be defined"); parameterAssert(typeof markdownText === 'string', `checkMarkdownFileContents: 'markdownText' parameter should be a string not a '${typeof markdownText}': ${markdownText}`); @@ -62,7 +60,7 @@ parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'mar result.successList.push(successString); } function addNoticePartial(noticeObject) { - // functionLog(`checkMarkdownFileContents addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? " " + excerpt : ""}${noticeObject.location}`); + // functionLog(`checkMarkdownFileContents addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.excerpt ? " " + noticeObject.excerpt : ""}${noticeObject.location}`); parameterAssert(noticeObject.priority !== undefined, "cMdT addNoticePartial: 'priority' parameter should be defined"); parameterAssert(typeof noticeObject.priority === 'number', `cMdT addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); parameterAssert(noticeObject.message !== undefined, "cMdT addNoticePartial: 'message' parameter should be defined"); @@ -74,7 +72,7 @@ parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'mar parameterAssert(noticeObject.location !== undefined, "cMdT addNoticePartial: 'location' parameter should be defined"); parameterAssert(typeof noticeObject.location === 'string', `cMdT addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - if (noticeObject.debugChain) noticeObject.debugChain = `checkMarkdownFileContents ${noticeObject.debugChain}`; + if (noticeObject.debugChain) noticeObject.debugChain = `checkMarkdownFileContents ${noticeObject.debugChain}`; // Prepend our name result.noticeList.push({ ...noticeObject, filename: markdownFilename }); } // end of addNoticePartial function @@ -98,11 +96,12 @@ parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'mar parameterAssert(optionalFieldLocation !== undefined, "cMdFC ourCheckMarkdownText: 'optionalFieldLocation' parameter should be defined"); parameterAssert(typeof optionalFieldLocation === 'string', `cMdFC ourCheckMarkdownText: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const dbtcResultObject = await checkMarkdownText(languageCode, repoCode, markdownFilename, markdownText, optionalFieldLocation, checkingOptions); + const cmtResultObject = await checkMarkdownText(languageCode, repoCode, markdownFilename, markdownText, optionalFieldLocation, checkingOptions); + // debugLog(`cmtResultObject=${JSON.stringify(cmtResultObject)}`); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line - for (const noticeEntry of dbtcResultObject.noticeList) + for (const noticeEntry of cmtResultObject.noticeList) addNoticePartial(noticeEntry); } // end of ourCheckMarkdownText function @@ -120,33 +119,34 @@ parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'mar // We assume that checking for compulsory fields is done elsewhere // Updates the global list of notices - // debugLog(`cMdT ourFileTextCheck(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${optionalFieldLocation}, …)`); + // debugLog(`cMdFC ourFileTextCheck(${markdownText}, (${markdownText.length}), ${optionalFieldLocation}, ${JSON.stringify(checkingOptions)})`); parameterAssert(markdownText !== undefined, "cMdFC ourFileTextCheck: 'markdownText' parameter should be defined"); parameterAssert(typeof markdownText === 'string', `cMdFC ourFileTextCheck: 'markdownText' parameter should be a string not a '${typeof markdownText}'`); parameterAssert(checkingOptions !== undefined, "cMdFC ourFileTextCheck: 'checkingOptions' parameter should be defined"); - const dbtcResultObject = checkTextfileContents(languageCode, repoCode, 'markdown', markdownFilename, markdownText, optionalFieldLocation, checkingOptions); + const ctfcResultObject = checkTextfileContents(languageCode, repoCode, 'markdown', markdownFilename, markdownText, optionalFieldLocation, checkingOptions); + // debugLog(`ctfcResultObject=${JSON.stringify(ctfcResultObject)}`); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line - for (const noticeEntry of dbtcResultObject.noticeList) + for (const noticeEntry of ctfcResultObject.noticeList) addNoticePartial(noticeEntry); } // end of ourFileTextCheck function // Main code for checkMarkdownFileContents function - ourCheckMarkdownText(markdownText, givenLocation, checkingOptions); + await ourCheckMarkdownText(markdownText, givenLocation, checkingOptions); ourFileTextCheck(markdownText, givenLocation, checkingOptions); + addSuccessMessage(`Checked markdown file: ${markdownFilename}`); - if (result.noticeList) + if (result.noticeList.length) addSuccessMessage(`checkMarkdownFileContents v${MARKDOWN_FILE_VALIDATOR_VERSION_STRING} finished with ${result.noticeList.length ? result.noticeList.length.toLocaleString() : "zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkMarkdownFileContents v${MARKDOWN_FILE_VALIDATOR_VERSION_STRING}`) // debugLog(` checkMarkdownFileContents returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); - if (markdownFilename.endsWith('walk.md')) - userLog("checkMarkdownFileContents result is", JSON.stringify(result)); + // userLog(`checkMarkdownFileContents result is ${JSON.stringify(result)}`); return result; } // end of checkMarkdownFileContents function diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 95ddc4830..c31318cc3 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -1,14 +1,13 @@ import { DEFAULT_EXCERPT_LENGTH } from './text-handling-functions' import { checkTextField } from './field-text-check'; -import { cachedGetFileUsingFullURL } from '../core/getApi'; +import { checkNotesLinksToOutside } from './notes-links-check'; +// import { cachedGetFileUsingFullURL } from '../core/getApi'; import { removeDisabledNotices } from './disabled-notices'; -import { parameterAssert, dataAssert } from './utilities'; +// eslint-disable-next-line no-unused-vars +import { parameterAssert, dataAssert, debugLog } from './utilities'; -const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.6.0'; - -const SIMPLE_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ "\\)]+?)\\)', 'g'); // ![alt](y) -const TITLED_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ \\)]+?) "([^"\\)]+?)"\\)', 'g'); // ![alt](link "title") +const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.7.0'; /** @@ -25,8 +24,6 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, This text may not necessarily be from a file -- it may be from a (multiline) field within a file - Note: This function does not check that any link targets in the markdown are valid links. - Returns a result object containing a successList and a noticeList */ // functionLog(`checkMarkdownText(${languageCode}, ${repoCode}, ${textOrFileName}, ${markdownText.length}, ${givenLocation}, …)…`); @@ -123,6 +120,53 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, // end of ourCheckTextField function + async function ourCheckNotesLinksToOutside(lineNumber, lineText, location, checkingOptions) { + // Checks that the TA/TW/Bible reference can be found + + // Updates the global list of notices + + // functionLog(`checkUSFMText ourCheckNotesLinksToOutside(${lineNumber}, ${C}:${V}, ${marker}, (${twLinkText.length}) '${twLinkText}', ${location}, ${JSON.stringify(checkingOptions)})`); + parameterAssert(lineNumber !== undefined, "checkUSFMText ourCheckNotesLinksToOutside: 'lineNumber' parameter should be defined"); + parameterAssert(typeof lineNumber === 'number', `checkUSFMText ourCheckNotesLinksToOutside: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); + parameterAssert(lineText !== undefined, "checkUSFMText ourCheckNotesLinksToOutside: 'lineText' parameter should be defined"); + parameterAssert(typeof lineText === 'string', `checkUSFMText ourCheckNotesLinksToOutside: 'lineText' parameter should be a string not a '${typeof lineText}': ${lineText}`); + parameterAssert(location !== undefined, "checkUSFMText ourCheckNotesLinksToOutside: 'location' parameter should be defined"); + parameterAssert(typeof location === 'string', `checkUSFMText ourCheckNotesLinksToOutside: 'location' parameter should be a string not a '${typeof location}': ${location}`); + + const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, '', '', '', 'MDFile', lineText, location, { ...checkingOptions, defaultLanguageCode: languageCode }); + // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); + + // Choose only ONE of the following + // This is the fast way of append the results from this field + // result.noticeList = result.noticeList.concat(coTNlResultObject.noticeList); + // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // process results line by line + for (const coqNoticeEntry of coTNlResultObject.noticeList) { + if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + result.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is -- would be confusing to have this lineNumber + else // For our direct checks, we add the repoCode as an extra value + addNotice({ ...coqNoticeEntry, lineNumber }); + } + // The following is needed coz we might be checking the linked TA and/or TW articles + if (coTNlResultObject.checkedFileCount && coTNlResultObject.checkedFileCount > 0) + if (typeof result.checkedFileCount === 'number') result.checkedFileCount += coTNlResultObject.checkedFileCount; + else result.checkedFileCount = coTNlResultObject.checkedFileCount; + if (coTNlResultObject.checkedFilesizes && coTNlResultObject.checkedFilesizes > 0) + if (typeof result.checkedFilesizes === 'number') result.checkedFilesizes += coTNlResultObject.checkedFilesizes; + else result.checkedFilesizes = coTNlResultObject.checkedFilesizes; + if (coTNlResultObject.checkedRepoNames && coTNlResultObject.checkedRepoNames.length > 0) + for (const checkedRepoName of coTNlResultObject.checkedRepoNames) + try { if (result.checkedRepoNames.indexOf(checkedRepoName) < 0) result.checkedRepoNames.push(checkedRepoName); } + catch { result.checkedRepoNames = [checkedRepoName]; } + if (coTNlResultObject.checkedFilenameExtensions && coTNlResultObject.checkedFilenameExtensions.length > 0) + for (const checkedFilenameExtension of coTNlResultObject.checkedFilenameExtensions) + try { if (result.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) result.checkedFilenameExtensions.push(checkedFilenameExtension); } + catch { result.checkedFilenameExtensions = [checkedFilenameExtension]; } + // if (result.checkedFilenameExtensions) userLog("result", JSON.stringify(result)); + } + // end of ourCheckNotesLinksToOutside function + + /** * * @param {string} lineNumber @@ -134,49 +178,52 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, // functionLog(`checkMarkdownLineContents for ${lineNumber} '${lineText}' at${lineLocation}`); - // Check for image links - let regexResultArray; - while ((regexResultArray = SIMPLE_IMAGE_REGEX.exec(lineText))) { - // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); - const [totalLink, altText, fetchLink] = regexResultArray; - // if (altText !== 'OBS Image') userLog("This code was only checked for 'OBS Image' links"); - if (!altText) - addNotice({ priority: 349, message: "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation }); - if (!fetchLink.startsWith('https://')) - addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); - else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { - // debugLog(`Need to check existence of ${fetchLink}`); - try { - const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); - dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); - // debugLog("Markdown link fetch got response: ", responseData.length); - } catch (flError) { - console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); - addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation }); - } - } - } - while ((regexResultArray = TITLED_IMAGE_REGEX.exec(lineText))) { - // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); - const [totalLink, alt, fetchLink, title] = regexResultArray; - if (!alt) - addNotice({ priority: 349, message: "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation }); - if (!title) - addNotice({ priority: 348, message: "Markdown image link has no title text", lineNumber, excerpt: totalLink, location: lineLocation }); - if (!fetchLink.startsWith('https://')) - addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); - else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { - // debugLog(`Need to check existence of ${fetchLink}`); - try { - const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); - dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); - // debugLog("Markdown link fetch got response: ", responseData.length); - } catch (flError) { - console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); - addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation }); - } - } - } + // // Check for image links + // let regexResultArray; + // while ((regexResultArray = SIMPLE_IMAGE_REGEX.exec(lineText))) { + // // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); + // const [totalLink, altText, fetchLink] = regexResultArray; + // // if (altText !== 'OBS Image') userLog("This code was only checked for 'OBS Image' links"); + // if (!altText) + // addNotice({ priority: 349, message: "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation }); + // if (!fetchLink.startsWith('https://')) + // addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); + // else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { + // // debugLog(`Need to check existence of ${fetchLink}`); + // try { + // const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); + // dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); + // // debugLog("Markdown link fetch got response: ", responseData.length); + // } catch (flError) { + // console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); + // addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation }); + // } + // } + // } + // while ((regexResultArray = TITLED_IMAGE_REGEX.exec(lineText))) { + // // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); + // const [totalLink, alt, fetchLink, title] = regexResultArray; + // if (!alt) + // addNotice({ priority: 349, message: "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation }); + // if (!title) + // addNotice({ priority: 348, message: "Markdown image link has no title text", lineNumber, excerpt: totalLink, location: lineLocation }); + // if (!fetchLink.startsWith('https://')) + // addNotice({ priority: 749, message: "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation }); + // else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { + // // debugLog(`Need to check existence of ${fetchLink}`); + // try { + // const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); + // dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); + // // debugLog("Markdown link fetch got response: ", responseData.length); + // } catch (flError) { + // console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); + // addNotice({ priority: 748, message: "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation }); + // } + // } + // } + + if (lineText.indexOf('[') >= 0) // Check for markdown links like [[xx]] or [xx](yy) etc. + await ourCheckNotesLinksToOutside(lineNumber, lineText, givenLocation, checkingOptions) let thisText = lineText; // so we can adjust it @@ -347,7 +394,7 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, } addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length === 1 ? '' : 's'}${ourLocation}.`); - if (result.noticeList) + if (result.noticeList.length) addSuccessMessage(`checkMarkdownText v${MARKDOWN_TEXT_VALIDATOR_VERSION_STRING} finished with ${result.noticeList.length ? result.noticeList.length.toLocaleString() : "zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkMarkdownText v${MARKDOWN_TEXT_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index c76a921c7..929534647 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -2,8 +2,9 @@ import localforage from 'localforage'; import Path from 'path'; import * as books from '../core/books/books'; import { DEFAULT_EXCERPT_LENGTH, countOccurrences } from './text-handling-functions' -import { cachedGetFile, checkMarkdownText } from '../core'; -import { userLog, debugLog, parameterAssert, logicAssert, ourParseInt } from './utilities'; +import { cachedGetFile, cachedGetFileUsingFullURL, checkMarkdownText } from '../core'; +// eslint-disable-next-line no-unused-vars +import { userLog, debugLog, functionLog, parameterAssert, logicAssert, dataAssert, ourParseInt } from './utilities'; // import { consoleLogObject } from '../core/utilities'; @@ -15,9 +16,12 @@ const DEFAULT_BRANCH = 'master'; const GENERAL_LINK1_REGEX = new RegExp('\\[[^\\]]+?\\]\\([^\\)]+?\\)', 'g'); // [displayLink](URL) const GENERAL_LINK2_REGEX = new RegExp('\\[\\[[^\\]]+?\\]\\]', 'g'); // [[combinedDisplayLink]] -const TA_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TA_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TA_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\(rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\)', 'g'); // [How to Translate Names](rc://en/ta/man/translate/translate-names) + const TW_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] const TWL_RAW_LINK_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g'); // Just a raw link +const TW_INTERNAL_REGEX = new RegExp('\\[([A-za-z]+?)\\]\\(\\.{2}/([a-z]{2,5})/([-A-Za-z]{2,20})\\.md\\)', 'g');// [Asher](../names/asher.md) // TODO: Do we need to normalise Bible links, i.e., make sure that the link itself // (we don't care about the displayed text) doesn't specify superfluous levels/information @@ -32,8 +36,13 @@ const THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})\\]\\(\\ const THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})[–-](\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g');// [2–7](../09/2.md) NOTE en-dash const BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})[–-](\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); // [Genesis 26:12-14](./12.md) NOTE en-dash +const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(rc://([^ /]+?)/tn/help/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\)', 'g'); // [Genesis 29:23](rc://en/tn/help/gen/29/23) + const TN_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})/([a-z][a-z0-9][a-z0-9][a-z0-9])\\)', 'g'); +const SIMPLE_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ "\\)]+?)\\)', 'g'); // ![alt](y) +const TITLED_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ \\)]+?) "([^"\\)]+?)"\\)', 'g'); // ![alt](link "title") + // Caches the path names of files which have been already checked // Used for storing paths to TA and TW articles that have already been checked @@ -79,7 +88,7 @@ async function alreadyChecked({ username, repository, path, branch }) { * @param {string} languageCode, e.g., 'en' * @param {string} repoCode, e.g., 'TN', 'SN', 'TN2', or even 'TWL' * @param {string} bookID - * @param {string} fieldName, e.g., 'OccurrenceNote' or 'Note' or 'TWLink' + * @param {string} fieldName, e.g., 'OccurrenceNote' or 'Note' or 'TWLink' or 'MDFile' * @param {string} fieldText * @param {string} givenLocation * @param {Object} checkingOptions @@ -112,21 +121,24 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // checkingOptions.disableLinkedTWArticlesCheckFlag */ - // if (fieldText.indexOf('brother') !== -1) functionLog(`checkNotesLinksToOutside v${NOTES_LINKS_VALIDATOR_VERSION_STRING} ${repoCode} ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + // if (fieldText.indexOf('brother') !== -1) + // functionLog(`checkNotesLinksToOutside('${languageCode}', '${repoCode}', ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkNotesLinksToOutside: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkNotesLinksToOutside: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode !== undefined, "checkNotesLinksToOutside: 'repoCode' parameter should be defined"); parameterAssert(typeof repoCode === 'string', `checkNotesLinksToOutside: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); parameterAssert(bookID !== undefined, "checkNotesLinksToOutside: 'bookID' parameter should be defined"); parameterAssert(typeof bookID === 'string', `checkNotesLinksToOutside: 'bookID' parameter should be a string not a '${typeof bookID}'`); - parameterAssert(bookID.length === 3, `checkNotesLinksToOutside: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkNotesLinksToOutside: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesLinksToOutside: '${bookID}' is not a valid USFM book identifier`); parameterAssert(typeof givenC === 'string', `checkNotesLinksToOutside: 'givenC' parameter should be a string not a '${typeof givenC}'`); parameterAssert(typeof givenV === 'string', `checkNotesLinksToOutside: 'givenV' parameter should be a string not a '${typeof givenV}'`); + if (fieldName !== 'MDFile') { + parameterAssert(bookID.length === 3, `checkNotesLinksToOutside: 'bookID' parameter should be three characters long not ${bookID.length}`); + parameterAssert(bookID.toUpperCase() === bookID, `checkNotesLinksToOutside: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesLinksToOutside: '${bookID}' is not a valid USFM book identifier`); + } parameterAssert(fieldName !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldName === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Note' || fieldName === 'TWLink', `checkNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' or 'Note' or 'TWLink' not '${fieldName}'`); + parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Note' || fieldName === 'TWLink' || fieldName === 'MDFile', `checkNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' or 'Note' or 'TWLink' or 'MDFile' not '${fieldName}'`); parameterAssert(fieldText !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldText === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); parameterAssert(givenLocation !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); @@ -188,540 +200,760 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g else break; // stop at the first non-digit } let givenCint, givenVint; - try { - givenCint = (givenC === 'front') ? 0 : ourParseInt(givenC); - givenVint = (givenV === 'intro') ? 0 : ourParseInt(givenVfirstPart); - if (givenVfirstPart !== givenV && givenV !== 'intro') debugLog(`From '${givenC}':'${givenV}' got '${givenC}':'${givenVfirstPart}' then integers ${givenCint}:${givenVint}`); - } catch (cvError) { - console.error(`TN Link Check couldn’t parse given chapter and verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName}' via ${givenC}:${givenVfirstPart} got ${givenCint}:${givenVint} with ${cvError}`); + if (fieldName !== 'MDFile') { + try { + givenCint = (givenC === 'front') ? 0 : ourParseInt(givenC); + givenVint = (givenV === 'intro') ? 0 : ourParseInt(givenVfirstPart); + if (givenVfirstPart !== givenV && givenV !== 'intro') debugLog(`From '${givenC}':'${givenV}' got '${givenC}':'${givenVfirstPart}' then integers ${givenCint}:${givenVint}`); + } catch (cvError) { + console.error(`TN Link Check couldn’t parse given chapter and verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName}' via ${givenC}:${givenVfirstPart} got ${givenCint}:${givenVint} with ${cvError}`); + } } let regexResultArray; - // Find total links + // Check for image links + while ((regexResultArray = SIMPLE_IMAGE_REGEX.exec(fieldText))) { + // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); + const [totalLink, altText, fetchLink] = regexResultArray; + // if (altText !== 'OBS Image') userLog("This code was only checked for 'OBS Image' links"); + if (!altText) + addNoticePartial({ priority: 349, message: "Markdown image link has no alternative text", excerpt: totalLink, location: ourLocation }); + if (!fetchLink.startsWith('https://')) + addNoticePartial({ priority: 749, message: "Markdown image link seems faulty", excerpt: fetchLink, location: ourLocation }); + else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { + // debugLog(`Need to check existence of ${fetchLink}`); + try { + const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); + dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); + // debugLog("Markdown link fetch got response: ", responseData.length); + } catch (flError) { + console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); + addNoticePartial({ priority: 748, message: "Error fetching markdown image link", excerpt: fetchLink, location: ourLocation }); + } + } + } + while ((regexResultArray = TITLED_IMAGE_REGEX.exec(fieldText))) { + // debugLog(`Got markdown image in line ${lineNumber}:`, JSON.stringify(regexResultArray)); + const [totalLink, alt, fetchLink, title] = regexResultArray; + if (!alt) + addNoticePartial({ priority: 349, message: "Markdown image link has no alternative text", excerpt: totalLink, location: ourLocation }); + if (!title) + addNoticePartial({ priority: 348, message: "Markdown image link has no title text", excerpt: totalLink, location: ourLocation }); + if (!fetchLink.startsWith('https://')) + addNoticePartial({ priority: 749, message: "Markdown image link seems faulty", excerpt: fetchLink, location: ourLocation }); + else if (checkingOptions?.disableAllLinkFetchingFlag !== true) { + // debugLog(`Need to check existence of ${fetchLink}`); + try { + const responseData = await cachedGetFileUsingFullURL({ uri: fetchLink }); + dataAssert(responseData.length > 10, `Expected ${fetchLink} image file to be longer: ${responseData.length}`); + // debugLog("Markdown link fetch got response: ", responseData.length); + } catch (flError) { + console.error(`Markdown image link fetch had an error fetching '${fetchLink}': ${flError}`); + addNoticePartial({ priority: 748, message: "Error fetching markdown image link", excerpt: fetchLink, location: ourLocation }); + } + } + } + + // Find total regular (non-image) links const linksList1 = fieldText.match(GENERAL_LINK1_REGEX) || []; - // debugLog(`linksList1=${JSON.stringify(linksList1)}`); + // if (linksList1.length) debugLog(`linksList1=${JSON.stringify(linksList1)}`); const linksList2 = fieldText.match(GENERAL_LINK2_REGEX) || []; + // if (linksList2.length) debugLog(`linksList2=${JSON.stringify(linksList2)}`); const totalLinks1 = linksList1.length; const totalLinks2 = linksList2.length; let taLinkCount = 0, twLinkCount = 0, thisChapterBibleLinkCount = 0, thisVerseBibleLinkCount = 0, thisBookBibleLinkCount = 0, otherBookBibleLinkCount = 0, TNLinkCount = 0; let processedLinkList = []; - // Check for TA links like [[rc://en/ta/man/translate/figs-metaphor]] - // if (fieldText.indexOf('brother') !== -1) debugLog("checkNotesLinksToOutside: Search for TA links") - while ((regexResultArray = TA_DOUBLE_BRACKETED_LINK_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside TA resultArray=${JSON.stringify(regexResultArray)}`); - taLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `TA_REGEX expected 4 fields (not ${regexResultArray.length})`) - let languageCode = regexResultArray[1]; - if (languageCode !== '*') { - const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); - } else if (repoCode === 'TN') { // but not TN2 - // At the moment, tC can’t handle these links with * so we have to ensure that they're not there - const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); + if (fieldName === 'MDFile') { + // Check for internal TW links like [Asher](../names/asher.md) + while ((regexResultArray = TW_INTERNAL_REGEX.exec(fieldText))) { + debugLog(` checkNotesLinksToOutside TW_INTERNAL_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + twLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 4, `TW_INTERNAL_REGEX expected 4 fields (not ${regexResultArray.length})`); + // eslint-disable-next-line no-unused-vars + let [_totalLink, _displayName, category, article] = regexResultArray; + + const twRepoName = `${languageCode}_tw`; + // debugLog(`Got twRepoName=${twRepoName}`); + const filepath = `bible/${category}/${article}.md`; + // debugLog(`Got tW filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); + const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; + let twFileContent; + try { + twFileContent = await getFile_(twPathParameters); + // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); + } catch (trcGCerror) { + console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); + addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + } + if (!twFileContent) + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else { // we got the content of the TW article + if (twFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else if (0 && checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { + // THIS IS DISABLED COZ IT CAN GIVE AN INFINITE LOOP !!! + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); + if (await alreadyChecked(twPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); + const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTWFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = twFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(twRepoName); + markAsChecked(twPathParameters); // don’t bother waiting for the result + } + } + else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); + } + } + else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } - if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; - const taRepoName = `${languageCode}_ta`; - // debugLog(`Got taRepoName=${taRepoName}`); - const filepath = `${regexResultArray[2]}/${regexResultArray[3]}/01.md`; // Other files are title.md, sub-title.md - // debugLog(`Got tA filepath=${filepath}`); - - if (!checkingOptions?.disableAllLinkFetchingFlag) { - // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); - const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; - let taFileContent, alreadyGaveError = false; - try { - taFileContent = await getFile_(taPathParameters); - // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); - } catch (trcGCerror) { - // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); - addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); - alreadyGaveError = true; - } - if (!alreadyGaveError) { - if (!taFileContent) - addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (taFileContent.length < 10) - addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); - if (await alreadyChecked(taPathParameters) !== true) { - // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); - const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); - for (const noticeObject of checkTAFileResult.noticeList) - ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); - ctarResult.checkedFileCount += 1; - ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); - ctarResult.checkedFilesizes = taFileContent.length; - ctarResult.checkedFilenameExtensions = ['md']; - ctarResult.checkedRepoNames.push(taRepoName); - markAsChecked(taPathParameters); // don’t bother waiting for the result + + // Check for TA links like [How to Translate Names](rc://en/ta/man/translate/translate-names) + while ((regexResultArray = TA_DISPLAY_LINK_REGEX.exec(fieldText))) { + debugLog(` checkNotesLinksToOutside TA_DISPLAY_LINK_REGEX resultArray=${JSON.stringify(regexResultArray)}`); + taLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 5, `TA_DISPLAY_LINK_REGEX expected 5 fields (not ${regexResultArray.length})`) + // eslint-disable-next-line no-unused-vars + let [_totalLink, _displayName, languageCode, part, article] = regexResultArray; + + if (languageCode !== '*') { + const characterIndex = TA_DISPLAY_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); + } else if (repoCode === 'TN') { // but not TN2 + // At the moment, tC can’t handle these links with * so we have to ensure that they're not there + const characterIndex = TA_DISPLAY_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); + } + if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; + const taRepoName = `${languageCode}_ta`; + // debugLog(`Got taRepoName=${taRepoName}`); + const filepath = `${part}/${article}/01.md`; // Other files are title.md, sub-title.md + // debugLog(`Got tA filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); + const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; + let taFileContent, alreadyGaveError = false; + try { + taFileContent = await getFile_(taPathParameters); + // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); + } catch (trcGCerror) { + // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); + addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + alreadyGaveError = true; + } + if (!alreadyGaveError) { + if (!taFileContent) + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else if (taFileContent.length < 10) + addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); + if (await alreadyChecked(taPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); + const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTAFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = taFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(taRepoName); + markAsChecked(taPathParameters); // don’t bother waiting for the result + } + } + } + } + } + } else { // not 'MDFile' + // Check for TA links like [[rc://en/ta/man/translate/figs-metaphor]] + // if (fieldText.indexOf('brother') !== -1) debugLog("checkNotesLinksToOutside: Search for TA links") + while ((regexResultArray = TA_DOUBLE_BRACKETED_LINK_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside TA resultArray=${JSON.stringify(regexResultArray)}`); + taLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 4, `TA_DOUBLE_BRACKETED_LINK_REGEX expected 4 fields (not ${regexResultArray.length})`) + // eslint-disable-next-line no-unused-vars + let [_totalLink, languageCode, part, article] = regexResultArray; + + if (languageCode !== '*') { + const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); + } else if (repoCode === 'TN') { // but not TN2 + // At the moment, tC can’t handle these links with * so we have to ensure that they're not there + const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); + } + if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; + const taRepoName = `${languageCode}_ta`; + // debugLog(`Got taRepoName=${taRepoName}`); + const filepath = `${part}/${article}/01.md`; // Other files are title.md, sub-title.md + // debugLog(`Got tA filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); + const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; + let taFileContent, alreadyGaveError = false; + try { + taFileContent = await getFile_(taPathParameters); + // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); + } catch (trcGCerror) { + // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); + addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + alreadyGaveError = true; + } + if (!alreadyGaveError) { + if (!taFileContent) + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else if (taFileContent.length < 10) + addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); + if (await alreadyChecked(taPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); + const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTAFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = taFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(taRepoName); + markAsChecked(taPathParameters); // don’t bother waiting for the result + } } } } } - } - // Check for TW links like [[rc://en/tw/dict/bible/other/death]] in TN or rc://en/tw/dict/bible/other/death in TWLinks - // (These are not nearly as many as TA links.) - const ourTWRegex = (fieldName === 'TWLink') ? TWL_RAW_LINK_REGEX : TW_DOUBLE_BRACKETED_LINK_REGEX; - // if (fieldText.indexOf('brother') !== -1) debugLog(`checkNotesLinksToOutside: ${bookID} ${givenC}:${givenV} Search for TW links with ${ourTWRegex}`) - while ((regexResultArray = ourTWRegex.exec(fieldText))) { - // if (fieldText.indexOf('brother') !== -1) debugLog(` checkNotesLinksToOutside ${givenC}:${givenV} found TW resultArray=${JSON.stringify(regexResultArray)}`); - twLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `TW_REGEX expected 4 fields (not ${regexResultArray.length})`) - let languageCode = regexResultArray[1]; - if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; - const twRepoName = `${languageCode}_tw`; - // debugLog(`Got twRepoName=${twRepoName}`); - const filepath = `bible/${regexResultArray[2]}/${regexResultArray[3]}.md`; // Other files are title.md, sub-title.md - // debugLog(`Got tW filepath=${filepath}`); - - if (!checkingOptions?.disableAllLinkFetchingFlag) { - // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); - const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; - let twFileContent; - try { - twFileContent = await getFile_(twPathParameters); - // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); - } catch (trcGCerror) { - console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); - addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); - } - if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else { // we got the content of the TW article - if (twFileContent.length < 10) - addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); - if (await alreadyChecked(twPathParameters) !== true) { - // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); - const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); - for (const noticeObject of checkTWFileResult.noticeList) - ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); - ctarResult.checkedFileCount += 1; - ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); - ctarResult.checkedFilesizes = twFileContent.length; - ctarResult.checkedFilenameExtensions = ['md']; - ctarResult.checkedRepoNames.push(twRepoName); - markAsChecked(twPathParameters); // don’t bother waiting for the result + // Check for external TW links like [[rc://en/tw/dict/bible/other/death]] in TN or rc://en/tw/dict/bible/other/death in TWLinks + // (These are not nearly as many as TA links.) + const ourTWRegex = (fieldName === 'TWLink') ? TWL_RAW_LINK_REGEX : TW_DOUBLE_BRACKETED_LINK_REGEX; + // if (fieldText.indexOf('brother') !== -1) debugLog(`checkNotesLinksToOutside: ${bookID} ${givenC}:${givenV} Search for TW links with ${ourTWRegex}`) + while ((regexResultArray = ourTWRegex.exec(fieldText))) { + // if (fieldText.indexOf('brother') !== -1) debugLog(` checkNotesLinksToOutside ${givenC}:${givenV} found TW resultArray=${JSON.stringify(regexResultArray)}`); + twLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 4, `TW_REGEX expected 4 fields (not ${regexResultArray.length})`) + let languageCode = regexResultArray[1]; + if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; + const twRepoName = `${languageCode}_tw`; + // debugLog(`Got twRepoName=${twRepoName}`); + const filepath = `bible/${regexResultArray[2]}/${regexResultArray[3]}.md`; + // debugLog(`Got tW filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); + const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; + let twFileContent; + try { + twFileContent = await getFile_(twPathParameters); + // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); + } catch (trcGCerror) { + console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); + addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + } + if (!twFileContent) + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else { // we got the content of the TW article + if (twFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + else if (checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); + if (await alreadyChecked(twPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); + const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTWFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = twFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(twRepoName); + markAsChecked(twPathParameters); // don’t bother waiting for the result + } } + else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); } - else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); } + else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } - else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } // debugLog("checkNotesLinksToOutside: Search for Bible links") + if (fieldName === 'MDFile') { + // Check for other book Bible links like [Genesis 29:23](rc://en/tn/help/gen/29/23) + while ((regexResultArray = BIBLE_FULL_HELP_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_FULL_HELP_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 9, `BIBLE_FULL_HELP_REGEX expected 9 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, Lg, B2, C2, V2] = regexResultArray; + // debugLog(`Lg='${Lg}' B2='${B2}' C2='${C2}' V2='${V2}'`); + + if (Lg !== '*' && Lg !== languageCode) + addNoticePartial({ priority: 669, message: "Unexpected language code in link", details: `resource language code is '${languageCode}'`, excerpt: Lg, location: ourLocation }); + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - // Check for this-chapter Bible links like [Revelation 3:11](./11.md) - while ((regexResultArray = BIBLE_REGEX_THIS_CHAPTER_RELATIVE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisChapterBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 6, `BIBLE_REGEX_THIS_CHAPTER_RELATIVE expected 6 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, V2] = regexResultArray; + let linkBookCode = B2 === '..' ? bookID : B2; - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link CheckA couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link CheckA couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); } - } - - let linkBookCode = bookID; - const linkVerseInt = ourParseInt(V2); - if (C1 === undefined) { - if (!books.isOneChapterBook(linkBookCode)) { - // debugLog(` checkNotesLinksToOutside C1 missing in BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } - C1 = '0'; // Try to avoid consequential errors - } - try { - if (ourParseInt(C1) !== givenCint) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${givenCint}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check1 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } - try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check1 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); } + } else { // it's not 'MDFile' + + // Check for this-chapter Bible links like [Revelation 3:11](./11.md) + while ((regexResultArray = BIBLE_REGEX_THIS_CHAPTER_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisChapterBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 6, `BIBLE_REGEX_THIS_CHAPTER_RELATIVE expected 6 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + let linkBookCode = bookID; + + const linkVerseInt = ourParseInt(V2); + if (C1 === undefined) { + if (!books.isOneChapterBook(linkBookCode)) { + // debugLog(` checkNotesLinksToOutside C1 missing in BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); + } + C1 = '0'; // Try to avoid consequential errors + } try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } + if (ourParseInt(C1) !== givenCint) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${givenCint}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check1 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenCint); - } catch (tlcNVerror) { } - if (!givenCint || givenCint < 1 || givenCint > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${givenCint} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenCint}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check1 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } - // Check for this-verse Bible links like [11](../03/11.md) - while ((regexResultArray = THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_VERSE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisVerseBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX expected 4 fields (not ${regexResultArray.length})`); - let [totalLink, V1, C2, V2] = regexResultArray; + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenCint); + } catch (tlcNVerror) { } + if (!givenCint || givenCint < 1 || givenCint > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${givenCint} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenCint}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - let linkBookCode = bookID; + // Check for this-verse Bible links like [11](../03/11.md) + while ((regexResultArray = THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside THIS_VERSE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisVerseBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 4, `THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX expected 4 fields (not ${regexResultArray.length})`); + let [totalLink, V1, C2, V2] = regexResultArray; - let linkChapterInt, linkVerseInt; - try { - linkChapterInt = ourParseInt(C2); - linkVerseInt = ourParseInt(V2); - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${V2}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check1b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + let linkBookCode = bookID; - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + let linkChapterInt, linkVerseInt; try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } + linkChapterInt = ourParseInt(C2); + linkVerseInt = ourParseInt(V2); + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${V2}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check1b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } - // Check for this-verse Bible links like [11](../03/11.md) - while ((regexResultArray = THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_VERSE_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisVerseBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 5, `THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX expected 5 fields (not ${regexResultArray.length})`); - let [totalLink, V1a, V1b, C2, V2] = regexResultArray; + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - let linkBookCode = bookID; + // Check for this-verse Bible links like [11](../03/11.md) + while ((regexResultArray = THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside THIS_VERSE_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisVerseBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 5, `THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX expected 5 fields (not ${regexResultArray.length})`); + let [totalLink, V1a, V1b, C2, V2] = regexResultArray; - let verseInt1a, verseInt1b, linkChapterInt, linkVerseInt; - try { - verseInt1a = ourParseInt(V1a); - verseInt1b = ourParseInt(V1b); - linkChapterInt = ourParseInt(C2); - linkVerseInt = ourParseInt(V2); - if (verseInt1a !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${V2}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check1c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1a} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } - if (verseInt1b <= verseInt1a) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); + let linkBookCode = bookID; - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + let verseInt1a, verseInt1b, linkChapterInt, linkVerseInt; try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } - - // Check for this-book Bible links like [Revelation 3:11](../03/11.md) - while ((regexResultArray = BIBLE_REGEX_THIS_BOOK_RELATIVE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 7, `BIBLE_REGEX_THIS_BOOK_RELATIVE expected 7 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, C2, V2] = regexResultArray; + verseInt1a = ourParseInt(V1a); + verseInt1b = ourParseInt(V1b); + linkChapterInt = ourParseInt(C2); + linkVerseInt = ourParseInt(V2); + if (verseInt1a !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${V2}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check1c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1a} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } + if (verseInt1b <= verseInt1a) + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } - let linkBookCode = bookID; - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check2 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); - } - try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + // Check for this-book Bible links like [Revelation 3:11](../03/11.md) + while ((regexResultArray = BIBLE_REGEX_THIS_BOOK_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisBookBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 7, `BIBLE_REGEX_THIS_BOOK_RELATIVE expected 7 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, C2, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + let linkBookCode = bookID; + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check2 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); + } try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } - - // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) - while ((regexResultArray = BCV_V_TO_THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_BOOK_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 9, `BCV_V_TO_THIS_BOOK_BIBLE_REGEX expected 9 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, B2, C2, V2] = regexResultArray; + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } - let linkBookCode = B2 === '..' ? bookID : B2; + // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) + while ((regexResultArray = BCV_V_TO_THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside THIS_BOOK_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisBookBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 9, `BCV_V_TO_THIS_BOOK_BIBLE_REGEX expected 9 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, B2, C2, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check2b couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); - } - try { - if (ourParseInt(V1a) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } - try { - if (ourParseInt(V1b) <= ourParseInt(V1a)) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + let linkBookCode = B2 === '..' ? bookID : B2; - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check2b couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); + } try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } - - // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) - while ((regexResultArray = BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisChapterBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 7, `BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX expected 7 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, V2] = regexResultArray; + if (ourParseInt(V1a) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } + try { + if (ourParseInt(V1b) <= ourParseInt(V1a)) + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } - let linkBookCode = bookID; + // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) + while ((regexResultArray = BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisChapterBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 7, `BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX expected 7 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - const linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(V1a) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2d couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); - } - try { - if (ourParseInt(V1b) <= ourParseInt(V1a)) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2e couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); - } + let linkBookCode = bookID; - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - // try { - // numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - // } catch (tlcNCerror) { } + const linkVerseInt = ourParseInt(V2); try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenC); - } catch (tlcNVerror) { } - if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenC}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } - - // Check for other book Bible links like [Revelation 3:11](rev/03/11.md) - while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_ABSOLUTE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_ABSOLUTE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - otherBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_ABSOLUTE expected 8 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + if (ourParseInt(V1a) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2d couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); + } + try { + if (ourParseInt(V1b) <= ourParseInt(V1a)) + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2e couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); + } - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + // try { + // numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + // } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenC); + } catch (tlcNVerror) { } + if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenC}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } - let linkBookCode = B2 === '..' ? bookID : B2; + // Check for other book Bible links like [Revelation 3:11](rev/03/11.md) + while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_ABSOLUTE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_ABSOLUTE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_ABSOLUTE expected 8 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } - try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); - } + let linkBookCode = B2 === '..' ? bookID : B2; - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } - } - - // Check for other book Bible links like [Revelation 3:11](../../rev/03/11.md) - while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_RELATIVE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - otherBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_RELATIVE expected 8 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } - let linkBookCode = B2 === '..' ? bookID : B2; + // Check for other book Bible links like [Revelation 3:11](../../rev/03/11.md) + while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount += 1; + processedLinkList.push(regexResultArray[0]); // Save the full link + parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_RELATIVE expected 8 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); + } + } - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } - try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); - } + let linkBookCode = B2 === '..' ? bookID : B2; - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } + + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } } } - // Check for TN links like [Titus 3:11](../03/11/zd2d) while ((regexResultArray = TN_REGEX.exec(fieldText))) { // debugLog(` checkNotesLinksToOutside TN_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); @@ -781,13 +1013,13 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g const BibleLinkCount = thisChapterBibleLinkCount + thisVerseBibleLinkCount + thisBookBibleLinkCount + otherBookBibleLinkCount + TNLinkCount; if (totalLinks1 > BibleLinkCount) { const leftoverLinksList1 = linksList1.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above - // if (leftoverLinksList1.length > 0) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); + // if (leftoverLinksList1.length) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); addNoticePartial({ priority: 648, message: "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check ${leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)}`, location: ourLocation }); } const twaLinkCount = twLinkCount + taLinkCount; if (totalLinks2 > twaLinkCount) { const leftoverLinksList2 = linksList2.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above - // if (leftoverLinksList2.length > 0) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); + // if (leftoverLinksList2.length) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); addNoticePartial({ priority: 649, message: "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check ${leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)}`, location: ourLocation }); } diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index 251fa3d62..f9f7f1bb4 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -263,19 +263,19 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // end of ourCheckTNOriginalLanguageQuote function - async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + async function ourCheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Updates the global list of notices - // functionLog(`checkNotesTSV7DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'Note', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'Note' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkNotesTSV7DataRow ourCheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'Note', `checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be 'Note' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkNotesTSV7DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); @@ -308,7 +308,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } - // end of ourcheckNotesLinksToOutside function + // end of ourCheckNotesLinksToOutside function // Main code for checkNotesTSV7DataRow function @@ -505,7 +505,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID else { // More than just whitespace const adjustedNote = note.replace(/\\n/g, '\n'); ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', adjustedNote, true, ourRowLocation, checkingOptions); - await ourcheckNotesLinksToOutside(rowID, 'Note', adjustedNote, ourRowLocation, linkCheckingOptions); + await ourCheckNotesLinksToOutside(rowID, 'Note', adjustedNote, ourRowLocation, linkCheckingOptions); let regexResultArray; while ((regexResultArray = TA_REGEX.exec(adjustedNote))) { // debugLog("Got TA Regex in Note", JSON.stringify(regexResultArray)); diff --git a/src/core/notes-tsv7-table-check.js b/src/core/notes-tsv7-table-check.js index 17c3e6555..9e2fae4fe 100644 --- a/src/core/notes-tsv7-table-check.js +++ b/src/core/notes-tsv7-table-check.js @@ -252,7 +252,7 @@ export async function checkNotesTSV7Table(languageCode, repoCode, bookID, filena addNoticePartial({ priority: 20, message: "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation }); addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); - if (carResult.noticeList) + if (carResult.noticeList.length) addSuccessMessage(`checkNotesTSV7Table v${NOTES_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkNotesTSV7Table v${NOTES_TABLE_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/plain-text-check.js b/src/core/plain-text-check.js index dc1433468..67fa3a9fe 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -249,7 +249,7 @@ export function checkPlainText(languageCode, repoCode, textType, textName, plain } addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length === 1 ? '' : 's'}${ourLocation}.`); - if (cptResult.noticeList) + if (cptResult.noticeList.length) addSuccessMessage(`checkPlainText v${PLAIN_TEXT_VALIDATOR_VERSION_STRING} finished with ${cptResult.noticeList.length ? cptResult.noticeList.length.toLocaleString() : "zero"} notice${cptResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkPlainText v${PLAIN_TEXT_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/questions-tsv7-row-check.js b/src/core/questions-tsv7-row-check.js index 017679fd0..fdb67f4b2 100644 --- a/src/core/questions-tsv7-row-check.js +++ b/src/core/questions-tsv7-row-check.js @@ -233,19 +233,19 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo // end of ourCheckQOriginalLanguageQuote function - // async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // async function ourCheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // // Checks that the TA/TW/Bible reference can be found // // Updates the global list of notices - // // functionLog(`checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - // parameterAssert(rowID !== undefined, "checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); - // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - // parameterAssert(fieldName !== undefined, "checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); - // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - // parameterAssert(fieldName === 'Question', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'Question' not '${fieldName}'`); - // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); - // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV7DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // // functionLog(`checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(fieldName === 'Question', `checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be 'Question' not '${fieldName}'`); + // parameterAssert(taLinkText !== undefined, "checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + // parameterAssert(typeof taLinkText === 'string', `checkQuestionsTSV7DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); // const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // // debugLog("coqResultObject", JSON.stringify(coqResultObject)); @@ -278,7 +278,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo // catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); // } - // // end of ourcheckNotesLinksToOutside function + // // end of ourCheckNotesLinksToOutside function // Main code for checkQuestionsTSV7DataRow function @@ -446,7 +446,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation }); else { // More than just whitespace RSuggestion = await ourMarkdownTextChecks(rowID, 'Question', question, true, ourRowLocation, checkingOptions); - // await ourcheckNotesLinksToOutside(rowID, 'Question', question, ourRowLocation, linkCheckingOptions); + // await ourCheckNotesLinksToOutside(rowID, 'Question', question, ourRowLocation, linkCheckingOptions); // let regexResultArray; // while ((regexResultArray = TA_REGEX.exec(question))) { // // debugLog("Got TA Regex in Question", JSON.stringify(regexResultArray)); @@ -471,7 +471,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation }); else { // More than just whitespace RSuggestion = await ourMarkdownTextChecks(rowID, 'Response', response, true, ourRowLocation, checkingOptions); - // await ourcheckNotesLinksToOutside(rowID, 'Response', response, ourRowLocation, linkCheckingOptions); + // await ourCheckNotesLinksToOutside(rowID, 'Response', response, ourRowLocation, linkCheckingOptions); // let regexResultArray; // while ((regexResultArray = TA_REGEX.exec(answer))) { // // debugLog("Got TA Regex in Response", JSON.stringify(regexResultArray)); diff --git a/src/core/questions-tsv7-table-check.js b/src/core/questions-tsv7-table-check.js index 81d484584..99e18d732 100644 --- a/src/core/questions-tsv7-table-check.js +++ b/src/core/questions-tsv7-table-check.js @@ -252,7 +252,7 @@ export async function checkQuestionsTSV7Table(languageCode, repoCode, bookID, fi addNoticePartial({ priority: 20, message: "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation }); addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); - if (carResult.noticeList) + if (carResult.noticeList.length) addSuccessMessage(`checkQuestionsTSV7Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkQuestionsTSV7Table v${QUESTIONS_TABLE_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index 7aec2612b..cc537eeae 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -278,7 +278,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, * @param {string} rowLocation * @param {Object} checkingOptions */ - async function ourcheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + async function ourCheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Uses @@ -288,14 +288,14 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // Updates the global list of notices - // functionLog(`checkTN_TSV9DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourcheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + // functionLog(`checkTN_TSV9DataRow ourCheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); + parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog("coqResultObject", JSON.stringify(coqResultObject)); @@ -328,7 +328,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } - // end of ourcheckNotesLinksToOutside function + // end of ourCheckNotesLinksToOutside function // Main code for checkTN_TSV9DataRow function @@ -532,7 +532,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, else { // More than just whitespace const adjustedOccurrenceNote = occurrenceNote.replace(/<br>/g, '\n'); ONSuggestion = await ourMarkdownTextChecks(rowID, 'OccurrenceNote', adjustedOccurrenceNote, true, ourRowLocation, checkingOptions); - await ourcheckNotesLinksToOutside(rowID, 'OccurrenceNote', adjustedOccurrenceNote, ourRowLocation, linkCheckingOptions); + await ourCheckNotesLinksToOutside(rowID, 'OccurrenceNote', adjustedOccurrenceNote, ourRowLocation, linkCheckingOptions); let regexResultArray; while ((regexResultArray = TA_REGEX.exec(adjustedOccurrenceNote))) { // debugLog("Got TA Regex in OccurrenceNote", JSON.stringify(regexResultArray)); diff --git a/src/core/tn-tsv9-table-check.js b/src/core/tn-tsv9-table-check.js index c043b9039..004714bfb 100644 --- a/src/core/tn-tsv9-table-check.js +++ b/src/core/tn-tsv9-table-check.js @@ -263,7 +263,7 @@ export async function checkTN_TSV9Table(languageCode, repoCode, bookID, filename addNoticePartial({ priority: 20, message: "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation }); addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); - if (ttResult.noticeList) + if (ttResult.noticeList.length) addSuccessMessage(`checkTN_TSV9Table v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING} finished with ${ttResult.noticeList.length ? ttResult.noticeList.length.toLocaleString() : "zero"} notice${ttResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkTN_TSV9Table v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index 4ad6e0150..5f53449b4 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -180,17 +180,17 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, // end of ourCheckTNOriginalLanguageQuote function - async function ourcheckNotesLinksToOutside(rowID, fieldName, twLinkText, rowLocation, checkingOptions) { + async function ourCheckNotesLinksToOutside(rowID, fieldName, twLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Updates the global list of notices - // functionLog(`checkTWL_TSV6DataRow ourcheckNotesLinksToOutside(${rowID}, ${fieldName}, (${twLinkText.length}) '${twLinkText}', ${rowLocation}, ${JSON.stringify(checkingOptions)})`); - parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName === 'TWLink', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'fieldName' parameter should be 'TWLink' not '${fieldName}'`); - parameterAssert(twLinkText !== undefined, "checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'twLinkText' parameter should be defined"); - parameterAssert(typeof twLinkText === 'string', `checkTWL_TSV6DataRow ourcheckNotesLinksToOutside: 'twLinkText' parameter should be a string not a '${typeof twLinkText}'`); + // functionLog(`checkTWL_TSV6DataRow ourCheckNotesLinksToOutside(${rowID}, ${fieldName}, (${twLinkText.length}) '${twLinkText}', ${rowLocation}, ${JSON.stringify(checkingOptions)})`); + parameterAssert(rowID !== undefined, "checkTWL_TSV6DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be defined"); + parameterAssert(typeof rowID === 'string', `checkTWL_TSV6DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + parameterAssert(fieldName === 'TWLink', `checkTWL_TSV6DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be 'TWLink' not '${fieldName}'`); + parameterAssert(twLinkText !== undefined, "checkTWL_TSV6DataRow ourCheckNotesLinksToOutside: 'twLinkText' parameter should be defined"); + parameterAssert(typeof twLinkText === 'string', `checkTWL_TSV6DataRow ourCheckNotesLinksToOutside: 'twLinkText' parameter should be a string not a '${typeof twLinkText}'`); const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, twLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); @@ -223,7 +223,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } - // end of ourcheckNotesLinksToOutside function + // end of ourCheckNotesLinksToOutside function // Main code for checkTWL_TSV6DataRow function @@ -402,7 +402,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, addNoticePartial({ priority: 797, message: "Field doesn’t contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation }); } else { // all good so far // debugLog(`checkTWL_TSV6DataRow looking up ${bookID} ${rowID} TWLink='${TWLink}' got bits=${JSON.stringify(bits)}`); - await ourcheckNotesLinksToOutside(rowID, 'TWLink', TWLink, ourRowLocation, linkCheckingOptions); + await ourCheckNotesLinksToOutside(rowID, 'TWLink', TWLink, ourRowLocation, linkCheckingOptions); } } } diff --git a/src/core/twl-tsv6-table-check.js b/src/core/twl-tsv6-table-check.js index 4fa25a07e..fce85440f 100644 --- a/src/core/twl-tsv6-table-check.js +++ b/src/core/twl-tsv6-table-check.js @@ -252,7 +252,7 @@ export async function checkTWL_TSV6Table(languageCode, repoCode, bookID, filenam addNoticePartial({ priority: 20, message: "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation }); addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); - if (carResult.noticeList) + if (carResult.noticeList.length) addSuccessMessage(`checkTWL_TSV6Table v${TWL_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkTWL_TSV6Table v${TWL_TABLE_VALIDATOR_VERSION_STRING}`) diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 5c1d4d9cf..5a6047306 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -844,7 +844,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex || (repoCode === 'UGNT' && !attributeValue.startsWith('Gr,')))) addNoticePartial({ priority: 852, message: "Unexpected original \\w x-morph language prefix", details: "Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation }); else if (attributeName === 'x-tw') - ourcheckNotesLinksToOutside(lineNumber, C, V, marker, attributeValue, lineLocation, checkingOptions); + ourCheckNotesLinksToOutside(lineNumber, C, V, marker, attributeValue, lineLocation, checkingOptions); } else { // a translation -- not UHB or UGNT if (attributeCounter === 1) { if (attributeName !== 'x-occurrence') @@ -976,16 +976,16 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex // end of checkUSFMLineContents function - async function ourcheckNotesLinksToOutside(lineNumber, C, V, marker, twLinkText, location, checkingOptions) { + async function ourCheckNotesLinksToOutside(lineNumber, C, V, marker, twLinkText, location, checkingOptions) { // Checks that the TA/TW/Bible reference can be found // Updates the global list of notices - // functionLog(`checkUSFMText ourcheckNotesLinksToOutside(${lineNumber}, ${C}:${V}, ${marker}, (${twLinkText.length}) '${twLinkText}', ${location}, ${JSON.stringify(checkingOptions)})`); - parameterAssert(marker !== undefined, "checkUSFMText ourcheckNotesLinksToOutside: 'marker' parameter should be defined"); - parameterAssert(typeof marker === 'string', `checkUSFMText ourcheckNotesLinksToOutside: 'marker' parameter should be a string not a '${typeof marker}': ${marker}`); - parameterAssert(twLinkText !== undefined, "checkUSFMText ourcheckNotesLinksToOutside: 'twLinkText' parameter should be defined"); - parameterAssert(typeof twLinkText === 'string', `checkUSFMText ourcheckNotesLinksToOutside: 'twLinkText' parameter should be a string not a '${typeof twLinkText}': ${twLinkText}`); + // functionLog(`checkUSFMText ourCheckNotesLinksToOutside(${lineNumber}, ${C}:${V}, ${marker}, (${twLinkText.length}) '${twLinkText}', ${location}, ${JSON.stringify(checkingOptions)})`); + parameterAssert(marker !== undefined, "checkUSFMText ourCheckNotesLinksToOutside: 'marker' parameter should be defined"); + parameterAssert(typeof marker === 'string', `checkUSFMText ourCheckNotesLinksToOutside: 'marker' parameter should be a string not a '${typeof marker}': ${marker}`); + parameterAssert(twLinkText !== undefined, "checkUSFMText ourCheckNotesLinksToOutside: 'twLinkText' parameter should be defined"); + parameterAssert(typeof twLinkText === 'string', `checkUSFMText ourCheckNotesLinksToOutside: 'twLinkText' parameter should be a string not a '${typeof twLinkText}': ${twLinkText}`); const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, C, V, 'TWLink', twLinkText, location, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); @@ -1018,7 +1018,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex catch { result.checkedFilenameExtensions = [checkedFilenameExtension]; } // if (result.checkedFilenameExtensions) userLog("result", JSON.stringify(result)); } - // end of ourcheckNotesLinksToOutside function + // end of ourCheckNotesLinksToOutside function function mainUSFMCheck(bookID, filename, givenText, location) { diff --git a/src/core/utilities.js b/src/core/utilities.js index d9edd1a84..35fc0e13d 100644 --- a/src/core/utilities.js +++ b/src/core/utilities.js @@ -148,7 +148,7 @@ export function ourParseInt(givenString) { // Optimised version const int = givenString * 1; // This one is less forgiving it seems // eslint-disable-next-line no-throw-literal - if (isNaN(int)) throw `String '${givenString}'is not a simple integer`; + if (isNaN(int)) throw `String '${givenString}' is not a simple integer`; return int; } diff --git a/src/core/yaml-text-check.js b/src/core/yaml-text-check.js index 9ec5f4745..882570053 100644 --- a/src/core/yaml-text-check.js +++ b/src/core/yaml-text-check.js @@ -207,7 +207,7 @@ export function checkYAMLText(languageCode, repoCode, textName, YAMLText, givenL } addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length === 1 ? '' : 's'}${ourLocation}.`); - if (cytResult.noticeList) + if (cytResult.noticeList.length) addSuccessMessage(`checkYAMLText v${YAML_VALIDATOR_VERSION_STRING} finished with ${cytResult.noticeList.length ? cytResult.noticeList.length.toLocaleString() : "zero"} notice${cytResult.noticeList.length === 1 ? '' : 's'}`); else addSuccessMessage(`No errors or warnings found by checkYAMLText v${YAML_VALIDATOR_VERSION_STRING}`) diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index c069a6a47..6e61d00fc 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -396,7 +396,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // debugLog(`cBPgfError=${cBPgfError} or ${JSON.stringify(cBPgfError)} or2 ${cBPgfError === 'TypeError: repoFileContent is null'} or3 ${cBPgfError.message === 'TypeError: repoFileContent is null'} or4 ${cBPgfError.message === 'TypeError: repoFileContent is null'}`); let details = `username=${username}`; // Next line has special code to handle book-package-check.test.js tests [so we don't call repositoryExistsOnDoor43()] - if (cBPgfError.startsWith('Tests could not find') || ! await repositoryExistsOnDoor43({ username, repository: repoName })) + if ((cBPgfError+'').startsWith('Tests could not find') || ! await repositoryExistsOnDoor43({ username, repository: repoName })) checkBookPackageResult.noticeList.push({ priority: 997, message: "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode }); else { // eslint-disable-next-line eqeqeq @@ -469,6 +469,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // else debugLog(`NOT fetching MANIFEST, etc. for ${repoName}`); numCheckedRepos += 1; + // debugLog(`At end of loop having checked ${numCheckedRepos} repos`); } // end of repo loop diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 664926862..56e6b7044 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -8,10 +8,11 @@ import { clearCaches, clearCheckedArticleCache, ourParseInt, cachedGetFile } fro import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; import { checkFileContents } from './checkFileContents'; -import { userLog } from '../../core/utilities'; +// eslint-disable-next-line no-unused-vars +import { debugLog, userLog } from '../../core/utilities'; -// const FILE_CHECK_VERSION_STRING = '0.2.6'; +// const FILE_CHECK_VERSION_STRING = '0.2.7'; function FileCheck(props) { @@ -64,18 +65,20 @@ function FileCheck(props) { if (fileContent) { const languageCode = repoName.split('_')[0]; - let repoCodeGuess; + let repoCodeGuess = ''; if (repoName === 'hbo_uhb') repoCodeGuess = 'UHB' else if (repoName === 'el-x-koine_ugnt') repoCodeGuess = 'UGNT' else if (repoName.endsWith('_tn')) repoCodeGuess = 'TN' else if (repoName.endsWith('_ta')) repoCodeGuess = 'TA' else if (repoName.endsWith('_tq')) repoCodeGuess = 'TQ' + else if (repoName.endsWith('_tw')) repoCodeGuess = 'TW' else if (repoName.endsWith('_sn')) repoCodeGuess = 'SN' else if (repoName.endsWith('_sq')) repoCodeGuess = 'SQ' else if (repoName.endsWith('lt')) repoCodeGuess = 'LT' else if (repoName.endsWith('st')) repoCodeGuess = 'ST' rawCFResults = await checkFileContents(username, languageCode, repoCodeGuess, branch, filename, fileContent, givenLocation, checkingOptions); + // debugLog(`rawCFResults=${JSON.stringify(rawCFResults)}`); // Because we know here that we're only checking one file, we don’t need the filename field in the notices // WRONG: We want the filename so that the lineNumber can be made into a live link diff --git a/src/demos/file-check/README.md b/src/demos/file-check/README.md index 824322edd..50c832d75 100644 --- a/src/demos/file-check/README.md +++ b/src/demos/file-check/README.md @@ -22,7 +22,7 @@ and then validates the content of one file selected from the repo. // repoName='hbo_uhb' // OT books only // repoName='el-x-koine_ugnt' // NT books only // repoName='en_ult' // Can use ult or ust here - repoName='en_tn' + repoName='en_tw' // Can use ta, tw, tn, tq, sn, or sq here // If we don’t put the branch here, the default branch is used // branch='master' @@ -48,17 +48,19 @@ and then validates the content of one file selected from the repo. // filename= 'en_tn_58-PHM.tsv' // for TN // filename= 'en_tn_61-1PE.tsv' // for TN // filename= 'en_tn_65-3JN.tsv' // for TN + // It's actually possible to put a filepath in the filename field + filename= 'bible/names/zilpah.md' // for TW // The location field appears in check messages to help the user locate the issue location="as specified in FileCheck demo" // Specifying excerptLength and cutoffPriorityLevel is just to show off options // —those fields are not necessary (or normal) here - excerptLength='12' // Default is 15 + excerptLength='20' // Default is 15 // cutoffPriorityLevel='200' // Default is to detect all errors/warnings // Normally links in files are downloaded to check that they really exist - disableAllLinkFetchingFlag='true' // 'true' or 'false' + disableAllLinkFetchingFlag='false' // 'true' or 'false' // The next two are only relevant if the above is 'false' disableLinkedTAArticlesCheckFlag='false' // 'true' or 'false' disableLinkedTWArticlesCheckFlag='false' // 'true' or 'false' diff --git a/src/demos/file-check/checkFileContents.js b/src/demos/file-check/checkFileContents.js index 299d01afa..53aa7b5fe 100644 --- a/src/demos/file-check/checkFileContents.js +++ b/src/demos/file-check/checkFileContents.js @@ -1,10 +1,11 @@ import * as books from '../../core/books/books'; import { - userLog, parameterAssert, logicAssert, formRepoName, checkUSFMText, checkMarkdownFileContents, checkPlainText, checkYAMLText, checkManifestText, checkTN_TSV9Table, checkNotesTSV7Table, checkQuestionsTSV7Table, checkTWL_TSV6Table, } from '../../core'; +// eslint-disable-next-line no-unused-vars +import {userLog, debugLog, parameterAssert, logicAssert} from '../../core'; // const CHECK_FILE_CONTENTS_VERSION_STRING = '0.4.1'; @@ -24,7 +25,7 @@ import { export async function checkFileContents(username, languageCode, repoCode, branch, filename, fileContent, givenLocation, checkingOptions) { // Determine the file type from the filename extension // and return the results of checking that kind of file text - // if (repoCode !== 'TQ') functionLog(`checkFileContents(${username}, ${languageCode}, ${repoCode}, ${branch}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkFileContents(${username}, ${languageCode}, ${repoCode}, ${branch}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(username !== undefined, "checkFileContents: 'username' parameter should be defined"); parameterAssert(typeof username === 'string', `checkFileContents: 'username' parameter should be a string not a '${typeof username}': ${username}`); parameterAssert(languageCode !== undefined, "checkFileContents: 'languageCode' parameter should be defined"); @@ -84,7 +85,8 @@ export async function checkFileContents(username, languageCode, repoCode, branch parameterAssert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); checkFileResult = checkUSFMText(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filenameLower.endsWith('.md')) - checkFileResult = checkMarkdownFileContents(languageCode, repoCode, filename, fileContent, ourCFLocation, checkingOptions); + // NOTE: File types with possible link checking need AWAIT + checkFileResult = await checkMarkdownFileContents(languageCode, repoCode, filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower.endsWith('.txt')) checkFileResult = checkPlainText(languageCode, repoCode, 'text', filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower === 'manifest.yaml') @@ -95,7 +97,8 @@ export async function checkFileContents(username, languageCode, repoCode, branch checkFileResult = checkPlainText(languageCode, repoCode, 'raw', filename, fileContent, ourCFLocation, checkingOptions); checkFileResult.noticeList.unshift({ priority: 995, message: "File extension is not recognized, so treated as plain text.", filename, location: filename }); } - // functionLog(`checkFileContents got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); + // debugLog(`checkFileContents got initial results: ${JSON.stringify(checkFileResult)}`); + // debugLog(`checkFileContents got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); // Make sure that we have the filename in all of our notices (in case other files are being checked as well) function addFilenameField(noticeObject) { @@ -114,7 +117,7 @@ export async function checkFileContents(username, languageCode, repoCode, branch checkFileResult.checkedOptions = checkingOptions; checkFileResult.elapsedSeconds = (new Date() - startTime) / 1000; // seconds - // functionLog(`checkFileContents() returning ${JSON.stringify(checkFileResult)}`); + // debugLog(`checkFileContents() returning ${JSON.stringify(checkFileResult)}`); return checkFileResult; }; // end of checkFileContents() diff --git a/yarn.lock b/yarn.lock index ecb9a4b84..b6d6b8b5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3490,9 +3490,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: - version "1.0.30001190" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001190.tgz#acc6d4a53c68be16cfc314d55c9cab637e558cba" - integrity sha512-62KVw474IK8E+bACBYhRS0/L6o/1oeAVkpF2WetjV58S5vkzNh0/Rz3lD8D4YCbOTqi0/aD4X3LtoP7V5xnuAg== + version "1.0.30001191" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001191.tgz#bacb432b6701f690c8c5f7c680166b9a9f0843d9" + integrity sha512-xJJqzyd+7GCJXkcoBiQ1GuxEiOBCLQ0aVW9HMekifZsAVGdj5eJ4mFB9fEhSHipq9IOk/QXFJUiIr9lZT+EsGw== canvg@^3.0.6: version "3.0.7" @@ -6811,7 +6811,7 @@ internal-ip@^4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" -internal-slot@^1.0.2: +internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== @@ -9516,13 +9516,13 @@ object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2: has "^1.0.3" object.fromentries@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.3.tgz#13cefcffa702dc67750314a3305e8cb3fad1d072" - integrity sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" + integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.18.0-next.2" has "^1.0.3" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0, object.getownpropertydescriptors@^2.1.1: @@ -11528,7 +11528,7 @@ regex-parser@^2.2.11: resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== @@ -12221,7 +12221,7 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -side-channel@^1.0.3, side-channel@^1.0.4: +side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== @@ -12642,17 +12642,17 @@ string-width@^4.1.0, string-width@^4.2.0: strip-ansi "^6.0.0" string.prototype.matchall@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" - integrity sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz#608f255e93e072107f5de066f81a2dfb78cf6b29" + integrity sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.18.0-next.2" has-symbols "^1.0.1" - internal-slot "^1.0.2" - regexp.prototype.flags "^1.3.0" - side-channel "^1.0.3" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.3: version "1.0.3" From 1ce218ac023caf4c8c3bbc68cc4401db735591c6 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Wed, 24 Feb 2021 21:43:51 +1300 Subject: [PATCH 12/16] More work on link checking --- package.json | 2 +- .../book-package-check.test.js.snap | 33 +- .../tn-table-row-check.test.js.snap | 116 +- src/__tests__/tn-table-row-check.test.js | 4 +- src/core/markdown-text-check.js | 2 +- src/core/notes-links-check.js | 1322 +++++++++-------- src/core/notes-tsv7-row-check.js | 6 +- src/core/tn-tsv9-row-check.js | 122 +- .../AllBookPackagesCheck.js | 4 +- .../book-package-check/checkBookPackage.js | 7 +- .../book-packages-check/BookPackagesCheck.js | 4 +- src/demos/file-check/FileCheck.js | 4 +- src/demos/file-check/README.md | 9 +- .../GlBookPackageCheck.js | 4 +- src/demos/repo-check/RepoCheck.js | 4 +- yarn.lock | 592 ++++---- 16 files changed, 1211 insertions(+), 1024 deletions(-) diff --git a/package.json b/package.json index 8eeda739f..3d873f406 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha7", + "version": "2.0.0_alpha8", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/__snapshots__/book-package-check.test.js.snap b/src/__tests__/__snapshots__/book-package-check.test.js.snap index 93d2ec842..2becb6999 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -4436,7 +4436,7 @@ Object { "filename": "en_tn_08-RUT.tsv", "lineNumber": 110, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unusual [ ]( ) link(s)—not normal Bible or TN links", + "message": "Unusual [ ]( ) link(s)—not a recognized Bible or TA, TN, or TW link", "priority": 648, "repoCode": "TN", "repoName": "en_tn", @@ -4552,6 +4552,22 @@ Object { "repoName": "en_tq", "username": "unfoldingWord", }, + Object { + "C": "1", + "V": "20", + "bookID": "RUT", + "characterIndex": 116, + "excerpt": "…with␣her.␣", + "extra": "TQ", + "filename": "rut/01/20.md", + "lineNumber": 3, + "location": " in unfoldingWord (master)", + "message": "Unexpected trailing space(s)", + "priority": 95, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, Object { "C": "1", "V": "20", @@ -4582,6 +4598,21 @@ Object { "repoName": "en_tq", "username": "unfoldingWord", }, + Object { + "C": "3", + "V": "9", + "bookID": "RUT", + "details": "left=0, right=1", + "extra": "TQ", + "filename": "rut/03/09.md", + "lineNumber": 3, + "location": " in unfoldingWord (master)", + "message": "Mismatched “” characters", + "priority": 163, + "repoCode": "TQ", + "repoName": "en_tq", + "username": "unfoldingWord", + }, Object { "C": "3", "V": "9", diff --git a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap index df9011606..f393762e6 100644 --- a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap +++ b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap @@ -22,6 +22,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -166,6 +167,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -210,6 +212,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -254,6 +257,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -298,6 +302,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -330,6 +335,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -361,6 +367,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -405,6 +412,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -449,6 +457,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -481,6 +490,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -510,6 +520,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -541,6 +552,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -569,6 +581,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -600,6 +613,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -668,23 +682,23 @@ Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=2, right=1", + "details": "left=1, right=0", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [] characters", - "priority": 563, + "message": "Mismatched [[ ]] link characters", + "priority": 845, "rowID": "gnn5", }, Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=1, right=0", + "details": "left=2, right=1", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched () characters", + "message": "Mismatched [] characters", "priority": 563, "rowID": "gnn5", }, @@ -694,9 +708,10 @@ Object { "bookID": "RUT", "details": "left=1, right=0", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [[ ]] link characters", - "priority": 845, + "message": "Mismatched () characters", + "priority": 563, "rowID": "gnn5", }, ], @@ -710,23 +725,23 @@ Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=1, right=2", + "details": "left=0, right=1", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [] characters", - "priority": 563, + "message": "Mismatched [[ ]] link characters", + "priority": 845, "rowID": "gnn5", }, Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=1, right=0", + "details": "left=1, right=2", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched () characters", + "message": "Mismatched [] characters", "priority": 563, "rowID": "gnn5", }, @@ -734,11 +749,12 @@ Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=0, right=1", + "details": "left=1, right=0", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [[ ]] link characters", - "priority": 845, + "message": "Mismatched () characters", + "priority": 563, "rowID": "gnn5", }, ], @@ -752,23 +768,24 @@ Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=2, right=0", + "details": "left=1, right=0", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [] characters", - "priority": 563, + "message": "Mismatched [[ ]] link characters", + "priority": 845, "rowID": "gnn5", }, Object { "C": "2", "V": "12", "bookID": "RUT", - "details": "left=1, right=0", + "details": "left=2, right=0", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [[ ]] link characters", - "priority": 845, + "message": "Mismatched [] characters", + "priority": 563, "rowID": "gnn5", }, ], @@ -790,17 +807,6 @@ Object { "priority": 563, "rowID": "gnn5", }, - Object { - "C": "2", - "V": "12", - "bookID": "RUT", - "details": "left=0, right=1", - "fieldName": "OccurrenceNote", - "location": " that was supplied", - "message": "Mismatched [[ ]] link characters", - "priority": 845, - "rowID": "gnn5", - }, ], } `; @@ -825,8 +831,9 @@ Object { "bookID": "GEN", "details": "need to carefully check \\"[[rc://*/ta/man/figs-parallelism]]\\"", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Unusual [[ ]] link(s)—not normal TA or TW links", + "message": "Unusual [[ ]] link(s)—not a recognized TA or TW link", "priority": 649, "rowID": "urb3", }, @@ -844,6 +851,7 @@ Object { "characterIndex": 170, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -855,8 +863,9 @@ Object { "bookID": "RUT", "details": "need to carefully check \\"[Doublet](../figs-doublet/01.md)\\"", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Unusual [ ]( ) link(s)—not normal Bible or TN links", + "message": "Unusual [ ]( ) link(s)—not a recognized Bible or TA, TN, or TW link", "priority": 648, "rowID": "gnn5", }, @@ -874,6 +883,7 @@ Object { "characterIndex": 235, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -885,6 +895,7 @@ Object { "bookID": "GEN", "excerpt": "[[rc://*/ta/man/translate/figs-activepassivez]]", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied translate/figs-activepassivez/01.md: tn-table-row-check.test getFile(): Could not find src/__tests__/fixtures/unfoldingWord/en_ta/translate/figs-activepassivez/01.md", "message": "Error loading OccurrenceNote TA link", "priority": 885, @@ -897,6 +908,7 @@ Object { "characterIndex": 287, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -939,8 +951,9 @@ Object { "bookID": "GEN", "details": "need to carefully check \\"[[rc://*/ta/woman/figs-imperative]]\\"", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Unusual [[ ]] link(s)—not normal TA or TW links", + "message": "Unusual [[ ]] link(s)—not a recognized TA or TW link", "priority": 649, "rowID": "urb3", }, @@ -958,6 +971,7 @@ Object { "characterIndex": 235, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -970,6 +984,7 @@ Object { "characterIndex": 286, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -981,6 +996,7 @@ Object { "bookID": "GEN", "excerpt": "[[rc://*/ta/man/translate/figs-imperativez]]", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied translate/figs-imperativez/01.md: tn-table-row-check.test getFile(): Could not find src/__tests__/fixtures/unfoldingWord/en_ta/translate/figs-imperativez/01.md", "message": "Error loading OccurrenceNote TA link", "priority": 885, @@ -1011,8 +1027,9 @@ Object { "bookID": "GEN", "details": "need to carefully check \\"[Genesis 1:7](../01/zzz.md)\\"", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Unusual [ ]( ) link(s)—not normal Bible or TN links", + "message": "Unusual [ ]( ) link(s)—not a recognized Bible or TA, TN, or TW link", "priority": 648, "rowID": "ha33", }, @@ -1027,23 +1044,24 @@ Object { "C": "1", "V": "9", "bookID": "GEN", - "details": "left=1, right=0", + "details": "left=1, middle=1, right=0", "fieldName": "OccurrenceNote", "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched () characters", - "priority": 563, + "message": "Mismatched [ ]( ) link characters", + "priority": 843, "rowID": "ha33", }, Object { "C": "1", "V": "9", "bookID": "GEN", - "details": "left=1, middle=1, right=0", + "details": "left=1, right=0", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", - "message": "Mismatched [ ]( ) link characters", - "priority": 843, + "message": "Mismatched () characters", + "priority": 563, "rowID": "ha33", }, ], @@ -1065,17 +1083,6 @@ Object { "priority": 563, "rowID": "ha33", }, - Object { - "C": "1", - "V": "9", - "bookID": "GEN", - "details": "left=0, middle=1, right=1", - "fieldName": "OccurrenceNote", - "location": " that was supplied", - "message": "Mismatched [ ]( ) link characters", - "priority": 843, - "rowID": "ha33", - }, ], } `; @@ -1310,6 +1317,7 @@ Object { "details": "not 'en'", "excerpt": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "Resource container link should have '*' language code", "priority": 450, @@ -1341,6 +1349,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, @@ -1384,6 +1393,7 @@ Object { "characterIndex": 90, "excerpt": "…[[rc://*/ta/man…", "fieldName": "OccurrenceNote", + "lineNumber": 1, "location": " that was supplied", "message": "tC cannot yet process '*' language code", "priority": 950, diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index f165b372d..d4410819c 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -50,7 +50,7 @@ describe('checkTN_TSV9DataRow() - ', () => { it('should fail double broken link start', async () => { const chosenLine = "RUT\t2\t12\tgnn5\tfigs-parallelism\tשְׁלֵמָ֗ה\t1\tmay your full wages come from Yahweh This is a poetic expression that is very similar to the previous sentence. Alternate translation: “May Yahweh fully give to you everything that you deserve” (See: rc://*/ta/man/translate/figs-parallelism]])"; const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'RUT', '2', '12', 'that was supplied', optionalCheckingOptions); - expect(rawResults.noticeList.length).toEqual(2); + expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); @@ -117,7 +117,7 @@ describe('checkTN_TSV9DataRow() - ', () => { it('should fail invalid verse link start', async () => { const chosenLine = "GEN\t1\t9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in Genesis 1:7](../01/07.md)."; const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); - expect(rawResults.noticeList.length).toEqual(2); + expect(rawResults.noticeList.length).toEqual(1); expect(rawResults).toMatchSnapshot(); }); diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index c31318cc3..3d7a47ddc 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -133,7 +133,7 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, parameterAssert(location !== undefined, "checkUSFMText ourCheckNotesLinksToOutside: 'location' parameter should be defined"); parameterAssert(typeof location === 'string', `checkUSFMText ourCheckNotesLinksToOutside: 'location' parameter should be a string not a '${typeof location}': ${location}`); - const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, '', '', '', 'MDFile', lineText, location, { ...checkingOptions, defaultLanguageCode: languageCode }); + const coTNlResultObject = await checkNotesLinksToOutside(languageCode, repoCode, '', '', '', textOrFileName, lineText, location, { ...checkingOptions, defaultLanguageCode: languageCode }); // debugLog(`coTNlResultObject=${JSON.stringify(coTNlResultObject)}`); // Choose only ONE of the following diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index 929534647..8adb32ec1 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -8,18 +8,19 @@ import { userLog, debugLog, functionLog, parameterAssert, logicAssert, dataAsser // import { consoleLogObject } from '../core/utilities'; -// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.8'; +// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.9'; -const DEFAULT_LANGUAGE_CODE = 'en'; +// const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; const GENERAL_LINK1_REGEX = new RegExp('\\[[^\\]]+?\\]\\([^\\)]+?\\)', 'g'); // [displayLink](URL) const GENERAL_LINK2_REGEX = new RegExp('\\[\\[[^\\]]+?\\]\\]', 'g'); // [[combinedDisplayLink]] -const TA_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] -const TA_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\(rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\)', 'g'); // [How to Translate Names](rc://en/ta/man/translate/translate-names) +const TA_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TA_FULL_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\(rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\)', 'g'); // [How to Translate Names](rc://en/ta/man/translate/translate-names) +const TA_RELATIVE_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\(\\.{2}/([^ /\\]]+?)/01\\.md\\)', 'g'); // [Borrow Words](../translate-transliterate/01.md) -const TW_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] +const TW_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ /\\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] const TWL_RAW_LINK_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g'); // Just a raw link const TW_INTERNAL_REGEX = new RegExp('\\[([A-za-z]+?)\\]\\(\\.{2}/([a-z]{2,5})/([-A-Za-z]{2,20})\\.md\\)', 'g');// [Asher](../names/asher.md) @@ -40,6 +41,8 @@ const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1, const TN_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})/([a-z][a-z0-9][a-z0-9][a-z0-9])\\)', 'g'); +const SIMPLE_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\((https?://[^\\)])\\)', 'g');// [ULT](https://something) + const SIMPLE_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ "\\)]+?)\\)', 'g'); // ![alt](y) const TITLED_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ \\)]+?) "([^"\\)]+?)"\\)', 'g'); // ![alt](link "title") @@ -88,7 +91,7 @@ async function alreadyChecked({ username, repository, path, branch }) { * @param {string} languageCode, e.g., 'en' * @param {string} repoCode, e.g., 'TN', 'SN', 'TN2', or even 'TWL' * @param {string} bookID - * @param {string} fieldName, e.g., 'OccurrenceNote' or 'Note' or 'TWLink' or 'MDFile' + * @param {string} fieldName, e.g., 'TWLink' or 'OccurrenceNote' or 'Note' or .md filename, etc. * @param {string} fieldText * @param {string} givenLocation * @param {Object} checkingOptions @@ -122,7 +125,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g */ // if (fieldText.indexOf('brother') !== -1) - // functionLog(`checkNotesLinksToOutside('${languageCode}', '${repoCode}', ${bookID} ${givenC}:${givenV} ${fieldName}, (${fieldText.length})'${fieldText}', ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + // functionLog(`checkNotesLinksToOutside('${languageCode}', '${repoCode}', ${bookID} ${givenC}:${givenV} '${fieldName}', (${fieldText.length})'${fieldText}', ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); parameterAssert(languageCode !== undefined, "checkNotesLinksToOutside: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkNotesLinksToOutside: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); parameterAssert(repoCode !== undefined, "checkNotesLinksToOutside: 'repoCode' parameter should be defined"); @@ -131,14 +134,14 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g parameterAssert(typeof bookID === 'string', `checkNotesLinksToOutside: 'bookID' parameter should be a string not a '${typeof bookID}'`); parameterAssert(typeof givenC === 'string', `checkNotesLinksToOutside: 'givenC' parameter should be a string not a '${typeof givenC}'`); parameterAssert(typeof givenV === 'string', `checkNotesLinksToOutside: 'givenV' parameter should be a string not a '${typeof givenV}'`); - if (fieldName !== 'MDFile') { - parameterAssert(bookID.length === 3, `checkNotesLinksToOutside: 'bookID' parameter should be three characters long not ${bookID.length}`); - parameterAssert(bookID.toUpperCase() === bookID, `checkNotesLinksToOutside: 'bookID' parameter should be UPPERCASE not '${bookID}'`); - parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesLinksToOutside: '${bookID}' is not a valid USFM book identifier`); - } + // if (fieldName !== 'MDFile') { + // parameterAssert(bookID.length === 3, `checkNotesLinksToOutside: 'bookID' parameter should be three characters long not ${bookID.length}`); + // parameterAssert(bookID.toUpperCase() === bookID, `checkNotesLinksToOutside: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + // parameterAssert(bookID === 'OBS' || books.isValidBookID(bookID), `checkNotesLinksToOutside: '${bookID}' is not a valid USFM book identifier`); + // } parameterAssert(fieldName !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldName === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Note' || fieldName === 'TWLink' || fieldName === 'MDFile', `checkNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' or 'Note' or 'TWLink' or 'MDFile' not '${fieldName}'`); + // parameterAssert(fieldName === 'OccurrenceNote' || fieldName === 'Note' || fieldName === 'TWLink', `checkNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' or 'Note' or 'TWLink' not '${fieldName}'`); parameterAssert(fieldText !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); parameterAssert(typeof fieldText === 'string', `checkNotesLinksToOutside: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); parameterAssert(givenLocation !== undefined, "checkNotesLinksToOutside: 'fieldText' parameter should be defined"); @@ -181,7 +184,8 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g const getFile_ = (checkingOptions && checkingOptions?.getFile) ? checkingOptions?.getFile : cachedGetFile; let defaultLanguageCode = checkingOptions?.defaultLanguageCode; - if (!defaultLanguageCode) defaultLanguageCode = DEFAULT_LANGUAGE_CODE; + // if (!defaultLanguageCode) defaultLanguageCode = DEFAULT_LANGUAGE_CODE; + if (!defaultLanguageCode) defaultLanguageCode = languageCode; // debugLog("checkNotesLinksToOutside defaultLanguageCode", defaultLanguageCode); let taRepoUsername = checkingOptions?.taRepoUsername; @@ -200,7 +204,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g else break; // stop at the first non-digit } let givenCint, givenVint; - if (fieldName !== 'MDFile') { + if (givenC && givenV) { try { givenCint = (givenC === 'front') ? 0 : ourParseInt(givenC); givenVint = (givenV === 'intro') ? 0 : ourParseInt(givenVfirstPart); @@ -256,91 +260,143 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g } // Find total regular (non-image) links - const linksList1 = fieldText.match(GENERAL_LINK1_REGEX) || []; - // if (linksList1.length) debugLog(`linksList1=${JSON.stringify(linksList1)}`); - const linksList2 = fieldText.match(GENERAL_LINK2_REGEX) || []; - // if (linksList2.length) debugLog(`linksList2=${JSON.stringify(linksList2)}`); + const linksList1 = fieldText.match(GENERAL_LINK1_REGEX) || []; // [[something]] + // if (linksList1.length) debugLog(`linksList1 (${linksList1.length}) = ${JSON.stringify(linksList1)}`); + const linksList2 = fieldText.match(GENERAL_LINK2_REGEX) || []; // [display](link) + // if (linksList2.length) debugLog(`linksList2 (${linksList2.length}) = ${JSON.stringify(linksList2)}`); const totalLinks1 = linksList1.length; const totalLinks2 = linksList2.length; - let taLinkCount = 0, twLinkCount = 0, thisChapterBibleLinkCount = 0, thisVerseBibleLinkCount = 0, thisBookBibleLinkCount = 0, otherBookBibleLinkCount = 0, TNLinkCount = 0; + let taLinkCount1 = 0, taLinkCount2 = 0, twLinkCount1 = 0, twLinkCount2 = 0, TNLinkCount1 = 0, + thisChapterBibleLinkCount1 = 0, thisVerseBibleLinkCount1 = 0, thisBookBibleLinkCount1 = 0, otherBookBibleLinkCount1 = 0, + generalLinkCount1 = 0; let processedLinkList = []; - if (fieldName === 'MDFile') { - // Check for internal TW links like [Asher](../names/asher.md) - while ((regexResultArray = TW_INTERNAL_REGEX.exec(fieldText))) { - debugLog(` checkNotesLinksToOutside TW_INTERNAL_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - twLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `TW_INTERNAL_REGEX expected 4 fields (not ${regexResultArray.length})`); - // eslint-disable-next-line no-unused-vars - let [_totalLink, _displayName, category, article] = regexResultArray; - - const twRepoName = `${languageCode}_tw`; - // debugLog(`Got twRepoName=${twRepoName}`); - const filepath = `bible/${category}/${article}.md`; - // debugLog(`Got tW filepath=${filepath}`); + // Check for internal TW links like [Asher](../names/asher.md) + while ((regexResultArray = TW_INTERNAL_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside TW_INTERNAL_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + twLinkCount1 += 1; + parameterAssert(regexResultArray.length === 4, `TW_INTERNAL_REGEX expected 4 fields (not ${regexResultArray.length})`); + // eslint-disable-next-line no-unused-vars + let [totalLink, _displayName, category, article] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + const twRepoName = `${languageCode}_tw`; + // debugLog(`Got twRepoName=${twRepoName}`); + const filepath = `bible/${category}/${article}.md`; + // debugLog(`Got tW filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); + const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; + let twFileContent; + try { + twFileContent = await getFile_(twPathParameters); + // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); + } catch (trcGCerror) { + console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); + addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + } + if (!twFileContent) + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else { // we got the content of the TW article + if (twFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + // THIS IS DISABLED COZ IT CAN GIVE AN INFINITE LOOP !!! + // else if (checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { + // // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); + // if (await alreadyChecked(twPathParameters) !== true) { + // // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); + // const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); + // for (const noticeObject of checkTWFileResult.noticeList) + // ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); + // ctarResult.checkedFileCount += 1; + // ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + // ctarResult.checkedFilesizes = twFileContent.length; + // ctarResult.checkedFilenameExtensions = ['md']; + // ctarResult.checkedRepoNames.push(twRepoName); + // markAsChecked(twPathParameters); // don’t bother waiting for the result + // } + // } + // else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); + } + } + else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); + } - if (!checkingOptions?.disableAllLinkFetchingFlag) { - // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); - const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; - let twFileContent; - try { - twFileContent = await getFile_(twPathParameters); - // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); - } catch (trcGCerror) { - console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); - addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); - } - if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else { // we got the content of the TW article - if (twFileContent.length < 10) - addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (0 && checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { - // THIS IS DISABLED COZ IT CAN GIVE AN INFINITE LOOP !!! - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); - if (await alreadyChecked(twPathParameters) !== true) { - // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); - const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); - for (const noticeObject of checkTWFileResult.noticeList) - ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); - ctarResult.checkedFileCount += 1; - ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); - ctarResult.checkedFilesizes = twFileContent.length; - ctarResult.checkedFilenameExtensions = ['md']; - ctarResult.checkedRepoNames.push(twRepoName); - markAsChecked(twPathParameters); // don’t bother waiting for the result - } + // Check for TA links like [How to Translate Names](rc://en/ta/man/translate/translate-names) + while ((regexResultArray = TA_FULL_DISPLAY_LINK_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside TA_FULL_DISPLAY_LINK_REGEX resultArray=${JSON.stringify(regexResultArray)}`); + taLinkCount1 += 1; + parameterAssert(regexResultArray.length === 5, `TA_FULL_DISPLAY_LINK_REGEX expected 5 fields (not ${regexResultArray.length})`) + // eslint-disable-next-line no-unused-vars + let [totalLink, _displayName, foundLanguageCode, part, article] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (foundLanguageCode !== '*') { + const characterIndex = TA_FULL_DISPLAY_LINK_REGEX.lastIndex - totalLink.length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${foundLanguageCode}'`, characterIndex, excerpt, location: ourLocation }); + } else if (repoCode === 'TN') { // but not TN2 + // At the moment, tC can’t handle these links with * so we have to ensure that they're not there + const characterIndex = TA_FULL_DISPLAY_LINK_REGEX.lastIndex - totalLink.length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); + } + if (!foundLanguageCode || foundLanguageCode === '*') foundLanguageCode = defaultLanguageCode; + const taRepoName = `${foundLanguageCode}_ta`; + // debugLog(`Got taRepoName=${taRepoName}`); + const filepath = `${part}/${article}/01.md`; // Other files are title.md, sub-title.md + // debugLog(`Got tA filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); + const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; + let taFileContent, alreadyGaveError = false; + try { + taFileContent = await getFile_(taPathParameters); + // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); + } catch (trcGCerror) { + // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); + addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + alreadyGaveError = true; + } + if (!alreadyGaveError) { + if (!taFileContent) + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else if (taFileContent.length < 10) + addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); + if (await alreadyChecked(taPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); + const checkTAFileResult = await checkMarkdownText(foundLanguageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTAFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = taFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(taRepoName); + markAsChecked(taPathParameters); // don’t bother waiting for the result } - else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); } } - else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } + } - // Check for TA links like [How to Translate Names](rc://en/ta/man/translate/translate-names) - while ((regexResultArray = TA_DISPLAY_LINK_REGEX.exec(fieldText))) { - debugLog(` checkNotesLinksToOutside TA_DISPLAY_LINK_REGEX resultArray=${JSON.stringify(regexResultArray)}`); - taLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 5, `TA_DISPLAY_LINK_REGEX expected 5 fields (not ${regexResultArray.length})`) + if (fieldName.startsWith('TA ')) { + // Check for relative TA links like [Borrow Words](../translate-transliterate/01.md) + while ((regexResultArray = TA_RELATIVE_DISPLAY_LINK_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside TA_RELATIVE_DISPLAY_LINK_REGEX resultArray=${JSON.stringify(regexResultArray)}`); + taLinkCount1 += 1; + parameterAssert(regexResultArray.length === 3, `TA_RELATIVE_DISPLAY_LINK_REGEX expected 3 fields (not ${regexResultArray.length})`) // eslint-disable-next-line no-unused-vars - let [_totalLink, _displayName, languageCode, part, article] = regexResultArray; - - if (languageCode !== '*') { - const characterIndex = TA_DISPLAY_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); - } else if (repoCode === 'TN') { // but not TN2 - // At the moment, tC can’t handle these links with * so we have to ensure that they're not there - const characterIndex = TA_DISPLAY_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); - } - if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; + let [totalLink, _displayName, article] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + const taRepoName = `${languageCode}_ta`; // debugLog(`Got taRepoName=${taRepoName}`); - const filepath = `${part}/${article}/01.md`; // Other files are title.md, sub-title.md + const filepath = `translate/${article}/01.md`; // Other files are title.md, sub-title.md // debugLog(`Got tA filepath=${filepath}`); if (!checkingOptions?.disableAllLinkFetchingFlag) { @@ -352,616 +408,621 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); } catch (trcGCerror) { // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); - addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); alreadyGaveError = true; } if (!alreadyGaveError) { if (!taFileContent) - addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); else if (taFileContent.length < 10) - addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); - if (await alreadyChecked(taPathParameters) !== true) { - // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); - const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); - for (const noticeObject of checkTAFileResult.noticeList) - ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); - ctarResult.checkedFileCount += 1; - ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); - ctarResult.checkedFilesizes = taFileContent.length; - ctarResult.checkedFilenameExtensions = ['md']; - ctarResult.checkedRepoNames.push(taRepoName); - markAsChecked(taPathParameters); // don’t bother waiting for the result - } - } + addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + // Don't do this or it gets infinite recursion!!! + // else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { + // // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); + // if (await alreadyChecked(taPathParameters) !== true) { + // // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); + // const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); + // for (const noticeObject of checkTAFileResult.noticeList) + // ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); + // ctarResult.checkedFileCount += 1; + // ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + // ctarResult.checkedFilesizes = taFileContent.length; + // ctarResult.checkedFilenameExtensions = ['md']; + // ctarResult.checkedRepoNames.push(taRepoName); + // markAsChecked(taPathParameters); // don’t bother waiting for the result + // } + // } } } } - } else { // not 'MDFile' - // Check for TA links like [[rc://en/ta/man/translate/figs-metaphor]] - // if (fieldText.indexOf('brother') !== -1) debugLog("checkNotesLinksToOutside: Search for TA links") - while ((regexResultArray = TA_DOUBLE_BRACKETED_LINK_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside TA resultArray=${JSON.stringify(regexResultArray)}`); - taLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `TA_DOUBLE_BRACKETED_LINK_REGEX expected 4 fields (not ${regexResultArray.length})`) - // eslint-disable-next-line no-unused-vars - let [_totalLink, languageCode, part, article] = regexResultArray; - - if (languageCode !== '*') { - const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${languageCode}'`, characterIndex, excerpt, location: ourLocation }); - } else if (repoCode === 'TN') { // but not TN2 - // At the moment, tC can’t handle these links with * so we have to ensure that they're not there - const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - regexResultArray[0].length + 7; // lastIndex points to the end of the field that was found - const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') - addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); - } - if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; - const taRepoName = `${languageCode}_ta`; - // debugLog(`Got taRepoName=${taRepoName}`); - const filepath = `${part}/${article}/01.md`; // Other files are title.md, sub-title.md - // debugLog(`Got tA filepath=${filepath}`); + } - if (!checkingOptions?.disableAllLinkFetchingFlag) { - // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); - const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; - let taFileContent, alreadyGaveError = false; - try { - taFileContent = await getFile_(taPathParameters); - // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); - } catch (trcGCerror) { - // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); - addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); - alreadyGaveError = true; - } - if (!alreadyGaveError) { - if (!taFileContent) - addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (taFileContent.length < 10) - addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); - if (await alreadyChecked(taPathParameters) !== true) { - // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); - const checkTAFileResult = await checkMarkdownText(languageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); - for (const noticeObject of checkTAFileResult.noticeList) - ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); - ctarResult.checkedFileCount += 1; - ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); - ctarResult.checkedFilesizes = taFileContent.length; - ctarResult.checkedFilenameExtensions = ['md']; - ctarResult.checkedRepoNames.push(taRepoName); - markAsChecked(taPathParameters); // don’t bother waiting for the result - } + // Check for TA links like [[rc://en/ta/man/translate/figs-metaphor]] + // if (fieldText.indexOf('brother') !== -1) debugLog("checkNotesLinksToOutside: Search for TA links") + while ((regexResultArray = TA_DOUBLE_BRACKETED_LINK_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside TA_DOUBLE_BRACKETED_LINK_REGEX resultArray=${JSON.stringify(regexResultArray)}`); + taLinkCount2 += 1; + parameterAssert(regexResultArray.length === 4, `TA_DOUBLE_BRACKETED_LINK_REGEX expected 4 fields (not ${regexResultArray.length})`) + let [totalLink, foundLanguageCode, part, article] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (foundLanguageCode !== '*') { + const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - totalLink.length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 450, message: "Resource container link should have '*' language code", details: `not '${foundLanguageCode}'`, characterIndex, excerpt, location: ourLocation }); + } else if (repoCode === 'TN') { // but not TN2 + // At the moment, tC can’t handle these links with * so we have to ensure that they're not there + const characterIndex = TA_DOUBLE_BRACKETED_LINK_REGEX.lastIndex - totalLink.length + 7; // lastIndex points to the end of the field that was found + const excerpt = (characterIndex > excerptHalfLength ? '…' : '') + fieldText.substring(characterIndex - excerptHalfLength, characterIndex + excerptHalfLengthPlus) + (characterIndex + excerptHalfLengthPlus < fieldText.length ? '…' : '') + addNoticePartial({ priority: 950, message: "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation }); + } + if (!foundLanguageCode || foundLanguageCode === '*') foundLanguageCode = defaultLanguageCode; + const taRepoName = `${foundLanguageCode}_ta`; + // debugLog(`Got taRepoName=${taRepoName}`); + const filepath = `${part}/${article}/01.md`; // Other files are title.md, sub-title.md + // debugLog(`Got tA filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // functionLog(`checkNotesLinksToOutside: need to check against ${taRepoName}`); + const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; + let taFileContent, alreadyGaveError = false; + try { + taFileContent = await getFile_(taPathParameters); + // debugLog("Fetched fileContent for", taRepoName, filepath, typeof fileContent, fileContent.length); + } catch (trcGCerror) { + // console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TA for '${taRepoUsername}', '${taRepoName}', '${filepath}', '${taRepoBranch}', ${trcGCerror.message}`); + addNoticePartial({ priority: 885, message: `Error loading ${fieldName} TA link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + alreadyGaveError = true; + } + if (!alreadyGaveError) { + if (!taFileContent) + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else if (taFileContent.length < 10) + addNoticePartial({ priority: 884, message: `Linked ${fieldName} TA article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else if (checkingOptions?.disableLinkedTAArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTAArticlesCheckFlag} so checking TA article: ${filepath}`); + if (await alreadyChecked(taPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TA article: ${filepath}`); + const checkTAFileResult = await checkMarkdownText(foundLanguageCode, repoCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTAFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: taRepoUsername, repoCode: 'TA', repoName: taRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TA' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = taFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(taRepoName); + markAsChecked(taPathParameters); // don’t bother waiting for the result } } } } + } - // Check for external TW links like [[rc://en/tw/dict/bible/other/death]] in TN or rc://en/tw/dict/bible/other/death in TWLinks - // (These are not nearly as many as TA links.) - const ourTWRegex = (fieldName === 'TWLink') ? TWL_RAW_LINK_REGEX : TW_DOUBLE_BRACKETED_LINK_REGEX; - // if (fieldText.indexOf('brother') !== -1) debugLog(`checkNotesLinksToOutside: ${bookID} ${givenC}:${givenV} Search for TW links with ${ourTWRegex}`) - while ((regexResultArray = ourTWRegex.exec(fieldText))) { - // if (fieldText.indexOf('brother') !== -1) debugLog(` checkNotesLinksToOutside ${givenC}:${givenV} found TW resultArray=${JSON.stringify(regexResultArray)}`); - twLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `TW_REGEX expected 4 fields (not ${regexResultArray.length})`) - let languageCode = regexResultArray[1]; - if (!languageCode || languageCode === '*') languageCode = defaultLanguageCode; - const twRepoName = `${languageCode}_tw`; - // debugLog(`Got twRepoName=${twRepoName}`); - const filepath = `bible/${regexResultArray[2]}/${regexResultArray[3]}.md`; - // debugLog(`Got tW filepath=${filepath}`); - - if (!checkingOptions?.disableAllLinkFetchingFlag) { - // if (regexResultArray[3] === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); - const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; - let twFileContent; - try { - twFileContent = await getFile_(twPathParameters); - // if (regexResultArray[3] === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); - } catch (trcGCerror) { - console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); - addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}: ${trcGCerror}` }); - } - if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else { // we got the content of the TW article - if (twFileContent.length < 10) - addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: regexResultArray[0], location: `${ourLocation} ${filepath}` }); - else if (checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { - // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); - if (await alreadyChecked(twPathParameters) !== true) { - // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); - const checkTWFileResult = await checkMarkdownText(languageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); - for (const noticeObject of checkTWFileResult.noticeList) - ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); - ctarResult.checkedFileCount += 1; - ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); - ctarResult.checkedFilesizes = twFileContent.length; - ctarResult.checkedFilenameExtensions = ['md']; - ctarResult.checkedRepoNames.push(twRepoName); - markAsChecked(twPathParameters); // don’t bother waiting for the result - } + // Check for external TW links like [[rc://en/tw/dict/bible/other/death]] in TN or rc://en/tw/dict/bible/other/death in TWLinks + // (These are not nearly as many as TA links.) + const ourTWRegex = (fieldName === 'TWLink') ? TWL_RAW_LINK_REGEX : TW_DOUBLE_BRACKETED_LINK_REGEX; + // if (fieldText.indexOf('brother') !== -1) debugLog(`checkNotesLinksToOutside: ${bookID} ${givenC}:${givenV} Search for TW links with ${ourTWRegex}`) + while ((regexResultArray = ourTWRegex.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside ${languageCode} ${repoCode} ${fieldName} ${givenC}:${givenV} found TW resultArray=${JSON.stringify(regexResultArray)}`); + twLinkCount2 += 1; + parameterAssert(regexResultArray.length === 4, `TW_REGEX expected 4 fields (not ${regexResultArray.length})`) + let [totalLink, foundLanguageCode, category, article] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (!foundLanguageCode || foundLanguageCode === '*') foundLanguageCode = defaultLanguageCode; + const twRepoName = `${foundLanguageCode}_tw`; + // debugLog(`Got twRepoName=${twRepoName}`); + const filepath = `bible/${category}/${article}.md`; + // debugLog(`Got tW filepath=${filepath}`); + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + // if (article === 'brother') debugLog(`Need to check ${fieldName} TW link ${regexResultArray} against ${twRepoName}`); + const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; + let twFileContent; + try { + twFileContent = await getFile_(twPathParameters); + // if (article === 'brother') debugLog(`Fetched fileContent for ${JSON.stringify(twPathParameters)}: ${typeof twFileContent} ${twFileContent.length}`); + } catch (trcGCerror) { + console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load TW`, twRepoUsername, twRepoName, filepath, twRepoBranch, trcGCerror.message); + addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); + } + if (!twFileContent) + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else { // we got the content of the TW article + if (twFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + else if (checkingOptions?.disableLinkedTWArticlesCheckFlag !== true) { + // functionLog(`checkNotesLinksToOutside got ${checkingOptions?.disableLinkedTWArticlesCheckFlag} so checking TW article: ${filepath}`); + if (await alreadyChecked(twPathParameters) !== true) { + // functionLog(`checkNotesLinksToOutside needs to check TW article: ${filepath}`); + const checkTWFileResult = await checkMarkdownText(foundLanguageCode, repoCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, checkingOptions); + for (const noticeObject of checkTWFileResult.noticeList) + ctarResult.noticeList.push({ ...noticeObject, username: twRepoUsername, repoCode: 'TW', repoName: twRepoName, filename: filepath, location: ` linked to${ourLocation}`, extra: 'TW' }); + ctarResult.checkedFileCount += 1; + ctarResult.checkedFilenames.push(`${regexResultArray[3]}.md`); + ctarResult.checkedFilesizes = twFileContent.length; + ctarResult.checkedFilenameExtensions = ['md']; + ctarResult.checkedRepoNames.push(twRepoName); + markAsChecked(twPathParameters); // don’t bother waiting for the result } - else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); } + else debugLog("disableLinkedTWArticlesCheckFlag is set to TRUE!"); } - else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } + else debugLog("disableAllLinkFetchingFlag is set to TRUE!"); } // debugLog("checkNotesLinksToOutside: Search for Bible links") - if (fieldName === 'MDFile') { - // Check for other book Bible links like [Genesis 29:23](rc://en/tn/help/gen/29/23) - while ((regexResultArray = BIBLE_FULL_HELP_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_FULL_HELP_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - otherBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 9, `BIBLE_FULL_HELP_REGEX expected 9 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, Lg, B2, C2, V2] = regexResultArray; - // debugLog(`Lg='${Lg}' B2='${B2}' C2='${C2}' V2='${V2}'`); - - if (Lg !== '*' && Lg !== languageCode) - addNoticePartial({ priority: 669, message: "Unexpected language code in link", details: `resource language code is '${languageCode}'`, excerpt: Lg, location: ourLocation }); - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } + // Check for other book Bible links like [Genesis 29:23](rc://en/tn/help/gen/29/23) + while ((regexResultArray = BIBLE_FULL_HELP_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_FULL_HELP_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 9, `BIBLE_FULL_HELP_REGEX expected 9 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, Lg, B2, C2, V2] = regexResultArray; + // debugLog(`Lg='${Lg}' B2='${B2}' C2='${C2}' V2='${V2}'`); + processedLinkList.push(totalLink); // Save the full link + + if (Lg !== '*' && Lg !== languageCode) + addNoticePartial({ priority: 669, message: "Unexpected language code in link", details: `resource language code is '${languageCode}'`, excerpt: Lg, location: ourLocation }); + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } + } - let linkBookCode = B2 === '..' ? bookID : B2; + let linkBookCode = B2 === '..' ? bookID : B2; - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link CheckA couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link CheckA couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } + + if (linkBookCode === 'obs') { + const numStories = 50, numFramesThisStory = 99; + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numStories) + addNoticePartial({ priority: 655, message: "Bad story number in markdown OBS help link", details: `${linkBookCode} ${linkChapterInt} vs ${numStories} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numFramesThisStory) + addNoticePartial({ priority: 653, message: "Bad frame number in markdown OBS help link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numFramesThisStory} verses`, excerpt: totalLink, location: ourLocation }); + } else { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BIBLE_FULL_HELP_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link CheckA couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link CheckA couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible help link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible help link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + // Check for this-chapter Bible links like [Revelation 3:11](./11.md) + while ((regexResultArray = BIBLE_REGEX_THIS_CHAPTER_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisChapterBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 6, `BIBLE_REGEX_THIS_CHAPTER_RELATIVE expected 6 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } - } else { // it's not 'MDFile' - - // Check for this-chapter Bible links like [Revelation 3:11](./11.md) - while ((regexResultArray = BIBLE_REGEX_THIS_CHAPTER_RELATIVE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisChapterBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 6, `BIBLE_REGEX_THIS_CHAPTER_RELATIVE expected 6 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, V2] = regexResultArray; - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } - } - let linkBookCode = bookID; + let linkBookCode = bookID; - const linkVerseInt = ourParseInt(V2); - if (C1 === undefined) { - if (!books.isOneChapterBook(linkBookCode)) { - // debugLog(` checkNotesLinksToOutside C1 missing in BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); - } - C1 = '0'; // Try to avoid consequential errors + const linkVerseInt = ourParseInt(V2); + if (C1 === undefined) { + if (!books.isOneChapterBook(linkBookCode)) { + // debugLog(` checkNotesLinksToOutside C1 missing in BIBLE_REGEX_THIS_CHAPTER_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + addNoticePartial({ priority: 555, message: "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation }); } + C1 = '0'; // Try to avoid consequential errors + } + try { + if (ourParseInt(C1) !== givenCint) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${givenCint}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check1 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check1 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } + + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BIBLE_REGEX_THIS_CHAPTER_RELATIVE linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - if (ourParseInt(C1) !== givenCint) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${givenCint}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check1 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check1 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); - } - - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenCint); - } catch (tlcNVerror) { } - if (!givenCint || givenCint < 1 || givenCint > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${givenCint} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenCint}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenCint); + } catch (tlcNVerror) { } + if (!givenCint || givenCint < 1 || givenCint > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${givenCint} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenCint}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } + } - // Check for this-verse Bible links like [11](../03/11.md) - while ((regexResultArray = THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_VERSE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisVerseBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 4, `THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX expected 4 fields (not ${regexResultArray.length})`); - let [totalLink, V1, C2, V2] = regexResultArray; + // Check for this-verse Bible links like [11](../03/11.md) + while ((regexResultArray = THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisVerseBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 4, `THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX expected 4 fields (not ${regexResultArray.length})`); + let [totalLink, V1, C2, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link - let linkBookCode = bookID; + let linkBookCode = bookID; - let linkChapterInt, linkVerseInt; - try { - linkChapterInt = ourParseInt(C2); - linkVerseInt = ourParseInt(V2); - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${V2}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check1b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + let linkChapterInt, linkVerseInt; + try { + linkChapterInt = ourParseInt(C2); + linkVerseInt = ourParseInt(V2); + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${V2}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check1b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); + try { + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } + } - // Check for this-verse Bible links like [11](../03/11.md) - while ((regexResultArray = THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_VERSE_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisVerseBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 5, `THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX expected 5 fields (not ${regexResultArray.length})`); - let [totalLink, V1a, V1b, C2, V2] = regexResultArray; + // Check for this-verse Bible links like [11](../03/11.md) + while ((regexResultArray = THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisVerseBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 5, `THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX expected 5 fields (not ${regexResultArray.length})`); + let [totalLink, V1a, V1b, C2, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link - let linkBookCode = bookID; + let linkBookCode = bookID; + + let verseInt1a, verseInt1b, linkChapterInt, linkVerseInt; + try { + verseInt1a = ourParseInt(V1a); + verseInt1b = ourParseInt(V1b); + linkChapterInt = ourParseInt(C2); + linkVerseInt = ourParseInt(V2); + if (verseInt1a !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${V2}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check1c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1a} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } + if (verseInt1b <= verseInt1a) + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); - let verseInt1a, verseInt1b, linkChapterInt, linkVerseInt; + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - verseInt1a = ourParseInt(V1a); - verseInt1b = ourParseInt(V1b); - linkChapterInt = ourParseInt(C2); - linkVerseInt = ourParseInt(V2); - if (verseInt1a !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${V2}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check1c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} ${V1a} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } - if (verseInt1b <= verseInt1a) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } + try { + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + // Check for this-book Bible links like [Revelation 3:11](../03/11.md) + while ((regexResultArray = BIBLE_REGEX_THIS_BOOK_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisBookBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 7, `BIBLE_REGEX_THIS_BOOK_RELATIVE expected 7 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, C2, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } - // Check for this-book Bible links like [Revelation 3:11](../03/11.md) - while ((regexResultArray = BIBLE_REGEX_THIS_BOOK_RELATIVE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_THIS_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 7, `BIBLE_REGEX_THIS_BOOK_RELATIVE expected 7 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, C2, V2] = regexResultArray; - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } - } + let linkBookCode = bookID; + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check2 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } - let linkBookCode = bookID; - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BIBLE_REGEX_THIS_BOOK_RELATIVE linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check2 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); - } + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) + while ((regexResultArray = BCV_V_TO_THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BCV_V_TO_THIS_BOOK_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisBookBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 9, `BCV_V_TO_THIS_BOOK_BIBLE_REGEX expected 9 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, B2, C2, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } - // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) - while ((regexResultArray = BCV_V_TO_THIS_BOOK_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside THIS_BOOK_RANGE_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 9, `BCV_V_TO_THIS_BOOK_BIBLE_REGEX expected 9 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, B2, C2, V2] = regexResultArray; - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } - } + let linkBookCode = B2 === '..' ? bookID : B2; - let linkBookCode = B2 === '..' ? bookID : B2; + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check2b couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1a) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } + try { + if (ourParseInt(V1b) <= ourParseInt(V1a)) + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); + } - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check2b couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2} from '${fieldText}': ${ccError}`); - } + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BCV_V_TO_THIS_BOOK_BIBLE_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - if (ourParseInt(V1a) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2b couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } try { - if (ourParseInt(V1b) <= ourParseInt(V1a)) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2c couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C2}:${V2} from '${fieldText}': ${vvError}`); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) + while ((regexResultArray = BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + thisChapterBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 7, `BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX expected 7 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } - // Check for this-book Bible links like [Revelation 3:11-12](../03/11.md) - while ((regexResultArray = BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - thisChapterBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 7, `BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX expected 7 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1a, V1b, V2] = regexResultArray; - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } - } + let linkBookCode = bookID; - let linkBookCode = bookID; + const linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(V1a) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2d couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); + } + try { + if (ourParseInt(V1b) <= ourParseInt(V1a)) + addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check2e couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); + } - const linkVerseInt = ourParseInt(V2); - try { - if (ourParseInt(V1a) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1a} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2d couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); - } + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); + // try { + // numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + // } catch (tlcNCerror) { } try { - if (ourParseInt(V1b) <= ourParseInt(V1a)) - addNoticePartial({ priority: 741, message: "Verse numbers of markdown Bible link range out of order", details: `${V1a} to ${V1b}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check2e couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V2} from '${fieldText}': ${vvError}`); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenC); + } catch (tlcNVerror) { } + if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenC}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - // try { - // numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - // } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), givenC); - } catch (tlcNVerror) { } - if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${givenC}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + // Check for other book Bible links like [Revelation 3:11](rev/03/11.md) + while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_ABSOLUTE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_ABSOLUTE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_ABSOLUTE expected 8 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } - // Check for other book Bible links like [Revelation 3:11](rev/03/11.md) - while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_ABSOLUTE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_ABSOLUTE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - otherBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_ABSOLUTE expected 8 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } - } + let linkBookCode = B2 === '..' ? bookID : B2; - let linkBookCode = B2 === '..' ? bookID : B2; + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BIBLE_REGEX_OTHER_BOOK_ABSOLUTE linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + } + } - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); + // Check for other book Bible links like [Revelation 3:11](../../rev/03/11.md) + while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_RELATIVE.exec(fieldText))) { + // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + otherBookBibleLinkCount1 += 1; + parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_RELATIVE expected 8 fields (not ${regexResultArray.length})`); + let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); + if (optionalB1) { + optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy + if (defaultLanguageCode === 'en') { // should be able to check the book name + const checkResult = books.isGoodEnglishBookName(optionalB1); + // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); + if (checkResult === undefined || checkResult === false) + addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); } } - // Check for other book Bible links like [Revelation 3:11](../../rev/03/11.md) - while ((regexResultArray = BIBLE_REGEX_OTHER_BOOK_RELATIVE.exec(fieldText))) { - // debugLog(` checkNotesLinksToOutside BIBLE_REGEX_OTHER_BOOK_RELATIVE regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - otherBookBibleLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link - parameterAssert(regexResultArray.length === 8, `BIBLE_REGEX_OTHER_BOOK_RELATIVE expected 8 fields (not ${regexResultArray.length})`); - let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2] = regexResultArray; - - if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); - if (optionalB1) { - optionalB1 = `${optionalN1}${optionalB1}`.trim(); // e.g., 1 Timothy - if (defaultLanguageCode === 'en') { // should be able to check the book name - const checkResult = books.isGoodEnglishBookName(optionalB1); - // debugLog(optionalB1, "isGoodEnglishBookName checkResult", checkResult); - if (checkResult === undefined || checkResult === false) - addNoticePartial({ priority: 143, message: "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation }); - } - } + let linkBookCode = B2 === '..' ? bookID : B2; - let linkBookCode = B2 === '..' ? bookID : B2; + const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + try { + if (ourParseInt(C1) !== linkChapterInt) + addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); + } catch (ccError) { + console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); + } + try { + if (ourParseInt(V1) !== linkVerseInt) + addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); + } catch (vvError) { + console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); + } - const linkChapterInt = ourParseInt(C2), linkVerseInt = ourParseInt(V2); + if (linkBookCode) { // then we know which Bible book this link is to + // So we can check for valid C:V numbers + let numChaptersThisBook, numVersesThisChapter; + logicAssert(linkBookCode.toLowerCase() !== 'obs', `BIBLE_REGEX_OTHER_BOOK_RELATIVE linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { - if (ourParseInt(C1) !== linkChapterInt) - addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don’t match", details: `${C1} vs ${linkChapterInt}`, excerpt: totalLink, location: ourLocation }); - } catch (ccError) { - console.error(`TN Link Check3 couldn’t compare chapter numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1} from '${fieldText}': ${ccError}`); - } + numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; + } catch (tlcNCerror) { } try { - if (ourParseInt(V1) !== linkVerseInt) - addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don’t match", details: `${V1} vs ${linkVerseInt}`, excerpt: totalLink, location: ourLocation }); - } catch (vvError) { - console.error(`TN Link Check3 couldn’t compare verse numbers for ${bookID} ${givenC}:${givenV} ${fieldName} with ${C1}:${V1} from '${fieldText}': ${vvError}`); - } - - if (linkBookCode) { // then we know which Bible book this link is to - // So we can check for valid C:V numbers - let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); - try { - numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; - } catch (tlcNCerror) { } - try { - numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); - } catch (tlcNVerror) { } - if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) - addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); - else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) - addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } + numVersesThisChapter = books.versesInChapter(linkBookCode.toLowerCase(), linkChapterInt); + } catch (tlcNVerror) { } + if (!linkChapterInt || linkChapterInt < 1 || linkChapterInt > numChaptersThisBook) + addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); + else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) + addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); } } + // Check for TN links like [Titus 3:11](../03/11/zd2d) while ((regexResultArray = TN_REGEX.exec(fieldText))) { // debugLog(` checkNotesLinksToOutside TN_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); - TNLinkCount += 1; - processedLinkList.push(regexResultArray[0]); // Save the full link + TNLinkCount1 += 1; parameterAssert(regexResultArray.length === 9, `TN_REGEX expected 9 fields (not ${regexResultArray.length})`); // eslint-disable-next-line no-unused-vars let [totalLink, optionalN1, optionalB1, C1, V1, B2, C2, V2, _noteID2] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link if (optionalN1) parameterAssert(optionalB1, `Should have book name as well as number '${optionalN1}'`); if (optionalB1) { @@ -993,7 +1054,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; - logicAssert(linkBookCode.toLowerCase() !== 'obs', "Shouldn’t happen in notes-links-check"); + logicAssert(linkBookCode.toLowerCase() !== 'obs', `TN_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); try { numChaptersThisBook = books.chaptersInBook(linkBookCode.toLowerCase()).length; } catch (tlcNCerror) { } @@ -1009,18 +1070,47 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // TODO: We should see if we can find the correct note } + // Check for simple display links like [ULT](https://something) + while ((regexResultArray = SIMPLE_DISPLAY_LINK_REGEX.exec(fieldText))) { + debugLog(` checkNotesLinksToOutside SIMPLE_DISPLAY_LINK_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + generalLinkCount1 += 1; + parameterAssert(regexResultArray.length === 2, `SIMPLE_DISPLAY_LINK_REGEX expected 2 fields (not ${regexResultArray.length})`); + // eslint-disable-next-line no-unused-vars + let [totalLink, displayText, uri] = regexResultArray; + processedLinkList.push(totalLink); // Save the full link + + if (!checkingOptions?.disableAllLinkFetchingFlag) { + let generalFileContent; + try { + generalFileContent = await cachedGetFileUsingFullURL({ uri }); + debugLog(`${displayText} ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); + } catch (trcGCerror) { + console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load general ${uri}`); + addNoticePartial({ priority: 882, message: `Error loading ${fieldName} general link`, excerpt: totalLink, location: `${ourLocation} ${uri}: ${trcGCerror}` }); + } + if (!generalFileContent) + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} general link`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); + else { // we got the content of the general article + if (generalFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked ${fieldName} general article seems empty`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); + } + } + } + // Check for additional links that we can’t explain - const BibleLinkCount = thisChapterBibleLinkCount + thisVerseBibleLinkCount + thisBookBibleLinkCount + otherBookBibleLinkCount + TNLinkCount; - if (totalLinks1 > BibleLinkCount) { + // if (processedLinkList.length) debugLog(`processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}`); + const linkCount1 = thisChapterBibleLinkCount1 + thisVerseBibleLinkCount1 + thisBookBibleLinkCount1 + otherBookBibleLinkCount1 + TNLinkCount1 + twLinkCount1 + taLinkCount1 + generalLinkCount1; + if (totalLinks1 > linkCount1) { const leftoverLinksList1 = linksList1.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above - // if (leftoverLinksList1.length) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); - addNoticePartial({ priority: 648, message: "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check ${leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)}`, location: ourLocation }); + if (leftoverLinksList1.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); + addNoticePartial({ priority: 648, message: "Unusual [ ]( ) link(s)—not a recognized Bible or TA, TN, or TW link", details: `need to carefully check ${leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)}`, location: ourLocation }); } - const twaLinkCount = twLinkCount + taLinkCount; - if (totalLinks2 > twaLinkCount) { + const linkCount2 = twLinkCount2 + taLinkCount2; // These are double-bracketed links, e.g., [[something]] + // debugLog(`twLinkCount2 ${twLinkCount2} + taLinkCount2 ${taLinkCount2} = linkCount2 ${linkCount2}`); + if (totalLinks2 > linkCount2) { const leftoverLinksList2 = linksList2.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above - // if (leftoverLinksList2.length) debugLog(`processedLinkList (${processedLinkList.length})=${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); - addNoticePartial({ priority: 649, message: "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check ${leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)}`, location: ourLocation }); + if (leftoverLinksList2.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); + addNoticePartial({ priority: 649, message: "Unusual [[ ]] link(s)—not a recognized TA or TW link", details: `need to carefully check ${leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)}`, location: ourLocation }); } // Check for badly formed links (not processed by the above code) diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index f9f7f1bb4..41061edcf 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -3,7 +3,7 @@ import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; import { checkSupportReferenceInTA } from './ta-reference-check'; -import { checkNotesLinksToOutside } from './notes-links-check'; +// import { checkNotesLinksToOutside } from './notes-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; @@ -263,6 +263,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // end of ourCheckTNOriginalLanguageQuote function + /* async function ourCheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { // Checks that the TA/TW/Bible reference can be found @@ -309,6 +310,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); } // end of ourCheckNotesLinksToOutside function + */ // Main code for checkNotesTSV7DataRow function @@ -505,7 +507,7 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID else { // More than just whitespace const adjustedNote = note.replace(/\\n/g, '\n'); ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', adjustedNote, true, ourRowLocation, checkingOptions); - await ourCheckNotesLinksToOutside(rowID, 'Note', adjustedNote, ourRowLocation, linkCheckingOptions); + // await ourCheckNotesLinksToOutside(rowID, 'Note', adjustedNote, ourRowLocation, linkCheckingOptions); let regexResultArray; while ((regexResultArray = TA_REGEX.exec(adjustedNote))) { // debugLog("Got TA Regex in Note", JSON.stringify(regexResultArray)); diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index cc537eeae..ea5b0022c 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -3,7 +3,7 @@ import * as books from './books/books'; import { checkTextField } from './field-text-check'; import { checkMarkdownText } from './markdown-text-check'; import { checkSupportReferenceInTA } from './ta-reference-check'; -import { checkNotesLinksToOutside } from './notes-links-check'; +// import { checkNotesLinksToOutside } from './notes-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; @@ -270,65 +270,65 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // end of ourCheckTNOriginalLanguageQuote function - /** - * - * @param {string} rowID - * @param {string} fieldName - * @param {string} taLinkText - * @param {string} rowLocation - * @param {Object} checkingOptions - */ - async function ourCheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { - // Checks that the TA/TW/Bible reference can be found - - // Uses - // checkingOptions.twRepoUsername - // checkingOptions.twRepoBranch (or tag) - // checkingOptions.disableLinkedTWArticlesCheckFlag - - // Updates the global list of notices - - // functionLog(`checkTN_TSV9DataRow ourCheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be defined"); - parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); - parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be defined"); - parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); - parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); - parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); - parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); - - const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); - // debugLog("coqResultObject", JSON.stringify(coqResultObject)); - - // Choose only ONE of the following - // This is the fast way of append the results from this field - // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); - // If we need to put everything through addNoticePartial, e.g., for debugging or filtering - // process results line by line - for (const coqNoticeEntry of coqResultObject.noticeList) { - if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check - drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is - else // For our direct checks, we add the repoCode as an extra value - addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); - } - // The following is needed coz we might be checking the linked TA and/or TW articles - if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) - if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; - else drResult.checkedFileCount = coqResultObject.checkedFileCount; - if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) - if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; - else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; - if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) - for (const checkedRepoName of coqResultObject.checkedRepoNames) - try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } - catch { drResult.checkedRepoNames = [checkedRepoName]; } - if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) - for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) - try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } - catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } - // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); - } - // end of ourCheckNotesLinksToOutside function + // /** + // * + // * @param {string} rowID + // * @param {string} fieldName + // * @param {string} taLinkText + // * @param {string} rowLocation + // * @param {Object} checkingOptions + // */ + // async function ourCheckNotesLinksToOutside(rowID, fieldName, taLinkText, rowLocation, checkingOptions) { + // // Checks that the TA/TW/Bible reference can be found + + // // Uses + // // checkingOptions.twRepoUsername + // // checkingOptions.twRepoBranch (or tag) + // // checkingOptions.disableLinkedTWArticlesCheckFlag + + // // Updates the global list of notices + + // // functionLog(`checkTN_TSV9DataRow ourCheckNotesLinksToOutside(${rowID}, ${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + // parameterAssert(rowID !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be defined"); + // parameterAssert(typeof rowID === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'rowID' parameter should be a string not a '${typeof rowID}'`); + // parameterAssert(fieldName !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be defined"); + // parameterAssert(typeof fieldName === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + // parameterAssert(fieldName === 'OccurrenceNote', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'fieldName' parameter should be 'OccurrenceNote' not '${fieldName}'`); + // parameterAssert(taLinkText !== undefined, "checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be defined"); + // parameterAssert(typeof taLinkText === 'string', `checkTN_TSV9DataRow ourCheckNotesLinksToOutside: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); + + // const coqResultObject = await checkNotesLinksToOutside(languageCode, repoCode, bookID, givenC, givenV, fieldName, taLinkText, rowLocation, { ...checkingOptions, defaultLanguageCode: languageCode }); + // // debugLog("coqResultObject", JSON.stringify(coqResultObject)); + + // // Choose only ONE of the following + // // This is the fast way of append the results from this field + // // result.noticeList = result.noticeList.concat(coqResultObject.noticeList); + // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering + // // process results line by line + // for (const coqNoticeEntry of coqResultObject.noticeList) { + // if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + // drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is + // else // For our direct checks, we add the repoCode as an extra value + // addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); + // } + // // The following is needed coz we might be checking the linked TA and/or TW articles + // if (coqResultObject.checkedFileCount && coqResultObject.checkedFileCount > 0) + // if (typeof drResult.checkedFileCount === 'number') drResult.checkedFileCount += coqResultObject.checkedFileCount; + // else drResult.checkedFileCount = coqResultObject.checkedFileCount; + // if (coqResultObject.checkedFilesizes && coqResultObject.checkedFilesizes > 0) + // if (typeof drResult.checkedFilesizes === 'number') drResult.checkedFilesizes += coqResultObject.checkedFilesizes; + // else drResult.checkedFilesizes = coqResultObject.checkedFilesizes; + // if (coqResultObject.checkedRepoNames && coqResultObject.checkedRepoNames.length > 0) + // for (const checkedRepoName of coqResultObject.checkedRepoNames) + // try { if (drResult.checkedRepoNames.indexOf(checkedRepoName) < 0) drResult.checkedRepoNames.push(checkedRepoName); } + // catch { drResult.checkedRepoNames = [checkedRepoName]; } + // if (coqResultObject.checkedFilenameExtensions && coqResultObject.checkedFilenameExtensions.length > 0) + // for (const checkedFilenameExtension of coqResultObject.checkedFilenameExtensions) + // try { if (drResult.checkedFilenameExtensions.indexOf(checkedFilenameExtension) < 0) drResult.checkedFilenameExtensions.push(checkedFilenameExtension); } + // catch { drResult.checkedFilenameExtensions = [checkedFilenameExtension]; } + // // if (drResult.checkedFilenameExtensions) userLog("drResult", JSON.stringify(drResult)); + // } + // // end of ourCheckNotesLinksToOutside function // Main code for checkTN_TSV9DataRow function @@ -532,7 +532,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, else { // More than just whitespace const adjustedOccurrenceNote = occurrenceNote.replace(/<br>/g, '\n'); ONSuggestion = await ourMarkdownTextChecks(rowID, 'OccurrenceNote', adjustedOccurrenceNote, true, ourRowLocation, checkingOptions); - await ourCheckNotesLinksToOutside(rowID, 'OccurrenceNote', adjustedOccurrenceNote, ourRowLocation, linkCheckingOptions); + // await ourCheckNotesLinksToOutside(rowID, 'OccurrenceNote', adjustedOccurrenceNote, ourRowLocation, linkCheckingOptions); let regexResultArray; while ((regexResultArray = TA_REGEX.exec(adjustedOccurrenceNote))) { // debugLog("Got TA Regex in OccurrenceNote", JSON.stringify(regexResultArray)); diff --git a/src/demos/all-book-packages-check/AllBookPackagesCheck.js b/src/demos/all-book-packages-check/AllBookPackagesCheck.js index 0f5b29a21..59f912f43 100644 --- a/src/demos/all-book-packages-check/AllBookPackagesCheck.js +++ b/src/demos/all-book-packages-check/AllBookPackagesCheck.js @@ -87,8 +87,8 @@ function AllBookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { } if (props.reloadAllFilesFirst && props.reloadAllFilesFirst.slice(0).toUpperCase() === 'Y') { - userLog("Clearing cache before running book package check…"); - setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running book package check…</p>); + userLog("Clearing cache before running all book packages check…"); + setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running all book packages check…</p>); await clearCaches(); } else await clearCheckedArticleCache(); diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index 6e61d00fc..9b0ab5579 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -6,7 +6,7 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { checkRepo } from '../repo-check/checkRepo'; -// const BP_VALIDATOR_VERSION_STRING = '0.6.0'; +// const BP_VALIDATOR_VERSION_STRING = '0.6.1'; const STANDARD_MANIFEST_FILENAME = 'manifest.yaml'; @@ -118,7 +118,10 @@ export async function checkBookPackage(username, languageCode, bookID, setResult parameterAssert(typeof fileLocation === 'string', `cBP ourCheckBPFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); parameterAssert(checkingOptions !== undefined, "cBP ourCheckBPFileContents: 'checkingOptions' parameter should be defined"); - const cfcResultObject = await checkFileContents(username, languageCode, repoCode, branch, cfFilename, fileContent, fileLocation, checkingOptions); + let adjustedLanguageCode = languageCode; + // if (repoCode === 'UHB') adjustedLanguageCode = 'hbo'; // NO -- we need the languageCode of the BP being checked (so we can resolve TW links with * for language) !!! + // else if (repoCode === 'UGNT') adjustedLanguageCode = 'el-x-koine'; + const cfcResultObject = await checkFileContents(username, adjustedLanguageCode, repoCode, branch, cfFilename, fileContent, fileLocation, checkingOptions); // debugLog("checkFileContents() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); // for (const successEntry of cfResultObject.successList) userLog(" ourCheckBPFileContents:", successEntry); // debugLog("cfcResultObject", JSON.stringify(cfcResultObject)); diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index c9cb823fb..44f48216c 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -76,8 +76,8 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { } if (props.reloadAllFilesFirst && props.reloadAllFilesFirst.slice(0).toUpperCase() === 'Y') { - userLog("Clearing cache before running book package check…"); - setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running book package check…</p>); + userLog("Clearing cache before running book packages check…"); + setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running book packages check…</p>); await clearCaches(); } else await clearCheckedArticleCache(); diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 56e6b7044..cb0060066 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -49,8 +49,8 @@ function FileCheck(props) { } if (props.reloadAllFilesFirst && props.reloadAllFilesFirst.slice(0).toUpperCase() === 'Y') { - userLog("Clearing cache before running book package check…"); - setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running book package check…</p>); + userLog("Clearing cache before running file check…"); + setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running file check…</p>); await clearCaches(); } else await clearCheckedArticleCache(); diff --git a/src/demos/file-check/README.md b/src/demos/file-check/README.md index 50c832d75..b83af89bc 100644 --- a/src/demos/file-check/README.md +++ b/src/demos/file-check/README.md @@ -22,7 +22,7 @@ and then validates the content of one file selected from the repo. // repoName='hbo_uhb' // OT books only // repoName='el-x-koine_ugnt' // NT books only // repoName='en_ult' // Can use ult or ust here - repoName='en_tw' // Can use ta, tw, tn, tq, sn, or sq here + repoName='en_tn' // Can use ta, tw, tn, tq, sn, or sq here // If we don’t put the branch here, the default branch is used // branch='master' @@ -40,16 +40,17 @@ and then validates the content of one file selected from the repo. // filename= '65-3JN.usfm' // e.g., for UGNT, LT, or ST // filename= '67-REV.usfm' // e.g., for UGNT, LT, or ST // filename= 'en_tn_01-GEN.tsv' // for TN + // filename= 'en_tn_15-EZR.tsv' // for TN // filename= 'en_tn_16-NEH.tsv' // for TN - filename= 'en_tn_17-EST.tsv' // for TN + // filename= 'en_tn_17-EST.tsv' // for TN // filename= 'en_tn_31-OBA.tsv' // for TN // filename= 'en_tn_50-EPH.tsv' // for TN // filename= 'en_tn_57-TIT.tsv' // for TN // filename= 'en_tn_58-PHM.tsv' // for TN // filename= 'en_tn_61-1PE.tsv' // for TN - // filename= 'en_tn_65-3JN.tsv' // for TN + filename= 'en_tn_65-3JN.tsv' // for TN // It's actually possible to put a filepath in the filename field - filename= 'bible/names/zilpah.md' // for TW + // filename= 'bible/names/zilpah.md' // for TW // The location field appears in check messages to help the user locate the issue location="as specified in FileCheck demo" diff --git a/src/demos/gl-book-package-check/GlBookPackageCheck.js b/src/demos/gl-book-package-check/GlBookPackageCheck.js index 1ff53b6d1..6cc6919a5 100644 --- a/src/demos/gl-book-package-check/GlBookPackageCheck.js +++ b/src/demos/gl-book-package-check/GlBookPackageCheck.js @@ -69,8 +69,8 @@ function GlBookPackageCheck(/*username, languageCode, bookIDs,*/ props) { } if (props.reloadAllFilesFirst && props.reloadAllFilesFirst.slice(0).toUpperCase() === 'Y') { - userLog("Clearing cache before running book package check…"); - setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running book package check…</p>); + userLog("Clearing cache before running GL book packages check…"); + setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running GL book packages check…</p>); await clearCaches(); } else await clearCheckedArticleCache(); diff --git a/src/demos/repo-check/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index 731238428..a68abc605 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -72,8 +72,8 @@ function RepoCheck(/*username, languageCode,*/ props) { } if (props.reloadAllFilesFirst && props.reloadAllFilesFirst.slice(0).toUpperCase() === 'Y') { - userLog("Clearing cache before running book package check…"); - setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running book package check…</p>); + userLog("Clearing cache before running respository check…"); + setResultValue(<p style={{ color: 'orange' }}>Clearing cache before running repository check…</p>); await clearCaches(); } else await clearCheckedArticleCache(); diff --git a/yarn.lock b/yarn.lock index b6d6b8b5d..087e809c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@babel/cli@^7.12.1": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.17.tgz#2db13a0f2ba9c05bed78b8aad9669b473dd7f267" - integrity sha512-R9dQbDshWvAp3x5XjANsfthqka+ToEdDUonKgtALNgzQxgiUg2Xa4ZwKIcE84wnoiobIJFXF+TCM4ylJvUuW5w== + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.13.0.tgz#48e77614e897615ca299bece587b68a70723ff4c" + integrity sha512-y5AohgeVhU+wO5kU1WGMLdocFj83xCxVjsVFa2ilII8NEwmBZvx7Ambq621FbFIK68loYJ9p43nfoi6es+rzSA== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -40,10 +40,10 @@ dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.12.13", "@babel/compat-data@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.13.tgz#27e19e0ed3726ccf54067ced4109501765e7e2e8" - integrity sha512-U/hshG5R+SIoW7HVWIdmy1cB7s3ki+r3FpyEZiCgpi4tFgPnX/vynY80ZGSASOIrUM6O7VxOgCZgdt7h97bUGg== +"@babel/compat-data@^7.13.0", "@babel/compat-data@^7.13.5", "@babel/compat-data@^7.9.0": + version "7.13.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.6.tgz#11972d07db4c2317afdbf41d6feb3a730301ef4e" + integrity sha512-VhgqKOWYVm7lQXlvbJnWOzwfAQATd2nV52koT0HZ/LdDH0m4DUDwkKYsH+IwpXb+bKPyBJzawA4I6nBKqZcpQw== "@babel/core@7.9.0": version "7.9.0" @@ -68,32 +68,33 @@ source-map "^0.5.0" "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.17.tgz#993c5e893333107a2815d8e0d73a2c3755e280b2" - integrity sha512-V3CuX1aBywbJvV2yzJScRxeiiw0v2KZZYYE3giywxzFJL13RiyPjaaDwhDnxmgFTTS7FgvM2ijr4QmKNIu0AtQ== + version "7.13.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.1.tgz#7ddd027176debe40f13bb88bac0c21218c5b1ecf" + integrity sha512-FzeKfFBG2rmFtGiiMdXZPFt/5R5DXubVi82uYhjGX4Msf+pgYQMCFIqFXZWs5vbIYbf14VeBIgdGI03CDOOM1w== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.17" - "@babel/helper-module-transforms" "^7.12.17" - "@babel/helpers" "^7.12.17" - "@babel/parser" "^7.12.17" + "@babel/generator" "^7.13.0" + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helpers" "^7.13.0" + "@babel/parser" "^7.13.0" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.17" - "@babel/types" "^7.12.17" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" convert-source-map "^1.7.0" debug "^4.1.0" - gensync "^1.0.0-beta.1" + gensync "^1.0.0-beta.2" json5 "^2.1.2" lodash "^4.17.19" - semver "^5.4.1" + semver "7.0.0" source-map "^0.5.0" -"@babel/generator@^7.12.17", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.17.tgz#9ef1dd792d778b32284411df63f4f668a9957287" - integrity sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg== +"@babel/generator@^7.13.0", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.0.tgz#bd00d4394ca22f220390c56a0b5b85568ec1ec0c" + integrity sha512-zBZfgvBB/ywjx0Rgc2+BwoH/3H+lDtlgD4hBOpEv5LxRnYsm/753iRuLepqnYlynpjC3AdQxtxsoeHJoEEwOAw== dependencies: - "@babel/types" "^7.12.17" + "@babel/types" "^7.13.0" jsesc "^2.5.1" source-map "^0.5.0" @@ -112,25 +113,25 @@ "@babel/helper-explode-assignable-expression" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.12.17", "@babel/helper-compilation-targets@^7.8.7": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.17.tgz#91d83fae61ef390d39c3f0507cb83979bab837c7" - integrity sha512-5EkibqLVYOuZ89BSg2lv+GG8feywLuvMXNYgf0Im4MssE0mFWPztSpJbildNnUgw0bLI2EsIN4MpSHC2iUJkQA== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.8.7": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.0.tgz#c9cf29b82a76fd637f0faa35544c4ace60a155a1" + integrity sha512-SOWD0JK9+MMIhTQiUVd4ng8f3NXhPVQvTv7D3UN4wbp/6cAHnB2EmMaU1zZA2Hh1gwme+THBrVSqTFxHczTh0Q== dependencies: - "@babel/compat-data" "^7.12.13" + "@babel/compat-data" "^7.13.0" "@babel/helper-validator-option" "^7.12.17" browserslist "^4.14.5" - semver "^5.5.0" + semver "7.0.0" -"@babel/helper-create-class-features-plugin@^7.12.13", "@babel/helper-create-class-features-plugin@^7.12.17", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.17.tgz#704b69c8a78d03fb1c5fcc2e7b593f8a65628944" - integrity sha512-I/nurmTxIxHV0M+rIpfQBF1oN342+yvl2kwZUrQuOClMamHF1w5tknfZubgNOLRoA73SzBFAdFcpb4M9HwOeWQ== +"@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.0.tgz#28d04ad9cfbd1ed1d8b988c9ea7b945263365846" + integrity sha512-twwzhthM4/+6o9766AW2ZBHpIHPSGrPGk1+WfHiu13u/lBnggXGNYCpeAyVfNwGDKfkhEDp+WOD/xafoJ2iLjA== dependencies: "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.12.17" + "@babel/helper-member-expression-to-functions" "^7.13.0" "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" + "@babel/helper-replace-supers" "^7.13.0" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-create-regexp-features-plugin@^7.12.13": @@ -141,12 +142,26 @@ "@babel/helper-annotate-as-pure" "^7.12.13" regexpu-core "^4.7.1" +"@babel/helper-define-polyfill-provider@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.2.tgz#619f01afe1deda460676c25c463b42eaefdb71a2" + integrity sha512-hWeolZJivTNGHXHzJjQz/NwDaG4mGXf22ZroOP8bQYgvHNzaQ5tylsVbAcAS2oDjXBwpu8qH2I/654QFS2rDpw== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + "@babel/helper-explode-assignable-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.13.tgz#0e46990da9e271502f77507efa4c9918d3d8634a" - integrity sha512-5loeRNvMo9mx1dA/d6yNi+YiKziJZFylZnCo1nmFF4qPU4yJ14abhWESuSMQSlQxWdxdOFzxXjk/PpfudTtYyw== + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz#17b5c59ff473d9f956f40ef570cf3a76ca12657f" + integrity sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.13.0" "@babel/helper-function-name@^7.12.13": version "7.12.13" @@ -165,18 +180,19 @@ "@babel/types" "^7.12.13" "@babel/helper-hoist-variables@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.12.13.tgz#13aba58b7480b502362316ea02f52cca0e9796cd" - integrity sha512-KSC5XSj5HreRhYQtZ3cnSnQwDzgnbdUDEFsxkN0m6Q3WrCRt72xrnZ8+h+pX7YxM7hr87zIO3a/v5p/H3TrnVw== + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz#5d5882e855b5c5eda91e0cadc26c6e7a2c8593d8" + integrity sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g== dependencies: - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" -"@babel/helper-member-expression-to-functions@^7.12.13", "@babel/helper-member-expression-to-functions@^7.12.17": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.17.tgz#f82838eb06e1235307b6d71457b6670ff71ee5ac" - integrity sha512-Bzv4p3ODgS/qpBE0DiJ9qf5WxSmrQ8gVTe8ClMfwwsY2x/rhykxxy3bXzG7AGTnPB2ij37zGJ/Q/6FruxHxsxg== +"@babel/helper-member-expression-to-functions@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" + integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== dependencies: - "@babel/types" "^7.12.17" + "@babel/types" "^7.13.0" "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.8.3": version "7.12.13" @@ -185,19 +201,19 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-module-transforms@^7.12.13", "@babel/helper-module-transforms@^7.12.17", "@babel/helper-module-transforms@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.17.tgz#7c75b987d6dfd5b48e575648f81eaac891539509" - integrity sha512-sFL+p6zOCQMm9vilo06M4VHuTxUAwa6IxgL56Tq1DVtA0ziAGTH1ThmJq7xwPqdQlgAbKX3fb0oZNbtRIyA5KQ== +"@babel/helper-module-transforms@^7.12.13", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz#42eb4bd8eea68bab46751212c357bfed8b40f6f1" + integrity sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw== dependencies: "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" + "@babel/helper-replace-supers" "^7.13.0" "@babel/helper-simple-access" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-validator-identifier" "^7.12.11" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.17" - "@babel/types" "^7.12.17" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.12.13": @@ -207,29 +223,29 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz#174254d0f2424d8aefb4dd48057511247b0a9eeb" - integrity sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" + integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== -"@babel/helper-remap-async-to-generator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.13.tgz#170365f4140e2d20e5c88f8ba23c24468c296878" - integrity sha512-Qa6PU9vNcj1NZacZZI1Mvwt+gXDH6CTfgAkSjeRMLE8HxtDK76+YDId6NQR+z7Rgd5arhD2cIbS74r0SxD6PDA== +"@babel/helper-remap-async-to-generator@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz#376a760d9f7b4b2077a9dd05aa9c3927cadb2209" + integrity sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg== dependencies: "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-wrap-function" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/helper-wrap-function" "^7.13.0" + "@babel/types" "^7.13.0" -"@babel/helper-replace-supers@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz#00ec4fb6862546bd3d0aff9aac56074277173121" - integrity sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg== +"@babel/helper-replace-supers@^7.12.13", "@babel/helper-replace-supers@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" + integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.13" + "@babel/helper-member-expression-to-functions" "^7.13.0" "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/helper-simple-access@^7.12.13": version "7.12.13" @@ -262,24 +278,24 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== -"@babel/helper-wrap-function@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.13.tgz#e3ea8cb3ee0a16911f9c1b50d9e99fe8fe30f9ff" - integrity sha512-t0aZFEmBJ1LojdtJnhOaQEVejnzYhyjWHSsNSNo8vOYRbAJNh6r6GQF7pd36SqG7OKGbn+AewVQ/0IfYfIuGdw== +"@babel/helper-wrap-function@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz#bdb5c66fda8526ec235ab894ad53a1235c79fcc4" + integrity sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA== dependencies: "@babel/helper-function-name" "^7.12.13" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" -"@babel/helpers@^7.12.17", "@babel/helpers@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.17.tgz#71e03d2981a6b5ee16899964f4101dc8471d60bc" - integrity sha512-tEpjqSBGt/SFEsFikKds1sLNChKKGGR17flIgQKXH4fG6m9gTgl3gnOC1giHNyaBCSKuTfxaSzHi7UnvqiVKxg== +"@babel/helpers@^7.13.0", "@babel/helpers@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.0.tgz#7647ae57377b4f0408bf4f8a7af01c42e41badc0" + integrity sha512-aan1MeFPxFacZeSz6Ld7YZo5aPuqnKlD7+HZY75xQsueczFccP9A7V05+oe0XpLwHK3oLorPe9eaAUljL7WEaQ== dependencies: "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.17" - "@babel/types" "^7.12.17" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/highlight@^7.0.0", "@babel/highlight@^7.12.13", "@babel/highlight@^7.8.3": version "7.12.13" @@ -290,18 +306,18 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.17", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.17.tgz#bc85d2d47db38094e5bb268fc761716e7d693848" - integrity sha512-r1yKkiUTYMQ8LiEI0UcQx5ETw5dpTLn9wijn9hk6KkTtOK95FndDN10M+8/s6k/Ymlbivw0Av9q4SlgF80PtHg== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": + version "7.13.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.4.tgz#340211b0da94a351a6f10e63671fa727333d13ab" + integrity sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA== -"@babel/plugin-proposal-async-generator-functions@^7.12.13", "@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.13.tgz#d1c6d841802ffb88c64a2413e311f7345b9e66b5" - integrity sha512-1KH46Hx4WqP77f978+5Ye/VUbuwQld2hph70yaw2hXS2v7ER2f3nlpNMu909HO2rbvP0NKLlMVDPh9KXklVMhA== +"@babel/plugin-proposal-async-generator-functions@^7.13.5", "@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.13.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.5.tgz#69e3fbb9958949b09036e27b26eba1aafa1ba3db" + integrity sha512-8cErJEDzhZgNKzYyjCKsHuyPqtWxG8gc9h4OFSUDJu0vCAOsObPU2LcECnW0kJwh/b+uUz46lObVzIXw0fzAbA== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-remap-async-to-generator" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/helper-remap-async-to-generator" "^7.13.0" "@babel/plugin-syntax-async-generators" "^7.8.0" "@babel/plugin-proposal-class-properties@7.8.3": @@ -312,13 +328,13 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.13.tgz#3d2ce350367058033c93c098e348161d6dc0d8c8" - integrity sha512-8SCJ0Ddrpwv4T7Gwb33EmW1V9PY5lggTO+A8WjyIwxrSHDUyBw4MtF96ifn1n8H806YlxbVCoKXbbmzD6RD+cA== +"@babel/plugin-proposal-class-properties@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz#146376000b94efd001e57a40a88a525afaab9f37" + integrity sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-proposal-decorators@7.8.3": version "7.8.3" @@ -369,12 +385,12 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.13", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.13.tgz#24867307285cee4e1031170efd8a7ac807deefde" - integrity sha512-Qoxpy+OxhDBI5kRqliJFAl4uWXk3Bn24WeFstPH0iLymFehSAUR8MHpqU7njyXv/qbo7oN6yTy5bfCmXdKpo1Q== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.0.tgz#1a96fdf2c43109cfe5568513c5379015a23f5380" + integrity sha512-UkAvFA/9+lBBL015gjA68NvKiCReNxqFLm3SdNKaM3XXoDisA7tMAIX4PmIwatFoFqMxxT3WyG9sK3MO0Kting== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" "@babel/plugin-proposal-numeric-separator@7.8.3": @@ -393,14 +409,14 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.12.13", "@babel/plugin-proposal-object-rest-spread@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.13.tgz#f93f3116381ff94bc676fdcb29d71045cd1ec011" - integrity sha512-WvA1okB/0OS/N3Ldb3sziSrXg6sRphsBgqiccfcQq7woEn5wQLNX82Oc4PlaFcdwcWHuQXAtb8ftbS8Fbsg/sg== +"@babel/plugin-proposal-object-rest-spread@^7.13.0", "@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.0.tgz#8f19ad247bb96bd5ad2d4107e6eddfe0a789937b" + integrity sha512-B4qphdSTp0nLsWcuei07JPKeZej4+Hd22MdnulJXQa1nCcGSBlk8FiqenGERaPZ+PuYhz4Li2Wjc8yfJvHgUMw== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.13" + "@babel/plugin-transform-parameters" "^7.13.0" "@babel/plugin-proposal-optional-catch-binding@^7.12.13", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": version "7.12.13" @@ -418,22 +434,22 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.17", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.17.tgz#e382becadc2cb16b7913b6c672d92e4b33385b5c" - integrity sha512-TvxwI80pWftrGPKHNfkvX/HnoeSTR7gC4ezWnAL39PuktYUe6r8kEpOLTYnkBTsaoeazXm2jHJ22EQ81sdgfcA== +"@babel/plugin-proposal-optional-chaining@^7.13.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.0.tgz#75b41ce0d883d19e8fe635fc3f846be3b1664f4d" + integrity sha512-OVRQOZEBP2luZrvEbNSX5FfWDousthhdEoAOpej+Tpe58HFLvqRClT89RauIvBuCDFEip7GW1eT86/5lMy2RNA== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-private-methods@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.13.tgz#ea78a12554d784ecf7fc55950b752d469d9c4a71" - integrity sha512-sV0V57uUwpauixvR7s2o75LmwJI6JECwm5oPUY5beZB1nBl2i37hc7CJGqB5G+58fur5Y6ugvl3LRONk5x34rg== +"@babel/plugin-proposal-private-methods@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.13.0.tgz#04bd4c6d40f6e6bbfa2f57e2d8094bad900ef787" + integrity sha512-MXyyKQd9inhx1kDYPkFRVOBXQ20ES8Pto3T7UZ92xj2mY0EVD8oAVzeyYuVfy/mxAdTSIayOvg+aVzcHV2bn6Q== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-proposal-unicode-property-regex@^7.12.13", "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": version "7.12.13" @@ -569,21 +585,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-arrow-functions@^7.12.13", "@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.13.tgz#eda5670b282952100c229f8a3bd49e0f6a72e9fe" - integrity sha512-tBtuN6qtCTd+iHzVZVOMNp+L04iIJBpqkdY42tWbmjIT5wvR2kx7gxMBsyhQtFzHwBbyGi9h8J8r9HgnOpQHxg== +"@babel/plugin-transform-arrow-functions@^7.13.0", "@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.13.0.tgz#10a59bebad52d637a027afa692e8d5ceff5e3dae" + integrity sha512-96lgJagobeVmazXFaDrbmCLQxBysKu7U6Do3mLsx27gf5Dk85ezysrs2BZUpXD703U/Su1xTBDxxar2oa4jAGg== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" -"@babel/plugin-transform-async-to-generator@^7.12.13", "@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.13.tgz#fed8c69eebf187a535bfa4ee97a614009b24f7ae" - integrity sha512-psM9QHcHaDr+HZpRuJcE1PXESuGWSCcbiGFFhhwfzdbTxaGDVzuVtdNYliAwcRo3GFg0Bc8MmI+AvIGYIJG04A== +"@babel/plugin-transform-async-to-generator@^7.13.0", "@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.13.0.tgz#8e112bf6771b82bf1e974e5e26806c5c99aa516f" + integrity sha512-3j6E004Dx0K3eGmhxVJxwwI89CTJrce7lg3UrtFuDAVQ/2+SJ/h/aSFOeE6/n0WB1GsOffsJp6MnPQNQ8nmwhg== dependencies: "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-remap-async-to-generator" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/helper-remap-async-to-generator" "^7.13.0" "@babel/plugin-transform-block-scoped-functions@^7.12.13", "@babel/plugin-transform-block-scoped-functions@^7.8.3": version "7.12.13" @@ -599,32 +615,32 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-classes@^7.12.13", "@babel/plugin-transform-classes@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.13.tgz#9728edc1838b5d62fc93ad830bd523b1fcb0e1f6" - integrity sha512-cqZlMlhCC1rVnxE5ZGMtIb896ijL90xppMiuWXcwcOAuFczynpd3KYemb91XFFPi3wJSe/OcrX9lXoowatkkxA== +"@babel/plugin-transform-classes@^7.13.0", "@babel/plugin-transform-classes@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.13.0.tgz#0265155075c42918bf4d3a4053134176ad9b533b" + integrity sha512-9BtHCPUARyVH1oXGcSJD3YpsqRLROJx5ZNP6tN5vnk17N0SVf9WCtf8Nuh1CFmgByKKAIMstitKduoCmsaDK5g== dependencies: "@babel/helper-annotate-as-pure" "^7.12.13" "@babel/helper-function-name" "^7.12.13" "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/helper-replace-supers" "^7.13.0" "@babel/helper-split-export-declaration" "^7.12.13" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.12.13", "@babel/plugin-transform-computed-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.13.tgz#6a210647a3d67f21f699cfd2a01333803b27339d" - integrity sha512-dDfuROUPGK1mTtLKyDPUavmj2b6kFu82SmgpztBFEO974KMjJT+Ytj3/oWsTUMBmgPcp9J5Pc1SlcAYRpJ2hRA== +"@babel/plugin-transform-computed-properties@^7.13.0", "@babel/plugin-transform-computed-properties@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.13.0.tgz#845c6e8b9bb55376b1fa0b92ef0bdc8ea06644ed" + integrity sha512-RRqTYTeZkZAz8WbieLTvKUEUxZlUTdmL5KGMyZj7FnMfLNKV4+r5549aORG/mgojRmFlQMJDUupwAMiF2Q7OUg== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" -"@babel/plugin-transform-destructuring@^7.12.13", "@babel/plugin-transform-destructuring@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.13.tgz#fc56c5176940c5b41735c677124d1d20cecc9aeb" - integrity sha512-Dn83KykIFzjhA3FDPA1z4N+yfF3btDGhjnJwxIj0T43tP0flCujnU8fKgEkf0C1biIpSv9NZegPBQ1J6jYkwvQ== +"@babel/plugin-transform-destructuring@^7.13.0", "@babel/plugin-transform-destructuring@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.0.tgz#c5dce270014d4e1ebb1d806116694c12b7028963" + integrity sha512-zym5em7tePoNT9s964c0/KU3JPPnuq7VhIxPRefJ4/s82cD+q1mgKfuGRDMCPL0HTyKz4dISuQlCusfgCJ86HA== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-transform-dotall-regex@^7.12.13", "@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": version "7.12.13" @@ -657,12 +673,12 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" -"@babel/plugin-transform-for-of@^7.12.13", "@babel/plugin-transform-for-of@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.13.tgz#561ff6d74d9e1c8879cb12dbaf4a14cd29d15cf6" - integrity sha512-xCbdgSzXYmHGyVX3+BsQjcd4hv4vA/FDy7Kc8eOpzKmBBPEOTurt0w5fCRQaGl+GSBORKgJdstQ1rHl4jbNseQ== +"@babel/plugin-transform-for-of@^7.13.0", "@babel/plugin-transform-for-of@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.13.0.tgz#c799f881a8091ac26b54867a845c3e97d2696062" + integrity sha512-IHKT00mwUVYE0zzbkDgNRP6SRzvfGCYsOxIRz8KsiaaHCcT9BWIkO+H9QRJseHBLOGBZkHUdHiqj6r0POsdytg== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-transform-function-name@^7.12.13", "@babel/plugin-transform-function-name@^7.8.3": version "7.12.13" @@ -686,22 +702,22 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-modules-amd@^7.12.13", "@babel/plugin-transform-modules-amd@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.13.tgz#43db16249b274ee2e551e2422090aa1c47692d56" - integrity sha512-JHLOU0o81m5UqG0Ulz/fPC68/v+UTuGTWaZBUwpEk1fYQ1D9LfKV6MPn4ttJKqRo5Lm460fkzjLTL4EHvCprvA== +"@babel/plugin-transform-modules-amd@^7.13.0", "@babel/plugin-transform-modules-amd@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.13.0.tgz#19f511d60e3d8753cc5a6d4e775d3a5184866cc3" + integrity sha512-EKy/E2NHhY/6Vw5d1k3rgoobftcNUmp9fGjb9XZwQLtTctsRBOTRO7RHHxfIky1ogMN5BxN7p9uMA3SzPfotMQ== dependencies: - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.12.13", "@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.13.tgz#5043b870a784a8421fa1fd9136a24f294da13e50" - integrity sha512-OGQoeVXVi1259HjuoDnsQMlMkT9UkZT9TpXAsqWplS/M0N1g3TJAn/ByOCeQu7mfjc5WpSsRU+jV1Hd89ts0kQ== +"@babel/plugin-transform-modules-commonjs@^7.13.0", "@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.0.tgz#276932693a20d12c9776093fdc99c0d9995e34c6" + integrity sha512-j7397PkIB4lcn25U2dClK6VLC6pr2s3q+wbE8R3vJvY6U1UTBBj0n6F+5v6+Fd/UwfDPAorMOs2TV+T4M+owpQ== dependencies: - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-simple-access" "^7.12.13" babel-plugin-dynamic-import-node "^2.3.3" @@ -716,13 +732,13 @@ "@babel/helper-validator-identifier" "^7.12.11" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.12.13", "@babel/plugin-transform-modules-umd@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.13.tgz#26c66f161d3456674e344b4b1255de4d530cfb37" - integrity sha512-BgZndyABRML4z6ibpi7Z98m4EVLFI9tVsZDADC14AElFaNHHBcJIovflJ6wtCqFxwy2YJ1tJhGRsr0yLPKoN+w== +"@babel/plugin-transform-modules-umd@^7.13.0", "@babel/plugin-transform-modules-umd@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.13.0.tgz#8a3d96a97d199705b9fd021580082af81c06e70b" + integrity sha512-D/ILzAh6uyvkWjKKyFE/W0FzWwasv6vPTSqPcjxFqn6QpX3u8DjRVliq4F2BamO2Wee/om06Vyy+vPkNrd4wxw== dependencies: - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-transform-named-capturing-groups-regex@^7.12.13", "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": version "7.12.13" @@ -746,12 +762,12 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/helper-replace-supers" "^7.12.13" -"@babel/plugin-transform-parameters@^7.12.13", "@babel/plugin-transform-parameters@^7.8.7": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.13.tgz#461e76dfb63c2dfd327b8a008a9e802818ce9853" - integrity sha512-e7QqwZalNiBRHCpJg/P8s/VJeSRYgmtWySs1JwvfwPqhBbiWfOcHDKdeAi6oAyIimoKWBlwc8oTgbZHdhCoVZA== +"@babel/plugin-transform-parameters@^7.13.0", "@babel/plugin-transform-parameters@^7.8.7": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz#8fa7603e3097f9c0b7ca1a4821bc2fb52e9e5007" + integrity sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-transform-property-literals@^7.12.13", "@babel/plugin-transform-property-literals@^7.8.3": version "7.12.13" @@ -846,13 +862,16 @@ semver "^5.5.1" "@babel/plugin-transform-runtime@^7.12.1": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.17.tgz#329cb61d293b7e60a7685b91dda7c300668cee18" - integrity sha512-s+kIJxnaTj+E9Q3XxQZ5jOo+xcogSe3V78/iFQ5RmoT0jROdpcdxhfGdq/VLqW1hFSzw6VjqN8aQqTaAMixWsw== + version "7.13.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.6.tgz#c11c806f023d2065bbcc9b751702f4008245951c" + integrity sha512-QsTomUTIeOdYrNsOMJRSp2QzGvB1KYD4ePCC8Mei2SuoHScncYS3h1E9PR5gDL7buJmcqIHrWyH6B5GZMgDrRg== dependencies: "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - semver "^5.5.1" + "@babel/helper-plugin-utils" "^7.13.0" + babel-plugin-polyfill-corejs2 "^0.1.4" + babel-plugin-polyfill-corejs3 "^0.1.3" + babel-plugin-polyfill-regenerator "^0.1.2" + semver "7.0.0" "@babel/plugin-transform-shorthand-properties@^7.12.13", "@babel/plugin-transform-shorthand-properties@^7.8.3": version "7.12.13" @@ -861,12 +880,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-spread@^7.12.13", "@babel/plugin-transform-spread@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.13.tgz#ca0d5645abbd560719c354451b849f14df4a7949" - integrity sha512-dUCrqPIowjqk5pXsx1zPftSq4sT0aCeZVAxhdgs3AMgyaDmoUT0G+5h3Dzja27t76aUEIJWlFgPJqJ/d4dbTtg== +"@babel/plugin-transform-spread@^7.13.0", "@babel/plugin-transform-spread@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.13.0.tgz#84887710e273c1815ace7ae459f6f42a5d31d5fd" + integrity sha512-V6vkiXijjzYeFmQTr3dBxPtZYLPcUfY34DebOU27jIl2M/Y8Egm52Hw82CSjjPqd54GTlJs5x+CR7HeNr24ckg== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-transform-sticky-regex@^7.12.13", "@babel/plugin-transform-sticky-regex@^7.8.3": @@ -876,12 +895,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-template-literals@^7.12.13", "@babel/plugin-transform-template-literals@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.13.tgz#655037b07ebbddaf3b7752f55d15c2fd6f5aa865" - integrity sha512-arIKlWYUgmNsF28EyfmiQHJLJFlAJNYkuQO10jL46ggjBpeb2re1P9K9YGxNJB45BqTbaslVysXDYm/g3sN/Qg== +"@babel/plugin-transform-template-literals@^7.13.0", "@babel/plugin-transform-template-literals@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.13.0.tgz#a36049127977ad94438dee7443598d1cefdf409d" + integrity sha512-d67umW6nlfmr1iehCcBv69eSUSySk1EsIS8aTDX4Xo9qajAh6mYtcl4kJrBkGXuxZPEgVr7RVfAvNW6YQkd4Mw== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-transform-typeof-symbol@^7.12.13", "@babel/plugin-transform-typeof-symbol@^7.8.4": version "7.12.13" @@ -891,12 +910,12 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-transform-typescript@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.17.tgz#4aa6a5041888dd2e5d316ec39212b0cf855211bb" - integrity sha512-1bIYwnhRoetxkFonuZRtDZPFEjl1l5r+3ITkxLC3mlMaFja+GQFo94b/WHEPjqWLU9Bc+W4oFZbvCGe9eYMu1g== + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz#4a498e1f3600342d2a9e61f60131018f55774853" + integrity sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.17" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-typescript" "^7.12.13" "@babel/plugin-transform-unicode-escapes@^7.12.13": @@ -981,27 +1000,26 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.4.5": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.17.tgz#94a3793ff089c32ee74d76a3c03a7597693ebaaa" - integrity sha512-9PMijx8zFbCwTHrd2P4PJR5nWGH3zWebx2OcpTjqQrHhCiL2ssSR2Sc9ko2BsI2VmVBfoaQmPrlMTCui4LmXQg== + version "7.13.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.13.5.tgz#68b3bbc821a97fcdbf4bd0f6895b83d07f84f33e" + integrity sha512-xUeKBIIcbwxGevyWMSWZOW98W1lp7toITvVsMxSddCEQy932yYiF4fCB+CG3E/MXzFX3KbefgvCqEQ7TDoE6UQ== dependencies: - "@babel/compat-data" "^7.12.13" - "@babel/helper-compilation-targets" "^7.12.17" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/compat-data" "^7.13.5" + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-validator-option" "^7.12.17" - "@babel/plugin-proposal-async-generator-functions" "^7.12.13" - "@babel/plugin-proposal-class-properties" "^7.12.13" + "@babel/plugin-proposal-async-generator-functions" "^7.13.5" + "@babel/plugin-proposal-class-properties" "^7.13.0" "@babel/plugin-proposal-dynamic-import" "^7.12.17" "@babel/plugin-proposal-export-namespace-from" "^7.12.13" "@babel/plugin-proposal-json-strings" "^7.12.13" "@babel/plugin-proposal-logical-assignment-operators" "^7.12.13" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.13" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.0" "@babel/plugin-proposal-numeric-separator" "^7.12.13" - "@babel/plugin-proposal-object-rest-spread" "^7.12.13" + "@babel/plugin-proposal-object-rest-spread" "^7.13.0" "@babel/plugin-proposal-optional-catch-binding" "^7.12.13" - "@babel/plugin-proposal-optional-chaining" "^7.12.17" - "@babel/plugin-proposal-private-methods" "^7.12.13" + "@babel/plugin-proposal-optional-chaining" "^7.13.0" + "@babel/plugin-proposal-private-methods" "^7.13.0" "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" "@babel/plugin-syntax-async-generators" "^7.8.0" "@babel/plugin-syntax-class-properties" "^7.12.13" @@ -1015,42 +1033,45 @@ "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" "@babel/plugin-syntax-top-level-await" "^7.12.13" - "@babel/plugin-transform-arrow-functions" "^7.12.13" - "@babel/plugin-transform-async-to-generator" "^7.12.13" + "@babel/plugin-transform-arrow-functions" "^7.13.0" + "@babel/plugin-transform-async-to-generator" "^7.13.0" "@babel/plugin-transform-block-scoped-functions" "^7.12.13" "@babel/plugin-transform-block-scoping" "^7.12.13" - "@babel/plugin-transform-classes" "^7.12.13" - "@babel/plugin-transform-computed-properties" "^7.12.13" - "@babel/plugin-transform-destructuring" "^7.12.13" + "@babel/plugin-transform-classes" "^7.13.0" + "@babel/plugin-transform-computed-properties" "^7.13.0" + "@babel/plugin-transform-destructuring" "^7.13.0" "@babel/plugin-transform-dotall-regex" "^7.12.13" "@babel/plugin-transform-duplicate-keys" "^7.12.13" "@babel/plugin-transform-exponentiation-operator" "^7.12.13" - "@babel/plugin-transform-for-of" "^7.12.13" + "@babel/plugin-transform-for-of" "^7.13.0" "@babel/plugin-transform-function-name" "^7.12.13" "@babel/plugin-transform-literals" "^7.12.13" "@babel/plugin-transform-member-expression-literals" "^7.12.13" - "@babel/plugin-transform-modules-amd" "^7.12.13" - "@babel/plugin-transform-modules-commonjs" "^7.12.13" + "@babel/plugin-transform-modules-amd" "^7.13.0" + "@babel/plugin-transform-modules-commonjs" "^7.13.0" "@babel/plugin-transform-modules-systemjs" "^7.12.13" - "@babel/plugin-transform-modules-umd" "^7.12.13" + "@babel/plugin-transform-modules-umd" "^7.13.0" "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.13" "@babel/plugin-transform-new-target" "^7.12.13" "@babel/plugin-transform-object-super" "^7.12.13" - "@babel/plugin-transform-parameters" "^7.12.13" + "@babel/plugin-transform-parameters" "^7.13.0" "@babel/plugin-transform-property-literals" "^7.12.13" "@babel/plugin-transform-regenerator" "^7.12.13" "@babel/plugin-transform-reserved-words" "^7.12.13" "@babel/plugin-transform-shorthand-properties" "^7.12.13" - "@babel/plugin-transform-spread" "^7.12.13" + "@babel/plugin-transform-spread" "^7.13.0" "@babel/plugin-transform-sticky-regex" "^7.12.13" - "@babel/plugin-transform-template-literals" "^7.12.13" + "@babel/plugin-transform-template-literals" "^7.13.0" "@babel/plugin-transform-typeof-symbol" "^7.12.13" "@babel/plugin-transform-unicode-escapes" "^7.12.13" "@babel/plugin-transform-unicode-regex" "^7.12.13" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.17" - core-js-compat "^3.8.0" - semver "^5.5.0" + "@babel/types" "^7.13.0" + babel-plugin-polyfill-corejs2 "^0.1.4" + babel-plugin-polyfill-corejs3 "^0.1.3" + babel-plugin-polyfill-regenerator "^0.1.2" + core-js-compat "^3.9.0" + semver "7.0.0" "@babel/preset-modules@^0.1.3": version "0.1.4" @@ -1095,9 +1116,9 @@ "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.12.1", "@babel/runtime-corejs3@^7.9.6": - version "7.12.18" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.18.tgz#e5663237e5658e4c09586995d2dd6d2c8cfd6fc0" - integrity sha512-ngR7yhNTjDxxe1VYmhqQqqXZWujGb6g0IoA4qeG6MxNGRnIw2Zo8ImY8HfaQ7l3T6GklWhdNfyhWk0C0iocdVA== + version "7.13.6" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.6.tgz#b7fea0fe5bb0ec92e78f2b5ed467a7bd30c53a84" + integrity sha512-wSbWQEOD7tk8zjRJVy41L85v+ctDk6AIv72hzVOyOhAeRSkzxKhamBP2jLPBYLYvLNgiJqa4gnpiYAIeedf/sA== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1110,9 +1131,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.12.18" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b" - integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg== + version "7.13.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.6.tgz#86e0fad6cbb46a680e21c1aa4748717a058d345a" + integrity sha512-Y/DEVhSQ91u27rxq7D0EH/sewS6+x06p/MgO1VppbDHMzYXLZrAR5cFjCom78e9RUw1BQAq6qJg6fXc/ep7glA== dependencies: regenerator-runtime "^0.13.4" @@ -1125,25 +1146,25 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.13", "@babel/traverse@^7.12.17", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.17.tgz#40ec8c7ffb502c4e54c7f95492dc11b88d718619" - integrity sha512-LGkTqDqdiwC6Q7fWSwQoas/oyiEYw6Hqjve5KOSykXkmFJFqzvGMb9niaUEag3Rlve492Mkye3gLw9FTv94fdQ== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" + integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.17" + "@babel/generator" "^7.13.0" "@babel/helper-function-name" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.12.17" - "@babel/types" "^7.12.17" + "@babel/parser" "^7.13.0" + "@babel/types" "^7.13.0" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.17.tgz#9d711eb807e0934c90b8b1ca0eb1f7230d150963" - integrity sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ== +"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.13.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" + integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== dependencies: "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" @@ -2935,6 +2956,30 @@ babel-plugin-named-asset-import@^0.3.6: resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.7.tgz#156cd55d3f1228a5765774340937afc8398067dd" integrity sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw== +babel-plugin-polyfill-corejs2@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.5.tgz#8fc4779965311393594a1b9ad3adefab3860c8fe" + integrity sha512-5IzdFIjYWqlOFVr/hMYUpc+5fbfuvJTAISwIY58jhH++ZtawtNlcJnxAixlk8ahVwHCz1ipW/kpXYliEBp66wg== + dependencies: + "@babel/compat-data" "^7.13.0" + "@babel/helper-define-polyfill-provider" "^0.1.2" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.4.tgz#2ae290200e953bade30907b7a3bebcb696e6c59d" + integrity sha512-ysSzFn/qM8bvcDAn4mC7pKk85Y5dVaoa9h4u0mHxOEpDzabsseONhUpR7kHxpUinfj1bjU7mUZqD23rMZBoeSg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.1.2" + core-js-compat "^3.8.1" + +babel-plugin-polyfill-regenerator@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.3.tgz#350f857225fc640ae1ec78d1536afcbb457db841" + integrity sha512-hRjTJQiOYt/wBKEc+8V8p9OJ9799blAJcuKzn1JXh3pApHoWl1Emxh2BHc6MC7Qt6bbr3uDpNxaYQnATLIudEg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.1.2" + babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" @@ -3099,9 +3144,9 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== bn.js@^5.0.0, bn.js@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" - integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== body-parser@1.19.0: version "1.19.0" @@ -4043,7 +4088,7 @@ copy-webpack-plugin@^4.6.0: p-limit "^1.0.0" serialize-javascript "^1.4.0" -core-js-compat@^3.6.2, core-js-compat@^3.8.0: +core-js-compat@^3.6.2, core-js-compat@^3.8.1, core-js-compat@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.9.0.tgz#29da39385f16b71e1915565aa0385c4e0963ad56" integrity sha512-YK6fwFjCOKWwGnjFUR3c544YsnA/7DoLL0ysncuOJ4pwbriAtOpvM2bygdlcXbvQCQZ7bBU9CL4t7tGl7ETRpQ== @@ -4888,9 +4933,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.671" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.671.tgz#8feaed6eae42d279fa4611f58c42a5a1eb81b2a0" - integrity sha512-RTD97QkdrJKaKwRv9h/wGAaoR2lGxNXEcBXS31vjitgTPwTWAbLdS7cEsBK68eEQy7p6YyT8D5BxBEYHu2SuwQ== + version "1.3.672" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz#3a6e335016dab4bc584d5292adc4f98f54541f6a" + integrity sha512-gFQe7HBb0lbOMqK2GAS5/1F+B0IMdYiAgB9OT/w1F4M7lgJK2aNOMNOM622aEax+nS1cTMytkiT0uMOkbtFmHw== elliptic@^6.5.3: version "6.5.4" @@ -5151,9 +5196,9 @@ eslint-plugin-flowtype@4.6.0: lodash "^4.17.15" eslint-plugin-flowtype@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.2.tgz#c6e5dd2fad4e757a1c63e652da6cff597659554f" - integrity sha512-C4PlPYpszr9h1cBfUbTNRI1IdxUCF0qrXAHkXS2+bESp7WUUCnvb3UBBnYlaQLvJYJ2lRz+2SPQQ/WyV7p/Tow== + version "5.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.3.0.tgz#5cd1f222633294444d695202e3322ce0262f5a41" + integrity sha512-QMA0+QXL+5bXM91T6qeO1yriEL79a6spXs1VUWk9IwExiNxl3AV8OFS8H4gsfYM54tIzMbF6qt8Z6J02r37ABw== dependencies: lodash "^4.17.15" string-natural-compare "^3.0.1" @@ -6054,7 +6099,7 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gensync@^1.0.0-beta.1: +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -8696,6 +8741,11 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -9369,9 +9419,9 @@ node-notifier@^8.0.0: which "^2.0.2" node-releases@^1.1.29, node-releases@^1.1.52, node-releases@^1.1.70: - version "1.1.70" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" - integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -9542,13 +9592,13 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.1.0, object.values@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731" - integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag== + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" + integrity sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.18.0-next.2" has "^1.0.3" obuf@^1.0.0, obuf@^1.1.2: @@ -11796,7 +11846,7 @@ resolve@1.15.0: dependencies: path-parse "^1.0.6" -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2, resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2, resolve@^1.8.1: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -12056,7 +12106,7 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@6.3.0, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -12655,19 +12705,19 @@ string.prototype.matchall@^4.0.2: side-channel "^1.0.4" string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" - integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" string.prototype.trimstart@^1.0.1, string.prototype.trimstart@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" - integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" string_decoder@^1.0.0, string_decoder@^1.1.1: From 0a2e04c85152cc69c07de04a521e9847358d923d Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Fri, 26 Feb 2021 14:28:45 +1300 Subject: [PATCH 13/16] Get general link check regex working; ok now except for cross-origin problem --- package.json | 2 +- src/core/notes-links-check.js | 70 ++++++++++++++++++++++------------ yarn.lock | 72 +++++++++++++++++------------------ 3 files changed, 82 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index 3d873f406..789aba7e7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha8", + "version": "2.0.0_alpha9", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index 8adb32ec1..529b874ac 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -8,13 +8,13 @@ import { userLog, debugLog, functionLog, parameterAssert, logicAssert, dataAsser // import { consoleLogObject } from '../core/utilities'; -// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.9'; +// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.11'; // const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; -const GENERAL_LINK1_REGEX = new RegExp('\\[[^\\]]+?\\]\\([^\\)]+?\\)', 'g'); // [displayLink](URL) -const GENERAL_LINK2_REGEX = new RegExp('\\[\\[[^\\]]+?\\]\\]', 'g'); // [[combinedDisplayLink]] +const GENERAL_MARKDOWN_LINK1_REGEX = new RegExp('\\[[^\\]]+?\\]\\([^\\)]+?\\)', 'g'); // [displayLink](URL) +const GENERAL_MARKDOWN_LINK2_REGEX = new RegExp('\\[\\[[^\\]]+?\\]\\]', 'g'); // [[combinedDisplayLink]] const TA_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] const TA_FULL_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\(rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\)', 'g'); // [How to Translate Names](rc://en/ta/man/translate/translate-names) @@ -41,7 +41,7 @@ const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1, const TN_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})/([a-z][a-z0-9][a-z0-9][a-z0-9])\\)', 'g'); -const SIMPLE_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\((https?://[^\\)])\\)', 'g');// [ULT](https://something) +const SIMPLE_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\((https?://[^\\)]+?)\\)', 'g');// [ULT](https://something) const SIMPLE_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ "\\)]+?)\\)', 'g'); // ![alt](y) const TITLED_IMAGE_REGEX = new RegExp('!\\[([^\\]]*?)\\]\\(([^ \\)]+?) "([^"\\)]+?)"\\)', 'g'); // ![alt](link "title") @@ -260,9 +260,9 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g } // Find total regular (non-image) links - const linksList1 = fieldText.match(GENERAL_LINK1_REGEX) || []; // [[something]] + const linksList1 = fieldText.match(GENERAL_MARKDOWN_LINK1_REGEX) || []; // [[something]] // if (linksList1.length) debugLog(`linksList1 (${linksList1.length}) = ${JSON.stringify(linksList1)}`); - const linksList2 = fieldText.match(GENERAL_LINK2_REGEX) || []; // [display](link) + const linksList2 = fieldText.match(GENERAL_MARKDOWN_LINK2_REGEX) || []; // [display](link) // if (linksList2.length) debugLog(`linksList2 (${linksList2.length}) = ${JSON.stringify(linksList2)}`); const totalLinks1 = linksList1.length; const totalLinks2 = linksList2.length; @@ -297,7 +297,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); } if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 883, message: `Unable to find/load ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); else { // we got the content of the TW article if (twFileContent.length < 10) addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); @@ -527,7 +527,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g addNoticePartial({ priority: 882, message: `Error loading ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}: ${trcGCerror}` }); } if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); + addNoticePartial({ priority: 883, message: `Unable to find/load ${fieldName} TW link`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); else { // we got the content of the TW article if (twFileContent.length < 10) addNoticePartial({ priority: 881, message: `Linked ${fieldName} TW article seems empty`, excerpt: totalLink, location: `${ourLocation} ${filepath}` }); @@ -1071,29 +1071,47 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g } // Check for simple display links like [ULT](https://something) + // if (fieldText.indexOf('http') !== -1) debugLog(`Checking for http links in '${fieldName}' '${fieldText}'`); while ((regexResultArray = SIMPLE_DISPLAY_LINK_REGEX.exec(fieldText))) { - debugLog(` checkNotesLinksToOutside SIMPLE_DISPLAY_LINK_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); + // debugLog(` checkNotesLinksToOutside SIMPLE_DISPLAY_LINK_REGEX regexResultArray(${regexResultArray.length})=${JSON.stringify(regexResultArray)}`); generalLinkCount1 += 1; - parameterAssert(regexResultArray.length === 2, `SIMPLE_DISPLAY_LINK_REGEX expected 2 fields (not ${regexResultArray.length})`); + parameterAssert(regexResultArray.length === 3, `SIMPLE_DISPLAY_LINK_REGEX expected 3 fields (not ${regexResultArray.length})`); // eslint-disable-next-line no-unused-vars let [totalLink, displayText, uri] = regexResultArray; processedLinkList.push(totalLink); // Save the full link if (!checkingOptions?.disableAllLinkFetchingFlag) { - let generalFileContent; - try { - generalFileContent = await cachedGetFileUsingFullURL({ uri }); - debugLog(`${displayText} ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); - } catch (trcGCerror) { - console.error(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load general ${uri}`); - addNoticePartial({ priority: 882, message: `Error loading ${fieldName} general link`, excerpt: totalLink, location: `${ourLocation} ${uri}: ${trcGCerror}` }); - } - if (!generalFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} general link`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); - else { // we got the content of the general article - if (generalFileContent.length < 10) - addNoticePartial({ priority: 881, message: `Linked ${fieldName} general article seems empty`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); + const dummyPathParameters = { username: uri, repository: '', path: '', branch: '' }; + if (await alreadyChecked(dummyPathParameters) !== true) { + // debugLog(`checkNotesLinksToOutside general link check needs to check: ${uri}`); + + let generalFileContent, hadError = false; + try { + // generalFileContent = await cachedGetFileUsingFullURL({ uri }); + // debugLog(`${displayText} ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); + const response = await fetch(uri); + if (response.ok) {// if HTTP-status is 200-299 + generalFileContent = await response.text(); + // debugLog(`General link ${displayText} @ ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); + } else throw new Error(`Our Network error: ${response.statusCode}`); + } catch (trcGCerror) { + // debugLog(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load general ${uri}: ${trcGCerror}`); + // TODO: Put back up to 882 if we can solve cross-origin problems + addNoticePartial({ priority: 82, message: `Error loading ${fieldName} general link`, details: "please double-check link—there may be no problem", excerpt: totalLink, location: `${ourLocation} ${uri}: ${trcGCerror}` }); + hadError = true; + } + if (!hadError && !generalFileContent) + addNoticePartial({ priority: 883, message: `Unable to find/load ${fieldName} general link`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); + else if (generalFileContent) { // we got the content of the general article + if (generalFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked ${fieldName} general article seems empty`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); + } + await markAsChecked(dummyPathParameters); // don’t bother waiting for the result } + // else debugLog(`Had already checked '${displayText}' ${uri}`); + + if (uri.startsWith('http:')) + addNoticePartial({ priority: 152, message: "Should http link be https", excerpt: totalLink, location: ourLocation }); } } @@ -1102,14 +1120,16 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g const linkCount1 = thisChapterBibleLinkCount1 + thisVerseBibleLinkCount1 + thisBookBibleLinkCount1 + otherBookBibleLinkCount1 + TNLinkCount1 + twLinkCount1 + taLinkCount1 + generalLinkCount1; if (totalLinks1 > linkCount1) { const leftoverLinksList1 = linksList1.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above - if (leftoverLinksList1.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); + // if (leftoverLinksList1.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}\n linksList1(${linksList1.length})=${JSON.stringify(linksList1)}\nleftoverLinksList1(${leftoverLinksList1.length})=${JSON.stringify(leftoverLinksList1)}`); + // if (leftoverLinksList1.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' leftoverLinksList1 (${leftoverLinksList1.length}) = ${JSON.stringify(leftoverLinksList1)}`); addNoticePartial({ priority: 648, message: "Unusual [ ]( ) link(s)—not a recognized Bible or TA, TN, or TW link", details: `need to carefully check ${leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)}`, location: ourLocation }); } const linkCount2 = twLinkCount2 + taLinkCount2; // These are double-bracketed links, e.g., [[something]] // debugLog(`twLinkCount2 ${twLinkCount2} + taLinkCount2 ${taLinkCount2} = linkCount2 ${linkCount2}`); if (totalLinks2 > linkCount2) { const leftoverLinksList2 = linksList2.filter(x => !processedLinkList.includes(x)); // Delete links that we processed above - if (leftoverLinksList2.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); + // if (leftoverLinksList2.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' processedLinkList (${processedLinkList.length}) = ${JSON.stringify(processedLinkList)}\n linksList2(${linksList2.length})=${JSON.stringify(linksList2)}\nleftoverLinksList2(${leftoverLinksList2.length})=${JSON.stringify(leftoverLinksList2)}`); + // if (leftoverLinksList2.length) debugLog(`'${languageCode}', ${repoCode}, '${bookID}', '${fieldName}' leftoverLinksList2 (${leftoverLinksList2.length}) = ${JSON.stringify(leftoverLinksList2)}`); addNoticePartial({ priority: 649, message: "Unusual [[ ]] link(s)—not a recognized TA or TW link", details: `need to carefully check ${leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)}`, location: ourLocation }); } diff --git a/yarn.lock b/yarn.lock index 087e809c0..c7c8879b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -862,9 +862,9 @@ semver "^5.5.1" "@babel/plugin-transform-runtime@^7.12.1": - version "7.13.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.6.tgz#c11c806f023d2065bbcc9b751702f4008245951c" - integrity sha512-QsTomUTIeOdYrNsOMJRSp2QzGvB1KYD4ePCC8Mei2SuoHScncYS3h1E9PR5gDL7buJmcqIHrWyH6B5GZMgDrRg== + version "7.13.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.7.tgz#a856b53681da9193d98dfb03d8192b0a3f4cdd8a" + integrity sha512-pXfYTTSbU5ThVTUyQ6TUdUkonZYKKq8M6vDUkFCjFw8vT42hhayrbJPVWGC7B97LkzFYBtdW/SBGVZtRaopW6Q== dependencies: "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" @@ -1116,9 +1116,9 @@ "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.12.1", "@babel/runtime-corejs3@^7.9.6": - version "7.13.6" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.6.tgz#b7fea0fe5bb0ec92e78f2b5ed467a7bd30c53a84" - integrity sha512-wSbWQEOD7tk8zjRJVy41L85v+ctDk6AIv72hzVOyOhAeRSkzxKhamBP2jLPBYLYvLNgiJqa4gnpiYAIeedf/sA== + version "7.13.7" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.7.tgz#f47f882b62961c1ada113dbafc717c69c18a9b09" + integrity sha512-zkDsGGSRU2YyYTXkPfcxuYuCVc6xBOeH1ZMh72ywBvmrDs+kSmoMuCUXZJUPbXZafrPivDHS2Oq7wI37gaTvqw== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1131,9 +1131,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.13.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.6.tgz#86e0fad6cbb46a680e21c1aa4748717a058d345a" - integrity sha512-Y/DEVhSQ91u27rxq7D0EH/sewS6+x06p/MgO1VppbDHMzYXLZrAR5cFjCom78e9RUw1BQAq6qJg6fXc/ep7glA== + version "7.13.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a" + integrity sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA== dependencies: regenerator-runtime "^0.13.4" @@ -2957,9 +2957,9 @@ babel-plugin-named-asset-import@^0.3.6: integrity sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw== babel-plugin-polyfill-corejs2@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.5.tgz#8fc4779965311393594a1b9ad3adefab3860c8fe" - integrity sha512-5IzdFIjYWqlOFVr/hMYUpc+5fbfuvJTAISwIY58jhH++ZtawtNlcJnxAixlk8ahVwHCz1ipW/kpXYliEBp66wg== + version "0.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.6.tgz#947a1227efa1a14ce09ac5fafc66ce8e039071e2" + integrity sha512-1PfghLDuzX5lFY6XXO0hrfxwYf0LD9YajMWeQBGNaPNLQ35paV7YB4hlFW+HfwFS5kcp4rtPI/237xLfQ1ah8A== dependencies: "@babel/compat-data" "^7.13.0" "@babel/helper-define-polyfill-provider" "^0.1.2" @@ -3139,9 +3139,9 @@ bluebird@^3.5.1, bluebird@^3.5.5: integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.11.9" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" - integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== bn.js@^5.0.0, bn.js@^5.1.1: version "5.2.0" @@ -3535,9 +3535,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: - version "1.0.30001191" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001191.tgz#bacb432b6701f690c8c5f7c680166b9a9f0843d9" - integrity sha512-xJJqzyd+7GCJXkcoBiQ1GuxEiOBCLQ0aVW9HMekifZsAVGdj5eJ4mFB9fEhSHipq9IOk/QXFJUiIr9lZT+EsGw== + version "1.0.30001192" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz#b848ebc0ab230cf313d194a4775a30155d50ae40" + integrity sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw== canvg@^3.0.6: version "3.0.7" @@ -3898,9 +3898,9 @@ color@^3.0.0: color-string "^1.5.4" colorette@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" - integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== colors@~0.6.0-1: version "0.6.2" @@ -4471,14 +4471,14 @@ cssstyle@^2.2.0: cssom "~0.3.6" csstype@^2.5.2: - version "2.6.15" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.15.tgz#655901663db1d652f10cb57ac6af5a05972aea1f" - integrity sha512-FNeiVKudquehtR3t9TRRnsHL+lJhuHF5Zn9dt01jpojlurLEPDhhEtUkWmAUJ7/fOLaLG4dCDEnUsR0N1rZSsg== + version "2.6.16" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.16.tgz#544d69f547013b85a40d15bff75db38f34fe9c39" + integrity sha512-61FBWoDHp/gRtsoDkq/B1nWrCUG/ok1E3tUrcNbZjsE9Cxd9yzUirjS3+nAATB8U4cTtaQmAHbNndoFz5L6C9Q== csstype@^3.0.2: - version "3.0.6" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.6.tgz#865d0b5833d7d8d40f4e5b8a6d76aea3de4725ef" - integrity sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw== + version "3.0.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" + integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g== cyclist@^1.0.1: version "1.0.1" @@ -4933,9 +4933,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.672" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz#3a6e335016dab4bc584d5292adc4f98f54541f6a" - integrity sha512-gFQe7HBb0lbOMqK2GAS5/1F+B0IMdYiAgB9OT/w1F4M7lgJK2aNOMNOM622aEax+nS1cTMytkiT0uMOkbtFmHw== + version "1.3.674" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.674.tgz#d97feefdf1d9411fdc9d56d17e1b9d67b818e710" + integrity sha512-DBmEKRVYLZAoQSW+AmLcTF5Bpwhk4RUkobtzXVDlfPPYIlbsH3Jfg3QbBjAfFcRARzMIo4YiMhp3N+RnMuo1Eg== elliptic@^6.5.3: version "6.5.4" @@ -5196,9 +5196,9 @@ eslint-plugin-flowtype@4.6.0: lodash "^4.17.15" eslint-plugin-flowtype@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.3.0.tgz#5cd1f222633294444d695202e3322ce0262f5a41" - integrity sha512-QMA0+QXL+5bXM91T6qeO1yriEL79a6spXs1VUWk9IwExiNxl3AV8OFS8H4gsfYM54tIzMbF6qt8Z6J02r37ABw== + version "5.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.3.1.tgz#df6227e28c61d967b825c1327a27818bbb2ad325" + integrity sha512-mziJD+zw+VTwLtF9qLIxYac0GJCbSEDyqMLP5ENzQeNY5EOxbAfitMFLo+UItjYOISQdh1BCobwE2d4i1o+9Rw== dependencies: lodash "^4.17.15" string-natural-compare "^3.0.1" @@ -11967,9 +11967,9 @@ run-queue@^1.0.0, run-queue@^1.0.3: aproba "^1.1.1" rxjs@^6.4.0, rxjs@^6.5.3, rxjs@^6.6.0: - version "6.6.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" - integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== + version "6.6.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70" + integrity sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg== dependencies: tslib "^1.9.0" From 3f7a589f5bf9435a78f001a0613da03c064006bc Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Mon, 1 Mar 2021 18:44:21 +1300 Subject: [PATCH 14/16] All demo functions working again now --- package.json | 2 +- src/core/field-link-check.js | 9 +- src/core/field-link-check.md | 3 +- src/core/manifest-text-check.md | 8 +- src/core/markdown-file-contents-check.js | 6 +- src/core/markdown-text-check.md | 6 +- src/core/notes-links-check.js | 57 ++-- src/core/notes-tsv7-row-check.md | 6 +- src/core/notes-tsv7-table-check.md | 6 +- src/core/questions-tsv7-row-check.js | 13 +- src/core/questions-tsv7-row-check.md | 8 +- src/core/questions-tsv7-table-check.md | 8 +- src/core/tn-tsv9-row-check.js | 10 +- src/core/tn-tsv9-row-check.md | 6 +- src/core/tn-tsv9-table-check.md | 6 +- src/core/twl-tsv6-row-check.js | 4 +- src/core/twl-tsv6-row-check.md | 35 ++- src/core/twl-tsv6-table-check.md | 8 +- src/core/usfm-text-check.js | 4 +- src/core/usfm-text-check.md | 3 +- src/core/yaml-text-check.md | 2 +- src/demos/RenderProcessedResults.js | 4 +- yarn.lock | 318 ++++++++++++----------- 23 files changed, 270 insertions(+), 262 deletions(-) diff --git a/package.json b/package.json index 789aba7e7..ac3c6892d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha9", + "version": "2.0.0_alpha10", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/core/field-link-check.js b/src/core/field-link-check.js index 49d204236..d872c0d2c 100644 --- a/src/core/field-link-check.js +++ b/src/core/field-link-check.js @@ -1,4 +1,4 @@ -// import { checkTextField } from './field-text-check' +import { checkTextField } from './field-text-check' import { cachedGetFileUsingFullURL } from './getApi'; import { userLog, parameterAssert } from './utilities'; @@ -60,10 +60,12 @@ export async function startLiveLinksCheck(linksList, existingNoticeList, callbac * @param {string} optionalFieldLocation * @param {Object} checkingOptions */ -/* export function checkFieldLinks(languageCode, repoCode, fieldName, fieldText, linkOptions, optionalFieldLocation, checkingOptions) { // Does basic checks for fields that are links or that contain links + // NOTE: This function is currently only called from field-link-check.md!!! + // TODO: Does it need to be deleted (or finished) ??? + // We assume that checking for compulsory fields is done elsewhere // Returns an error list and a warning list @@ -72,7 +74,7 @@ export function checkFieldLinks(languageCode, repoCode, fieldName, fieldText, li // 2/ the detailed location string // (Returned in this way for more intelligent processing at a higher level) - userLog(`checkFieldLinks('${fieldName}', '${fieldText}')…`); + userLog(`checkFieldLinks('${languageCode}', '${repoCode}', '${fieldName}', '${fieldText}', ${JSON.stringify(linkOptions)}, '${optionalFieldLocation}', ${JSON.stringify(checkingOptions)})…`); // debugLog( "linkOptions", JSON.stringify(linkOptions)); // debugLog( "linkOptionsEC", linkOptions.expectedCount); parameterAssert(languageCode !== undefined, "checkFieldLinks: 'languageCode' parameter should be defined"); @@ -172,4 +174,3 @@ export function checkFieldLinks(languageCode, repoCode, fieldName, fieldText, li return result; } // end of checkFieldLinks function -*/ diff --git a/src/core/field-link-check.md b/src/core/field-link-check.md index 60044b7bf..c141672a5 100644 --- a/src/core/field-link-check.md +++ b/src/core/field-link-check.md @@ -9,6 +9,7 @@ This function is for checking text fields that are links, or that contain links. import { checkFieldLinks } from './field-link-check'; import { processNoticesToErrorsWarnings } from '../demos/notice-processing-functions'; import { RenderLines, RenderRawResults, RenderSuccessesErrorsWarnings } from '../demos/RenderProcessedResults'; +import { userLog } from './utilities'; // Empty, space, link, RC, good, and bad text samples const textE = ""; @@ -48,7 +49,7 @@ const linkOptions = { // This function returns the results of the fast checks // and if specified in linkOptions, the callback will update result later with results of slower checks -rawResults = checkFieldLinks(chosenTextName, chosenText, linkOptions, 'that was supplied'); +rawResults = checkFieldLinks('en', '', chosenTextName, chosenText, linkOptions, 'that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic link checks"]; diff --git a/src/core/manifest-text-check.md b/src/core/manifest-text-check.md index 2fd74b040..6157b0657 100644 --- a/src/core/manifest-text-check.md +++ b/src/core/manifest-text-check.md @@ -223,7 +223,7 @@ const data = { givenLocation : "that was supplied", } -function CheckManifestText(props) { +function OurCheckManifestText(props) { const { languageCode, chosenText, chosenTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -236,7 +236,7 @@ function CheckManifestText(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {chosenTextName}…</p>); const checkingOptions = {}; - const rawResults = await checkManifestText('', '', '', chosenText, 'in manifest data that was supplied', checkingOptions); + const rawResults = await checkManifestText('en', 'LT', 'unfoldingWord', 'en_ult', 'master', chosenText, 'in manifest data that was supplied', checkingOptions); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done manifest text checks"]; setResults( @@ -250,7 +250,7 @@ function CheckManifestText(props) { }, []); // end of useEffect part return results; -} // end of CheckManifestText function +} // end of OurCheckManifestText function -<CheckManifestText data={data}/> +<OurCheckManifestText data={data}/> ``` diff --git a/src/core/markdown-file-contents-check.js b/src/core/markdown-file-contents-check.js index 6c4820fa5..402871f75 100644 --- a/src/core/markdown-file-contents-check.js +++ b/src/core/markdown-file-contents-check.js @@ -5,13 +5,13 @@ import { checkTextfileContents } from './file-text-check'; import { userLog, functionLog, debugLog, parameterAssert } from './utilities'; -const MARKDOWN_FILE_VALIDATOR_VERSION_STRING = '0.4.0'; +const MARKDOWN_FILE_VALIDATOR_VERSION_STRING = '0.4.1'; /** * * @param {string} languageCode - * @param {string} repoCode -- e.g., 'TW' or 'TQ', etc. + * @param {string} repoCode -- e.g., 'TW', 'TA', or 'TQ', etc. * @param {string} markdownFilename -- used for identification * @param {string} markdownText -- the actual text to be checked * @param {string} givenLocation @@ -25,7 +25,7 @@ export async function checkMarkdownFileContents(languageCode, repoCode, markdown // functionLog(`checkMarkdownFileContents(${languageCode}, ${repoCode}, ${markdownFilename}, ${markdownText.length}, ${givenLocation})…`); parameterAssert(languageCode !== undefined, "checkMarkdownFileContents: 'languageCode' parameter should be defined"); parameterAssert(typeof languageCode === 'string', `checkMarkdownFileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); - parameterAssert(repoCode === 'TW' || repoCode === 'TQ', `checkMarkdownFileContents: 'repoCode' parameter should be a 'TW' or 'TQ' not '${repoCode}'`); + parameterAssert(repoCode === 'TW' || repoCode === 'TA' || repoCode === 'TQ', `checkMarkdownFileContents: 'repoCode' parameter should be a 'TW', 'TA', or 'TQ' not '${repoCode}'`); parameterAssert(markdownFilename !== undefined, "checkMarkdownFileContents: 'markdownFilename' parameter should be defined"); parameterAssert(typeof markdownFilename === 'string', `checkMarkdownFileContents: 'markdownFilename' parameter should be a string not a '${typeof markdownFilename}': ${markdownFilename}`); parameterAssert(markdownText !== undefined, "checkMarkdownFileContents: 'markdownText' parameter should be defined"); diff --git a/src/core/markdown-text-check.md b/src/core/markdown-text-check.md index 0b27c9d06..d5f4d8069 100644 --- a/src/core/markdown-text-check.md +++ b/src/core/markdown-text-check.md @@ -48,7 +48,7 @@ const data = { givenLocation : "that was supplied", } -function CheckMarkdownText(props) { +function OurCheckMarkdownText(props) { const { languageCode, repoCode, chosenText, chosenTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -74,7 +74,7 @@ function CheckMarkdownText(props) { }, []); // end of useEffect part return results; -} // end of CheckMarkdownText function +} // end of OurCheckMarkdownText function -<CheckMarkdownText data={data}/> +<OurCheckMarkdownText data={data}/> ``` diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index 529b874ac..6f3448545 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -8,7 +8,7 @@ import { userLog, debugLog, functionLog, parameterAssert, logicAssert, dataAsser // import { consoleLogObject } from '../core/utilities'; -// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.11'; +// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.12'; // const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; @@ -37,7 +37,7 @@ const THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})\\]\\(\\ const THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})[–-](\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g');// [2–7](../09/2.md) NOTE en-dash const BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})[–-](\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); // [Genesis 26:12-14](./12.md) NOTE en-dash -const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\(rc://([^ /]+?)/tn/help/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\)', 'g'); // [Genesis 29:23](rc://en/tn/help/gen/29/23) +const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})(?:-\\d{1,3})\\]\\(rc://([^ /]+?)/tn/help/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\)', 'g'); // [Genesis 29:23-24](rc://en/tn/help/gen/29/23) const TN_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})/([a-z][a-z0-9][a-z0-9][a-z0-9])\\)', 'g'); @@ -1085,28 +1085,39 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g if (await alreadyChecked(dummyPathParameters) !== true) { // debugLog(`checkNotesLinksToOutside general link check needs to check: ${uri}`); - let generalFileContent, hadError = false; - try { - // generalFileContent = await cachedGetFileUsingFullURL({ uri }); - // debugLog(`${displayText} ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); - const response = await fetch(uri); - if (response.ok) {// if HTTP-status is 200-299 - generalFileContent = await response.text(); - // debugLog(`General link ${displayText} @ ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); - } else throw new Error(`Our Network error: ${response.statusCode}`); - } catch (trcGCerror) { - // debugLog(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load general ${uri}: ${trcGCerror}`); - // TODO: Put back up to 882 if we can solve cross-origin problems - addNoticePartial({ priority: 82, message: `Error loading ${fieldName} general link`, details: "please double-check link—there may be no problem", excerpt: totalLink, location: `${ourLocation} ${uri}: ${trcGCerror}` }); - hadError = true; - } - if (!hadError && !generalFileContent) - addNoticePartial({ priority: 883, message: `Unable to find/load ${fieldName} general link`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); - else if (generalFileContent) { // we got the content of the general article - if (generalFileContent.length < 10) - addNoticePartial({ priority: 881, message: `Linked ${fieldName} general article seems empty`, excerpt: totalLink, location: `${ourLocation} ${uri}` }); + // TODO: Uncomment this block and get it working better + if (false) // don't try to fetch general links + addNoticePartial({ priority: 32, message: `Untested general link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation }); + else { // Try to fetch general links + let generalFileContent, hadError = false; + try { + // generalFileContent = await cachedGetFileUsingFullURL({ uri }); + // debugLog(`${displayText} ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); + // const serverString = uri.replace('://','!!!').split('/')[0].replace('!!!','://'); // Get the bit before any forward slashes + // debugLog(`uri='${uri}', serverString='${serverString}'`); + // NOTE: The following line (with or without the mode) doesn't help -- actually makes things slightly worse + // const response = await fetch(uri, {headers:{'Access-Control-Allow-Origin': serverString}}); + // const response = await fetch(uri, {mode: 'cors'}); + // const response = await fetch(uri, {mode: 'cors', headers:{'Access-Control-Allow-Origin': serverString}}); + const response = await fetch(uri); + if (response.ok) {// if HTTP-status is 200-299 + generalFileContent = await response.text(); + // debugLog(`General link ${displayText} @ ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); + } else throw new Error(`Our Network error: ${response.statusCode}`); + } catch (trcGCerror) { + // debugLog(`checkNotesLinksToOutside(${bookID}, ${fieldName}, …) failed to load general ${uri}: ${trcGCerror}`); + // TODO: Put back up to 882 if we can solve cross-origin problems + addNoticePartial({ priority: 82, message: `Error loading general link`, details: "please double-check link—there may be no problem", excerpt: totalLink, location: `${ourLocation}: ${trcGCerror}` }); + hadError = true; + } + if (!hadError && !generalFileContent) + addNoticePartial({ priority: 883, message: `Unable to find/load general link`, excerpt: totalLink, location: ourLocation }); + else if (generalFileContent) { // we got the content of the general article + if (generalFileContent.length < 10) + addNoticePartial({ priority: 881, message: `Linked general article seems empty`, excerpt: totalLink, location: ourLocation }); + } } - await markAsChecked(dummyPathParameters); // don’t bother waiting for the result + await markAsChecked(dummyPathParameters); // don’t bother waiting for the result of this async call } // else debugLog(`Had already checked '${displayText}' ${uri}`); diff --git a/src/core/notes-tsv7-row-check.md b/src/core/notes-tsv7-row-check.md index 6148f9f7b..1e11db56a 100644 --- a/src/core/notes-tsv7-row-check.md +++ b/src/core/notes-tsv7-row-check.md @@ -50,7 +50,7 @@ const data = { givenLocation : 'that was supplied', } -function CheckNotesRow(props) { +function OurCheckNotesRow(props) { const { languageCode, repoCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -74,7 +74,7 @@ function CheckNotesRow(props) { }, []); // end of useEffect part return results; -} // end of CheckNotesRow function +} // end of OurCheckNotesRow function -<CheckNotesRow data={data}/> +<OurCheckNotesRow data={data}/> ``` diff --git a/src/core/notes-tsv7-table-check.md b/src/core/notes-tsv7-table-check.md index d97ee5ce0..2fa52c986 100644 --- a/src/core/notes-tsv7-table-check.md +++ b/src/core/notes-tsv7-table-check.md @@ -48,7 +48,7 @@ const data = { givenLocation : 'that was supplied', } -function CheckNotesTSV7Table(props) { +function OurCheckNotesTSV7Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -72,7 +72,7 @@ function CheckNotesTSV7Table(props) { }, []); // end of useEffect part return results; -} // end of CheckNotesTSV7Table function +} // end of OurCheckNotesTSV7Table function -<CheckNotesTSV7Table data={data}/> +<OurCheckNotesTSV7Table data={data}/> ``` diff --git a/src/core/questions-tsv7-row-check.js b/src/core/questions-tsv7-row-check.js index fdb67f4b2..d24b76b44 100644 --- a/src/core/questions-tsv7-row-check.js +++ b/src/core/questions-tsv7-row-check.js @@ -20,9 +20,9 @@ const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz012345678 /** * - * @description - Checks one TSV data row of translation notes (TN2) + * @description - Checks one TSV data row of translation notes (TQ2) * @param {string} languageCode - the language code, e.g., 'en' - * @param {string} repoCode - TN2, TQ2, TWL, SN, or SQ -- allows more specific checks + * @param {string} repoCode - 'TQ2' or 'SQ' * @param {string} line - the TSV line to be checked * @param {string} bookID - 3-character UPPERCASE USFM book identifier or 'OBS' * @param {string} givenC - chapter number or (for OBS) story number string @@ -35,8 +35,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo /* This function is only for checking one data row and the function doesn’t assume that it has any previous context. - TN2, TQ2, TWL, SN, or SQ - being translation or study notes, questions, or word-links. + TQ2 being translation or study questions. bookID is a three-character UPPERCASE USFM book identifier or 'OBS' so givenC and givenV are usually chapter number and verse number @@ -413,7 +412,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); } else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (repoCode === 'TN2' && V !== 'intro' && occurrence !== '0') + if (repoCode === 'TQ2' && V !== 'intro' && occurrence !== '0') addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); if (occurrence.length) { // This should usually be a digit @@ -459,7 +458,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo } } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (repoCode === 'TN2') + if (repoCode === 'TQ2') addNoticePartial({ priority: 274, message: "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation }); if (response.length) { @@ -484,7 +483,7 @@ export async function checkQuestionsTSV7DataRow(languageCode, repoCode, line, bo } } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (repoCode === 'TN2') + if (repoCode === 'TQ2') addNoticePartial({ priority: 274, message: "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation }); // 7 [reference, rowID, tags, question, answer] diff --git a/src/core/questions-tsv7-row-check.md b/src/core/questions-tsv7-row-check.md index f3e047483..b1a85ea36 100644 --- a/src/core/questions-tsv7-row-check.md +++ b/src/core/questions-tsv7-row-check.md @@ -43,14 +43,14 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - repoCode: 'TN2', + repoCode: 'TQ2', tableLineName : 'lineA9', tableLine : lineA9, bookID : 'GEN', C:'1', V:'2', givenLocation : 'that was supplied', } -function CheckQuestionsRow(props) { +function OurCheckQuestionsRow(props) { const { languageCode, repoCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -74,7 +74,7 @@ function CheckQuestionsRow(props) { }, []); // end of useEffect part return results; -} // end of CheckQuestionsRow function +} // end of OurCheckQuestionsRow function -<CheckQuestionsRow data={data}/> +<OurCheckQuestionsRow data={data}/> ``` diff --git a/src/core/questions-tsv7-table-check.md b/src/core/questions-tsv7-table-check.md index fae77af12..8f75a4146 100644 --- a/src/core/questions-tsv7-table-check.md +++ b/src/core/questions-tsv7-table-check.md @@ -40,7 +40,7 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - repoCode: 'TN2', + repoCode: 'TQ2', tableTextName : 'textG', tableText : textG, bookID : 'GEN', @@ -48,7 +48,7 @@ const data = { givenLocation : 'that was supplied', } -function CheckQuestionsTSV7Table(props) { +function OurCheckQuestionsTSV7Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -72,7 +72,7 @@ function CheckQuestionsTSV7Table(props) { }, []); // end of useEffect part return results; -} // end of CheckQuestionsTSV7Table function +} // end of OurCheckQuestionsTSV7Table function -<CheckQuestionsTSV7Table data={data}/> +<OurCheckQuestionsTSV7Table data={data}/> ``` diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index ea5b0022c..2cc8f41c2 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -22,7 +22,7 @@ const TA_REGEX = new RegExp('\\[\\[rc://[^ /]+?/ta/man/[^ /]+?/([^ \\]]+?)\\]\\] /** * - * @description - Checks one TSV data row of translation notes (TN2) + * @description - Checks one TSV data row of translation notes (TN) * @param {string} languageCode - the language code, e.g., 'en' * @param {string} repoCode - 'TN' * @param {string} line - the TSV line to be checked @@ -306,7 +306,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // // process results line by line // for (const coqNoticeEntry of coqResultObject.noticeList) { - // if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check + // if (coqNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN check // drResult.noticeList.push(coqNoticeEntry); // Just copy the complete notice as is // else // For our direct checks, we add the repoCode as an extra value // addNoticePartial({ ...coqNoticeEntry, rowID, fieldName }); @@ -450,7 +450,7 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, addNoticePartial({ priority: 173, message: "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation }); } - if (supportReference.length) { // need to check TN2 against TA + if (supportReference.length) { // need to check TN against TA if (isWhitespace(supportReference)) addNoticePartial({ priority: 373, message: "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation }); else { // More than just whitespace @@ -549,8 +549,8 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, // 9 [B, C, V, rowID, supportReference, quote, occurrence, GLQuote, occurrenceNote] const suggestion = `${B}\t${C}\t${V}\t${RIDSuggestion === undefined ? rowID : RIDSuggestion}\t${SRSuggestion === undefined ? supportReference : SRSuggestion}\t${OQSuggestion === undefined ? quote : OQSuggestion}\t${OSuggestion === undefined ? occurrence : OSuggestion}\t${GLQSuggestion === undefined ? GLQuote : GLQSuggestion}\t${ONSuggestion === undefined ? occurrenceNote : ONSuggestion}`; if (suggestion !== line) { - // debugLog(`Had TN2 ${line}`); - // debugLog(`Sug TN2 ${suggestion}`); + // debugLog(`Had TN ${line}`); + // debugLog(`Sug TN ${suggestion}`); drResult.suggestion = suggestion; } diff --git a/src/core/tn-tsv9-row-check.md b/src/core/tn-tsv9-row-check.md index ad9c0db08..700f1fe35 100644 --- a/src/core/tn-tsv9-row-check.md +++ b/src/core/tn-tsv9-row-check.md @@ -49,7 +49,7 @@ const data = { givenLocation : "that was supplied", } -function CheckTNTSVRow(props) { +function OurCheckTNTSVRow(props) { const { languageCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -73,7 +73,7 @@ function CheckTNTSVRow(props) { }, []); // end of useEffect part return results; -} // end of CheckTNTSVRow function +} // end of OurCheckTNTSVRow function -<CheckTNTSVRow data={data}/> +<OurCheckTNTSVRow data={data}/> ``` diff --git a/src/core/tn-tsv9-table-check.md b/src/core/tn-tsv9-table-check.md index 0c08c2a55..68b3a9a88 100644 --- a/src/core/tn-tsv9-table-check.md +++ b/src/core/tn-tsv9-table-check.md @@ -47,7 +47,7 @@ const data = { givenLocation : 'that was supplied', } -function checkTN_TSV9Table(props) { +function OurCheckTN_TSV9Table(props) { const { languageCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -71,7 +71,7 @@ function checkTN_TSV9Table(props) { }, []); // end of useEffect part return results; -} // end of checkTN_TSV9Table function +} // end of OurCheckTN_TSV9Table function -<checkTN_TSV9Table data={data}/> +<OurCheckTN_TSV9Table data={data}/> ``` diff --git a/src/core/twl-tsv6-row-check.js b/src/core/twl-tsv6-row-check.js index 5f53449b4..141ec98c4 100644 --- a/src/core/twl-tsv6-row-check.js +++ b/src/core/twl-tsv6-row-check.js @@ -20,7 +20,7 @@ const LC_ALPHABET_PLUS_DIGITS_PLUS_HYPHEN = 'abcdefghijklmnopqrstuvwxyz012345678 /** * - * @description - Checks one TSV data row of translation notes (TN2) + * @description - Checks one TSV data row of translation word links (TWL) * @param {string} languageCode - the language code, e.g., 'en' * @param {string} repoCode - 'TWL' -- keeps parameter set consistent with other similar functions * @param {string} line - the TSV line to be checked @@ -358,7 +358,7 @@ export async function checkTWL_TSV6DataRow(languageCode, repoCode, line, bookID, addNoticePartial({ priority: 750, message: "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation }); } else // TODO: Find more details about when these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (repoCode === 'TN2' && V !== 'intro' && occurrence !== '0') + if (repoCode === 'TWL' && V !== 'intro' && occurrence !== '0') addNoticePartial({ priority: 919, message: "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation }); if (occurrence.length) { // This should usually be a digit diff --git a/src/core/twl-tsv6-row-check.md b/src/core/twl-tsv6-row-check.md index df50bb16b..58a8a705c 100644 --- a/src/core/twl-tsv6-row-check.md +++ b/src/core/twl-tsv6-row-check.md @@ -11,7 +11,7 @@ These raw notice components can then be filtered and/or sorted as required by th // Simply click inside here and add, change, or delete text as required. import React, { useState, useEffect } from 'react'; -import { checkTWL_TSV7DataRow } from './twl-tsv6-row-check'; +import { checkTWL_TSV6DataRow } from './twl-tsv6-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, Header, Nonsense, Good, Bad, Very bad, and Actual line samples @@ -29,33 +29,28 @@ const lineB7 = "2:3\tw3r5\t\t17\t\tNote7"; const lineB8 = "2:3\tw3r5\t\t1\tBad ellipse...\tNote8"; const lineB9 = "2:3\tw3r\t\t1\t\t<br>Boo hoo,, lost my shoe !"; const lineV = "200:9\tW-3r5\tLaugh\t\t17\tBad ellipse...\t<br>Boo hoo,,<br> lost my shoe !"; -const lineA1 = "front:intro\td9wn\t\t\t0\t\t# Introduction to Genesis<br><br>## Part 1: General Introduction<br><br>### Outline of Genesis<br><br>1. From the Creation to the Tower of Babel<br>- The account of the creation of the heavens and the earth (1:1–4:26)<br>- The account of Adam (5:1–6:8)<br>- The account of Noah (6:9–11:9)<br>- The account of Shem (11:10–11:26)<br>- The account of Terah (11:27–11:32)<br>1. The accounts of the Patriarchs<br>- The account of Abraham (12:1-25:11)<br>- The account of Ishmael (25:12–25:18)<br>- The account of Isaac, focusing on Jacob (25:19–35:29)<br>- The account of Esau (36:1–37:1)<br>- The account of Jacob, focusing on Joseph (37:2–50:26)<br><br>### What is Genesis about?<br><br>Genesis begins with the early years of creation. It tells about God creating heaven, earth, and the first humans. It also tells about the first time humans sinned. This caused humans to be separated from God and to eventually die. Genesis 1-11 briefly tells about other important events that occurred over many hundreds of years. (See: [[rc://en/tw/dict/bible/kt/sin]] and [[rc://en/tw/dict/bible/other/death]])<br><br>Genesis is also about the beginning of God’s people. Genesis 12-50 tells about how God remained faithful to Abraham and his descendants. Abraham’s descendants became known as the Hebrews and later as the Israelites. These people would worship Yahweh and be his people.<br><br>Genesis ends with Abraham’s descendants living in Egypt with the hope of returning one day to the Promised Land. (See: [[rc://en/tw/dict/bible/kt/promisedland]])<br><br>### How should the title of this book be translated?<br><br>“Genesis” means “beginning,” so translators should express this idea in their title. Titles such as “The Beginning of Things” may be suitable. (See: [[rc://en/ta/man/translate/translate-names]])<br><br>### Who wrote Genesis?<br><br>The writers of both the Old and New Testaments presented Moses as being very involved with writing the book of Genesis. Since ancient times, both Jews and Christians have thought that Moses wrote Genesis, Exodus, Leviticus, Numbers, and Deuteronomy.<br><br>## Part 2: Important Religious and Cultural Concepts<br><br>### What are the covenants mentioned in Genesis?<br><br>A covenant is a formal, binding agreement between two parties that one or both parties must fulfill.<br><br>God made three covenants in Genesis. In the covenant with Adam, God promised to bless Adam and cause him to prosper. Adam was not allowed to eat fruit from the tree of knowledge of good and evil. God promised that Adam would die if he disobeyed what he commanded.<br><br>In the covenant with Noah, God promised to never again destroy the world with a flood.<br><br>In the covenant with Abraham, God promised to make Abraham’s descendants into a great nation. He also promised to protect them and to give them a land of their own.<br><br>### What was God’s purpose for the book of Genesis?<br><br>The book of Genesis says that God created a very good world. However, the world became cursed because human beings began to sin. But Genesis shows that God continues to have complete control over the world.<br><br>Genesis also describes the start of God’s plan to bless the whole world again. This is shown when God makes a covenant with Abraham. With this covenant, God chose Abraham and his descendants to be his people. God promised to bless the world through Abraham’s descendants.<br><br>### What was the custom for inheritance as described by Genesis?<br><br>There are several passages in Genesis that show the customs of a father who is about to die passing on a blessing to his son. Abraham blessed his son, Isaac, and made him the ancestor of the people of Israel. However, Ishmael, Abraham’s other son, did not receive that same divine blessing. Likewise, Isaac’s older son Esau did not receive the blessing. Isaac’s younger son, Jacob, received it instead. (See: [[rc://en/tw/dict/bible/kt/inherit]] and [[rc://en/tw/dict/bible/kt/bless]])<br><br>Also, it was the custom for a man to divide among his sons his material wealth and land. All his sons received equal portions except the oldest son. The firstborn son received twice as much. His portion was called a double portion. Esau gave up his right to receive the double portion.<br><br>### How does Genesis present sin and evil?<br><br>Genesis presents sin as doing things that are against God’s word and God’s ways. It presents evil as the opposite of good.<br><br>Sin and evil have affected all people. This started when Adam disobeyed God in the Garden of Eden.<br><br>## Part 3: Important Translation Issues<br><br>### What is one way in which Genesis marks the beginning of important sections?<br><br>Genesis uses one Hebrew phrase that the ULT translates as “this is the record of,” “these were the events concerning,” or “these were the descendants of.” The information in these sections may have come from sources much older than Moses. These passages are 2:4; 5:1; 6:9; 10:1; 11:10, 27; 25:12, 19; 36:1, 9; 37:2.<br><br>If the translator wants to translate in only two ways, we recommend for most passages a phrase such as, “this is the record about” or “this is information about.” Some passages will be better translated, however, as “These were the descendants of.”<br><br>### Why are the beginnings of some narrative sections in Genesis difficult to translate?<br><br>Often in Genesis, the author first summarizes what is about to happen. Then in the following verses, the author tells the details of what happened. Probable examples of this style occur in Gen. 1:1, 6:22, 18:1, 21:1 and 22:1.<br><br>However, in many languages, it is preferred to write summaries at the end of a narrative. In this case, translators may choose a different approach. For example, in Gen. 1:1 (“In the beginning God created the heavens and the earth”), translators may decide to translate like this: “This is about how God made the heavens and the earth in the beginning.”<br><br>### What is the difference between “people,” “peoples,” and “people groups”?<br><br>The word “people” refers to all the individuals who belong to a group, such as “the people of Israel.” The word “peoples” (used in the ULT) refers to multiple groups of people. Each people group might speak their own language, have their own customs, and worships their own gods. Some different peoples in the ancient Near East were those of Israel, Egypt, Edom, Moab, and Ammon.<br><br>The expression “people groups” (used in the UST) means the same thing as “peoples” in the ULT. The translator should use the most equivalent term that is common in the project language.<br><br>### What is the relationship between individuals and peoples that have similar names?<br><br>Many individuals in Genesis eventually had large numbers of descendants who were called after their ancestor’s name. For example, Cush was the name of an individual. But, “Cush” also became the name of nation that his descendants formed. They were called “Cushites.” If possible, when translating these names, the translator should make the individual’s name and the nation’s name similar. Examples of this are “Cush” and “Cushite” or “Moab” and “Moabite.” Otherwise, the translator may say, “the descendants of Cush” or “the descendants of Moab.”<br><br>### What do the phrases “to this day” or “of today” mean?<br><br>These phrases were used by the narrator to refer to the time when he was writing. The translator should be aware that “to this day” and “of today” refer to a time already passed. The translator might decide to say, “to this day, at the time when this is being written,” or, “to this day, at the time of writing.” This Hebrew phrase occurs in Gen. 19:37, 19:38, 22:14, 26:33, 32:32, 35:20, 47:26, 48:18."; -const lineA2 = "1:intro\tzb6f\t\t\t0\t\t# Genesis 01 General Notes<br><br>## Structure and formatting<br><br>This chapter presents the first account of God creating the world. There is a pattern to this account: “God said…God saw that it was good…This was evening and morning, the first day.” Translators should preserve this pattern in their versions.<br><br>## Special concepts in this chapter<br><br>### The universe<br><br>This account of creation is told within the framework of ancient Hebrew ideas about the universe: the earth was resting with water around it and below it. Over the earth was something like a vast dome, called “an expanse between the waters” (1:6), on top of which was more water. Translators should try to keep these original images in their work, even though readers in their project language might have a completely different idea of what the universe is like.<br><br>### Evening and morning<br><br>Genesis 1 presents the ancient Hebrew idea of a day: it begins with sunset, lasts through the night and continues through the daylight hours until the next sunset. This pattern should be preserved in translation, even if readers in the project language define “day” differently.<br><br>## Other possible translation difficulties in this chapter<br><br>### “In the beginning”<br><br>Some languages and cultures speak of the world as if it has always existed, as if it had no beginning. But “very long ago” is different from “in the beginning,” and you need to be sure that your translation communicates correctly.<br><br>### “God said, ‘Let there be’”<br><br>This expression occurs often in this chapter. It can be difficult to translate, because God is not shown as talking to a particular person. If God is talking to a thing, it is something not yet in existence. Translators should find the most natural way in the project language to signal the idea that God spoke things into existence; he created the world and the things in it by simply commanding that they should exist."; -const lineA3 = "1:1\tf2mg\t\t0\t\t\tIn the beginning, God created the heavens and the earth “This is about how God made the heavens and the earth in the beginning.” This statement summarizes the rest of the chapter. Some languages translate it as “A very long time ago God created the heavens and the earth.” Translate it in a way that shows this actually happened and is not just a folk story."; -const lineA4 = "1:3\td7qw\tfigs-imperative\t\t0\tLet there be light\tThis is a command. By commanding that light should exist, God made it exist. (See: [[rc://en/ta/man/translate/figs-imperative]])"; -const lineA5 = "1:5\tjc2d\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. (See: [[rc://en/ta/man/translate/figs-merism]])"; -const lineA6 = "1:6\turb3\tfigs-imperative\t\t0\tLet there be an expanse…let it divide\tThese are commands. By commanding that the expanse should exist and that it divide the waters, God made it exist and divide the waters. (See: [[rc://en/ta/man/translate/figs-imperative]])"; -const lineA7 = "1:8\tss9r\tfigs-merism\t\t0\tevening and morning\tThis refers to the whole day. The writer speaks of the whole day as if it were these two parts. In the Jewish culture, a day begins when the sun sets. See how you translated this in [Genesis 1:5](../01/05.md). (See: [[rc://en/ta/man/translate/figs-merism]])"; -const lineA8 = "1:9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://en/ta/man/translate/figs-activepassive]] and [[rc://en/ta/man/translate/figs-imperative]])"; -const lineA9 = "1:9\tha33\t\t\t0\tIt was so\t“It happened like that” or “That is what happened.” What God commanded happened just as he said it should. This phrase appears throughout the chapter and has the same meaning wherever it appears. See how you translated it in [Genesis 1:7](../01/07.md)."; +const lineA1 = "1:1\tgfme\tkeyterm\tהַשּׁפְטִ֔ים\t1\trc://*/tw/dict/bible/kt/judge"; +const lineA2 = "1:1\trenf\t\tרָעָ֖ב\t1\trc://*/tw/dict/bible/other/famine"; +const lineA3 = "1:1\tqury\tname\tמִבֵּית לֶ֣חֶם\t1\trc://*/tw/dict/bible/names/bethlehem"; +const lineA4 = "2:16\tytc7\tkeyterm; name\tΧριστοῦ Ἰησοῦ\t1\trc://*/tw/dict/bible/kt/jesus"; const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - repoCode: 'TN2', - tableLineName : 'lineA9', - tableLine : lineA9, - bookID : 'GEN', C:'1', V:'2', + repoCode: 'TWL', + tableLineName : 'lineA4', + tableLine : lineA4, + bookID : 'ROM', C:'2', V:'16', givenLocation : 'that was supplied', } -function CheckTWLRow(props) { +function OurCheckTWLRow(props) { const { languageCode, repoCode, bookID, C, V, tableLine, tableLineName, givenLocation } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkTWL_TSV7DataRow is an ASYNC function + // We need the following construction because checkTWL_TSV6DataRow is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 @@ -63,10 +58,10 @@ function CheckTWLRow(props) { // Display our "waiting" message setResults(<p style={{ color: 'magenta' }}>Checking {tableLineName} <b>{bookID}</b>…</p>); const checkingOptions = {}; - const rawResults = await checkTWL_TSV7DataRow(languageCode, repoCode, tableLine, bookID, C, V, givenLocation, checkingOptions); + const rawResults = await checkTWL_TSV6DataRow(languageCode, repoCode, tableLine, bookID, C, V, givenLocation, checkingOptions); setResults( <div> - <b>Check</b> {tableLineName}: "{tableLine.substr(0,256)}…"<br/><br/> + <b>Check</b> {tableLineName}: "{tableLine}"<br/><br/> <RenderRawResults results={rawResults} /> </div> ); @@ -74,7 +69,7 @@ function CheckTWLRow(props) { }, []); // end of useEffect part return results; -} // end of CheckTWLRow function +} // end of OurCheckTWLRow function -<CheckTWLRow data={data}/> +<OurCheckTWLRow data={data}/> ``` diff --git a/src/core/twl-tsv6-table-check.md b/src/core/twl-tsv6-table-check.md index 099fc00a8..20aecb718 100644 --- a/src/core/twl-tsv6-table-check.md +++ b/src/core/twl-tsv6-table-check.md @@ -40,7 +40,7 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - repoCode: 'TN2', + repoCode: 'TWL', tableTextName : 'textG', tableText : textG, bookID : 'GEN', @@ -48,7 +48,7 @@ const data = { givenLocation : 'that was supplied', } -function CheckTWL_TSV6Table(props) { +function OurCheckTWL_TSV6Table(props) { const { languageCode, repoCode, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -72,7 +72,7 @@ function CheckTWL_TSV6Table(props) { }, []); // end of useEffect part return results; -} // end of CheckTWL_TSV6Table function +} // end of OurCheckTWL_TSV6Table function -<CheckTWL_TSV6Table data={data}/> +<OurCheckTWL_TSV6Table data={data}/> ``` diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 5a6047306..10206bc39 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -864,7 +864,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } while ((regexResultArray1 = KS_REGEX.exec(adjustedRest))) { // debugLog(`Got ${repoCode} \\k-s Regex in ${C}:${V} line: '${JSON.stringify(regexResultArray1)}`); - dataAssert(repoCode === 'UHB' || repoCode === 'UGNT') + dataAssert(repoCode === 'UHB' || repoCode === 'UGNT', `checkUSFMLineAttributes expected an original language repo not '${repoCode}'`); let attributeCounter = 0; while ((regexResultArray2 = ATTRIBUTE_REGEX.exec(regexResultArray1[1]))) { attributeCounter += 1; @@ -881,7 +881,7 @@ export function checkUSFMText(languageCode, repoCode, bookID, filename, givenTex } while ((regexResultArray1 = ZALNS_REGEX.exec(adjustedRest))) { // debugLog(`Got ${repoCode} \\zaln-s Regex in ${C}:${V} line: '${JSON.stringify(regexResultArray1)}`); - dataAssert(repoCode !== 'UHB' && repoCode !== 'UGNT') + dataAssert(repoCode !== 'UHB' && repoCode !== 'UGNT', `checkUSFMLineAttributes eExpected not an original language repo not '${repoCode}'`); let attributeCounter = 0; while ((regexResultArray2 = ATTRIBUTE_REGEX.exec(regexResultArray1[1]))) { attributeCounter += 1; diff --git a/src/core/usfm-text-check.md b/src/core/usfm-text-check.md index 113f1e908..2f658c681 100644 --- a/src/core/usfm-text-check.md +++ b/src/core/usfm-text-check.md @@ -183,10 +183,9 @@ const textB = `\\id GEN Bad USFM test // (to demonstrate differing results) const chosenText = textH; -// Second (unused) parameter is repoCode // Fourth (unused) parameter is filename const checkingOptions = {}; -const rawResults = checkUSFMText('en', '', 'GEN', '', chosenText, 'that was supplied', checkingOptions); +const rawResults = checkUSFMText('en', 'UHB', 'GEN', '', chosenText, 'that was supplied', checkingOptions); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done USFM text checks"]; diff --git a/src/core/yaml-text-check.md b/src/core/yaml-text-check.md index fa14c2d5e..39280cd4c 100644 --- a/src/core/yaml-text-check.md +++ b/src/core/yaml-text-check.md @@ -221,7 +221,7 @@ const chosenText = textG2; const chosenTextName = 'textG2'; const checkingOptions = {}; -const rawResults = checkYAMLText('en', chosenTextName, chosenText, 'in YAML data that was supplied', checkingOptions); +const rawResults = checkYAMLText('en', '', chosenTextName, chosenText, 'in YAML data that was supplied', checkingOptions); <> <b>YAML contents</b>: <RenderLines text={chosenText} /> diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index d39c7ef28..e9e768824 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -41,7 +41,7 @@ const tableIcons = { }; -// const RENDER_PROCESSED_RESULTS_VERSION = '0.5.10'; +// const RENDER_PROCESSED_RESULTS_VERSION = '0.5.11'; export function RenderSuccesses({ username, results }) { @@ -257,7 +257,7 @@ function RenderFileDetails({ username, repoName, branch, filename, lineNumber, r // debugLog(`RenderFileDetails(${repoName}, ${branch}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); if (!repoName && !filename && !lineNumber && !rowID && !fieldName) return null; // They're all undefined or blank! - if (!branch) branch = repoName.endsWith('2')? 'newFormat':'master'; // default but with TEMP code for newFormat + if (!branch) branch = repoName?.endsWith('2')? 'newFormat':'master'; // default but with TEMP code for newFormat // debugLog(`RenderFileDetails2 ${repoName}, ${filename}, ${lineNumber}`); let resultStart = '', lineResult = '', resultEnd = '', fileLineLink = '', fileLink = ''; if (repoName && repoName.length) resultStart += ` in ${repoName} repository`; diff --git a/yarn.lock b/yarn.lock index c7c8879b3..2e4f9d875 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,10 +40,10 @@ dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.13.0", "@babel/compat-data@^7.13.5", "@babel/compat-data@^7.9.0": - version "7.13.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.6.tgz#11972d07db4c2317afdbf41d6feb3a730301ef4e" - integrity sha512-VhgqKOWYVm7lQXlvbJnWOzwfAQATd2nV52koT0HZ/LdDH0m4DUDwkKYsH+IwpXb+bKPyBJzawA4I6nBKqZcpQw== +"@babel/compat-data@^7.13.0", "@babel/compat-data@^7.13.8", "@babel/compat-data@^7.9.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.8.tgz#5b783b9808f15cef71547f1b691f34f8ff6003a6" + integrity sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog== "@babel/core@7.9.0": version "7.9.0" @@ -68,16 +68,16 @@ source-map "^0.5.0" "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.1.tgz#7ddd027176debe40f13bb88bac0c21218c5b1ecf" - integrity sha512-FzeKfFBG2rmFtGiiMdXZPFt/5R5DXubVi82uYhjGX4Msf+pgYQMCFIqFXZWs5vbIYbf14VeBIgdGI03CDOOM1w== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.8.tgz#c191d9c5871788a591d69ea1dc03e5843a3680fb" + integrity sha512-oYapIySGw1zGhEFRd6lzWNLWFX2s5dA/jm+Pw/+59ZdXtjyIuwlXbrId22Md0rgZVop+aVoqow2riXhBLNyuQg== dependencies: "@babel/code-frame" "^7.12.13" "@babel/generator" "^7.13.0" - "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-compilation-targets" "^7.13.8" "@babel/helper-module-transforms" "^7.13.0" "@babel/helpers" "^7.13.0" - "@babel/parser" "^7.13.0" + "@babel/parser" "^7.13.4" "@babel/template" "^7.12.13" "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.0" @@ -86,7 +86,7 @@ gensync "^1.0.0-beta.2" json5 "^2.1.2" lodash "^4.17.19" - semver "7.0.0" + semver "^6.3.0" source-map "^0.5.0" "@babel/generator@^7.13.0", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": @@ -113,20 +113,20 @@ "@babel/helper-explode-assignable-expression" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.8.7": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.0.tgz#c9cf29b82a76fd637f0faa35544c4ace60a155a1" - integrity sha512-SOWD0JK9+MMIhTQiUVd4ng8f3NXhPVQvTv7D3UN4wbp/6cAHnB2EmMaU1zZA2Hh1gwme+THBrVSqTFxHczTh0Q== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.8", "@babel/helper-compilation-targets@^7.8.7": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.8.tgz#02bdb22783439afb11b2f009814bdd88384bd468" + integrity sha512-pBljUGC1y3xKLn1nrx2eAhurLMA8OqBtBP/JwG4U8skN7kf8/aqwwxpV1N6T0e7r6+7uNitIa/fUxPFagSXp3A== dependencies: - "@babel/compat-data" "^7.13.0" + "@babel/compat-data" "^7.13.8" "@babel/helper-validator-option" "^7.12.17" browserslist "^4.14.5" - semver "7.0.0" + semver "^6.3.0" "@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.0.tgz#28d04ad9cfbd1ed1d8b988c9ea7b945263365846" - integrity sha512-twwzhthM4/+6o9766AW2ZBHpIHPSGrPGk1+WfHiu13u/lBnggXGNYCpeAyVfNwGDKfkhEDp+WOD/xafoJ2iLjA== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.8.tgz#0367bd0a7505156ce018ca464f7ac91ba58c1a04" + integrity sha512-qioaRrKHQbn4hkRKDHbnuQ6kAxmmOF+kzKGnIfxPK4j2rckSJCpKzr/SSTlohSCiE3uAQpNDJ9FIh4baeE8W+w== dependencies: "@babel/helper-function-name" "^7.12.13" "@babel/helper-member-expression-to-functions" "^7.13.0" @@ -142,10 +142,10 @@ "@babel/helper-annotate-as-pure" "^7.12.13" regexpu-core "^4.7.1" -"@babel/helper-define-polyfill-provider@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.2.tgz#619f01afe1deda460676c25c463b42eaefdb71a2" - integrity sha512-hWeolZJivTNGHXHzJjQz/NwDaG4mGXf22ZroOP8bQYgvHNzaQ5tylsVbAcAS2oDjXBwpu8qH2I/654QFS2rDpw== +"@babel/helper-define-polyfill-provider@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.4.tgz#b618b087c6a0328127e5d53576df818bcee2b15f" + integrity sha512-K5V2GaQZ1gpB+FTXM4AFVG2p1zzhm67n9wrQCJYNzvuLzQybhJyftW7qeDd2uUxPDNdl5Rkon1rOAeUeNDZ28Q== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -179,7 +179,7 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-hoist-variables@^7.12.13": +"@babel/helper-hoist-variables@^7.13.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz#5d5882e855b5c5eda91e0cadc26c6e7a2c8593d8" integrity sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g== @@ -201,7 +201,7 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-module-transforms@^7.12.13", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.9.0": +"@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.9.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz#42eb4bd8eea68bab46751212c357bfed8b40f6f1" integrity sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw== @@ -298,27 +298,27 @@ "@babel/types" "^7.13.0" "@babel/highlight@^7.0.0", "@babel/highlight@^7.12.13", "@babel/highlight@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" - integrity sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.8.tgz#10b2dac78526424dfc1f47650d0e415dfd9dc481" + integrity sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw== dependencies: "@babel/helper-validator-identifier" "^7.12.11" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.13.4", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": version "7.13.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.4.tgz#340211b0da94a351a6f10e63671fa727333d13ab" integrity sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA== -"@babel/plugin-proposal-async-generator-functions@^7.13.5", "@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.13.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.5.tgz#69e3fbb9958949b09036e27b26eba1aafa1ba3db" - integrity sha512-8cErJEDzhZgNKzYyjCKsHuyPqtWxG8gc9h4OFSUDJu0vCAOsObPU2LcECnW0kJwh/b+uUz46lObVzIXw0fzAbA== +"@babel/plugin-proposal-async-generator-functions@^7.13.8", "@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.8.tgz#87aacb574b3bc4b5603f6fe41458d72a5a2ec4b1" + integrity sha512-rPBnhj+WgoSmgq+4gQUtXx/vOcU+UYtjy1AA/aeD61Hwj410fwYyqfUcRP3lR8ucgliVJL/G7sXcNUecC75IXA== dependencies: "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-remap-async-to-generator" "^7.13.0" - "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-proposal-class-properties@7.8.3": version "7.8.3" @@ -345,13 +345,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-decorators" "^7.8.3" -"@babel/plugin-proposal-dynamic-import@^7.12.17", "@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.12.17" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.17.tgz#e0ebd8db65acc37eac518fa17bead2174e224512" - integrity sha512-ZNGoFZqrnuy9H2izB2jLlnNDAfVPlGl5NhFEiFe4D84ix9GQGygF+CWMGHKuE+bpyS/AOuDQCnkiRNqW2IzS1Q== +"@babel/plugin-proposal-dynamic-import@^7.13.8", "@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.13.8.tgz#876a1f6966e1dec332e8c9451afda3bebcdf2e1d" + integrity sha512-ONWKj0H6+wIRCkZi9zSbZtE/r73uOhMVHh256ys0UzfM7I3d4n+spZNWjOnJv2gzopumP2Wxi186vI8N0Y2JyQ== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-proposal-export-namespace-from@^7.12.13": version "7.12.13" @@ -361,20 +361,20 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.12.13", "@babel/plugin-proposal-json-strings@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.13.tgz#ced7888a2db92a3d520a2e35eb421fdb7fcc9b5d" - integrity sha512-v9eEi4GiORDg8x+Dmi5r8ibOe0VXoKDeNPYcTTxdGN4eOWikrJfDJCJrr1l5gKGvsNyGJbrfMftC2dTL6oz7pg== +"@babel/plugin-proposal-json-strings@^7.13.8", "@babel/plugin-proposal-json-strings@^7.8.3": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.13.8.tgz#bf1fb362547075afda3634ed31571c5901afef7b" + integrity sha512-w4zOPKUFPX1mgvTmL/fcEqy34hrQ1CRcGxdphBc6snDnnqJ47EZDIyop6IwXzAC8G916hsIuXB2ZMBCExC5k7Q== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.13.tgz#575b5d9a08d8299eeb4db6430da6e16e5cf14350" - integrity sha512-fqmiD3Lz7jVdK6kabeSr1PZlWSUVqSitmHEe3Z00dtGTKieWnX9beafvavc32kjORa5Bai4QNHgFDwWJP+WtSQ== +"@babel/plugin-proposal-logical-assignment-operators@^7.13.8": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.13.8.tgz#93fa78d63857c40ce3c8c3315220fd00bfbb4e1a" + integrity sha512-aul6znYB4N4HGweImqKn59Su9RS8lbUIqxtXTOcAGtNIDczoEFv+l1EhmX8rUBp3G1jMjKJm8m0jXVp63ZpS4A== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-proposal-nullish-coalescing-operator@7.8.3": @@ -385,13 +385,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.0.tgz#1a96fdf2c43109cfe5568513c5379015a23f5380" - integrity sha512-UkAvFA/9+lBBL015gjA68NvKiCReNxqFLm3SdNKaM3XXoDisA7tMAIX4PmIwatFoFqMxxT3WyG9sK3MO0Kting== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz#3730a31dafd3c10d8ccd10648ed80a2ac5472ef3" + integrity sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A== dependencies: "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@7.8.3": version "7.8.3" @@ -409,22 +409,24 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.13.0", "@babel/plugin-proposal-object-rest-spread@^7.9.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.0.tgz#8f19ad247bb96bd5ad2d4107e6eddfe0a789937b" - integrity sha512-B4qphdSTp0nLsWcuei07JPKeZej4+Hd22MdnulJXQa1nCcGSBlk8FiqenGERaPZ+PuYhz4Li2Wjc8yfJvHgUMw== +"@babel/plugin-proposal-object-rest-spread@^7.13.8", "@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz#5d210a4d727d6ce3b18f9de82cc99a3964eed60a" + integrity sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g== dependencies: + "@babel/compat-data" "^7.13.8" + "@babel/helper-compilation-targets" "^7.13.8" "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.13.0" -"@babel/plugin-proposal-optional-catch-binding@^7.12.13", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.13.tgz#4640520afe57728af14b4d1574ba844f263bcae5" - integrity sha512-9+MIm6msl9sHWg58NvqpNpLtuFbmpFYk37x8kgnGzAHvX35E1FyAwSUt5hIkSoWJFSAH+iwU8bJ4fcD1zKXOzg== +"@babel/plugin-proposal-optional-catch-binding@^7.13.8", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.13.8.tgz#3ad6bd5901506ea996fc31bdcf3ccfa2bed71107" + integrity sha512-0wS/4DUF1CuTmGo+NiaHfHcVSeSLj5S3e6RivPTg/2k3wOv3jO35tZ6/ZWsQhQMvdgI7CwphjQa/ccarLymHVA== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining@7.9.0": version "7.9.0" @@ -434,14 +436,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.13.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.0.tgz#75b41ce0d883d19e8fe635fc3f846be3b1664f4d" - integrity sha512-OVRQOZEBP2luZrvEbNSX5FfWDousthhdEoAOpej+Tpe58HFLvqRClT89RauIvBuCDFEip7GW1eT86/5lMy2RNA== +"@babel/plugin-proposal-optional-chaining@^7.13.8", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.8.tgz#e39df93efe7e7e621841babc197982e140e90756" + integrity sha512-hpbBwbTgd7Cz1QryvwJZRo1U0k1q8uyBmeXOSQUjdg/A2TASkhR/rz7AyqZ/kS8kbpsNA80rOYbxySBJAqmhhQ== dependencies: "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-proposal-private-methods@^7.13.0": version "7.13.0" @@ -487,7 +489,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-dynamic-import@^7.8.0": +"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -711,24 +713,24 @@ "@babel/helper-plugin-utils" "^7.13.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.13.0", "@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.0.tgz#276932693a20d12c9776093fdc99c0d9995e34c6" - integrity sha512-j7397PkIB4lcn25U2dClK6VLC6pr2s3q+wbE8R3vJvY6U1UTBBj0n6F+5v6+Fd/UwfDPAorMOs2TV+T4M+owpQ== +"@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz#7b01ad7c2dcf2275b06fa1781e00d13d420b3e1b" + integrity sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw== dependencies: "@babel/helper-module-transforms" "^7.13.0" "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-simple-access" "^7.12.13" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.12.13", "@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.13.tgz#351937f392c7f07493fc79b2118201d50404a3c5" - integrity sha512-aHfVjhZ8QekaNF/5aNdStCGzwTbU7SI5hUybBKlMzqIMC7w7Ho8hx5a4R/DkTHfRfLwHGGxSpFt9BfxKCoXKoA== +"@babel/plugin-transform-modules-systemjs@^7.13.8", "@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.13.8.tgz#6d066ee2bff3c7b3d60bf28dec169ad993831ae3" + integrity sha512-hwqctPYjhM6cWvVIlOIe27jCIBgHCsdH2xCJVAYQm7V5yTMoilbVMi9f6wKg0rpQAOn6ZG4AOyvCqFF/hUh6+A== dependencies: - "@babel/helper-hoist-variables" "^7.12.13" - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-hoist-variables" "^7.13.0" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-validator-identifier" "^7.12.11" babel-plugin-dynamic-import-node "^2.3.3" @@ -862,16 +864,16 @@ semver "^5.5.1" "@babel/plugin-transform-runtime@^7.12.1": - version "7.13.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.7.tgz#a856b53681da9193d98dfb03d8192b0a3f4cdd8a" - integrity sha512-pXfYTTSbU5ThVTUyQ6TUdUkonZYKKq8M6vDUkFCjFw8vT42hhayrbJPVWGC7B97LkzFYBtdW/SBGVZtRaopW6Q== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.8.tgz#8c9a16db6cb6c2a1f748e36ae23558b92d223010" + integrity sha512-6UbZ7P0FuuJiiUyRCfDgLw4PIG9bR2x6swHocv4qNZItkhXad0WsN6YX0deILuyZY2++meDKiDMuSVcejDZN0Q== dependencies: "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" babel-plugin-polyfill-corejs2 "^0.1.4" babel-plugin-polyfill-corejs3 "^0.1.3" babel-plugin-polyfill-regenerator "^0.1.2" - semver "7.0.0" + semver "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.12.13", "@babel/plugin-transform-shorthand-properties@^7.8.3": version "7.12.13" @@ -1000,38 +1002,38 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.4.5": - version "7.13.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.13.5.tgz#68b3bbc821a97fcdbf4bd0f6895b83d07f84f33e" - integrity sha512-xUeKBIIcbwxGevyWMSWZOW98W1lp7toITvVsMxSddCEQy932yYiF4fCB+CG3E/MXzFX3KbefgvCqEQ7TDoE6UQ== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.13.8.tgz#1133d7ae806d6bf981b7a1a49e336d4d88db1953" + integrity sha512-Sso1xOpV4S3ofnxW2DsWTE5ziRk62jEAKLGuQ+EJHC+YHTbFG38QUTixO3JVa1cYET9gkJhO1pMu+/+2dDhKvw== dependencies: - "@babel/compat-data" "^7.13.5" - "@babel/helper-compilation-targets" "^7.13.0" + "@babel/compat-data" "^7.13.8" + "@babel/helper-compilation-targets" "^7.13.8" "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-validator-option" "^7.12.17" - "@babel/plugin-proposal-async-generator-functions" "^7.13.5" + "@babel/plugin-proposal-async-generator-functions" "^7.13.8" "@babel/plugin-proposal-class-properties" "^7.13.0" - "@babel/plugin-proposal-dynamic-import" "^7.12.17" + "@babel/plugin-proposal-dynamic-import" "^7.13.8" "@babel/plugin-proposal-export-namespace-from" "^7.12.13" - "@babel/plugin-proposal-json-strings" "^7.12.13" - "@babel/plugin-proposal-logical-assignment-operators" "^7.12.13" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.0" + "@babel/plugin-proposal-json-strings" "^7.13.8" + "@babel/plugin-proposal-logical-assignment-operators" "^7.13.8" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" "@babel/plugin-proposal-numeric-separator" "^7.12.13" - "@babel/plugin-proposal-object-rest-spread" "^7.13.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.12.13" - "@babel/plugin-proposal-optional-chaining" "^7.13.0" + "@babel/plugin-proposal-object-rest-spread" "^7.13.8" + "@babel/plugin-proposal-optional-catch-binding" "^7.13.8" + "@babel/plugin-proposal-optional-chaining" "^7.13.8" "@babel/plugin-proposal-private-methods" "^7.13.0" "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" - "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.12.13" "@babel/plugin-transform-arrow-functions" "^7.13.0" "@babel/plugin-transform-async-to-generator" "^7.13.0" @@ -1048,8 +1050,8 @@ "@babel/plugin-transform-literals" "^7.12.13" "@babel/plugin-transform-member-expression-literals" "^7.12.13" "@babel/plugin-transform-modules-amd" "^7.13.0" - "@babel/plugin-transform-modules-commonjs" "^7.13.0" - "@babel/plugin-transform-modules-systemjs" "^7.12.13" + "@babel/plugin-transform-modules-commonjs" "^7.13.8" + "@babel/plugin-transform-modules-systemjs" "^7.13.8" "@babel/plugin-transform-modules-umd" "^7.13.0" "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.13" "@babel/plugin-transform-new-target" "^7.12.13" @@ -1065,15 +1067,15 @@ "@babel/plugin-transform-typeof-symbol" "^7.12.13" "@babel/plugin-transform-unicode-escapes" "^7.12.13" "@babel/plugin-transform-unicode-regex" "^7.12.13" - "@babel/preset-modules" "^0.1.3" + "@babel/preset-modules" "^0.1.4" "@babel/types" "^7.13.0" babel-plugin-polyfill-corejs2 "^0.1.4" babel-plugin-polyfill-corejs3 "^0.1.3" babel-plugin-polyfill-regenerator "^0.1.2" core-js-compat "^3.9.0" - semver "7.0.0" + semver "^6.3.0" -"@babel/preset-modules@^0.1.3": +"@babel/preset-modules@^0.1.3", "@babel/preset-modules@^0.1.4": version "0.1.4" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== @@ -1116,9 +1118,9 @@ "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.12.1", "@babel/runtime-corejs3@^7.9.6": - version "7.13.7" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.7.tgz#f47f882b62961c1ada113dbafc717c69c18a9b09" - integrity sha512-zkDsGGSRU2YyYTXkPfcxuYuCVc6xBOeH1ZMh72ywBvmrDs+kSmoMuCUXZJUPbXZafrPivDHS2Oq7wI37gaTvqw== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.8.tgz#149749463be6692e3688584130e4300beba0e93c" + integrity sha512-iaInhjy1BbDnqc7pZiIXAfWvBnczgWobHceR4Wkhs5tWZG8aIazBYH0Vo73lixecHKh3Vy9yqbQBqVDrmcVDlQ== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1131,9 +1133,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.13.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a" - integrity sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.8.tgz#cc886a85c072df1de23670dc1aa59fc116c4017c" + integrity sha512-CwQljpw6qSayc0fRG1soxHAKs1CnQMOChm4mlQP6My0kf9upVGizj/KhlTTgyUnETmHpcUXjaluNAkteRFuafg== dependencies: regenerator-runtime "^0.13.4" @@ -2957,28 +2959,28 @@ babel-plugin-named-asset-import@^0.3.6: integrity sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw== babel-plugin-polyfill-corejs2@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.6.tgz#947a1227efa1a14ce09ac5fafc66ce8e039071e2" - integrity sha512-1PfghLDuzX5lFY6XXO0hrfxwYf0LD9YajMWeQBGNaPNLQ35paV7YB4hlFW+HfwFS5kcp4rtPI/237xLfQ1ah8A== + version "0.1.8" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.8.tgz#54ef37b1c4b2311e515029e8f1f07bbd4d7a5321" + integrity sha512-kB5/xNR9GYDuRmVlL9EGfdKBSUVI/9xAU7PCahA/1hbC2Jbmks9dlBBYjHF9IHMNY2jV/G2lIG7z0tJIW27Rog== dependencies: "@babel/compat-data" "^7.13.0" - "@babel/helper-define-polyfill-provider" "^0.1.2" + "@babel/helper-define-polyfill-provider" "^0.1.4" semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.4.tgz#2ae290200e953bade30907b7a3bebcb696e6c59d" - integrity sha512-ysSzFn/qM8bvcDAn4mC7pKk85Y5dVaoa9h4u0mHxOEpDzabsseONhUpR7kHxpUinfj1bjU7mUZqD23rMZBoeSg== + version "0.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.6.tgz#ed1b02fba4885e0892e06094e27865f499758d27" + integrity sha512-IkYhCxPrjrUWigEmkMDXYzM5iblzKCdCD8cZrSAkQOyhhJm26DcG+Mxbx13QT//Olkpkg/AlRdT2L+Ww4Ciphw== dependencies: - "@babel/helper-define-polyfill-provider" "^0.1.2" + "@babel/helper-define-polyfill-provider" "^0.1.4" core-js-compat "^3.8.1" babel-plugin-polyfill-regenerator@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.3.tgz#350f857225fc640ae1ec78d1536afcbb457db841" - integrity sha512-hRjTJQiOYt/wBKEc+8V8p9OJ9799blAJcuKzn1JXh3pApHoWl1Emxh2BHc6MC7Qt6bbr3uDpNxaYQnATLIudEg== + version "0.1.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.5.tgz#f42a58fd86a1c97fbe3a2752d80a4a3e017203e1" + integrity sha512-EyhBA6uN94W97lR7ecQVTvH9F5tIIdEw3ZqHuU4zekMlW82k5cXNXniiB7PRxQm06BqAjVr4sDT1mOy4RcphIA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.1.2" + "@babel/helper-define-polyfill-provider" "^0.1.4" babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" @@ -4089,17 +4091,17 @@ copy-webpack-plugin@^4.6.0: serialize-javascript "^1.4.0" core-js-compat@^3.6.2, core-js-compat@^3.8.1, core-js-compat@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.9.0.tgz#29da39385f16b71e1915565aa0385c4e0963ad56" - integrity sha512-YK6fwFjCOKWwGnjFUR3c544YsnA/7DoLL0ysncuOJ4pwbriAtOpvM2bygdlcXbvQCQZ7bBU9CL4t7tGl7ETRpQ== + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.9.1.tgz#4e572acfe90aff69d76d8c37759d21a5c59bb455" + integrity sha512-jXAirMQxrkbiiLsCx9bQPJFA6llDadKMpYrBJQJ3/c4/vsPP/fAf29h24tviRlvwUL6AmY5CHLu2GvjuYviQqA== dependencies: browserslist "^4.16.3" semver "7.0.0" core-js-pure@^3.0.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.9.0.tgz#326cc74e1fef8b7443a6a793ddb0adfcd81f9efb" - integrity sha512-3pEcmMZC9Cq0D4ZBh3pe2HLtqxpGNJBLXF/kZ2YzK17RbKp94w0HFbdbSx8H8kAlZG5k76hvLrkPm57Uyef+kg== + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.9.1.tgz#677b322267172bd490e4464696f790cbc355bec5" + integrity sha512-laz3Zx0avrw9a4QEIdmIblnVuJz8W51leY9iLThatCsFawWxC3sE4guASC78JbCin+DkwMpCdp1AVAuzL/GN7A== core-js@^2.4.0: version "2.6.12" @@ -4107,9 +4109,9 @@ core-js@^2.4.0: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.0.0, core-js@^3.5.0, core-js@^3.6.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.0.tgz#790b1bb11553a2272b36e2625c7179db345492f8" - integrity sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ== + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.1.tgz#cec8de593db8eb2a85ffb0dbdeb312cb6e5460ae" + integrity sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -4933,9 +4935,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.674" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.674.tgz#d97feefdf1d9411fdc9d56d17e1b9d67b818e710" - integrity sha512-DBmEKRVYLZAoQSW+AmLcTF5Bpwhk4RUkobtzXVDlfPPYIlbsH3Jfg3QbBjAfFcRARzMIo4YiMhp3N+RnMuo1Eg== + version "1.3.675" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.675.tgz#7ad29f98d7b48da581554eb28bb9a71fd5fd4956" + integrity sha512-GEQw+6dNWjueXGkGfjgm7dAMtXfEqrfDG3uWcZdeaD4cZ3dKYdPRQVruVXQRXtPLtOr5GNVVlNLRMChOZ611pQ== elliptic@^6.5.3: version "6.5.4" @@ -5466,9 +5468,9 @@ eventemitter3@^4.0.0: integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" - integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== eventsource@^1.0.7: version "1.0.7" @@ -5917,9 +5919,9 @@ flush-write-stream@^1.0.0: readable-stream "^2.3.6" follow-redirects@^1.0.0, follow-redirects@^1.10.0: - version "1.13.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.2.tgz#dd73c8effc12728ba5cf4259d760ea5fb83e3147" - integrity sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA== + version "1.13.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" + integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== for-each@^0.3.3: version "0.3.3" @@ -6343,9 +6345,9 @@ has-flag@^4.0.0: integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== has-value@^0.3.1: version "0.3.1" @@ -12683,9 +12685,9 @@ string-width@^3.0.0, string-width@^3.1.0: strip-ansi "^5.1.0" string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" @@ -13969,9 +13971,9 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5: iconv-lite "0.4.24" whatwg-fetch@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.1.tgz#93bc4005af6c2cc30ba3e42ec3125947c8f54ed3" - integrity sha512-IEmN/ZfmMw6G1hgZpVd0LuZXOQDisrMOZrzYd5x3RAK4bMPlJohKUZWZ9t/QsTvH0dV9TbPDcc2OSuIDcihnHA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: version "2.3.0" From 3c30046112088cbb6d33176e6d4a868954371a2d Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Wed, 3 Mar 2021 09:22:18 +1300 Subject: [PATCH 15/16] Fix for multiple TA links in TNs; issue #150 --- noticeList.txt | 588 +++++++++--------- package.json | 2 +- .../book-package-check.test.js.snap | 26 +- .../tn-table-row-check.test.js.snap | 24 +- src/__tests__/tn-table-row-check.test.js | 2 +- src/core/notes-links-check.js | 9 +- src/core/notes-tsv7-row-check.js | 20 +- src/core/notes-tsv7-row-check.md | 2 +- src/core/notes-tsv7-table-check.md | 2 +- src/core/questions-tsv7-row-check.md | 2 +- src/core/questions-tsv7-table-check.md | 2 +- src/core/tn-tsv9-row-check.js | 20 +- src/core/tn-tsv9-row-check.md | 2 +- src/core/tn-tsv9-table-check.md | 2 +- styleguide.config.js | 6 +- yarn.lock | 173 ++++-- 16 files changed, 479 insertions(+), 403 deletions(-) diff --git a/noticeList.txt b/noticeList.txt index c42eafe50..b0f9055ea 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,10 +1,10 @@ -Last updated 2021-02-20 08:26:26.258391 by makeNoticeList.py -Got 470 notices: +Last updated 2021-03-03 08:50:12.058433 by makeNoticeList.py +Got 496 notices: checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 256 - languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 941 - marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 969 - `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,048 - C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,141 + languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 945 + marker === 's5' ? 111 : 809, `$marker === 's5' ? 'Deprecated' : 'Unexpected' '\\$marker' marker at start of line`, C, V, lineNumber, characterIndex: 1, location: lineLocation from usfm-text-check.js line 973 + `"`.indexOf(line[0]) < 0 ? 880 : 180, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, excerpt: line[0], location: ourLocation from usfm-text-check.js line 1,097 + C === '1' ? 657 : 457, C, V, "Paragraph marker expected before first verse", lineNumber: n, characterIndex: 1, details: `'\\$marker' after '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,190 const notice = 95, "Unexpected trailing space(s)", excerpt, location: ourLocation ; from field-text-check.js line 193 notice from field-text-check.js line 196 notice = 124, "Unexpected double spaces", excerpt, location: ourLocation ; from field-text-check.js line 227 @@ -22,75 +22,76 @@ Got 470 notices: notice from field-text-check.js line 361 thisPriority, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from field-text-check.js line 402 thisPriority, thisMessage, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 417 - const notice = 252, "Markdown headers should be preceded by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 234 - notice from markdown-text-check.js line 237 - const notice = 252, "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 240 - notice from markdown-text-check.js line 243 - const notice = 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 253 - notice from markdown-text-check.js line 256 - const notice = 282, "Nesting of header levels seems confused", details: `recent indent levels=$JSON.stringify(indentLevels) but now $numLeadingSpaces`, lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 284 - notice from markdown-text-check.js line 287 - const notice = 250, "Multiple blank lines are not expected in markdown", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 301 - notice from markdown-text-check.js line 304 + const notice = 252, "Markdown headers should be preceded by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 281 + notice from markdown-text-check.js line 284 + const notice = 252, "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 287 + notice from markdown-text-check.js line 290 + const notice = 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 300 + notice from markdown-text-check.js line 303 + const notice = 282, "Nesting of header levels seems confused", details: `recent indent levels=$JSON.stringify(indentLevels) but now $numLeadingSpaces`, lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 331 + notice from markdown-text-check.js line 334 + const notice = 250, "Multiple blank lines are not expected in markdown", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 348 + notice from markdown-text-check.js line 351 leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from plain-text-check.js line 243 999, "checkRepo function FAILED", repoName, excerpt: checkRepoError, location: repoName from RepoCheck.js line 107 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 179 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 243 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 399 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 592 - 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 618 - 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 183 - 996, "Unable to load", details: `username=$username error=$cBPgfError`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 247 - 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 403 - 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 594 - 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 622 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 183 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: markdownLocation, extra: repoCode from checkBookPackage.js line 247 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 403 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 597 + 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 623 + 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 187 + 996, "Unable to load", details: `username=$username error=$cBPgfError`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 251 + 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 407 + 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 599 + 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 627 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 260 - 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 96 + 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 98 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 120 993, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 139 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 126 992, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 143 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from field-text-check.js line 132 991, "Unresolved GIT conflict", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 147 - 990, "Unable to load file", details: `username=$username`, repoName, filename ], elapsedSeconds: 0 ; from FileCheck.js line 63 + 990, "Unable to load file", details: `username=$username`, repoName, filename ], elapsedSeconds: 0 ; from FileCheck.js line 64 989, "Unable to find/load repository", location: ourLocation from checkRepo.js line 186 988, "Bad TSV header", details: `expected '$EXPECTED_TN_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from tn-tsv9-table-check.js line 125 988, "Bad TSV header", details: `expected '$EXPECTED_TWL_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from twl-tsv6-table-check.js line 117 988, "Bad TSV header", details: `expected '$EXPECTED_NOTES_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from notes-tsv7-table-check.js line 117 988, "Bad TSV header", details: `expected '$EXPECTED_QUESTIONS_HEADING_LINE'`, excerpt: lines[0], lineNumber: 1, location: ourLocation from questions-tsv7-table-check.js line 117 - 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,125 + 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, excerpt, location: ourLocation from usfm-text-check.js line 1,174 986, "Repository doesn’t seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 166 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 697 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 424 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 561 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv7-row-check.js line 502 - 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 536 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from twl-tsv6-row-check.js line 423 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 569 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from questions-tsv7-row-check.js line 501 + 984, `Found wrong number of TSV fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, details: `Found $fields.length field$fields.length === 1 ? '' : 's'`, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 546 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TN_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 251 - 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 241 + 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_TWL_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 240 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_NOTES_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 240 983, `Wrong number of tabbed fields (expected $NUM_EXPECTED_QUESTIONS_TSV_FIELDS)`, excerpt: `Found $fields.length field$fields.length === 1 ? '' : 's'`, C, V, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 240 - 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 258 + 979, "Invalid book identifier passed to checkTWL_TSV6DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from twl-tsv6-row-check.js line 256 979, "Invalid book identifier passed to checkTN_TSV9DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-tsv9-row-check.js line 358 - 979, "Invalid book identifier passed to checkQuestionsTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv7-row-check.js line 311 - 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 341 + 979, "Invalid book identifier passed to checkQuestionsTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from questions-tsv7-row-check.js line 310 + 979, "Invalid book identifier passed to checkNotesTSV7DataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from notes-tsv7-row-check.js line 343 978, "Wrong book identifier", details: `expected '$bookID'`, fieldName: 'Book', rowID, excerpt: B, location: ourRowLocation from tn-tsv9-row-check.js line 373 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 376 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 276 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from twl-tsv6-row-check.js line 274 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Chapter', rowID, excerpt: C, location: ourRowLocation from tn-tsv9-row-check.js line 381 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv7-row-check.js line 329 - 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 359 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 312 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from questions-tsv7-row-check.js line 328 + 976, "Wrong chapter number", details: `expected '$givenC'`, fieldName: 'Reference', rowID, excerpt: C, location: ourRowLocation from notes-tsv7-row-check.js line 361 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 310 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 413 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 365 - 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 395 - 956, "Got empty manifest file", repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 204 - 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 277 - 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 234 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 364 + 975, "Wrong verse number", details: `expected '$givenV'`, rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 397 + 956, "Got empty manifest file", repoName, filename: STANDARD_MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 208 + 956, "Got empty markdown file", repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 281 + 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 343 + 950, "tC cannot yet process '*' language code", characterIndex, excerpt, location: ourLocation from notes-links-check.js line 457 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 285 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 283 944, `USFM3 Grammar Check ($strictnessString mode) doesn’t pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 176 943, `USFM3 toJSON Check doesn’t pass`, location: ourLocation from usfm-js-check.js line 91 - 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,175 + 942, "USFM Grammar check fails", location from usfm-text-check.js line 1,224 939, "Key is missing for project", details: keyName, excerpt: JSON.stringify(projectEntry), location: ourLocation from manifest-text-check.js line 709 938, `Unable to find project file mentioned in manifest`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 726 937, `Linked project file seems empty`, excerpt: projectFilepath, location: ourLocation from manifest-text-check.js line 728 @@ -98,10 +99,10 @@ Got 470 notices: 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 662 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 660 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 174 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 364 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 362 919, "Missing Quote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 487 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 417 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 475 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 416 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 477 917, "Unable to find duplicate original language quote in verse text", details: `occurrence=$occurrenceString, passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 339 916, "Unable to find original language quote in verse text", details: "quote which starts with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 381 916, "Unable to find original language quote in verse text", details: "quote which ends with a space" + (noBreakSpaceText ? ' ' + noBreakSpaceText : ''), excerpt, location: ourLocation from orig-quote-check.js line 384 @@ -114,359 +115,384 @@ Got 470 notices: 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 405 915, "Unable to find original language quote portion in verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 326 914, "Unable to find original language quote portion in the right place in the verse text", details: `passage ►$verseText◄`, excerpt, location: ourLocation from orig-quote-check.js line 323 - 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 674 - 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 730 + 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 676 + 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 732 909, "Seems original language quote might not start at the beginning of a word", details: `passage ►$verseText◄`, characterIndex: 0, excerpt, location: ourLocation from orig-quote-check.js line 361 908, "Seems original language quote might not finish at the end of a word", details: `passage ►$verseText◄`, characterIndex: fieldText.length, excerpt, location: ourLocation from orig-quote-check.js line 370 - 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ourLocation from usfm-text-check.js line 990 - 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 308 + 903, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ourLocation from usfm-text-check.js line 1,039 + 902, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 312 900, "Bad parameter: should be given a valid book abbreviation", excerpt: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 76 895, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 105 889, `Unable to find TA link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 109 888, `Error loading TA link`, excerpt: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 114 887, `Linked TA article seems empty`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 111 - 886, `Unable to find $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 256 - 885, `Error loading $fieldName TA link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 251 - 884, `Linked $fieldName TA article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 258 - 883, `Unable to find $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 306 - 882, `Error loading $fieldName TW link`, excerpt: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 303 - 881, `Linked $fieldName TW article seems empty`, excerpt: regexResultArray[0], location: `$ourLocation $filepath` from notes-links-check.js line 309 + 886, `Unable to find $fieldName TA link`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 365 + 886, `Unable to find $fieldName TA link`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 416 + 886, `Unable to find $fieldName TA link`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 479 + 885, `Error loading $fieldName TA link`, excerpt: totalLink, location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 360 + 885, `Error loading $fieldName TA link`, excerpt: totalLink, location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 411 + 885, `Error loading $fieldName TA link`, excerpt: totalLink, location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 474 + 884, `Linked $fieldName TA article seems empty`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 367 + 884, `Linked $fieldName TA article seems empty`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 418 + 884, `Linked $fieldName TA article seems empty`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 481 + 883, `Unable to find/load $fieldName TW link`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 300 + 883, `Unable to find/load $fieldName TW link`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 530 + 883, `Unable to find/load general link`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,115 + 882, `Error loading $fieldName TW link`, excerpt: totalLink, location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 297 + 882, `Error loading $fieldName TW link`, excerpt: totalLink, location: `$ourLocation $filepath: $trcGCerror` from notes-links-check.js line 527 + 881, `Linked $fieldName TW article seems empty`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 303 + 881, `Linked $fieldName TW article seems empty`, excerpt: totalLink, location: `$ourLocation $filepath` from notes-links-check.js line 533 + 881, `Linked general article seems empty`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,118 879, `Badly formatted Resource Container link`, excerpt: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 96 - 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 777 - 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 569 - 869, "Chapter number out of range", C: chapterNumberString, excerpt: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 419 - 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, excerpt: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 458 - 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 472 - 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 477 - 857, "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 822 - 856, "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 825 - 855, "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 828 - 854, "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 831 - 854, "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 834 - 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 837 - 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 839 - 852, "Unexpected original \\w x-morph language prefix", details:"Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 843 + 875, "Unexpected USFM field", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 779 + 873, `Mismatched $opener$closer fields`, excerpt: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 570 + 869, "Chapter number out of range", C: chapterNumberString, excerpt: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 420 + 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, excerpt: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 459 + 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 473 + 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 478 + 857, "Unexpected first original \\w attribute", details: "expected 'lemma'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 824 + 856, "Unexpected second original \\w attribute", details: "expected 'strong'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 827 + 855, "Unexpected third original \\w attribute", details: "expected 'x-morph'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 830 + 854, "Unexpected fourth original \\w attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 833 + 854, "Unexpected fifth original \\w attribute", details: "expected second 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 836 + 854, "Unexpected sixth original \\w attribute", details: "expected third 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 839 + 853, "Unexpected extra original \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 841 + 852, "Unexpected original \\w x-morph language prefix", details: "Expected 'He,' 'Ar,' or 'Gr,'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 845 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 295 849, `Unexpected '$badCharCombination' character combination`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 371 - 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 847 - 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 850 - 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 852 - 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 805 - 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 809 - 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 816 - 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 871 - 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 873 - 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 857 - 836, "Seems too few translation \\w attributes", details: `Expected two attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 859 - 835, "Seems too few original \\k-s attributes", details: `Expected one attribute but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 876 - 834, "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 908 - 833, "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 905 - 830, "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 888 - 829, "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 891 - 828, "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 894 - 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 897 - 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 900 - 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 903 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 281 + 848, "Unexpected first translation \\w attribute", details: "expected 'x-occurrence'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 851 + 847, "Unexpected second translation \\w attribute", details: "expected 'x-occurrences'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 854 + 846, "Unexpected extra translation \\w attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 856 + 845, `Mismatched [[ ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 1,153 + 844, `Mismatched [[rc:// ]] link characters`, details: `left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 1,157 + 843, `Mismatched [ ]( ) link characters`, details: `left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString()`, location: ourLocation from notes-links-check.js line 1,164 + 839, "Unexpected first \\k-s attribute", details: "expected 'x-tw'", lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 875 + 838, "Unexpected extra \\k-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 877 + 837, "Seems too few original \\w attributes", details: `Expected 3-4 attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 861 + 836, "Seems too few translation \\w attributes", details: `Expected two attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 863 + 835, "Seems too few original \\k-s attributes", details: `Expected one attribute but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 880 + 834, "Seems too few translation \\zaln-s attributes", details: `Expected six attributes but only found $attributeCounter`, lineNumber, C, V, excerpt: regexResultArray1[0], location: lineLocation from usfm-text-check.js line 912 + 833, "Unexpected extra \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 909 + 830, "Unexpected first \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 892 + 829, "Unexpected second \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 895 + 828, "Unexpected third \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 898 + 827, "Unexpected fourth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 901 + 826, "Unexpected fifth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 904 + 825, "Unexpected sixth \\zaln-s attribute", details, lineNumber, C, V, excerpt: regexResultArray2[0], location: lineLocation from usfm-text-check.js line 907 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 279 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 386 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 334 - 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 364 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 286 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 333 + 824, `Invalid zero chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 366 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 284 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 391 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 339 - 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 369 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 299 - 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 933 - 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 937 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 338 + 823, `Invalid large chapter number`, excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 371 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 297 + 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, excerpt: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 937 + 822, "Expected field to contain an integer", characterIndex: 3, excerpt: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 941 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 401 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 352 - 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 382 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 305 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 351 + 822, "Unable to check chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 384 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 303 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-tsv9-row-check.js line 406 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 358 - 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 388 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 308 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 357 + 821, "Bad chapter number", excerpt: C, rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 390 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from twl-tsv6-row-check.js line 306 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-tsv9-row-check.js line 409 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv7-row-check.js line 361 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 391 - 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 599 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 317 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from questions-tsv7-row-check.js line 360 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from notes-tsv7-row-check.js line 393 + 819, "Missing compulsory USFM line", excerpt: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 600 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 315 814, "Invalid zero verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 418 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 370 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 400 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 321 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 369 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 402 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from twl-tsv6-row-check.js line 319 813, "Invalid large verse number", rowID, fieldName: 'Verse', excerpt: V, location: ourRowLocation from tn-tsv9-row-check.js line 422 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 374 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 404 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 323 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from questions-tsv7-row-check.js line 373 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', excerpt: V, location: ourRowLocation from notes-tsv7-row-check.js line 406 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 321 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 424 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 376 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 406 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 327 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 375 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 408 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from twl-tsv6-row-check.js line 325 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-tsv9-row-check.js line 428 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv7-row-check.js line 380 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 410 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 330 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from questions-tsv7-row-check.js line 379 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from notes-tsv7-row-check.js line 412 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from twl-tsv6-row-check.js line 328 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-tsv9-row-check.js line 431 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv7-row-check.js line 383 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 413 - 799, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 412 - 798, "Field doesn’t contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 396 - 797, "Field doesn’t contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation from twl-tsv6-row-check.js line 403 - 796, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 393 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 378 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from questions-tsv7-row-check.js line 382 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from notes-tsv7-row-check.js line 415 + 799, "Missing TWLink field", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 411 + 798, "Field doesn’t contain expected TW link", details: `should start with 'rc://*/tw/dict/bible/'`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 395 + 797, "Field doesn’t contain proper TW link", details: `should be 'kt', 'names', or 'other'`, fieldName: 'TWLink', rowID, characterIndex, excerpt, location: ourRowLocation from twl-tsv6-row-check.js line 402 + 796, "Field is only whitespace", fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 392 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 376 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 501 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 431 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 489 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 383 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 430 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 491 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 381 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 506 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 436 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 494 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 435 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 496 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-tsv9-table-check.js line 230 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 220 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from twl-tsv6-table-check.js line 219 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from notes-tsv7-table-check.js line 219 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from questions-tsv7-table-check.js line 219 + 789, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation from tn-tsv9-row-check.js line 550 + 789, "Should have a SupportReference when Note has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation from notes-tsv7-row-check.js line 526 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 462 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 449 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 451 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from tn-tsv9-row-check.js line 467 - 787, "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 454 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation from tn-tsv9-row-check.js line 541 - 786, "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation from notes-tsv7-row-check.js line 515 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 333 + 787, "Link to TA should also be in Note", fieldName: 'SupportReference', excerpt: supportReference, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 456 + 786, "Shouldn’t have multiple TA links in OccurrenceNote", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation from tn-tsv9-row-check.js line 548 + 786, "Shouldn’t have multiple TA links in Note", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation from notes-tsv7-row-check.js line 524 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from twl-tsv6-row-check.js line 331 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-tsv9-row-check.js line 434 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 386 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 416 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 336 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from questions-tsv7-row-check.js line 385 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from notes-tsv7-row-check.js line 418 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 334 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 437 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 389 - 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 419 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 388 + 778, "Row ID should be exactly 4 characters", details: `not $rowID.length`, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 421 777, `Bad punctuation nesting: $char closing character doesn’t match`, details, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 203 - 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 764 - 775, "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 769 + 776, 'Unexpected " straight quote character', details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 766 + 775, "Unexpected ' straight quote character", details, lineNumber, C, V, excerpt, location: lineLocation from usfm-text-check.js line 771 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, excerpt, location: ourLocation from plain-text-check.js line 210 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 171 772, `Unexpected trailing word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 166 771, `Unexpected leading zero-width joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 149 770, `Unexpected leading word-joiner`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 145 - 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,101 + 769, C, V, "Verse bridge numbers not in ascending order", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($firstV → $secondV)`, location: ourLocation from usfm-text-check.js line 1,150 768, `At end of text with unclosed $char opening character`, details, lineNumber: n, characterIndex: x, excerpt, location: ourLocation from plain-text-check.js line 228 - 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,103 + 766, C, V, "Bridged verse numbers didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : '' ($lastV → $firstV)`, location: ourLocation from usfm-text-check.js line 1,152 765, "Unexpected link", characterIndex, excerpt, location: ourLocation from field-text-check.js line 444 - 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,074 - 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,087 - 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 446 - 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,097 - 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,118 - 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 762 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 369 + 764, C, V, "Chapter number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastC ? lastC : '0' → $C)`, location: ourLocation from usfm-text-check.js line 1,123 + 763, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,136 + 762, "Unable to convert verse bridge numbers to integers", C: chapterNumberString, V: verseNumberString, characterIndex: 3, excerpt: verseNumberString, location: `$CVlocation with $usfmVIerror` from usfm-text-check.js line 447 + 762, C, V, "Unable to convert verse bridge numbers to integers", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, Math.max(9, excerptLength))$rest.length > excerptLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,146 + 761, C, V, "Verse number didn’t increment correctly", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : '' ($lastV ? lastV : '0' → $V)`, location: ourLocation from usfm-text-check.js line 1,167 + 752, "Verse numbers of markdown TN link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,050 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from twl-tsv6-row-check.js line 367 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from tn-tsv9-row-check.js line 492 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 422 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 480 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 360 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from questions-tsv7-row-check.js line 421 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, excerpt: occurrence, location: ourRowLocation from notes-tsv7-row-check.js line 482 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 358 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 483 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 413 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 471 - 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 146 - 749, "Markdown image link seems faulty", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 167 - 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 155 - 748, "Error fetching markdown image link", lineNumber, excerpt: fetchLink, location: lineLocation from markdown-text-check.js line 176 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 412 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 473 + 749, "Markdown image link seems faulty", excerpt: fetchLink, location: ourLocation from notes-links-check.js line 227 + 749, "Markdown image link seems faulty", excerpt: fetchLink, location: ourLocation from notes-links-check.js line 248 + 748, "Error fetching markdown image link", excerpt: fetchLink, location: ourLocation from notes-links-check.js line 236 + 748, "Error fetching markdown image link", excerpt: fetchLink, location: ourLocation from notes-links-check.js line 257 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from tn-tsv9-table-check.js line 110 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from twl-tsv6-table-check.js line 101 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from notes-tsv7-table-check.js line 101 747, "Bad function call: should be given a valid book abbreviation", excerpt: bookID, location: ` (not '$bookID')$ourLocation` from questions-tsv7-table-check.js line 101 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 180 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 183 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 362 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 491 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 543 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 651 - 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 703 - 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 756 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 368 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 405 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 444 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 497 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 549 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 601 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 657 - 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 709 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 449 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 555 - 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 607 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 584 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $givenCint`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 650 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 779 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 831 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 939 + 743, "Chapter numbers of markdown Bible link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 991 + 743, "Chapter numbers of markdown TN link don’t match", details: `$C1 vs $linkChapterInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,044 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 590 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 656 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 693 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $V2`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 732 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 785 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 837 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1a vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 889 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 945 + 742, "Verse numbers of markdown Bible link don’t match", details: `$V1 vs $linkVerseInt`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 997 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 737 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 843 + 741, "Verse numbers of markdown Bible link range out of order", details: `$V1a to $V1b`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 895 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-tsv9-table-check.js line 207 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 197 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from twl-tsv6-table-check.js line 196 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from notes-tsv7-table-check.js line 196 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from questions-tsv7-table-check.js line 196 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 226 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 216 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 215 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 215 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 215 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 194 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 184 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 183 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 183 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 183 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 198 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 188 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 187 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 187 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 187 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 200 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 190 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 189 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 189 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 189 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 204 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 216 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 194 - 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 206 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 193 + 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 205 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 193 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 205 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 193 734, C, V, "Invalid large verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 205 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 220 - 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 210 + 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 209 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 209 733, C, V, "Receding verse number", details: `'$V' after '$lastV for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 209 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 236 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 226 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 225 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 225 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 225 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-tsv9-table-check.js line 234 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 224 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from twl-tsv6-table-check.js line 223 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from notes-tsv7-table-check.js line 223 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from questions-tsv7-table-check.js line 223 - 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,070 - 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,083 - 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,114 + 724, C, V, "Unable to convert chapter number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,119 + 723, C, V, "Unable to convert verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$rest.substring(0, excerptHalfLength)$rest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,132 + 720, C, V, "Unable to convert internal verse number to integer", lineNumber: n, characterIndex: 3, excerpt: `$restRest.substring(0, excerptHalfLength)$restRest.length > excerptHalfLength ? '…' : ''`, location: ourLocation from usfm-text-check.js line 1,163 716, `Misplaced $rightChar character`, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 425 - 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 966 - 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,034 - 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 778 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 384 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 421 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 462 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 513 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 571 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 673 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 725 - 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 780 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 386 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 423 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 464 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 515 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 573 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 623 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 675 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 727 - 649, "Unusual [[ ]] link(s)—not normal TA or TW links", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 797 - 648, "Unusual [ ]( ) link(s)—not normal Bible or TN links", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 791 - 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 256 + 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 970 + 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,083 + 669, "Unexpected language code in link", details: `resource language code is '$languageCode'`, excerpt: Lg, location: ourLocation from notes-links-check.js line 566 + 656, "Bad chapter number in markdown TN link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,066 + 655, "Bad story number in markdown OBS help link", details: `$linkBookCode $linkChapterInt vs $numStories chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 598 + 655, "Bad chapter number in markdown Bible help link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 612 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $givenCint vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 672 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 709 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 750 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 801 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 859 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 961 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $linkChapterInt vs $numChaptersThisBook chapters`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,013 + 654, "Bad verse number in markdown TN link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,068 + 653, "Bad frame number in markdown OBS help link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numFramesThisStory verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 600 + 653, "Bad verse number in markdown Bible help link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 614 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenCint:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 674 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 711 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 752 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 803 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 861 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $givenC:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 911 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 963 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $linkChapterInt:$linkVerseInt vs $numVersesThisChapter verses`, excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,015 + 649, "Unusual [[ ]] link(s)—not a recognized TA or TW link", details: `need to carefully check $leftoverLinksList2.length === 1 ? '"' + leftoverLinksList2[0] + '"' : JSON.stringify(leftoverLinksList2)`, location: ourLocation from notes-links-check.js line 1,145 + 648, "Unusual [ ]( ) link(s)—not a recognized Bible or TA, TN, or TW link", details: `need to carefully check $leftoverLinksList1.length === 1 ? '"' + leftoverLinksList1[0] + '"' : JSON.stringify(leftoverLinksList1)`, location: ourLocation from notes-links-check.js line 1,137 + 644, "USFM3 Grammar Check (relaxed mode) doesn’t pass either", location: fileLocation from usfm-text-check.js line 257 638, "Only found whitespace", location: ourLocation from field-text-check.js line 111 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 131 - 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,004 + 603, "USFM marker doesn’t end with space", C, V, lineNumber, characterIndex, excerpt, location: ourLocation from usfm-text-check.js line 1,053 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 117 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 150 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 158 - 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 167 + 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 169 583, "Unexpected newLine character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 239 582, "Unexpected carriageReturn character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 245 581, "Unexpected non-break space character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 251 - 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 356 + 555, "Possible missing chapter number in markdown Bible link", excerpt: totalLink, location: ourLocation from notes-links-check.js line 644 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from tn-tsv9-table-check.js line 214 - 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 204 + 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from twl-tsv6-table-check.js line 203 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from notes-tsv7-table-check.js line 203 552, C, V, "Invalid zero verse number", details: `for chapter $C`, rowID, lineNumber: n + 1, excerpt: V, location: ourLocation from questions-tsv7-table-check.js line 203 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from tn-tsv9-table-check.js line 192 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 182 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from twl-tsv6-table-check.js line 181 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from notes-tsv7-table-check.js line 181 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, excerpt: C, location: ourLocation from questions-tsv7-table-check.js line 181 539, "File starts with empty line", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 153 538, "File ends without newline character", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 158 - 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 603 - 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 611 - 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 607 - 450, "Resource container link should have '*' language code", details: `not '$languageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 229 - 444, "Shouldn’t have consecutive word fields without a space", details: badCount> 1? details+`$badCount occurrences found in line`: details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 645 - 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 149 + 519, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 604 + 518, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 612 + 517, "Missing expected USFM line", excerpt: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 608 + 450, "Resource container link should have '*' language code", details: `not '$foundLanguageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 338 + 450, "Resource container link should have '*' language code", details: `not '$foundLanguageCode'`, characterIndex, excerpt, location: ourLocation from notes-links-check.js line 452 + 444, "Shouldn’t have consecutive word fields without a space", details: badCount > 1 ? details + `$badCount occurrences found in line` : details, lineNumber, C, V, characterIndex, excerpt, location: lineLocation from usfm-text-check.js line 646 + 441, `Unknown linkType parameter`, excerpt: linkType from field-link-check.js line 151 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 44 - 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 121 - 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 964 - 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,138 - 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 332 + 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 123 + 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 968 + 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `'\\$lastMarker' before '\\$marker'`, location: ourLocation from usfm-text-check.js line 1,187 + 378, `Possible mismatched '$thisField' markdown formatting pairs`, details: `$count.toLocaleString() total occurrence$count === 1 ? '' : 's'`, characterIndex, excerpt, location: ourLocation from markdown-text-check.js line 379 375, "Divider without surrounding snippet", location: ourLocation from orig-quote-check.js line 332 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 390 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'TWLink', rowID, location: ourRowLocation from twl-tsv6-row-check.js line 389 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 471 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 513 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 528 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 443 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 468 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 459 - 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 501 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 442 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 467 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'SupportReference', characterIndex, rowID, location: ourRowLocation from notes-tsv7-row-check.js line 461 + 374, "Field contains zero-width space(s)", details: `$charCount occurrence$charCount === 1 ? '' : 's' found`, fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 503 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 455 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 516 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 531 - 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 446 - 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 471 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 440 - 373, "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 504 - 349, "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 144 - 349, "Markdown image link has no alternative text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 163 - 348, "Markdown image link has no title text", lineNumber, excerpt: totalLink, location: lineLocation from markdown-text-check.js line 165 - 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 698 - 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 962 - 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 163 - 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 547 - 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 463 - 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 488 - 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 522 - 256, "Possibly missing current copyright year", details: `possibly expecting '$fullYearString'`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 270 - 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 614 + 373, "Field is only whitespace", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 445 + 373, "Field is only whitespace", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 470 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 442 + 373, "Field is only whitespace", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 506 + 349, "Markdown image link has no alternative text", excerpt: totalLink, location: ourLocation from notes-links-check.js line 225 + 349, "Markdown image link has no alternative text", excerpt: totalLink, location: ourLocation from notes-links-check.js line 244 + 348, "Markdown image link has no title text", excerpt: totalLink, location: ourLocation from notes-links-check.js line 246 + 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 700 + 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, excerpt: rest, location: lineLocation from usfm-text-check.js line 966 + 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 165 + 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-tsv9-row-check.js line 555 + 274, "Missing Question field", fieldName: 'Question', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 462 + 274, "Missing Response field", fieldName: 'Response', rowID, location: ourRowLocation from questions-tsv7-row-check.js line 487 + 274, "Missing Note field", fieldName: 'Note', rowID, location: ourRowLocation from notes-tsv7-row-check.js line 532 + 256, "Possibly missing current copyright year", details: `possibly expecting '$fullYearString'`, username, repoName, filename, location: markdownLocation, extra: repoCode from checkBookPackage.js line 274 + 218, "Using deprecated USFM marker", excerpt: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 615 195, `Unexpected $punctChar character at start of line`, characterIndex, excerpt, location: ourLocation from field-text-check.js line 322 179, "Unexpected space before ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 267 178, "Unexpected space after ellipse character", characterIndex, excerpt, location: ourLocation from field-text-check.js line 273 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 343 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 341 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 444 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 396 - 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 426 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 345 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 395 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 343 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 446 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 398 - 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 428 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 347 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 397 + 175, "Row ID should end with a lowercase letter or digit", characterIndex: 3, rowID, fieldName: 'ID', excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 345 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 448 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 400 - 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 430 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 349 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 399 + 174, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 1, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 432 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from twl-tsv6-row-check.js line 347 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from tn-tsv9-row-check.js line 450 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 402 - 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 432 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from questions-tsv7-row-check.js line 401 + 173, "Row ID characters should only be lowercase letters, digits, or hypen", fieldName: 'ID', characterIndex: 2, rowID, excerpt: rowID, location: ourRowLocation from notes-tsv7-row-check.js line 434 159, "Should use proper ellipse character (not periods)", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 256 158, `Unexpected space(s) beside divider $discontiguousDivider`, characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 265 156, "Unexpected space(s) beside ellipse characters", characterIndex, excerpt, location: ourLocation from orig-quote-check.js line 279 + 152, "Should http link be https", excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,126 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 664 - 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 747 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 346 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 483 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 534 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 592 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 642 - 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 694 + 144, "Unknown Bible book name in TN link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 1,035 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 575 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 634 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 771 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 822 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 880 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 930 + 143, "Unknown Bible book name in link", details: totalLink, excerpt: optionalB1, location: ourLocation from notes-links-check.js line 982 138, "File ends with additional blank line(s)", characterIndex, excerpt, location: ourLocation from plain-text-check.js line 163 - 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 131 + 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 133 110, `Unexpected leading spaces`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 140 109, `Unexpected leading space`, characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 142 107, "Unexpected leading line break", characterIndex: 0, excerpt, location: ourLocation from field-text-check.js line 181 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, excerpt, location: ourLocation from field-text-check.js line 214 - 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,179 - 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 250 + 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 1,228 + 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 251 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 184 94, "Unexpected trailing space(s) before break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 201 93, "Unexpected trailing space(s) before line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 206 - 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,131 - 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,133 - 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 470 + 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,180 + 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `not '\\$lastMarker'`, location: ourLocation from usfm-text-check.js line 1,182 + 82, `Error loading general link`, details: "please double-check link—there may be no problem", excerpt: totalLink, location: `$ourLocation: $trcGCerror` from notes-links-check.js line 1,111 + 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 471 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 155 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 160 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 305 + 32, `Untested general link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,092 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 263 - 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 253 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 252 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 252 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from questions-tsv7-table-check.js line 252 diff --git a/package.json b/package.json index ac3c6892d..1b261995f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha10", + "version": "2.0.0_alpha11", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/__snapshots__/book-package-check.test.js.snap b/src/__tests__/__snapshots__/book-package-check.test.js.snap index 2becb6999..277969c60 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -4337,7 +4337,7 @@ Object { "V": "6", "bookID": "RUT", "branch": "master", - "details": "(SR='figs-idiom')", + "details": "SR='figs-idiom'", "excerpt": "figs-synecdoche", "extra": "TN", "fieldName": "OccurrenceNote", @@ -4345,7 +4345,7 @@ Object { "lineNumber": 19, "location": " in en RUT book package from unfoldingWord master branch", "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, + "priority": 789, "repoCode": "TN", "repoName": "en_tn", "rowID": "ab01", @@ -4393,7 +4393,7 @@ Object { "V": "9", "bookID": "RUT", "branch": "master", - "details": "(empty SR field)", + "details": "empty SR field", "excerpt": "figs-euphemism", "extra": "TN", "fieldName": "OccurrenceNote", @@ -4401,7 +4401,7 @@ Object { "lineNumber": 94, "location": " in en RUT book package from unfoldingWord master branch", "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, + "priority": 789, "repoCode": "TN", "repoName": "en_tn", "rowID": "v5e4", @@ -4448,7 +4448,7 @@ Object { "V": "12", "bookID": "RUT", "branch": "master", - "details": "(empty SR field)", + "details": "empty SR field", "excerpt": "grammar-connect-logic-contrast", "extra": "TN", "fieldName": "OccurrenceNote", @@ -4456,7 +4456,7 @@ Object { "lineNumber": 184, "location": " in en RUT book package from unfoldingWord master branch", "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, + "priority": 789, "repoCode": "TN", "repoName": "en_tn", "rowID": "jdr7", @@ -4486,7 +4486,7 @@ Object { "V": "7", "bookID": "RUT", "branch": "master", - "details": "(empty SR field)", + "details": "empty SR field", "excerpt": "figs-idiom", "extra": "TN", "fieldName": "OccurrenceNote", @@ -4494,7 +4494,7 @@ Object { "lineNumber": 230, "location": " in en RUT book package from unfoldingWord master branch", "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, + "priority": 789, "repoCode": "TN", "repoName": "en_tn", "rowID": "d46w", @@ -26870,7 +26870,7 @@ Object { "V": "10", "bookID": "TIT", "branch": "master", - "details": "(empty SR field)", + "details": "empty SR field", "excerpt": "figs-metaphor", "extra": "TN", "fieldName": "OccurrenceNote", @@ -26878,7 +26878,7 @@ Object { "lineNumber": 44, "location": " in en TIT book package from unfoldingWord master branch", "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, + "priority": 789, "repoCode": "TN", "repoName": "en_tn", "rowID": "w9kk", @@ -26889,14 +26889,14 @@ Object { "V": "5", "bookID": "TIT", "branch": "master", - "details": "(SR='figs-activepassive')", - "excerpt": "figs-metonymy", + "details": "SR='figs-activepassive'—found 2 TA links", + "excerpt": "[\\"figs-activepassive\\",\\"figs-metonymy\\"]", "extra": "TN", "fieldName": "OccurrenceNote", "filename": "en_tn_57-TIT.tsv", "lineNumber": 91, "location": " in en TIT book package from unfoldingWord master branch", - "message": "Should have a SupportReference when OccurrenceNote has a TA link", + "message": "Shouldn’t have multiple TA links in OccurrenceNote", "priority": 786, "repoCode": "TN", "repoName": "en_tn", diff --git a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap index f393762e6..719e32761 100644 --- a/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap +++ b/src/__tests__/__snapshots__/tn-table-row-check.test.js.snap @@ -918,24 +918,12 @@ Object { "C": "1", "V": "9", "bookID": "GEN", - "details": "(SR='figs-activepassive')", - "excerpt": "figs-activepassivez", + "details": "SR='figs-activepassive'—found 2 TA links", + "excerpt": "[\\"figs-activepassivez\\",\\"figs-imperative\\"]", "fieldName": "OccurrenceNote", "location": " that was supplied", "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, - "rowID": "zu6f", - }, - Object { - "C": "1", - "V": "9", - "bookID": "GEN", - "details": "(SR='figs-activepassive')", - "excerpt": "figs-imperative", - "fieldName": "OccurrenceNote", - "location": " that was supplied", - "message": "Should have a SupportReference when OccurrenceNote has a TA link", - "priority": 786, + "priority": 789, "rowID": "zu6f", }, ], @@ -1006,11 +994,11 @@ Object { "C": "1", "V": "9", "bookID": "GEN", - "details": "(SR='figs-activepassive')", - "excerpt": "figs-imperativez", + "details": "SR='figs-activepassive'—found 2 TA links", + "excerpt": "[\\"figs-activepassive\\",\\"figs-imperativez\\"]", "fieldName": "OccurrenceNote", "location": " that was supplied", - "message": "Should have a SupportReference when OccurrenceNote has a TA link", + "message": "Shouldn’t have multiple TA links in OccurrenceNote", "priority": 786, "rowID": "zu6f", }, diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index d4410819c..07dfbeb8b 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -90,7 +90,7 @@ describe('checkTN_TSV9DataRow() - ', () => { it('should fail invalid first link', async () => { const chosenLine = "GEN\t1\t9\tzu6f\tfigs-activepassive\t\t0\tLet the waters…be gathered\tThis can be translated with an active verb. This is a command. By commanding that the waters gather together, God made them gather together. Alternate translation: “Let the waters…gather” or “Let the waters…come together” (See: [[rc://*/ta/man/translate/figs-activepassivez]] and [[rc://*/ta/man/translate/figs-imperative]])"; const rawResults = await checkTN_TSV9DataRow(languageCode, repoCode, chosenLine, 'GEN', '1', '9', 'that was supplied', optionalCheckingOptions); - expect(rawResults.noticeList.length).toEqual(5); + expect(rawResults.noticeList.length).toEqual(4); expect(rawResults).toMatchSnapshot(); }); diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index 6f3448545..ca243bc71 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -598,7 +598,7 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g addNoticePartial({ priority: 655, message: "Bad story number in markdown OBS help link", details: `${linkBookCode} ${linkChapterInt} vs ${numStories} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numFramesThisStory) addNoticePartial({ priority: 653, message: "Bad frame number in markdown OBS help link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numFramesThisStory} verses`, excerpt: totalLink, location: ourLocation }); - } else { // then we know which Bible book this link is to + } else if (linkBookCode) { // then we know which Bible book this link is to // So we can check for valid C:V numbers let numChaptersThisBook, numVersesThisChapter; logicAssert(linkBookCode.toLowerCase() !== 'obs', `BIBLE_FULL_HELP_REGEX linkBookCode shouldn’t be '${linkBookCode}' in notes-links-check`); @@ -612,7 +612,8 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g addNoticePartial({ priority: 655, message: "Bad chapter number in markdown Bible help link", details: `${linkBookCode} ${linkChapterInt} vs ${numChaptersThisBook} chapters`, excerpt: totalLink, location: ourLocation }); else if (!linkVerseInt || linkVerseInt < 0 || linkVerseInt > numVersesThisChapter) addNoticePartial({ priority: 653, message: "Bad verse number in markdown Bible help link", details: `${linkBookCode} ${linkChapterInt}:${linkVerseInt} vs ${numVersesThisChapter} verses`, excerpt: totalLink, location: ourLocation }); - } + } else + debugLog(`Seems BIBLE_FULL_HELP_REGEX '${totalLink}' didn't have a link book code!`); } // Check for this-chapter Bible links like [Revelation 3:11](./11.md) @@ -1084,16 +1085,16 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g const dummyPathParameters = { username: uri, repository: '', path: '', branch: '' }; if (await alreadyChecked(dummyPathParameters) !== true) { // debugLog(`checkNotesLinksToOutside general link check needs to check: ${uri}`); + const serverString = uri.replace('://','!!!').split('/')[0].replace('!!!','://').toLowerCase(); // Get the bit before any forward slashes // TODO: Uncomment this block and get it working better - if (false) // don't try to fetch general links + if (!serverString.endsWith('door43.org') && !serverString.endsWith('unfoldingword.org')) // don't try to fetch general links addNoticePartial({ priority: 32, message: `Untested general link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation }); else { // Try to fetch general links let generalFileContent, hadError = false; try { // generalFileContent = await cachedGetFileUsingFullURL({ uri }); // debugLog(`${displayText} ${uri} got: (${generalFileContent.length}) ${generalFileContent.substring(0, 10)}...`); - // const serverString = uri.replace('://','!!!').split('/')[0].replace('!!!','://'); // Get the bit before any forward slashes // debugLog(`uri='${uri}', serverString='${serverString}'`); // NOTE: The following line (with or without the mode) doesn't help -- actually makes things slightly worse // const response = await fetch(uri, {headers:{'Access-Control-Allow-Origin': serverString}}); diff --git a/src/core/notes-tsv7-row-check.js b/src/core/notes-tsv7-row-check.js index 41061edcf..545c15b8a 100644 --- a/src/core/notes-tsv7-row-check.js +++ b/src/core/notes-tsv7-row-check.js @@ -8,7 +8,7 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.9'; +// const NOTES_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.10'; const NUM_EXPECTED_NOTES_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_NOTES_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tNote'; @@ -508,14 +508,22 @@ export async function checkNotesTSV7DataRow(languageCode, repoCode, line, bookID const adjustedNote = note.replace(/\\n/g, '\n'); ASuggestion = await ourMarkdownTextChecks(rowID, 'Note', adjustedNote, true, ourRowLocation, checkingOptions); // await ourCheckNotesLinksToOutside(rowID, 'Note', adjustedNote, ourRowLocation, linkCheckingOptions); - let regexResultArray; + let regexResultArray, linksList = [], foundSR = false; while ((regexResultArray = TA_REGEX.exec(adjustedNote))) { // debugLog("Got TA Regex in Note", JSON.stringify(regexResultArray)); + linksList.push(regexResultArray[1]) const adjustedLink = regexResultArray[0].substring(2, regexResultArray[0].length - 2) - if (supportReference !== adjustedLink && V !== 'intro') { - const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'Note', excerpt: adjustedLink, location: ourRowLocation }); - } + if (adjustedLink === supportReference) foundSR = true; + } + if (linksList.length && V !== 'intro') { + let details = supportReference ? `SR='${supportReference}'` : "empty SR field" + if (linksList.length > 1) details += `—found ${linksList.length} TA links`; + const excerpt = linksList.length > 1? JSON.stringify(linksList): linksList[0]; + if (foundSR) { + if (linksList.length > 1) + addNoticePartial({ priority: 786, message: "Shouldn’t have multiple TA links in Note", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation }); + } else // didn't find SR + addNoticePartial({ priority: 789, message: "Should have a SupportReference when Note has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation }); } } } diff --git a/src/core/notes-tsv7-row-check.md b/src/core/notes-tsv7-row-check.md index 1e11db56a..72493a63a 100644 --- a/src/core/notes-tsv7-row-check.md +++ b/src/core/notes-tsv7-row-check.md @@ -1,6 +1,6 @@ ## Notes (TSV) Row Check Sandbox -This function checks one tab-separated line for typical formatting errors. +Designed for the new Translation Notes (TN2) and Study Notes (SN), this function checks one tab-separated line for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) diff --git a/src/core/notes-tsv7-table-check.md b/src/core/notes-tsv7-table-check.md index 2fa52c986..55f431ad2 100644 --- a/src/core/notes-tsv7-table-check.md +++ b/src/core/notes-tsv7-table-check.md @@ -1,6 +1,6 @@ ## Notes (TSV) Table Text Check Sandbox -This function checks the given block of note (TSV) table lines for typical formatting errors. +Designed for the new Translation Notes (TN2) and Study Notes (SN), this function checks the given block of note (TSV) table lines for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) diff --git a/src/core/questions-tsv7-row-check.md b/src/core/questions-tsv7-row-check.md index b1a85ea36..04c5e60b8 100644 --- a/src/core/questions-tsv7-row-check.md +++ b/src/core/questions-tsv7-row-check.md @@ -1,6 +1,6 @@ ## Questions (TSV) Row Check Sandbox -This function checks one tab-separated line for typical formatting errors. +Designed for the new Translation Questions (TQ2) and Study Questions (SQ), this function checks one tab-separated line for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) diff --git a/src/core/questions-tsv7-table-check.md b/src/core/questions-tsv7-table-check.md index 8f75a4146..85566d3b8 100644 --- a/src/core/questions-tsv7-table-check.md +++ b/src/core/questions-tsv7-table-check.md @@ -1,6 +1,6 @@ ## Questions (TSV) Table Text Check Sandbox -This function checks the given block of question/response (TSV) table lines for typical formatting errors. +Designed for the new Translation Questions (TQ2) and Study Questions (SQ), this function checks the given block of question/response (TSV) table lines for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) diff --git a/src/core/tn-tsv9-row-check.js b/src/core/tn-tsv9-row-check.js index 2cc8f41c2..8eb08e677 100644 --- a/src/core/tn-tsv9-row-check.js +++ b/src/core/tn-tsv9-row-check.js @@ -8,7 +8,7 @@ import { checkOriginalLanguageQuote } from './orig-quote-check'; import { parameterAssert } from './utilities'; -// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.7.0'; +// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.7.1'; const NUM_EXPECTED_TN_TSV_FIELDS = 9; // so expects 8 tabs per line const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOrigQuote\tOccurrence\tGLQuote\tOccurrenceNote'; @@ -533,13 +533,21 @@ export async function checkTN_TSV9DataRow(languageCode, repoCode, line, bookID, const adjustedOccurrenceNote = occurrenceNote.replace(/<br>/g, '\n'); ONSuggestion = await ourMarkdownTextChecks(rowID, 'OccurrenceNote', adjustedOccurrenceNote, true, ourRowLocation, checkingOptions); // await ourCheckNotesLinksToOutside(rowID, 'OccurrenceNote', adjustedOccurrenceNote, ourRowLocation, linkCheckingOptions); - let regexResultArray; + let regexResultArray, linksList = [], foundSR = false; while ((regexResultArray = TA_REGEX.exec(adjustedOccurrenceNote))) { // debugLog("Got TA Regex in OccurrenceNote", JSON.stringify(regexResultArray)); - if (supportReference !== regexResultArray[1] && V !== 'intro') { - const details = supportReference ? `(SR='${supportReference}')` : "(empty SR field)" - addNoticePartial({ priority: 786, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt: regexResultArray[1], location: ourRowLocation }); - } + linksList.push(regexResultArray[1]) + if (regexResultArray[1] === supportReference) foundSR = true; + } + if (linksList.length && V !== 'intro') { + let details = supportReference ? `SR='${supportReference}'` : "empty SR field" + if (linksList.length > 1) details += `—found ${linksList.length} TA links`; + const excerpt = linksList.length > 1? JSON.stringify(linksList): linksList[0]; + if (foundSR) { + if (linksList.length > 1) + addNoticePartial({ priority: 786, message: "Shouldn’t have multiple TA links in OccurrenceNote", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation }); + } else // didn't find SR + addNoticePartial({ priority: 789, message: "Should have a SupportReference when OccurrenceNote has a TA link", details, rowID, fieldName: 'OccurrenceNote', excerpt, location: ourRowLocation }); } } } diff --git a/src/core/tn-tsv9-row-check.md b/src/core/tn-tsv9-row-check.md index 700f1fe35..8663bc11c 100644 --- a/src/core/tn-tsv9-row-check.md +++ b/src/core/tn-tsv9-row-check.md @@ -1,6 +1,6 @@ ## TN TSV Table Row Check Sandbox -This function checks one TranslationNotes tab-separated line for typical formatting errors. +This function checks one Translation Notes (TN) tab-separated (9-columns) line for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) diff --git a/src/core/tn-tsv9-table-check.md b/src/core/tn-tsv9-table-check.md index 68b3a9a88..32b7584ee 100644 --- a/src/core/tn-tsv9-table-check.md +++ b/src/core/tn-tsv9-table-check.md @@ -1,6 +1,6 @@ ## TN TSV Table Text Check Sandbox -This function checks the given block of TranslationNote TSV table lines for typical formatting errors. +This function checks the given block of Translation Note (TN) 9-column TSV table lines for typical formatting errors. It returns a list of success messages and a list of notice components. (There is always a priority number in the range 0..999 and the main message string, as well as other details to help locate the error as available.) diff --git a/styleguide.config.js b/styleguide.config.js index 7bd86ff0e..8b3fde9fc 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -123,17 +123,17 @@ let sections = [ // content: 'src/core/README.md', sections: [ { - name: 'TWLLinks TSV6 table check', + name: 'TW Links TSV6 table check', content: 'src/core/twl-tsv6-table-check.md', // description: '' }, { - name: 'TQ/SQ TSV7 table check', + name: 'TQ2/SQ TSV7 table check', content: 'src/core/questions-tsv7-table-check.md', // description: '' }, { - name: 'TN/SN TSV7 table check', + name: 'TN2/SN TSV7 table check', content: 'src/core/notes-tsv7-table-check.md', // description: '' }, diff --git a/yarn.lock b/yarn.lock index 2e4f9d875..2c168ccca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -90,9 +90,9 @@ source-map "^0.5.0" "@babel/generator@^7.13.0", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.0.tgz#bd00d4394ca22f220390c56a0b5b85568ec1ec0c" - integrity sha512-zBZfgvBB/ywjx0Rgc2+BwoH/3H+lDtlgD4hBOpEv5LxRnYsm/753iRuLepqnYlynpjC3AdQxtxsoeHJoEEwOAw== + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" + integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== dependencies: "@babel/types" "^7.13.0" jsesc "^2.5.1" @@ -142,10 +142,10 @@ "@babel/helper-annotate-as-pure" "^7.12.13" regexpu-core "^4.7.1" -"@babel/helper-define-polyfill-provider@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.4.tgz#b618b087c6a0328127e5d53576df818bcee2b15f" - integrity sha512-K5V2GaQZ1gpB+FTXM4AFVG2p1zzhm67n9wrQCJYNzvuLzQybhJyftW7qeDd2uUxPDNdl5Rkon1rOAeUeNDZ28Q== +"@babel/helper-define-polyfill-provider@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz#3c2f91b7971b9fc11fe779c945c014065dea340e" + integrity sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -307,9 +307,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.13.4", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.13.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.4.tgz#340211b0da94a351a6f10e63671fa727333d13ab" - integrity sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA== + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99" + integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw== "@babel/plugin-proposal-async-generator-functions@^7.13.8", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.13.8" @@ -864,9 +864,9 @@ semver "^5.5.1" "@babel/plugin-transform-runtime@^7.12.1": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.8.tgz#8c9a16db6cb6c2a1f748e36ae23558b92d223010" - integrity sha512-6UbZ7P0FuuJiiUyRCfDgLw4PIG9bR2x6swHocv4qNZItkhXad0WsN6YX0deILuyZY2++meDKiDMuSVcejDZN0Q== + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.9.tgz#744d3103338a0d6c90dee0497558150b490cee07" + integrity sha512-XCxkY/wBI6M6Jj2mlWxkmqbKPweRanszWbF3Tyut+hKh+PHcuIH/rSr/7lmmE7C3WW+HSIm2GT+d5jwmheuB0g== dependencies: "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" @@ -1002,9 +1002,9 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.4.5": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.13.8.tgz#1133d7ae806d6bf981b7a1a49e336d4d88db1953" - integrity sha512-Sso1xOpV4S3ofnxW2DsWTE5ziRk62jEAKLGuQ+EJHC+YHTbFG38QUTixO3JVa1cYET9gkJhO1pMu+/+2dDhKvw== + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.13.9.tgz#3ee5f233316b10d066d7f379c6d1e13a96853654" + integrity sha512-mcsHUlh2rIhViqMG823JpscLMesRt3QbMsv1+jhopXEb3W2wXvQ9QoiOlZI9ZbR3XqPtaFpZwEZKYqGJnGMZTQ== dependencies: "@babel/compat-data" "^7.13.8" "@babel/helper-compilation-targets" "^7.13.8" @@ -1118,9 +1118,9 @@ "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.12.1", "@babel/runtime-corejs3@^7.9.6": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.8.tgz#149749463be6692e3688584130e4300beba0e93c" - integrity sha512-iaInhjy1BbDnqc7pZiIXAfWvBnczgWobHceR4Wkhs5tWZG8aIazBYH0Vo73lixecHKh3Vy9yqbQBqVDrmcVDlQ== + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.9.tgz#b2fa9a6e5690ef8d4c4f2d30cac3ec1a8bb633ce" + integrity sha512-p6WSr71+5u/VBf1KDS/Y4dK3ZwbV+DD6wQO3X2EbUVluEOiyXUk09DzcwSaUH4WomYXrEPC+i2rqzuthhZhOJw== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1133,9 +1133,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.8.tgz#cc886a85c072df1de23670dc1aa59fc116c4017c" - integrity sha512-CwQljpw6qSayc0fRG1soxHAKs1CnQMOChm4mlQP6My0kf9upVGizj/KhlTTgyUnETmHpcUXjaluNAkteRFuafg== + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.9.tgz#97dbe2116e2630c489f22e0656decd60aaa1fcee" + integrity sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA== dependencies: regenerator-runtime "^0.13.4" @@ -1932,9 +1932,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.0.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.1.tgz#374e31645d58cb18a07b3ecd8e9dede4deb2cccd" - integrity sha512-DxZZbyMAM9GWEzXL+BMZROWz9oo6A9EilwwOMET2UVu2uZTqMWS5S69KVtuVKaRjCUpcrOXRalet86/OpG4kqw== + version "2.2.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.2.tgz#e2280c89ddcbeef340099d6968d8c86ba155fdf6" + integrity sha512-i99hy7Ki19EqVOl77WplDrvgNugHnsSjECVR/wUrzw2TJXz1zlUfT2ngGckR6xN7yFYaijsMAqPkOLx9HgUqHg== "@types/prop-types@*": version "15.7.3" @@ -2814,9 +2814,9 @@ axe-core@^4.0.2: integrity sha512-V+Nq70NxKhYt89ArVcaNL9FDryB3vQOd+BFXZIfO3RP6rwtj+2yqqqdHEkacutglPaZLkJeuXKCjCJDMGPtPqg== axios-cache-adapter@^2.5.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/axios-cache-adapter/-/axios-cache-adapter-2.7.0.tgz#3da2871840634457cd449d485a781aecc630a035" - integrity sha512-itggIo9i8tnsBFnniNh8+7RxXfdCKZT+cEvyjzBdU8IIyudpj4WyrY7288KE8MICs6+u7YFRVlLZi3vvXufz8w== + version "2.7.2" + resolved "https://registry.yarnpkg.com/axios-cache-adapter/-/axios-cache-adapter-2.7.2.tgz#71e38728eacdbeb4a05d8bccdc98d29c01ec2814" + integrity sha512-g+h3CVcrpCl39Hmnh+/TqqDdUUGJQkWNEEyuaPryU8ubL4hJpSZYCQjy4h153doas1I+YxjZetvH9tQoNMNxBQ== dependencies: cache-control-esm "1.0.0" md5 "^2.2.1" @@ -2959,28 +2959,28 @@ babel-plugin-named-asset-import@^0.3.6: integrity sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw== babel-plugin-polyfill-corejs2@^0.1.4: - version "0.1.8" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.8.tgz#54ef37b1c4b2311e515029e8f1f07bbd4d7a5321" - integrity sha512-kB5/xNR9GYDuRmVlL9EGfdKBSUVI/9xAU7PCahA/1hbC2Jbmks9dlBBYjHF9IHMNY2jV/G2lIG7z0tJIW27Rog== + version "0.1.10" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.10.tgz#a2c5c245f56c0cac3dbddbf0726a46b24f0f81d1" + integrity sha512-DO95wD4g0A8KRaHKi0D51NdGXzvpqVLnLu5BTvDlpqUEpTmeEtypgC1xqesORaWmiUOQI14UHKlzNd9iZ2G3ZA== dependencies: "@babel/compat-data" "^7.13.0" - "@babel/helper-define-polyfill-provider" "^0.1.4" + "@babel/helper-define-polyfill-provider" "^0.1.5" semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.6.tgz#ed1b02fba4885e0892e06094e27865f499758d27" - integrity sha512-IkYhCxPrjrUWigEmkMDXYzM5iblzKCdCD8cZrSAkQOyhhJm26DcG+Mxbx13QT//Olkpkg/AlRdT2L+Ww4Ciphw== + version "0.1.7" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz#80449d9d6f2274912e05d9e182b54816904befd0" + integrity sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw== dependencies: - "@babel/helper-define-polyfill-provider" "^0.1.4" + "@babel/helper-define-polyfill-provider" "^0.1.5" core-js-compat "^3.8.1" babel-plugin-polyfill-regenerator@^0.1.2: - version "0.1.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.5.tgz#f42a58fd86a1c97fbe3a2752d80a4a3e017203e1" - integrity sha512-EyhBA6uN94W97lR7ecQVTvH9F5tIIdEw3ZqHuU4zekMlW82k5cXNXniiB7PRxQm06BqAjVr4sDT1mOy4RcphIA== + version "0.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.6.tgz#0fe06a026fe0faa628ccc8ba3302da0a6ce02f3f" + integrity sha512-OUrYG9iKPKz8NxswXbRAdSwF0GhRdIEMTloQATJi4bDuFqrXaXcCUT/VGNrr8pBcjMh1RxZ7Xt9cytVJTJfvMg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.1.4" + "@babel/helper-define-polyfill-provider" "^0.1.5" babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" @@ -3537,9 +3537,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: - version "1.0.30001192" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz#b848ebc0ab230cf313d194a4775a30155d50ae40" - integrity sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw== + version "1.0.30001194" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001194.tgz#3d16ff3d734a5a7d9818402c28b1f636c5be5bed" + integrity sha512-iDUOH+oFeBYk5XawYsPtsx/8fFpndAPUQJC7gBTfxHM8xw5nOZv7ceAD4frS1MKCLUac7QL5wdAJiFQlDRjXlA== canvg@^3.0.6: version "3.0.7" @@ -4935,9 +4935,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.649: - version "1.3.675" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.675.tgz#7ad29f98d7b48da581554eb28bb9a71fd5fd4956" - integrity sha512-GEQw+6dNWjueXGkGfjgm7dAMtXfEqrfDG3uWcZdeaD4cZ3dKYdPRQVruVXQRXtPLtOr5GNVVlNLRMChOZ611pQ== + version "1.3.678" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.678.tgz#c7c6960463167126b7ed076fade14cac6223bfff" + integrity sha512-E5ha1pE9+aWWrT2fUD5wdPBWUnYtKnEnloewbtVyrkAs79HvodOiNO4rMR94+hKbxgMFQG4fnPQACOc1cfMfBg== elliptic@^6.5.3: version "6.5.4" @@ -4978,9 +4978,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.0.0: - version "9.2.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.1.tgz#c9b25604256bb3428964bead3ab63069d736f7ee" - integrity sha512-117l1H6U4X3Krn+MrzYrL57d5H7siRHWraBs7s+LjRuFK7Fe7hJqnJ0skWlinqsycVLU5YAo6L8CsEYQ0V5prg== + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== emojis-list@^2.0.0: version "2.1.0" @@ -5055,24 +5055,26 @@ es-abstract@^1.17.2: string.prototype.trimstart "^1.0.1" es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: - version "1.18.0-next.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" - integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== + version "1.18.0-next.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.3.tgz#56bc8b5cc36b2cca25a13be07f3c02c2343db6b7" + integrity sha512-VMzHx/Bczjg59E6jZOQjHeN3DEoptdhejpARgflAViidlqSpjdq9zA6lKwlhRRs/lOw1gHJv2xkkSFRgvEwbQg== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" - get-intrinsic "^1.0.2" + get-intrinsic "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" + has-symbols "^1.0.2" + is-callable "^1.2.3" is-negative-zero "^2.0.1" - is-regex "^1.1.1" + is-regex "^1.1.2" + is-string "^1.0.5" object-inspect "^1.9.0" object-keys "^1.1.1" object.assign "^4.1.2" - string.prototype.trimend "^1.0.3" - string.prototype.trimstart "^1.0.3" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.0" es-to-primitive@^1.2.1: version "1.2.1" @@ -6334,6 +6336,11 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-bigints@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -6344,7 +6351,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1: +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== @@ -6948,6 +6955,11 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +is-bigint@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2" + integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg== + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -6962,6 +6974,13 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.0.tgz#e2aaad3a3a8fca34c28f6eee135b156ed2587ff0" + integrity sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA== + dependencies: + call-bind "^1.0.0" + is-buffer@^1.0.2, is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -6972,7 +6991,7 @@ is-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.2: +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.2, is-callable@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== @@ -7116,6 +7135,11 @@ is-negative-zero@^2.0.1: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-number-object@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -7174,7 +7198,7 @@ is-potential-custom-element-name@^1.0.0: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= -is-regex@^1.0.4, is-regex@^1.1.1: +is-regex@^1.0.4, is-regex@^1.1.1, is-regex@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== @@ -7219,7 +7243,7 @@ is-svg@^3.0.0: dependencies: html-comment-regex "^1.1.0" -is-symbol@^1.0.2: +is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== @@ -12706,7 +12730,7 @@ string.prototype.matchall@^4.0.2: regexp.prototype.flags "^1.3.1" side-channel "^1.0.4" -string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.3: +string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== @@ -12714,7 +12738,7 @@ string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.3: call-bind "^1.0.2" define-properties "^1.1.3" -string.prototype.trimstart@^1.0.1, string.prototype.trimstart@^1.0.3: +string.prototype.trimstart@^1.0.1, string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== @@ -13295,6 +13319,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +unbox-primitive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f" + integrity sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.0" + has-symbols "^1.0.0" + which-boxed-primitive "^1.0.1" + unherit@^1.0.4: version "1.1.3" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" @@ -14007,6 +14041,17 @@ whatwg-url@^8.0.0: tr46 "^2.0.2" webidl-conversions "^6.1.0" +which-boxed-primitive@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" From 1da630bb37c3c8d14b7be48317c421b463228166 Mon Sep 17 00:00:00 2001 From: Robert Hunt <Freely.Given.org@gmail.com> Date: Wed, 3 Mar 2021 14:23:37 +1300 Subject: [PATCH 16/16] More fine-tuning of link checking --- noticeList.txt | 6 ++-- package.json | 2 +- .../book-package-check.test.js.snap | 2 +- src/core/markdown-text-check.js | 4 +-- src/core/notes-links-check.js | 12 +++---- src/demos/RenderProcessedResults.js | 36 +++++++++++++++---- 6 files changed, 43 insertions(+), 19 deletions(-) diff --git a/noticeList.txt b/noticeList.txt index b0f9055ea..60472fca4 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,4 +1,4 @@ -Last updated 2021-03-03 08:50:12.058433 by makeNoticeList.py +Last updated 2021-03-03 14:21:40.746190 by makeNoticeList.py Got 496 notices: checkRepoResult.noticeList.push( 997, "Repository doesn’t exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 256 languageCode === 'en' || languageCode === 'fr' ? 490 : 190, "Expected header field to contain a mixed-case string", fieldName: `\\$marker`, excerpt: rest, C, V, location: lineLocation from usfm-text-check.js line 945 @@ -24,7 +24,7 @@ Got 496 notices: thisPriority, thisMessage, excerpt: regexResultArray[0], location: ourLocation from field-text-check.js line 417 const notice = 252, "Markdown headers should be preceded by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 281 notice from markdown-text-check.js line 284 - const notice = 252, "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 287 + const notice = 251, "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation ; from markdown-text-check.js line 287 notice from markdown-text-check.js line 290 const notice = 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation ; from markdown-text-check.js line 300 notice from markdown-text-check.js line 303 @@ -491,7 +491,7 @@ Got 496 notices: 64, "Unexpected leading space(s) after break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 155 63, "Unexpected leading space(s) after line break", characterIndex, excerpt, location: ourLocation from field-text-check.js line 160 50, "Is this quote/occurrence correct???", details: `Occurrence=$occurrence`, excerpt: fieldText, location: ourLocation from orig-quote-check.js line 305 - 32, `Untested general link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,092 + 32, `Untested general/outside link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation from notes-links-check.js line 1,092 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-tsv9-table-check.js line 263 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from twl-tsv6-table-check.js line 252 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from notes-tsv7-table-check.js line 252 diff --git a/package.json b/package.json index 1b261995f..a4b7c2903 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uw-content-validation", "description": "Functions for Checking Door43.org Scriptural Content/Resources.", - "version": "2.0.0_alpha11", + "version": "2.0.0", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/__tests__/__snapshots__/book-package-check.test.js.snap b/src/__tests__/__snapshots__/book-package-check.test.js.snap index 277969c60..84a8a4337 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -27139,7 +27139,7 @@ Object { "lineNumber": 2, "location": " in en TIT book package from unfoldingWord master branch", "message": "Markdown headers should be followed by a blank line", - "priority": 252, + "priority": 251, "repoCode": "SQ", "repoName": "en_sq", "rowID": "gtn1", diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 3d7a47ddc..3a1b81647 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -7,7 +7,7 @@ import { removeDisabledNotices } from './disabled-notices'; import { parameterAssert, dataAssert, debugLog } from './utilities'; -const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.7.0'; +const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.7.1'; /** @@ -284,7 +284,7 @@ export async function checkMarkdownText(languageCode, repoCode, textOrFileName, addNotice(notice); } if (nextLine?.length !== 0) { - const notice = { priority: 252, message: "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation }; + const notice = { priority: 251, message: "Markdown headers should be followed by a blank line", lineNumber: n, location: ourLocation }; if (textOrFileName === 'Note' || textOrFileName === 'OccurrenceNote') notice.details = `markdown line ${n}`; addNotice(notice); diff --git a/src/core/notes-links-check.js b/src/core/notes-links-check.js index ca243bc71..61ea571ce 100644 --- a/src/core/notes-links-check.js +++ b/src/core/notes-links-check.js @@ -8,7 +8,7 @@ import { userLog, debugLog, functionLog, parameterAssert, logicAssert, dataAsser // import { consoleLogObject } from '../core/utilities'; -// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.12'; +// const NOTES_LINKS_VALIDATOR_VERSION_STRING = '0.7.14'; // const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; @@ -22,7 +22,7 @@ const TA_RELATIVE_DISPLAY_LINK_REGEX = new RegExp('\\[([^\\]]+?)\\]\\(\\.{2}/([^ const TW_DOUBLE_BRACKETED_LINK_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ /\\]]+?)\\]\\]', 'g'); // Enclosed in [[ ]] const TWL_RAW_LINK_REGEX = new RegExp('rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/(.+)', 'g'); // Just a raw link -const TW_INTERNAL_REGEX = new RegExp('\\[([A-za-z]+?)\\]\\(\\.{2}/([a-z]{2,5})/([-A-Za-z]{2,20})\\.md\\)', 'g');// [Asher](../names/asher.md) +const TW_INTERNAL_REGEX = new RegExp('\\[([A-za-z ()]+?)\\]\\(\\.{2}/([a-z]{2,5})/([-A-Za-z\\d]{2,20})\\.md\\)', 'g');// [Asher](../names/asher.md) // TODO: Do we need to normalise Bible links, i.e., make sure that the link itself // (we don't care about the displayed text) doesn't specify superfluous levels/information @@ -37,7 +37,7 @@ const THIS_VERSE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})\\]\\(\\ const THIS_VERSE_RANGE_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[(\\d{1,3})[–-](\\d{1,3})\\]\\(\\.{2}/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g');// [2–7](../09/2.md) NOTE en-dash const BCV_V_TO_THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})[–-](\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); // [Genesis 26:12-14](./12.md) NOTE en-dash -const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})(?:-\\d{1,3})\\]\\(rc://([^ /]+?)/tn/help/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\)', 'g'); // [Genesis 29:23-24](rc://en/tn/help/gen/29/23) +const BIBLE_FULL_HELP_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})(?:-\\d{1,3})?\\]\\(rc://([^ /]+?)/tn/help/([123a-z]{3})/(\\d{1,3})/(\\d{1,3})\\)', 'g'); // [Genesis 29:23-24](rc://en/tn/help/gen/29/23) const TN_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(\\d{1,3}):(\\d{1,3})\\]\\((\\.{2})/(\\d{1,3})/(\\d{1,3})/([a-z][a-z0-9][a-z0-9][a-z0-9])\\)', 'g'); @@ -1087,9 +1087,9 @@ export async function checkNotesLinksToOutside(languageCode, repoCode, bookID, g // debugLog(`checkNotesLinksToOutside general link check needs to check: ${uri}`); const serverString = uri.replace('://','!!!').split('/')[0].replace('!!!','://').toLowerCase(); // Get the bit before any forward slashes - // TODO: Uncomment this block and get it working better - if (!serverString.endsWith('door43.org') && !serverString.endsWith('unfoldingword.org')) // don't try to fetch general links - addNoticePartial({ priority: 32, message: `Untested general link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation }); + // NOTE: These message strings must match RenderProcessedResults.js + if (!serverString.endsWith('door43.org') && !serverString.endsWith('unfoldingword.org') && !serverString.endsWith('ufw.io')) // don't try to fetch general links + addNoticePartial({ priority: 32, message: `Untested general/outside link`, details: "please manually double-check link—probably no problem", excerpt: totalLink, location: ourLocation }); else { // Try to fetch general links let generalFileContent, hadError = false; try { diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index e9e768824..d2436a118 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -1,6 +1,7 @@ import React from 'react'; import { forwardRef } from 'react'; -import { parameterAssert, userLog } from '../core/utilities'; +// eslint-disable-next-line no-unused-vars +import { parameterAssert, userLog, debugLog } from '../core/utilities'; // NOTE: The following line is currently giving compile warnings -- a problem in a dependency it seems import MaterialTable from 'material-table'; @@ -41,7 +42,7 @@ const tableIcons = { }; -// const RENDER_PROCESSED_RESULTS_VERSION = '0.5.11'; +// const RENDER_PROCESSED_RESULTS_VERSION = '0.6.0'; export function RenderSuccesses({ username, results }) { @@ -257,7 +258,7 @@ function RenderFileDetails({ username, repoName, branch, filename, lineNumber, r // debugLog(`RenderFileDetails(${repoName}, ${branch}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); if (!repoName && !filename && !lineNumber && !rowID && !fieldName) return null; // They're all undefined or blank! - if (!branch) branch = repoName?.endsWith('2')? 'newFormat':'master'; // default but with TEMP code for newFormat + if (!branch) branch = repoName?.endsWith('2') ? 'newFormat' : 'master'; // default but with TEMP code for newFormat // debugLog(`RenderFileDetails2 ${repoName}, ${filename}, ${lineNumber}`); let resultStart = '', lineResult = '', resultEnd = '', fileLineLink = '', fileLink = ''; if (repoName && repoName.length) resultStart += ` in ${repoName} repository`; @@ -287,6 +288,29 @@ function RenderFileDetails({ username, repoName, branch, filename, lineNumber, r else if (fileLink) return <>{resultStart} in file <a rel="noopener noreferrer" target="_blank" href={fileLink}>{filename}</a>{resultEnd}</>; else return <>{resultStart}<b>{lineResult}</b>{resultEnd}</>; } +// end of RenderFileDetails + +function RenderExcerpt({ excerpt, message }) { + // debugLog(`RenderExcerpt(${excerpt}, ${message})`); + // NOTE: These message strings must match notes-links-check.js (priority 82, and priority 32,) + // Note that messages might start with a repo code, e.g., "TN Actual message start" + if (message.endsWith("Untested general/outside link") + || message.endsWith("Error loading general link") + || message.endsWith("Should http link be https")) { + // debugLog(`Here1 RenderExcerpt(${excerpt}, ${message})`); + if (excerpt && excerpt[0] === '[' && excerpt.slice(-1) === ')') { + // debugLog(`Here2 RenderExcerpt(${excerpt}, ${message})`); + const ix = excerpt.indexOf(']('); + const displayPart = excerpt.substring(1, ix); // Start after the [ unril before the ]( + const linkPart = excerpt.substring(ix+2, excerpt.length-1); // Step past the ]( but don't include the final ) + const adjLinkPart = message === "Should http link be https" ? linkPart.replace('http:', 'https:') : linkPart; + // debugLog(`RenderExcerpt from '${excerpt}' got ix=${ix}, displayPart='${displayPart}', linkPart='${linkPart}', adjLinkPart='${adjLinkPart}'`); + return <><span style={{ color: 'DimGray' }}>` around ►[${displayPart}](<a rel="noopener noreferrer" target="_blank" href={adjLinkPart}>{linkPart}</a>)◄`</span></> + } + } + return <><span style={{ color: 'DimGray' }}>{excerpt ? ` around ►${excerpt}◄` : ""}</span></> +} +// end of RenderExcerpt function RenderSuccessesColored({ results }) { // Display our array of success message strings in a nicer format @@ -347,7 +371,7 @@ function RenderProcessedArray({ arrayType, results }) { <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} branch={listEntry.branch} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex > 0 ? " (at character " + (listEntry.characterIndex + 1) + ")" : ""} - <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> + <RenderExcerpt excerpt={listEntry.excerpt} message={listEntry.message} /> {listEntry.location} <RenderPriority entry={listEntry} /> </li>; @@ -375,7 +399,7 @@ function RenderGivenArray({ array, color }) { <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} branch={listEntry.branch} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} - <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> + <RenderExcerpt excerpt={listEntry.excerpt} message={listEntry.message} /> {listEntry.location} <RenderPriority entry={listEntry} /> </li>; @@ -413,7 +437,7 @@ function RenderWarningsGradient({ results }) { <RenderBCV bookID={listEntry.bookID} C={listEntry.C} V={listEntry.V} /> <RenderFileDetails username={listEntry.username} repoName={listEntry.repoName} branch={listEntry.branch} filename={listEntry.filename} lineNumber={listEntry.lineNumber} rowID={listEntry.rowID} fieldName={listEntry.fieldName} /> {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} - <span style={{ color: 'DimGray' }}>{listEntry.excerpt ? ` around ►${listEntry.excerpt}◄` : ""}</span> + <RenderExcerpt excerpt={listEntry.excerpt} message={listEntry.message} /> {listEntry.location} <RenderPriority entry={listEntry} /> </li>;