diff --git a/README.md b/README.md index fc13f04d..2868374e 100644 --- a/README.md +++ b/README.md @@ -37,13 +37,13 @@ In addition, there are Styleguidist pages viewable at https://unfoldingword.gith 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 (TSV) files +1. Translation Notes (TN2) tables in Tab-Separated Values (TSV) files 1. General annotation tables in Tab-Separated Values (TSV) files (work-in-progress) 1. Markdown files (and markdown fields in TSV files) 1. Plain-text files 1. Metadata (manifest) YAML files -Note: There is also a separate function for checking individual TN/TSV lines which is intended to be able to provide immediate user feedback if built into a TSV editor. +Note: There is also a separate function for checking individual TN2/TSV lines which is intended to be able to provide immediate user feedback if built into a TSV editor. The top-level checking demonstrations return: diff --git a/noticeList.txt b/noticeList.txt index 1bc395c4..3401597e 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -1,276 +1,294 @@ -Last updated 2020-11-10 08:59:10.555207 by makeNoticeList.py -Got 274 notices: - checkRepoResult.noticeList.push( 997, "Repository doesn't exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 232 - 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 735 - `"`.indexOf(line[0]) < 0 ? 880 : 280, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, extract: line[0], location: ourLocation from usfm-text-check.js line 814 - 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 906 - leftChar === '“' ? 163 : 563, `Mismatched $leftChar$rightChar characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from field-text-check.js line 286 - leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from plain-text-check.js line 198 +Last updated 2020-11-20 17:20:25.277130 by makeNoticeList.py +Got 292 notices: + checkRepoResult.noticeList.push( 997, "Repository doesn't exist", details, username, repoCode, repoName, location: givenLocation, extra: repoCode from checkRepo.js line 243 + 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 729 + 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 752 + `"`.indexOf(line[0]) < 0 ? 880 : 280, C, V, "Expected line to start with backslash", lineNumber: n, characterIndex: 0, extract: line[0], location: ourLocation from usfm-text-check.js line 831 + 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 923 + const notice = 95, "Unexpected trailing space(s)", extract, location: ourLocation ; from field-text-check.js line 174 + notice from field-text-check.js line 176 + const notice = 194, "Unexpected double spaces", extract, location: ourLocation from field-text-check.js line 199 + notice from field-text-check.js line 201 + const notice = 580, "Unexpected narrow non-break space character", extract, location: ourLocation ; from field-text-check.js line 220 + notice from field-text-check.js line 222 + const notice = 177, `Unexpected doubled $punctChar characters`, extract, location: ourLocation ; from field-text-check.js line 252 + notice from field-text-check.js line 254 + const notice = 191, `Unexpected $punctChar character after space`, extract, location: ourLocation ; from field-text-check.js line 267 + notice from field-text-check.js line 269 + const notice = 192, `Unexpected space after $punctChar character`, extract, location: ourLocation ; from field-text-check.js line 292 + notice from field-text-check.js line 294 + const notice = 193, `Unexpected $punctChar character at end of line`, extract, location: ourLocation ; from field-text-check.js line 299 + notice from field-text-check.js line 301 + leftChar === '“' ? 163 : 563, `Mismatched $leftChar$rightChar characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from field-text-check.js line 330 + leftChar === '“' ? 162 : 462, `Mismatched $leftChar$rightChar characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from plain-text-check.js line 216 999, "checkRepo function FAILED", repoName, extract: checkRepoError, location: repoName from RepoCheck.js line 103 - 997, "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 102 - 997, "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 128 - 997, "Repository doesn't exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 302 - 997, "Repository doesn't exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 438 - 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 104 - 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 132 - 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 306 - 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 442 - 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 236 - 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 65 - 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 101 - 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 178 - 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 107 - 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 182 - 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 113 - 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 186 + 997, "Repository doesn't exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 168 + 997, "Repository doesn't exist", details, username, repoCode, repoName, location: manifestLocation, extra: repoCode from checkBookPackage.js line 225 + 997, "Repository doesn't exist", details, username, repoCode, repoName, location: repoLocation, extra: repoCode from checkBookPackage.js line 365 + 997, "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 527 + 997, "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode from checkBookPackage.js line 553 + 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 172 + 996, "Unable to load", details: `username=$username error=$cBPgfError`, repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: repoCode from checkBookPackage.js line 229 + 996, "Unable to load", details, repoCode, repoName, filename, location: repoLocation, extra: repoCode from checkBookPackage.js line 369 + 996, "Unable to load", details, bookID, location: generalLocation, extra: repoCode from checkBookPackage.js line 529 + 996, "Unable to load", details, bookID, C, V, filename: thisPath, location: `$generalLocation $thisPath`, extra: repoCode from checkBookPackage.js line 557 + 996, "Unable to load", details: `username=$username error=$cRgfError`, bookID: ourBookID, filename: thisFilename, location: `$givenLocation $thisFilepath`, extra: repoName from checkRepo.js line 247 + 995, "File extension is not recognized, so treated as plain text.", filename, location: filename from checkFileContents.js line 76 + 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 109 + 993, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 128 + 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 115 + 992, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 132 + 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from field-text-check.js line 121 + 991, "Unresolved GIT conflict", characterIndex, extract, location: ourLocation from plain-text-check.js line 136 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 160 + 989, "Unable to find/load repository", location: ourLocation from checkRepo.js line 170 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 225 - 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 226 - 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, extract, location: ourLocation from usfm-text-check.js line 891 - 986, "Repository doesn't seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 140 - 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 655 - 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 515 - 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 518 - 979, "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-table-row-check.js line 319 - 979, "Invalid book identifier passed to checkAnnotationTSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from annotation-row-check.js line 329 - 978, "Wrong book identifier", details: `(expected '$bookID')`, fieldName: 'Book', rowID, extract: B, location: ourRowLocation from tn-table-row-check.js line 334 - 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-table-row-check.js line 337 - 976, "Wrong chapter number", details: `(expected '$givenC')`, fieldName: 'Chapter', rowID, extract: C, location: ourRowLocation from tn-table-row-check.js line 342 - 976, "Wrong chapter number", details: `(expected '$givenC')`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from annotation-row-check.js line 347 - 975, "Wrong verse number", details: `(expected '$givenV')`, rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 374 - 975, "Wrong verse number", details: `(expected '$givenV')`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 383 - 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 327 - 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 261 - 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 259 + 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 227 + 987, C, V, "Expected \\id line to start with book identifier", lineNumber: n, characterIndex: 4, extract, location: ourLocation from usfm-text-check.js line 908 + 986, "Repository doesn't seem to exist", details: `username=$username`, location: givenLocation, extra: repoName from checkRepo.js line 150 + 985, `Field does not match schema $errorObject.keyword`, details: errorObject.message, fieldName: errorObject.dataPath, location: ourLocation from manifest-text-check.js line 656 + 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 523 + 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 528 + 979, "Invalid book identifier passed to checkTN_TSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from tn-table-row-check.js line 326 + 979, "Invalid book identifier passed to checkAnnotationTSVDataRow", location: ` '$bookID' in first parameter: $tlcNCerror` from annotation-row-check.js line 338 + 978, "Wrong book identifier", details: `(expected '$bookID')`, fieldName: 'Book', rowID, extract: B, location: ourRowLocation from tn-table-row-check.js line 341 + 977, "Missing book identifier", characterIndex: 0, rowID, location: ourRowLocation from tn-table-row-check.js line 344 + 976, "Wrong chapter number", details: `(expected '$givenC')`, fieldName: 'Chapter', rowID, extract: C, location: ourRowLocation from tn-table-row-check.js line 349 + 976, "Wrong chapter number", details: `(expected '$givenC')`, fieldName: 'Reference', rowID, extract: C, location: ourRowLocation from annotation-row-check.js line 356 + 975, "Wrong verse number", details: `(expected '$givenV')`, rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 381 + 975, "Wrong verse number", details: `(expected '$givenV')`, rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 392 + 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 193 + 956, "Got empty manifest file", repoName, filename: MANIFEST_FILENAME, location: manifestLocation, extra: `$repoCode MANIFEST` from checkBookPackage.js line 250 + 947, "Missing manifest.yaml", location: ourLocation, extra: `$repoName MANIFEST` from checkRepo.js line 272 + 946, "Missing LICENSE.md", location: ourLocation, extra: `$repoName LICENSE` from checkRepo.js line 270 944, `USFM3 Grammar Check ($strictnessString mode) doesn't pass`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 177 - 943, `USFM3 toJSON Check doesn't pass`, location: ourLocation from usfm-js-check.js line 78 - 942, "USFM Grammar check fails", location from usfm-text-check.js line 940 - 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 620 - 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 618 - 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 120 - 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 445 - 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from annotation-row-check.js line 459 - 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 303 - 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 338 - 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 341 - 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 344 - 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 347 - 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 350 - 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 353 - 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ⸢$verseText⸣`, extract, location: ourLocation from orig-quote-check.js line 356 - 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, extract, location: lineLocation from usfm-text-check.js line 587 - 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, extract, location: lineLocation from usfm-text-check.js line 643 - 903, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 756 - 902, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 351 + 943, `USFM3 toJSON Check doesn't pass`, location: ourLocation from usfm-js-check.js line 90 + 942, "USFM Grammar check fails", location from usfm-text-check.js line 957 + 929, "'projects' key is missing", location: ourLocation from manifest-text-check.js line 621 + 928, "'dublin_core' key is missing", location: ourLocation from manifest-text-check.js line 619 + 920, yamlError.message, location: ourLocation ) from yaml-text-check.js line 158 + 919, "Missing OrigQuote field", fieldName: 'OrigQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 453 + 919, "Missing Quote field", fieldName: 'Quote', rowID, location: ourRowLocation from annotation-row-check.js line 469 + 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 308 + 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 343 + 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 346 + 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 349 + 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 352 + 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 355 + 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 358 + 916, "Unable to find original language quote in verse text", details: noBreakSpaceText ? noBreakSpaceText : `passage ⸢$verseText⸣`, extract, location: ourLocation from orig-quote-check.js line 361 + 912, 'Missing | character in \\w line', lineNumber, C, V, characterIndex, extract, location: lineLocation from usfm-text-check.js line 599 + 911, 'Missing | character in \\w field', details, lineNumber, C, V, characterIndex, extract, location: lineLocation from usfm-text-check.js line 655 + 903, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from usfm-text-check.js line 773 + 902, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$generalLocation` ); return checkBookPackageResult; from checkBookPackage.js line 274 900, "Bad parameter: should be given a valid book abbreviation", extract: bookIDList, location: ` (not '$bookIDList')` from checkBookPackages.js line 65 - 895, "Field contains zero-width space(s)", characterIndex, extract, location: ourLocation from field-text-check.js line 88 - 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 217 - 885, `Error loading $fieldName TA link`, extract: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 214 - 884, `Linked $fieldName TA article seems empty`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 219 - 883, `Unable to find $fieldName TW link`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 263 - 882, `Error loading $fieldName TW link`, extract: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 260 - 881, `Linked $fieldName TW article seems empty`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 266 - 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 690 - 873, `Mismatched $opener$closer fields`, extract: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 512 - 869, "Chapter number out of range", C: chapterNumberString, extract: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 367 - 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, extract: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 406 - 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 420 - 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 425 - 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 273 - 845, `Mismatched [[ ]] link characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from tn-links-check.js line 456 - 844, `Mismatched [[rc:// ]] link characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from tn-links-check.js line 460 - 843, `Mismatched [ ]( ) link characters`, details: `(left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from tn-links-check.js line 467 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 347 - 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 352 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 352 - 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 357 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 362 - 822, "Expected \\c field to contain an integer", lineNumber, C, V, characterIndex: 3, extract: `\\c $rest`, location: lineLocation from usfm-text-check.js line 705 - 822, C, V, "Expected \\v field to contain an integer", characterIndex: 3, extract: `\\v $rest`, location: lineLocation from usfm-text-check.js line 709 - 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 370 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 367 - 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 376 - 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-table-row-check.js line 370 - 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from annotation-row-check.js line 379 - 819, "Missing compulsory USFM line", extract: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 534 - 814, "Invalid zero verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 379 - 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 388 - 813, "Invalid large verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 383 - 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 392 - 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-table-row-check.js line 385 - 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 394 - 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-table-row-check.js line 389 - 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from annotation-row-check.js line 398 - 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-table-row-check.js line 392 - 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from annotation-row-check.js line 401 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-table-row-check.js line 459 - 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from annotation-row-check.js line 473 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-table-row-check.js line 464 - 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from annotation-row-check.js line 478 + 895, "Field contains zero-width space(s)", characterIndex, extract, location: ourLocation from field-text-check.js line 95 + 889, `Unable to find TA link`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 108 + 888, `Error loading TA link`, extract: fieldText, location: `$ourLocation $filepath: $trcGCerror` from ta-reference-check.js line 113 + 887, `Linked TA article seems empty`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 110 + 886, `Unable to find $fieldName TA link`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 218 + 885, `Error loading $fieldName TA link`, extract: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 215 + 884, `Linked $fieldName TA article seems empty`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 220 + 883, `Unable to find $fieldName TW link`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 266 + 882, `Error loading $fieldName TW link`, extract: regexResultArray[0], location: `$ourLocation $filepath: $trcGCerror` from tn-links-check.js line 263 + 881, `Linked $fieldName TW article seems empty`, extract: regexResultArray[0], location: `$ourLocation $filepath` from tn-links-check.js line 269 + 879, `Badly formatted Resource Container link`, extract: fieldText, location: `$ourLocation $filepath` from ta-reference-check.js line 95 + 875, "Unexpected USFM field", details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 702 + 873, `Mismatched $opener$closer fields`, extract: `(left=$lCount.toLocaleString(), right=$rCount.toLocaleString())`, location: fileLocation from usfm-text-check.js line 524 + 869, "Chapter number out of range", C: chapterNumberString, extract: `$bookID $chapterNumberString`, location: CVlocation from usfm-text-check.js line 375 + 868, "Verse number out of range", C: chapterNumberString, V: verseNumberString, extract: `$bookID $chapterNumberString:$verseNumberString`, location: CVlocation from usfm-text-check.js line 414 + 867, C: chapterNumberString, V: `$v`, "Verse appears to be missing", location: CVlocation from usfm-text-check.js line 428 + 866, C: chapterNumberString, V: `$v`, "Verse seems to have no text", location: CVlocation from usfm-text-check.js line 433 + 851, bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation from orig-quote-check.js line 276 + 849, "Unexpected \\[ or \\] characters", characterIndex, extract, location: ourLocation from field-text-check.js line 310 + 845, `Mismatched [[ ]] link characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from tn-links-check.js line 460 + 844, `Mismatched [[rc:// ]] link characters`, details: `(left=$leftCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from tn-links-check.js line 464 + 843, `Mismatched [ ]( ) link characters`, details: `(left=$leftCount.toLocaleString(), middle=$middleCount.toLocaleString(), right=$rightCount.toLocaleString())`, location: ourLocation from tn-links-check.js line 471 + 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 354 + 824, `Invalid zero chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 361 + 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 359 + 823, `Invalid large chapter number`, extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 366 + 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 369 + 822, "Expected field to contain an integer", lineNumber, characterIndex: 3, extract: `\\c $rest`, C, V, location: lineLocation from usfm-text-check.js line 721 + 822, "Expected field to contain an integer", characterIndex: 3, extract: `\\v $rest`, C, V, location: lineLocation from usfm-text-check.js line 725 + 822, "Unable to check chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 379 + 821, "Bad chapter number", extract: C, rowID, fieldName: 'Chapter', location: ourRowLocation from tn-table-row-check.js line 374 + 821, "Bad chapter number", extract: C, rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 385 + 820, "Missing chapter number", rowID, fieldName: 'Chapter', location: ` ?:$V$ourRowLocation` from tn-table-row-check.js line 377 + 820, "Missing chapter number", rowID, fieldName: 'Reference', location: ` ?:$V$ourRowLocation` from annotation-row-check.js line 388 + 819, "Missing compulsory USFM line", extract: `missing \\$compulsoryMarker`, location: fileLocation from usfm-text-check.js line 546 + 814, "Invalid zero verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 386 + 814, "Invalid zero verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 397 + 813, "Invalid large verse number", rowID, fieldName: 'Verse', extract: V, location: ourRowLocation from tn-table-row-check.js line 390 + 813, "Invalid large verse number", rowID, fieldName: 'Reference', extract: V, location: ourRowLocation from annotation-row-check.js line 401 + 812, "Unable to check verse number", rowID, fieldName: 'Verse', location: ourRowLocation from tn-table-row-check.js line 392 + 812, "Unable to check verse number", rowID, fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 403 + 811, "Bad verse number", rowID, fieldName: 'Verse', location: ` '$V'$ourRowLocation` from tn-table-row-check.js line 396 + 811, "Bad verse number", rowID, fieldName: 'Reference', location: ` '$V'$ourRowLocation` from annotation-row-check.js line 407 + 810, "Missing verse number", rowID, fieldName: 'Verse', location: ` after $C:?$ourRowLocation` from tn-table-row-check.js line 399 + 810, "Missing verse number", rowID, fieldName: 'Reference', location: ` after $C:?$ourRowLocation` from annotation-row-check.js line 410 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from tn-table-row-check.js line 467 + 792, `Invalid occurrence field`, fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from annotation-row-check.js line 483 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-table-row-check.js line 472 + 791, `Missing occurrence field`, fieldName: 'Occurrence', rowID, location: ourRowLocation from annotation-row-check.js line 488 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from tn-table-text-check.js line 204 - 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from annotation-table-check.js line 205 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-table-row-check.js line 423 - 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from annotation-row-check.js line 437 - 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-table-row-check.js line 427 - 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from annotation-row-check.js line 441 - 786, "Link to TA should also be in SupportReference", details, rowID, fieldName: 'OccurrenceNote', extract: regexResultArray[1], location: ourRowLocation from tn-table-row-check.js line 495 - 786, "Link to TA should also be in SupportReference", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from annotation-row-check.js line 497 - 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-table-row-check.js line 395 - 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 404 - 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 398 - 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 407 - 777, `Bad nesting: $char closing character doesn't match`, details, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 156 - 776, 'Unexpected " straight quote character', details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 677 - 775, "Unexpected ' straight quote character", details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 682 - 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 161 - 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 140 - 772, `Unexpected trailing word joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 136 - 771, `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 130 - 770, `Unexpected leading word joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 126 - 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 867 - 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 869 - 765, "Unexpected link", characterIndex, extract, location: ourLocation from field-text-check.js line 302 - 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 840 - 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 853 - 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 394 - 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 863 - 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 884 - 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 450 - 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from annotation-row-check.js line 464 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-table-row-check.js line 441 - 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from annotation-row-check.js line 455 + 790, C, V, "Missing verse number", rowID, lineNumber: n + 1, location: ` after $C:$lastV$ourLocation` from annotation-table-check.js line 206 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-table-row-check.js line 430 + 788, "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from annotation-row-check.js line 446 + 787, "Link to TA should also be in OccurrenceNote", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from tn-table-row-check.js line 435 + 787, "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation from annotation-row-check.js line 451 + 786, "Link to TA should also be in SupportReference", details, rowID, fieldName: 'OccurrenceNote', extract: regexResultArray[1], location: ourRowLocation from tn-table-row-check.js line 503 + 786, "Link to TA should also be in SupportReference", details, rowID, fieldName: 'Annotation', extract: adjustedLink, location: ourRowLocation from annotation-row-check.js line 507 + 779, "Missing row ID field", fieldName: 'Verse', location: ourRowLocation from tn-table-row-check.js line 402 + 779, "Missing row ID field", fieldName: 'Reference', location: ourRowLocation from annotation-row-check.js line 413 + 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 405 + 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 416 + 777, `Bad nesting: $char closing character doesn't match`, details, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 186 + 776, 'Unexpected " straight quote character', details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 689 + 775, "Unexpected ' straight quote character", details, lineNumber, C, V, extract, location: lineLocation from usfm-text-check.js line 694 + 774, `Unexpected $char closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation from plain-text-check.js line 192 + 773, `Unexpected trailing zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 156 + 772, `Unexpected trailing word joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 152 + 771, `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 138 + 770, `Unexpected leading word joiner`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 134 + 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 884 + 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 886 + 765, "Unexpected link", characterIndex, extract, location: ourLocation from field-text-check.js line 345 + 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 857 + 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 870 + 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 402 + 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 880 + 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 901 + 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 458 + 751, "Invalid zero occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, extract: occurrence, location: ourRowLocation from annotation-row-check.js line 474 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from tn-table-row-check.js line 449 + 750, "Missing occurrence field when we have an original quote", fieldName: 'Occurrence', rowID, location: ourRowLocation from annotation-row-check.js line 465 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from tn-table-text-check.js line 84 - 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from annotation-table-check.js line 87 + 747, "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '$bookID')$ourLocation` from annotation-table-check.js line 88 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from tn-table-text-check.js line 99 - 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from annotation-table-check.js line 103 + 746, "Bad TSV header", lineNumber: n + 1, location: `$ourLocation: '$lines[0]'` from annotation-table-check.js line 104 745, C, V, `Wrong '$B' book identifier (expected '$bookID')`, rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 154 744, C, V, "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 157 - 743, "Chapter numbers of markdown Bible link don't match", details: `$C1 vs $chapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 311 - 743, "Chapter numbers of markdown Bible link don't match", details: `$C1 vs $chapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 363 - 743, "Chapter numbers of markdown Bible link don't match", details: `$C1 vs $chapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 415 - 742, "Verse numbers of markdown Bible link don't match", details: `$V1 vs $verseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 317 - 742, "Verse numbers of markdown Bible link don't match", details: `$V1 vs $verseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 369 - 742, "Verse numbers of markdown Bible link don't match", details: `$V1 vs $verseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 421 + 743, "Chapter numbers of markdown Bible link don't match", details: `$C1 vs $chapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 315 + 743, "Chapter numbers of markdown Bible link don't match", details: `$C1 vs $chapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 367 + 743, "Chapter numbers of markdown Bible link don't match", details: `$C1 vs $chapterInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 419 + 742, "Verse numbers of markdown Bible link don't match", details: `$V1 vs $verseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 321 + 742, "Verse numbers of markdown Bible link don't match", details: `$V1 vs $verseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 373 + 742, "Verse numbers of markdown Bible link don't match", details: `$V1 vs $verseInt`, extract: totalLink, location: ourLocation from tn-links-check.js line 425 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from tn-table-text-check.js line 181 - 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from annotation-table-check.js line 182 + 739, C, V, "Missing chapter number", rowID, lineNumber: n + 1, location: ` after $lastC:$V$ourLocation` from annotation-table-check.js line 183 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 200 - 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 201 + 738, C, V, "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 202 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-table-text-check.js line 168 - 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from annotation-table-check.js line 169 + 737, C, V, "Invalid large chapter number", rowID, lineNumber: n + 1, extract: C, location: ourLocation from annotation-table-check.js line 170 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 172 - 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 173 + 736, C, V, "Receding chapter number", details: `'$C' after '$lastC'`, rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 174 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 174 - 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 175 + 735, C, V, "Advancing chapter number", details: `'$C' after '$lastC'`.rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 176 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 178 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 190 - 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 179 - 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 191 + 734, C, V, "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 180 + 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 192 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 194 - 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 195 + 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 196 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 210 - 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 211 + 730, C, V, "Missing ID", fieldName: 'ID', lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 212 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from tn-table-text-check.js line 208 - 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 209 - 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 836 - 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 849 - 721, "Unable to find original language quote in verse text", extract, location: ourLocation from orig-quote-check.js line 292 - 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 880 - 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 732 - 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, extract, location: ourLocation from usfm-text-check.js line 800 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $chapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 333 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $chapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 385 - 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $chapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 437 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $chapterInt:$verseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 335 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $chapterInt:$verseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 387 - 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $chapterInt:$verseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 439 - 649, "More [[ ]] links than valid TA/TW links", details: `detected $totalLinks2 link$totalLinks2 === 1 ? '' : 's' but $twaLinkCount ? `only $twaLinkCount` : 'no' TA/TW link$twaLinkCount === 1 ? '' : 's' from $JSON.stringify(linksList2)`, location: ourLocation from tn-links-check.js line 449 - 648, "More [ ]( ) links than valid Bible links", details: `detected $totalLinks1 link$totalLinks1 === 1 ? '' : 's' but $BibleLinkCount ? `only $BibleLinkCount` : 'no' Bible link$BibleLinkCount === 1 ? '' : 's' from $JSON.stringify(linksList1)`, location: ourLocation from tn-links-check.js line 446 - 644, "USFM3 Grammar Check (relaxed mode) doesn't pass either", location: fileLocation from usfm-text-check.js line 229 - 638, "Only found whitespace", location: ourLocation from field-text-check.js line 93 - 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 117 - 621, "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 327 - 620, "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 319 - 603, "USFM marker doesn't end with space", C, V, lineNumber, characterIndex, extract, location: ourLocation from usfm-text-check.js line 770 + 729, C, V, `Duplicate '$rowID' ID`, fieldName: 'ID', rowID, lineNumber: n + 1, location: ourLocation from annotation-table-check.js line 210 + 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 853 + 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 866 + 721, "Unable to find original language quote in verse text", extract, location: ourLocation from orig-quote-check.js line 297 + 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 897 + 711, "Expected compulsory content", C, V, lineNumber, characterIndex: marker.length, location: ` after \\$marker marker$lineLocation` from usfm-text-check.js line 749 + 703, C, V, "Unexpected CarriageReturn character", lineNumber: n, characterIndex, extract, location: ourLocation from usfm-text-check.js line 817 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $chapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 337 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $chapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 389 + 655, "Bad chapter number in markdown Bible link", details: `$linkBookCode $chapterInt vs $numChaptersThisBook chapters`, extract: totalLink, location: ourLocation from tn-links-check.js line 441 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $chapterInt:$verseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 339 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $chapterInt:$verseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 391 + 653, "Bad verse number in markdown Bible link", details: `$linkBookCode $chapterInt:$verseInt vs $numVersesThisChapter verses`, extract: totalLink, location: ourLocation from tn-links-check.js line 443 + 649, "More [[ ]] links than valid TA/TW links", details: `detected $totalLinks2 link$totalLinks2 === 1 ? '' : 's' but $twaLinkCount ? `only $twaLinkCount` : 'no' TA/TW link$twaLinkCount === 1 ? '' : 's' from $JSON.stringify(linksList2)`, location: ourLocation from tn-links-check.js line 453 + 648, "More [ ]( ) links than valid Bible links", details: `detected $totalLinks1 link$totalLinks1 === 1 ? '' : 's' but $BibleLinkCount ? `only $BibleLinkCount` : 'no' Bible link$BibleLinkCount === 1 ? '' : 's' from $JSON.stringify(linksList1)`, location: ourLocation from tn-links-check.js line 450 + 644, "USFM3 Grammar Check (relaxed mode) doesn't pass either", location: fileLocation from usfm-text-check.js line 237 + 638, "Only found whitespace", location: ourLocation from field-text-check.js line 100 + 638, "Only found whitespace", location: ourLocation from plain-text-check.js line 120 + 621, "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 332 + 620, "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 324 + 603, "USFM marker doesn't end with space", C, V, lineNumber, characterIndex, extract, location: ourLocation from usfm-text-check.js line 787 601, "Unable to load", details: `username=$username error=$gcUHBerror`, OBSPathname, location: ourLocation, extra: OBSRepoName from orig-quote-check.js line 99 601, "Unable to load", details: `username=$username error=$gcUHBerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 131 601, "Unable to load", details: `username=$username error=$gcUGNTerror`, filename, location: ourLocation, extra: originalLanguageRepoName from orig-quote-check.js line 139 - 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourAtString from field-link-check.js line 139 - 583, "Unexpected newLine character", characterIndex, extract, location: ourLocation from field-text-check.js line 185 - 582, "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation from field-text-check.js line 190 - 581, "Unexpected non-break space character", characterIndex, extract, location: ourLocation from field-text-check.js line 195 - 580, "Unexpected narrow non-break space character", characterIndex, extract, location: ourLocation from field-text-check.js line 200 + 600, `$regexResultsArray.length link target$regexResultsArray.length === 1 ? ' is' : 's are' still being checked…`, location: ourLocation from field-link-check.js line 151 + 583, "Unexpected newLine character", characterIndex, extract, location: ourLocation from field-text-check.js line 205 + 582, "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation from field-text-check.js line 210 + 581, "Unexpected non-break space character", characterIndex, extract, location: ourLocation from field-text-check.js line 215 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 188 - 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 189 + 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 190 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from tn-table-text-check.js line 166 - 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from annotation-table-check.js line 167 - 519, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 538 - 518, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 546 - 517, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 542 - 472, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 158 + 551, C, V, `Invalid zero chapter number`, rowID, lineNumber: n + 1, extract: C, location: ourLocation from annotation-table-check.js line 168 + 538, "File ends without newline character", characterIndex, extract, location: ourLocation from plain-text-check.js line 142 + 519, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 550 + 518, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 558 + 517, "Missing expected USFM line", extract: `missing \\$expectedMarker`, location: fileLocation from usfm-text-check.js line 554 + 472, "Nesting of header levels seems confused", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 186 450, "Resource container link should have '*' language code", details: `(not '$languageCode')`, characterIndex, extract, location: ourLocation from tn-links-check.js line 198 - 441, `Unknown linkType parameter`, extract: linkType from field-link-check.js line 121 + 441, `Unknown linkType parameter`, extract: linkType from field-link-check.js line 133 439, "Error fetching link", location: ` $fetchLink` from field-link-check.js line 43 - 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourAtString from field-link-check.js line 93 - 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 730 - 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `('\\$lastMarker' before '\\$marker')`, location: ourLocation from usfm-text-check.js line 904 - 375, "Ellipsis without surrounding snippet", location: ourLocation from orig-quote-check.js line 296 - 374, "Field contains zero-width space(s)", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-table-row-check.js line 430 - 374, "Field contains zero-width space(s)", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 470 - 374, "Field contains zero-width space(s)", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 483 - 374, "Field contains zero-width space(s)", fieldName: 'SupportReference', rowID, location: ourRowLocation from annotation-row-check.js line 444 - 374, "Field contains zero-width space(s)", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 484 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-table-row-check.js line 416 - 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 472 - 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 485 - 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from annotation-row-check.js line 428 - 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 486 - 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 611 - 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 728 - 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourAtString` from field-link-check.js line 135 - 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 501 - 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 504 - 218, "Using deprecated USFM marker", extract: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 549 - 195, `Unexpected $punctChar character at start of line`, characterIndex, extract, location: ourLocation from field-text-check.js line 249 - 194, "Unexpected double spaces", characterIndex, extract, location: ourLocation from field-text-check.js line 181 - 193, `Unexpected $punctChar character at end of line`, characterIndex, extract, location: ourLocation from field-text-check.js line 270 - 192, `Unexpected space after $punctChar character`, characterIndex, extract, location: ourLocation from field-text-check.js line 265 - 191, `Unexpected $punctChar character after space`, characterIndex, extract, location: ourLocation from field-text-check.js line 244 - 179, "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 206 - 178, "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 211 - 177, `Unexpected doubled $punctChar characters`, characterIndex, extract, location: ourLocation from field-text-check.js line 230 - 176, "Row ID should start with a lowercase letter or digit", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from tn-table-row-check.js line 405 - 176, "Row ID should start with a lowercase letter or digit", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from annotation-row-check.js line 414 - 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 407 - 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 416 - 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 409 - 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 418 - 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 411 - 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 420 - 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 151 + 438, `Blank field / missing link (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ourLocation from field-link-check.js line 105 + 401, `Unexpected content after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 747 + 399, C, V, "Useless paragraph marker", lineNumber: n, characterIndex: 1, details: `('\\$lastMarker' before '\\$marker')`, location: ourLocation from usfm-text-check.js line 921 + 375, "Ellipsis without surrounding snippet", location: ourLocation from orig-quote-check.js line 301 + 374, "Field contains zero-width space(s)", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-table-row-check.js line 438 + 374, "Field contains zero-width space(s)", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 478 + 374, "Field contains zero-width space(s)", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 491 + 374, "Field contains zero-width space(s)", fieldName: 'SupportReference', rowID, location: ourRowLocation from annotation-row-check.js line 454 + 374, "Field contains zero-width space(s)", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 494 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from tn-table-row-check.js line 423 + 373, "Field is only whitespace", fieldName: 'GLQuote', rowID, location: ourRowLocation from tn-table-row-check.js line 480 + 373, "Field is only whitespace", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 493 + 373, "Field is only whitespace", fieldName: 'SupportReference', rowID, location: ourRowLocation from annotation-row-check.js line 437 + 373, "Field is only whitespace", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 496 + 312, 'Possible unclosed footnote', details, lineNumber, C, V, location: lineLocation from usfm-text-check.js line 623 + 301, `Unexpected whitespace after \\$marker marker`, C, V, lineNumber, characterIndex: marker.length, extract: rest, location: lineLocation from usfm-text-check.js line 745 + 287, `Not enough links (expected $linkOptions.expectedCount link$linkOptions.expectedCount === 1 ? "" : "s")`, location: ` (only found $regexResultsArray.length)$ourLocation` from field-link-check.js line 147 + 274, "Missing OccurrenceNote field", fieldName: 'OccurrenceNote', rowID, location: ourRowLocation from tn-table-row-check.js line 509 + 274, "Missing Annotation field", fieldName: 'Annotation', rowID, location: ourRowLocation from annotation-row-check.js line 514 + 218, "Using deprecated USFM marker", extract: `\\$deprecatedMarker`, location: fileLocation from usfm-text-check.js line 561 + 195, `Unexpected $punctChar character at start of line`, characterIndex, extract, location: ourLocation from field-text-check.js line 276 + 179, "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 228 + 178, "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation from field-text-check.js line 233 + 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 412 + 176, "Row ID should start with a lowercase letter", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation from annotation-row-check.js line 423 + 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 414 + 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 425 + 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 416 + 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 427 + 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 418 + 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 429 + 172, "Header levels should only increment by one", lineNumber: n, characterIndex: 0, location: ourLocation from markdown-text-check.js line 179 159, "Should use proper ellipse character (not periods)", characterIndex, extract, location: ourLocation from orig-quote-check.js line 237 158, "Unexpected space(s) beside ellipse character", characterIndex, extract, location: ourLocation from orig-quote-check.js line 246 157, "Unexpected space(s) beside ↔ divider character", characterIndex, extract, location: ourLocation from orig-quote-check.js line 253 156, "Unexpected space(s) beside ellipse characters", characterIndex, extract, location: ourLocation from orig-quote-check.js line 260 - 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 622 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 302 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 354 - 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 406 - 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 103 - 110, `Unexpected leading spaces`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 121 - 109, `Unexpected leading space`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 123 - 107, "Unexpected leading line break", characterIndex: 0, extract, location: ourLocation from field-text-check.js line 149 - 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, extract, location: ourLocation from field-text-check.js line 173 - 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 944 - 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 223 + 148, "'checking' key is missing", location: ourLocation from manifest-text-check.js line 623 + 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 306 + 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 358 + 143, "Unknown Bible book name in link", details: totalLink, extract: optionalB1, location: ourLocation from tn-links-check.js line 410 + 138, "File ends with additional blank line(s)", characterIndex, extract, location: ourLocation from plain-text-check.js line 147 + 111, `Bad options for checkFieldLinks: expectedCount=$linkOptions.expectedCount but allowedCount=$linkOptions.allowedCount` from field-link-check.js line 115 + 110, `Unexpected leading spaces`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 129 + 109, `Unexpected leading space`, characterIndex: 0, extract, location: ourLocation from field-text-check.js line 131 + 107, "Unexpected leading line break", characterIndex: 0, extract, location: ourLocation from field-text-check.js line 165 + 104, "Unexpected trailing line break", characterIndex: fieldText.length - 1, extract, location: ourLocation from field-text-check.js line 191 + 103, `USFMGrammar: $warningString.trim()`, location from usfm-text-check.js line 961 + 102, `USFMGrammar: $warningString`, location: fileLocation from usfm-text-check.js line 231 101, `USFMGrammar: $warningString`, filename, location: ourLocation from BCS-usfm-grammar-check.js line 185 - 95, "Unexpected trailing space(s)", characterIndex: fieldText.length - 1, extract, location: ourLocation from field-text-check.js line 158 - 94, "Unexpected trailing space(s) before break", characterIndex, extract, location: ourLocation from field-text-check.js line 162 - 93, "Unexpected trailing space(s) before line break", characterIndex, extract, location: ourLocation from field-text-check.js line 166 - 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `(not '\\$lastMarker')`, location: ourLocation from usfm-text-check.js line 897 - 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `(not '\\$lastMarker')`, location: ourLocation from usfm-text-check.js line 899 - 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 418 + 94, "Unexpected trailing space(s) before break", characterIndex, extract, location: ourLocation from field-text-check.js line 180 + 93, "Unexpected trailing space(s) before line break", characterIndex, extract, location: ourLocation from field-text-check.js line 184 + 87, C, V, "Expected \\toc2 line to follow \\toc1", lineNumber: n, characterIndex: 1, details: `(not '\\$lastMarker')`, location: ourLocation from usfm-text-check.js line 914 + 87, C, V, "Expected \\toc3 line to follow \\toc2", lineNumber: n, characterIndex: 1, details: `(not '\\$lastMarker')`, location: ourLocation from usfm-text-check.js line 916 + 67, C: chapterNumberString, V: `$v`, "Verse appears to be left out", location: CVlocation from usfm-text-check.js line 426 + 64, "Unexpected leading space(s) after break", characterIndex, extract, location: ourLocation from field-text-check.js line 143 + 63, "Unexpected leading space(s) after line break", characterIndex, extract, location: ourLocation from field-text-check.js line 147 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from tn-table-text-check.js line 231 + 20, "Note that 'disableAllLinkFetchingFlag' was set so link targets were not checked", location: ourLocation from annotation-table-check.js line 233 diff --git a/package.json b/package.json index 9d8d4ed8..58bb947e 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": "0.9.0", + "version": "0.9.1", "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 b2eb3e7f..3cb7cd48 100644 --- a/src/__tests__/__snapshots__/book-package-check.test.js.snap +++ b/src/__tests__/__snapshots__/book-package-check.test.js.snap @@ -204,118 +204,6 @@ Object { "repoName": "hbo_uhb", "username": "unfoldingWord", }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 23, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 47, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 105, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 295, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 300, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 354, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 414, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 5, - "extra": "UHB", - "extract": "\\\\k-s | x-tw=\\"…", - "filename": "08-RUT.usfm", - "lineNumber": 1196, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected space after | character", - "priority": 192, - "repoCode": "UHB", - "repoName": "hbo_uhb", - "username": "unfoldingWord", - }, Object { "C": "2", "V": "1", @@ -444,6 +332,19 @@ Object { "repoName": "en_ult", "username": "unfoldingWord", }, + Object { + "bookID": "RUT", + "characterIndex": 311926, + "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", + "priority": 538, + "repoCode": "LT", + "repoName": "en_ult", + "username": "unfoldingWord", + }, Object { "C": "1", "V": "3", @@ -4097,15579 +3998,3167 @@ Object { }, Object { "bookID": "RUT", - "characterIndex": 279, + "characterIndex": 324394, "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", + "extract": "…n-e\\\\*\\\\zaln-e\\\\*.", "filename": "08-RUT.usfm", - "lineNumber": 244, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, + "message": "File ends without newline character", + "priority": 538, "repoCode": "ST", "repoName": "en_ust", "username": "unfoldingWord", }, Object { + "C": "front", + "V": "intro", "bookID": "RUT", - "characterIndex": 64, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 311, + "characterIndex": 805, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 2, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "f68r", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "1", "bookID": "RUT", - "characterIndex": 181, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 325, + "characterIndex": 108, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 4, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "sb2j", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "1", "bookID": "RUT", - "characterIndex": 54, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 456, + "characterIndex": 69, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 5, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "m9nl", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "1", "bookID": "RUT", - "characterIndex": 184, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 477, + "characterIndex": 95, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 6, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "nm13", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "1", "bookID": "RUT", - "characterIndex": 60, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 601, + "characterIndex": 86, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 7, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "mmb4", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "4", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 613, + "characterIndex": 119, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 10, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "pk7g", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "6", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…aln-e\\\\* '\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 623, + "characterIndex": 222, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 16, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected ' character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "sa4z", "username": "unfoldingWord", }, Object { - "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…aln-e\\\\* '\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 630, + "C": "1", + "V": "6", + "bookID": "RUT", + "extra": "TN", + "extract": "figs-idiom", + "fieldName": "SupportReference", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 19, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected ' character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Link to TA should also be in OccurrenceNote", + "priority": 787, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab01", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "6", "bookID": "RUT", - "characterIndex": 173, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 741, + "characterIndex": 144, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 19, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab01", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "6", "bookID": "RUT", - "characterIndex": 67, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 768, + "details": "(SR='figs-idiom')", + "extra": "TN", + "extract": "figs-synecdoche", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 19, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Link to TA should also be in SupportReference", + "priority": 786, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab01", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "7", "bookID": "RUT", - "characterIndex": 183, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 814, + "extra": "TN", + "extract": "figs-idiom", + "fieldName": "SupportReference", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 20, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Link to TA should also be in OccurrenceNote", + "priority": 787, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "w7ti", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "8", "bookID": "RUT", - "characterIndex": 58, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 820, + "characterIndex": 128, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 22, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "lxs2", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "8", "bookID": "RUT", - "characterIndex": 85, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 834, + "characterIndex": 96, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 25, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "g4r8", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "8", "bookID": "RUT", - "characterIndex": 103, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 843, + "characterIndex": 41, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 26, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "acb4", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "9", "bookID": "RUT", - "characterIndex": 53, - "extra": "ST", - "extract": "…ln-e\\\\*, '\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 859, + "characterIndex": 195, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 28, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected ' character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "c74v", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "9", "bookID": "RUT", - "characterIndex": 166, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 898, + "characterIndex": 258, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 29, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "v2vx", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "9", "bookID": "RUT", - "characterIndex": 60, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 988, + "characterIndex": 112, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 30, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "t69w", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "10", "bookID": "RUT", - "characterIndex": 85, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1013, + "characterIndex": 184, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 31, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "mag8", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "10", "bookID": "RUT", - "characterIndex": 58, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1091, + "characterIndex": 67, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 32, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "bq4j", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "11", "bookID": "RUT", - "characterIndex": 54, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1135, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 67, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1193, + "characterIndex": 147, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 33, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ggi3", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "11", "bookID": "RUT", - "characterIndex": 163, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1320, + "characterIndex": 242, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 34, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "q2hn", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "12", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1360, + "characterIndex": 152, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 35, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "dyc4", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "12", "bookID": "RUT", - "characterIndex": 148, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1379, + "characterIndex": 299, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 36, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "abc1", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "13", "bookID": "RUT", - "characterIndex": 300, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1404, + "characterIndex": 306, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 38, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "gmc2", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "13", "bookID": "RUT", - "characterIndex": 181, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1435, + "characterIndex": 96, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 40, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "gh99", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "13", "bookID": "RUT", - "characterIndex": 170, - "extra": "ST", - "extract": "…ln-e\\\\*, '\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1438, + "characterIndex": 145, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 41, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected ' character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "z9u3", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "13", "bookID": "RUT", - "characterIndex": 166, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1460, + "characterIndex": 117, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 42, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab02", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "14", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1537, + "characterIndex": 67, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 43, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "n47v", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "14", "bookID": "RUT", - "characterIndex": 67, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1678, + "characterIndex": 117, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 44, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "t4sl", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "15", "bookID": "RUT", - "characterIndex": 54, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1787, + "characterIndex": 133, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 46, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "nqm3", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "16", "bookID": "RUT", - "characterIndex": 58, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1791, + "characterIndex": 213, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 49, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "b518", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "17", "bookID": "RUT", - "characterIndex": 58, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1818, + "characterIndex": 116, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 50, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "lql7", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "17", "bookID": "RUT", - "characterIndex": 56, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 1994, + "characterIndex": 250, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 51, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "sje3", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "17", "bookID": "RUT", - "characterIndex": 54, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2038, + "characterIndex": 147, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 53, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab05", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "19", "bookID": "RUT", - "characterIndex": 54, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2081, + "characterIndex": 64, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 55, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "j9wa", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "19", "bookID": "RUT", - "characterIndex": 56, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2103, + "characterIndex": 132, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 56, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "jdr1", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "19", "bookID": "RUT", - "characterIndex": 294, - "extra": "ST", - "extract": "…ln-e\\\\*, '\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2109, + "characterIndex": 109, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 57, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected ' character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "y3us", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "19", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2123, + "characterIndex": 157, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 58, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "abc3", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "20", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2188, + "characterIndex": 246, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 61, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "swe9", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "22", "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2217, + "characterIndex": 178, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 65, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "cx7g", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "22", "bookID": "RUT", - "characterIndex": 59, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2237, + "characterIndex": 187, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 66, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "jdr2", "username": "unfoldingWord", }, Object { + "C": "1", + "V": "22", "bookID": "RUT", - "characterIndex": 58, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2332, + "characterIndex": 194, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 67, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "bgy3", "username": "unfoldingWord", }, Object { + "C": "2", + "V": "intro", "bookID": "RUT", - "characterIndex": 54, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2341, + "characterIndex": 414, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 68, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ld2v", "username": "unfoldingWord", }, Object { + "C": "2", + "V": "1", "bookID": "RUT", - "characterIndex": 181, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2385, + "characterIndex": 182, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", + "fieldName": "OccurrenceNote", + "filename": "en_tn_08-RUT.tsv", + "lineNumber": 69, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2474, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 56, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2510, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 55, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2619, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 173, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2742, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", - "username": "unfoldingWord", - }, - Object { - "bookID": "RUT", - "characterIndex": 175, - "extra": "ST", - "extract": "…ln-e\\\\*, \\"\\\\zaln-…", - "filename": "08-RUT.usfm", - "lineNumber": 2832, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected \\" character after space", - "priority": 191, - "repoCode": "ST", - "repoName": "en_ust", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", + "repoName": "en_tn", + "rowID": "ab10", "username": "unfoldingWord", }, Object { - "C": "front", - "V": "intro", + "C": "2", + "V": "1", "bookID": "RUT", - "characterIndex": 805, + "characterIndex": 248, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 2, + "lineNumber": 70, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "f68r", + "rowID": "t2sn", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "1", + "C": "2", + "V": "2", "bookID": "RUT", - "characterIndex": 108, + "characterIndex": 236, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 4, + "lineNumber": 76, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "sb2j", + "rowID": "j59b", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "1", + "C": "2", + "V": "2", "bookID": "RUT", - "characterIndex": 69, + "characterIndex": 196, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 5, + "lineNumber": 77, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "m9nl", + "rowID": "abc5", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "1", + "C": "2", + "V": "4", "bookID": "RUT", - "characterIndex": 95, + "characterIndex": 255, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 6, + "lineNumber": 81, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "nm13", + "rowID": "vys2", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "1", + "C": "2", + "V": "8", "bookID": "RUT", - "characterIndex": 86, + "characterIndex": 149, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 7, + "lineNumber": 89, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "mmb4", + "rowID": "ltk3", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "4", + "C": "2", + "V": "8", "bookID": "RUT", - "characterIndex": 119, + "characterIndex": 206, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 10, + "lineNumber": 90, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "pk7g", + "rowID": "ke9b", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "6", + "C": "2", + "V": "9", "bookID": "RUT", - "characterIndex": 222, + "characterIndex": 147, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 16, + "lineNumber": 91, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "sa4z", + "rowID": "jq6n", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "6", + "C": "2", + "V": "9", "bookID": "RUT", - "extra": "TN1", - "extract": "figs-idiom", - "fieldName": "SupportReference", + "characterIndex": 52, + "extra": "TN", + "extract": "…itality - that …", + "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 19, + "lineNumber": 92, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Link to TA should also be in OccurrenceNote", - "priority": 787, - "repoCode": "TN1", + "message": "Unexpected - character after space", + "priority": 191, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab01", + "rowID": "xc6u", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "6", + "C": "2", + "V": "9", "bookID": "RUT", - "characterIndex": 144, + "characterIndex": 200, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 19, + "lineNumber": 92, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab01", + "rowID": "xc6u", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "6", + "C": "2", + "V": "9", "bookID": "RUT", - "details": "(SR='figs-idiom')", - "extra": "TN1", - "extract": "figs-synecdoche", + "characterIndex": 196, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 19, + "lineNumber": 94, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Link to TA should also be in SupportReference", - "priority": 786, - "repoCode": "TN1", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab01", + "rowID": "v5e4", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "7", + "C": "2", + "V": "9", "bookID": "RUT", - "extra": "TN1", - "extract": "figs-idiom", - "fieldName": "SupportReference", + "details": "(empty SR field)", + "extra": "TN", + "extract": "figs-euphemism", + "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 20, + "lineNumber": 94, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Link to TA should also be in OccurrenceNote", - "priority": 787, - "repoCode": "TN1", + "message": "Link to TA should also be in SupportReference", + "priority": 786, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "w7ti", + "rowID": "v5e4", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "8", + "C": "2", + "V": "10", "bookID": "RUT", - "characterIndex": 128, + "characterIndex": 169, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 22, + "lineNumber": 96, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "lxs2", + "rowID": "az6y", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "8", + "C": "2", + "V": "10", "bookID": "RUT", - "characterIndex": 96, + "characterIndex": 140, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 25, + "lineNumber": 97, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "g4r8", + "rowID": "ab12", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "8", + "C": "2", + "V": "10", "bookID": "RUT", - "characterIndex": 41, + "characterIndex": 89, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 26, + "lineNumber": 98, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "acb4", + "rowID": "ab13", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "9", + "C": "2", + "V": "10", "bookID": "RUT", - "characterIndex": 195, + "characterIndex": 237, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 28, + "lineNumber": 100, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "c74v", + "rowID": "abc7", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "9", + "C": "2", + "V": "10", "bookID": "RUT", - "characterIndex": 258, + "characterIndex": 200, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 29, + "lineNumber": 101, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "v2vx", + "rowID": "abc8", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "9", + "C": "2", + "V": "11", "bookID": "RUT", - "characterIndex": 112, + "characterIndex": 168, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 30, + "lineNumber": 103, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "t69w", + "rowID": "ab14", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "10", + "C": "2", + "V": "11", "bookID": "RUT", - "characterIndex": 184, + "characterIndex": 129, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 31, + "lineNumber": 104, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "mag8", + "rowID": "app6", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "10", + "C": "2", + "V": "11", "bookID": "RUT", - "characterIndex": 67, + "characterIndex": 151, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 32, + "lineNumber": 105, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "bq4j", + "rowID": "abc9", "username": "unfoldingWord", }, Object { - "C": "1", + "C": "2", "V": "11", "bookID": "RUT", - "characterIndex": 147, + "characterIndex": 141, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 33, + "lineNumber": 106, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ggi3", + "rowID": "r44n", "username": "unfoldingWord", }, Object { - "C": "1", + "C": "2", "V": "11", "bookID": "RUT", - "characterIndex": 242, - "details": "(not 'en')", - "extra": "TN1", - "extract": "…[[rc://en/ta/ma…", - "fieldName": "OccurrenceNote", + "extra": "TN", + "extract": "figs-idiom", + "fieldName": "SupportReference", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 34, + "lineNumber": 107, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Resource container link should have '*' language code", - "priority": 450, - "repoCode": "TN1", + "message": "Link to TA should also be in OccurrenceNote", + "priority": 787, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "q2hn", + "rowID": "ab60", "username": "unfoldingWord", }, Object { - "C": "1", + "C": "2", "V": "12", "bookID": "RUT", - "characterIndex": 152, + "characterIndex": 170, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 35, + "lineNumber": 110, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "dyc4", + "rowID": "gnn5", "username": "unfoldingWord", }, Object { - "C": "1", + "C": "2", "V": "12", "bookID": "RUT", - "characterIndex": 299, - "details": "(not 'en')", - "extra": "TN1", - "extract": "…[[rc://en/ta/ma…", + "details": "detected 1 link but no Bible links from [\\"[[rc://en/ta/man/translate/figs-parallelism]], [Doublet](../figs-doublet/01.md)\\"]", + "extra": "TN", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 36, + "lineNumber": 110, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Resource container link should have '*' language code", - "priority": 450, - "repoCode": "TN1", + "message": "More [ ]( ) links than valid Bible links", + "priority": 648, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc1", + "rowID": "gnn5", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "13", + "C": "2", + "V": "12", "bookID": "RUT", - "characterIndex": 306, + "characterIndex": 259, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 38, + "lineNumber": 111, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "gmc2", + "rowID": "eh86", "username": "unfoldingWord", }, Object { - "C": "1", + "C": "2", "V": "13", "bookID": "RUT", - "characterIndex": 96, + "characterIndex": 206, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 40, + "lineNumber": 112, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "gh99", + "rowID": "abc6", "username": "unfoldingWord", }, Object { - "C": "1", + "C": "2", "V": "13", "bookID": "RUT", - "characterIndex": 145, + "characterIndex": 175, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 41, + "lineNumber": 113, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "z9u3", + "rowID": "v2q1", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "13", + "C": "2", + "V": "15", "bookID": "RUT", - "characterIndex": 117, + "characterIndex": 221, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 42, + "lineNumber": 119, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab02", + "rowID": "v6wr", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "14", + "C": "2", + "V": "17", "bookID": "RUT", - "characterIndex": 67, + "characterIndex": 184, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 43, + "lineNumber": 125, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "n47v", + "rowID": "mq6b", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "14", + "C": "2", + "V": "18", "bookID": "RUT", - "characterIndex": 117, + "characterIndex": 61, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 44, + "lineNumber": 126, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "t4sl", + "rowID": "etn8", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "15", + "C": "2", + "V": "19", "bookID": "RUT", - "characterIndex": 133, + "characterIndex": 208, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 46, + "lineNumber": 128, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "nqm3", + "rowID": "bg28", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "16", + "C": "2", + "V": "19", "bookID": "RUT", - "characterIndex": 213, + "characterIndex": 164, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 49, + "lineNumber": 129, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "b518", + "rowID": "ab07", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "17", + "C": "2", + "V": "20", "bookID": "RUT", - "characterIndex": 116, + "characterIndex": 79, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 50, + "lineNumber": 131, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "lql7", + "rowID": "ab20", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "17", + "C": "2", + "V": "20", "bookID": "RUT", - "characterIndex": 250, + "characterIndex": 188, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 51, + "lineNumber": 133, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "sje3", + "rowID": "ljz3", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "17", + "C": "2", + "V": "20", "bookID": "RUT", - "characterIndex": 147, + "characterIndex": 192, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 53, + "lineNumber": 134, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab05", + "rowID": "wjr4", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "19", + "C": "2", + "V": "20", "bookID": "RUT", - "characterIndex": 64, + "characterIndex": 98, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 55, + "lineNumber": 135, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "j9wa", + "rowID": "cyy2", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "19", + "C": "2", + "V": "22", "bookID": "RUT", - "characterIndex": 132, + "characterIndex": 225, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 56, + "lineNumber": 141, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "jdr1", + "rowID": "ab64", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "19", + "C": "3", + "V": "intro", "bookID": "RUT", - "characterIndex": 109, + "characterIndex": 846, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 57, + "lineNumber": 144, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "y3us", + "rowID": "t4y5", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "19", + "C": "3", + "V": "1", "bookID": "RUT", - "characterIndex": 157, + "characterIndex": 149, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 58, + "lineNumber": 145, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc3", + "rowID": "jdr3", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "20", + "C": "3", + "V": "1", "bookID": "RUT", - "characterIndex": 246, + "characterIndex": 256, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 61, + "lineNumber": 148, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "swe9", + "rowID": "nxr8", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "22", + "C": "3", + "V": "1", "bookID": "RUT", - "characterIndex": 178, + "characterIndex": 161, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 65, + "lineNumber": 149, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "cx7g", + "rowID": "uw2p", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "22", + "C": "3", + "V": "2", "bookID": "RUT", - "characterIndex": 187, + "characterIndex": 456, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 66, + "lineNumber": 150, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "jdr2", + "rowID": "jdr4", "username": "unfoldingWord", }, Object { - "C": "1", - "V": "22", + "C": "3", + "V": "2", "bookID": "RUT", - "characterIndex": 194, + "characterIndex": 217, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 67, + "lineNumber": 151, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "bgy3", + "rowID": "b4h8", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "intro", + "C": "3", + "V": "2", "bookID": "RUT", - "characterIndex": 414, + "characterIndex": 213, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 68, + "lineNumber": 152, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ld2v", + "rowID": "j31t", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "1", + "C": "3", + "V": "2", "bookID": "RUT", - "characterIndex": 182, + "characterIndex": 89, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 69, + "lineNumber": 153, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab10", + "rowID": "nd8v", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "1", + "C": "3", + "V": "4", "bookID": "RUT", - "characterIndex": 248, + "characterIndex": 231, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 70, + "lineNumber": 157, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "t2sn", + "rowID": "jdr5", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "2", + "C": "3", + "V": "4", "bookID": "RUT", - "characterIndex": 236, + "characterIndex": 102, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 76, + "lineNumber": 158, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "j59b", + "rowID": "ab21", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "2", + "C": "3", + "V": "4", "bookID": "RUT", - "characterIndex": 196, + "characterIndex": 163, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 77, + "lineNumber": 159, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc5", + "rowID": "ln1m", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "4", + "C": "3", + "V": "6", "bookID": "RUT", - "characterIndex": 255, + "characterIndex": 427, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 81, + "lineNumber": 164, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "vys2", + "rowID": "ab22", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "8", + "C": "3", + "V": "7", "bookID": "RUT", - "characterIndex": 149, + "characterIndex": 221, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 89, + "lineNumber": 165, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ltk3", + "rowID": "fz7e", "username": "unfoldingWord", }, Object { - "C": "2", + "C": "3", "V": "8", "bookID": "RUT", - "characterIndex": 206, + "characterIndex": 92, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 90, + "lineNumber": 169, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ke9b", + "rowID": "pz92", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "9", + "C": "3", + "V": "8", "bookID": "RUT", - "characterIndex": 147, + "characterIndex": 124, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 91, + "lineNumber": 171, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", - "repoName": "en_tn", - "rowID": "jq6n", - "username": "unfoldingWord", - }, - Object { - "C": "2", - "V": "9", - "bookID": "RUT", - "characterIndex": 52, - "extra": "TN1", - "extract": "…itality - that …", - "fieldName": "OccurrenceNote", - "filename": "en_tn_08-RUT.tsv", - "lineNumber": 92, - "location": " in en RUT book package from unfoldingWord master branch", - "message": "Unexpected - character after space", - "priority": 191, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "xc6u", + "rowID": "ab23", "username": "unfoldingWord", }, Object { - "C": "2", + "C": "3", "V": "9", "bookID": "RUT", - "characterIndex": 200, + "characterIndex": 94, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 92, + "lineNumber": 174, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "xc6u", + "rowID": "xp1b", "username": "unfoldingWord", }, Object { - "C": "2", + "C": "3", "V": "9", "bookID": "RUT", - "characterIndex": 196, - "details": "(not 'en')", - "extra": "TN1", - "extract": "…[[rc://en/ta/ma…", + "details": "detected 1 link but no Bible links from [\\"[2:20](../02/20/zu5f)\\"]", + "extra": "TN", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 94, + "lineNumber": 175, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Resource container link should have '*' language code", - "priority": 450, - "repoCode": "TN1", + "message": "More [ ]( ) links than valid Bible links", + "priority": 648, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "v5e4", + "rowID": "l5g4", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "9", + "C": "3", + "V": "10", "bookID": "RUT", - "details": "(empty SR field)", - "extra": "TN1", - "extract": "figs-euphemism", + "characterIndex": 205, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 94, + "lineNumber": 179, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Link to TA should also be in SupportReference", - "priority": 786, - "repoCode": "TN1", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "v5e4", + "rowID": "n84d", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "10", + "C": "3", + "V": "11", "bookID": "RUT", - "characterIndex": 169, + "characterIndex": 488, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 96, + "lineNumber": 180, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "az6y", + "rowID": "jdr6", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "10", + "C": "3", + "V": "11", "bookID": "RUT", - "characterIndex": 140, + "characterIndex": 199, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 97, + "lineNumber": 182, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab12", + "rowID": "ab08", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "10", + "C": "3", + "V": "12", "bookID": "RUT", - "characterIndex": 89, + "characterIndex": 277, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 98, + "lineNumber": 184, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab13", + "rowID": "jdr7", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "10", + "C": "3", + "V": "12", "bookID": "RUT", - "characterIndex": 237, - "details": "(not 'en')", - "extra": "TN1", - "extract": "…[[rc://en/ta/ma…", + "details": "(empty SR field)", + "extra": "TN", + "extract": "grammar-connect-logic-contrast", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 100, + "lineNumber": 184, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Resource container link should have '*' language code", - "priority": 450, - "repoCode": "TN1", + "message": "Link to TA should also be in SupportReference", + "priority": 786, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc7", + "rowID": "jdr7", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "10", + "C": "3", + "V": "12", "bookID": "RUT", - "characterIndex": 200, + "characterIndex": 209, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 101, + "lineNumber": 185, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc8", + "rowID": "ab30", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "11", + "C": "3", + "V": "12", "bookID": "RUT", - "characterIndex": 168, - "details": "(not 'en')", - "extra": "TN1", - "extract": "…[[rc://en/ta/ma…", + "details": "detected 1 link but no Bible links from [\\"[2:20](../02/20/zu5f)\\"]", + "extra": "TN", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 103, + "lineNumber": 186, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Resource container link should have '*' language code", - "priority": 450, - "repoCode": "TN1", + "message": "More [ ]( ) links than valid Bible links", + "priority": 648, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab14", + "rowID": "fvq5", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "11", + "C": "3", + "V": "13", "bookID": "RUT", - "characterIndex": 129, + "characterIndex": 249, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 104, + "lineNumber": 187, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "app6", + "rowID": "gcl8", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "11", + "C": "3", + "V": "14", "bookID": "RUT", - "characterIndex": 151, + "characterIndex": 121, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 105, + "lineNumber": 190, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc9", + "rowID": "dwx1", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "11", + "C": "3", + "V": "16", "bookID": "RUT", - "characterIndex": 141, + "characterIndex": 248, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 106, + "lineNumber": 195, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "r44n", + "rowID": "s7dr", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "11", + "C": "3", + "V": "17", "bookID": "RUT", - "extra": "TN1", - "extract": "figs-idiom", - "fieldName": "SupportReference", + "details": "detected 1 link but no Bible links from [\\"[3:15](../03/15/f5zg)\\"]", + "extra": "TN", + "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 107, + "lineNumber": 198, "location": " in en RUT book package from unfoldingWord master branch", - "message": "Link to TA should also be in OccurrenceNote", - "priority": 787, - "repoCode": "TN1", + "message": "More [ ]( ) links than valid Bible links", + "priority": 648, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "ab60", + "rowID": "abca", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "12", + "C": "3", + "V": "17", "bookID": "RUT", - "characterIndex": 170, + "characterIndex": 222, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 110, + "lineNumber": 199, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "gnn5", + "rowID": "e9xx", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "12", + "C": "3", + "V": "18", "bookID": "RUT", - "details": "detected 1 link but no Bible links from [\\"[[rc://en/ta/man/translate/figs-parallelism]], [Doublet](../figs-doublet/01.md)\\"]", - "extra": "TN1", + "characterIndex": 125, + "details": "(not 'en')", + "extra": "TN", + "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 110, + "lineNumber": 200, "location": " in en RUT book package from unfoldingWord master branch", - "message": "More [ ]( ) links than valid Bible links", - "priority": 648, - "repoCode": "TN1", + "message": "Resource container link should have '*' language code", + "priority": 450, + "repoCode": "TN", "repoName": "en_tn", - "rowID": "gnn5", + "rowID": "ab36", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "12", + "C": "3", + "V": "18", "bookID": "RUT", - "characterIndex": 259, + "characterIndex": 98, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 111, + "lineNumber": 202, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "eh86", + "rowID": "ab37", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "13", + "C": "3", + "V": "18", "bookID": "RUT", - "characterIndex": 206, + "characterIndex": 137, "details": "(not 'en')", - "extra": "TN1", + "extra": "TN", "extract": "…[[rc://en/ta/ma…", "fieldName": "OccurrenceNote", "filename": "en_tn_08-RUT.tsv", - "lineNumber": 112, + "lineNumber": 203, "location": " in en RUT book package from unfoldingWord master branch", "message": "Resource container link should have '*' language code", "priority": 450, - "repoCode": "TN1", + "repoCode": "TN", "repoName": "en_tn", - "rowID": "abc6", + "rowID": "ab38", "username": "unfoldingWord", }, Object { - "C": "2", - "V": "13", + "C": "4", + "V": "intro", "bookID": "RUT", - "characterIndex": 175, - "details": "(not 'en')", - "extra": "TN1", - "extract": "…[[rc://en/ta/ma…", + "characterIndex": 407, + "extra": "TN", + "extract": "…in␣him.␣
␣los…", + "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", diff --git a/src/__tests__/tn-table-row-check.test.js b/src/__tests__/tn-table-row-check.test.js index dd7532c4..f53100a1 100644 --- a/src/__tests__/tn-table-row-check.test.js +++ b/src/__tests__/tn-table-row-check.test.js @@ -33,28 +33,28 @@ describe('checkTN_TSVDataRow() - ', () => { 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); - expect(rawResults.noticeList.length).toEqual(1); + 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); - expect(rawResults.noticeList.length).toEqual(1); + 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 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); - expect(rawResults.noticeList.length).toEqual(1); + 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 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); - expect(rawResults.noticeList.length).toEqual(1); + expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -114,14 +114,14 @@ describe('checkTN_TSVDataRow() - ', () => { 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); - expect(rawResults.noticeList.length).toEqual(1); + 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); - expect(rawResults.noticeList.length).toEqual(1); + expect(rawResults.noticeList.length).toEqual(2); expect(rawResults).toMatchSnapshot(); }); @@ -336,7 +336,7 @@ describe('checkTN_TSVDataRow() - ', () => { 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
Boo hoo,,
lost my shoe !"; const rawResults = await checkTN_TSVDataRow(languageCode, chosenLine, 'GEN','1','2', 'that was supplied', optionalCheckingOptions); - expect(rawResults.noticeList.length).toEqual(15); + expect(rawResults.noticeList.length).toEqual(16); expect(rawResults).toMatchSnapshot(); }); diff --git a/src/core/BCS-usfm-grammar-check.md b/src/core/BCS-usfm-grammar-check.md index 61a0dc42..76f843d6 100644 --- a/src/core/BCS-usfm-grammar-check.md +++ b/src/core/BCS-usfm-grammar-check.md @@ -7,6 +7,9 @@ Our packaged function returns a list of success messages and a list of (prioriti 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 { checkUSFMGrammar } from './BCS-usfm-grammar-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; diff --git a/src/core/annotation-row-check.js b/src/core/annotation-row-check.js index 91c69b5b..c47c6e01 100644 --- a/src/core/annotation-row-check.js +++ b/src/core/annotation-row-check.js @@ -7,21 +7,23 @@ import { checkTNLinksToOutside } from './tn-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; -// const ANNOTATION_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.0'; +// const ANNOTATION_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.3'; 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 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 (TN) + * @description - Checks one TSV data row of translation notes (TN2) * @param {String} languageCode - the language code, e.g., 'en' - * @param {String} annotationType - TN, TQ, TWL, SN, or SQ -- allows more specific checks + * @param {String} annotationType - 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 @@ -34,7 +36,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li /* This function is only for checking one data row and the function doesn't assume that it has any previous context. - TN, TQ, TWL, SN, or SQ + 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' @@ -61,6 +63,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li if (givenV) console.assert(typeof givenV === 'string', `checkAnnotationTSVDataRow: 'givenV' parameter should be a string not a '${typeof givenV}'`); console.assert(givenRowLocation !== undefined, "checkAnnotationTSVDataRow: 'givenRowLocation' parameter should be defined"); console.assert(typeof givenRowLocation === 'string', `checkAnnotationTSVDataRow: 'givenRowLocation' parameter should be a string not a '${typeof givenRowLocation}'`); + console.assert(givenRowLocation.indexOf('true') === -1, "checkAnnotationTSVDataRow: 'givenRowLocation' parameter should not be 'true'"); let ourRowLocation = givenRowLocation; if (ourRowLocation && ourRowLocation[0] !== ' ') ourRowLocation = ` ${ourRowLocation}`; @@ -94,7 +97,9 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `checkAnnotationTSVDataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "checkAnnotationTSVDataRow addNoticePartial: 'location' parameter should be defined"); console.assert(typeof noticeObject.location === 'string', `checkAnnotationTSVDataRow 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})`; drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); } @@ -125,9 +130,11 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li console.assert(fieldText !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "checkAnnotationTSVDataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + console.assert(rowLocation !== undefined, "checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + console.assert(typeof rowLocation === 'string', `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); console.assert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const omtcResultObject = checkMarkdownText(fieldName, fieldText, rowLocation, optionalCheckingOptions); + const omtcResultObject = checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -171,6 +178,8 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li console.assert(fieldText !== undefined, "checkAnnotationTSVDataRow ourCheckTextField: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `checkAnnotationTSVDataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "checkAnnotationTSVDataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + console.assert(rowLocation !== undefined, "checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + console.assert(typeof rowLocation === 'string', `checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); console.assert(rowLocation.indexOf(fieldName) < 0, `checkAnnotationTSVDataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'Annotation' ? 'markdown' : 'raw'; @@ -274,7 +283,7 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li // 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 TN check + 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 }); @@ -405,28 +414,28 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li 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); + 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_PLUS_DIGITS.indexOf(rowID[0]) < 0) - addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter or digit", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + } 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.indexOf(rowID[1]) < 0) + 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.indexOf(rowID[2]) < 0) + 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 (supportReference.length) { // need to check TN against TA + 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 === 'TN') { // More than just whitespace + else if (annotationType === 'TN2') { // More than just whitespace const supportReferenceArticlePart = supportReference.replace('rc://*/ta/man/translate/', ''); // console.log("supportReferenceArticlePart", supportReferenceArticlePart); if (!supportReferenceArticlePart.startsWith('figs-') @@ -436,7 +445,8 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li && supportReferenceArticlePart !== 'guidelines-sonofgodprinciples') addNoticePartial({ priority: 788, message: "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); SRSuggestion = ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, optionalCheckingOptions); - await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); + if (optionalCheckingOptions.disableAllLinkFetchingFlag !== true) + await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); if (annotation.indexOf(supportReference) < 0) addNoticePartial({ priority: 787, message: "Link to TA should also be in Annotation", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); } @@ -455,7 +465,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 === 'TN' && V !== 'intro' && occurrence !== '0') + if (annotationType === '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 @@ -500,11 +510,11 @@ export async function checkAnnotationTSVDataRow(languageCode, annotationType, li } } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - if (annotationType === 'TN') + if (annotationType === 'TN2') addNoticePartial({ priority: 274, message: "Missing Annotation field", fieldName: 'Annotation', 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}`; + 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}`; if (suggestion !== line) { // console.log(`Had annotation ${line}`); // console.log(`Sug annotation ${suggestion}`); diff --git a/src/core/annotation-row-check.md b/src/core/annotation-row-check.md index 82d1fe5c..e0f9e9a2 100644 --- a/src/core/annotation-row-check.md +++ b/src/core/annotation-row-check.md @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 { checkAnnotationTSVDataRow } from './annotation-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -40,7 +43,7 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - annotationType: 'TN', + annotationType: 'TN2', tableLineName : 'lineA9', tableLine : lineA9, bookID : 'GEN', C:'1', V:'2', @@ -59,7 +62,8 @@ function CheckAnnotationRow(props) { (async () => { // Display our "waiting" message setResults(

Checking {tableLineName} {bookID}

); - const rawResults = await checkAnnotationTSVDataRow(languageCode, annotationType, tableLine, bookID, C, V, givenLocation); + // (Final unused parameter is optionalCheckingOptions) + const rawResults = await checkAnnotationTSVDataRow(languageCode, annotationType, tableLine, bookID, C, V, givenLocation, {}); setResults(
Check {tableLineName}: "{tableLine.substr(0,256)}…"

diff --git a/src/core/annotation-table-check.js b/src/core/annotation-table-check.js index 5baf8e4e..39264418 100644 --- a/src/core/annotation-table-check.js +++ b/src/core/annotation-table-check.js @@ -3,7 +3,7 @@ import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' import { checkAnnotationTSVDataRow } from './annotation-row-check'; -const ANNOTATION_TABLE_VALIDATOR_VERSION_STRING = '0.2.6'; +const ANNOTATION_TABLE_VALIDATOR_VERSION_STRING = '0.2.7'; 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'; @@ -31,7 +31,6 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - // if (bookID) ourLocation = ` in ${bookID}${ourLocation}`; const carResult = { successList: [], noticeList: [] }; @@ -55,6 +54,8 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "ATSV addNoticePartial: 'location' parameter should be defined"); console.assert(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 }); } @@ -118,7 +119,7 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, // 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 TN check + 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 }); @@ -227,6 +228,10 @@ export async function checkAnnotationRows(languageCode, annotationType, bookID, } } } + + if (optionalCheckingOptions.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(`checkAnnotationRows v${ANNOTATION_TABLE_VALIDATOR_VERSION_STRING} finished with ${carResult.noticeList.length ? carResult.noticeList.length.toLocaleString() : "zero"} notice${carResult.noticeList.length === 1 ? '' : 's'}`); diff --git a/src/core/annotation-table-check.md b/src/core/annotation-table-check.md index 4786671b..d7ff9413 100644 --- a/src/core/annotation-table-check.md +++ b/src/core/annotation-table-check.md @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 { checkAnnotationRows } from './annotation-table-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -37,7 +40,7 @@ const data = { // You can choose any of the above lines here // (to demonstrate differing results) languageCode: 'en', - annotationType: 'TN', + annotationType: 'TN2', tableTextName : 'textG', tableText : textG, bookID : 'GEN', @@ -57,7 +60,8 @@ function CheckAnnotationRows(props) { (async () => { // Display our "waiting" message setResults(

Checking {languageCode} {annotationType} for {tableTextName} {bookID}

); - const rawResults = await checkAnnotationRows(languageCode, annotationType, bookID, filename, tableText, givenLocation); + // (Final unused parameter is optionalCheckingOptions) + const rawResults = await checkAnnotationRows(languageCode, annotationType, bookID, filename, tableText, givenLocation, {}); setResults(
Check {tableTextName}: "{tableText.substr(0,256)}…"

diff --git a/src/core/field-link-check.js b/src/core/field-link-check.js index 9e091348..16b0b24c 100644 --- a/src/core/field-link-check.js +++ b/src/core/field-link-check.js @@ -63,6 +63,16 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField console.log(`checkFieldLinks('${fieldName}', '${fieldText}')…`); // console.log( "linkOptions", JSON.stringify(linkOptions)); // console.log( "linkOptionsEC", linkOptions.expectedCount); + console.assert(fieldName !== undefined, "checkFieldLinks: 'fieldName' parameter should be defined"); + console.assert(typeof fieldName === 'string', `checkFieldLinks: 'fieldName' parameter should be a string not a '${typeof fieldName}': ${fieldName}`); + console.assert(fieldText !== undefined, "checkFieldLinks: 'fieldText' parameter should be defined"); + console.assert(typeof fieldText === 'string', `checkFieldLinks: 'fieldText' parameter should be a string not a '${typeof fieldText}': ${fieldText}`); + console.assert(optionalFieldLocation !== undefined, "checkFieldLinks: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof optionalFieldLocation === 'string', `checkFieldLinks: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}': ${optionalFieldLocation}`); + console.assert(optionalFieldLocation.indexOf('true') === -1, `checkFieldLinks: 'optionalFieldLocation' parameter should not be '${optionalFieldLocation}'`); + + let ourLocation = optionalFieldLocation; + if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; let result = { noticeList: [] }; @@ -78,19 +88,21 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField if (extract) console.assert(typeof extract === 'string', `cFLs addNotice5: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); console.assert(location !== undefined, "cFLs addNotice5: 'location' parameter should be defined"); console.assert(typeof location === 'string', `cFLs addNotice5: 'location' parameter should be a string not a '${typeof location}': ${location}`); + result.noticeList.push({ priority, message, characterIndex, extract, location }); } - // Create our more detailed location string by prepending the fieldName - let ourAtString = ` in '${fieldName}'`; - if (optionalFieldLocation) { - if (optionalFieldLocation[0] !== ' ') ourAtString += ' '; - ourAtString += optionalFieldLocation; - } + // // Create our more detailed location string by prepending the fieldName + // let ourAtString = ` in '${fieldName}'`; + // if (optionalFieldLocation) { + // if (optionalFieldLocation[0] !== ' ') ourAtString += ' '; + // ourAtString += optionalFieldLocation; + // } + if (!fieldText) { // Nothing to check if (linkOptions.expectedCount > 0) - addNotice5({ priority: 438, message: `Blank field / missing link (expected ${linkOptions.expectedCount} link${linkOptions.expectedCount === 1 ? "" : "s"})`, location: ourAtString }); + addNotice5({ priority: 438, message: `Blank field / missing link (expected ${linkOptions.expectedCount} link${linkOptions.expectedCount === 1 ? "" : "s"})`, location: ourLocation }); return result; } @@ -132,11 +144,11 @@ export function checkFieldLinks(fieldName, fieldText, linkOptions, optionalField // console.log("checkFieldLinks regexResultsArray", regexResultsArray.length, JSON.stringify(regexResultsArray)); if (regexResultsArray.length < linkOptions.expectedCount) - addNotice5({ priority: 287, message: `Not enough links (expected ${linkOptions.expectedCount} link${linkOptions.expectedCount === 1 ? "" : "s"})`, location: ` (only found ${regexResultsArray.length})${ourAtString}` }); + addNotice5({ priority: 287, message: `Not enough links (expected ${linkOptions.expectedCount} link${linkOptions.expectedCount === 1 ? "" : "s"})`, location: ` (only found ${regexResultsArray.length})${ourLocation}` }); if (linkOptions.checkTargets && linkOptions.callbackFunction && regexResultsArray) { startLiveLinksCheck(regexResultsArray, result.noticeList.slice(0), linkOptions.callbackFunction); - addNotice5({ priority: 600, message: `${regexResultsArray.length} link target${regexResultsArray.length === 1 ? ' is' : 's are'} still being checked…`, location: ourAtString }); + addNotice5({ priority: 600, message: `${regexResultsArray.length} link target${regexResultsArray.length === 1 ? ' is' : 's are'} still being checked…`, location: ourLocation }); console.log("checkFieldLinks now returning initial result…"); } diff --git a/src/core/field-link-check.md b/src/core/field-link-check.md index ee375bfc..34f5f32a 100644 --- a/src/core/field-link-check.md +++ b/src/core/field-link-check.md @@ -3,6 +3,9 @@ This function is for checking text fields that are links, or that contain links. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import { checkFieldLinks } from './field-link-check'; import { processNoticesToErrorsWarnings } from '../demos/notice-processing-functions'; import { RenderLines, RenderRawResults, RenderSuccessesErrorsWarnings } from '../demos/RenderProcessedResults'; diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index f19412ba..a4823c11 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -1,7 +1,7 @@ import { DEFAULT_EXTRACT_LENGTH, MATCHED_PUNCTUATION_PAIRS, isWhitespace, countOccurrences } from './text-handling-functions' -// const FIELD_TEXT_VALIDATOR_VERSION_STRING = '0.2.0'; +// const FIELD_TEXT_VALIDATOR_VERSION_STRING = '0.2.4'; /** @@ -27,7 +27,7 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op // console.log(`checkTextField(${fieldName}, ${fieldText.length.toLocaleString()} chars, ${allowedLinks}, '${optionalFieldLocation}')…`); console.assert(fieldType !== undefined, "checkTextField: 'fieldType' parameter should be defined"); console.assert(typeof fieldType === 'string', `checkTextField: 'fieldType' parameter should be a string not a '${typeof fieldType}': ${fieldType}`); - console.assert(fieldType !== '', `checkTextField: 'fieldType' ${fieldName} parameter should be not be an empty string`); + console.assert(fieldType !== '', `checkTextField: 'fieldType' ${fieldType} parameter should be not be an empty string`); console.assert(fieldType === 'markdown' || fieldType === 'USFM' || fieldType === 'YAML' || fieldType === 'raw' || fieldType === 'link', `checkTextField: unrecognised 'fieldType' parameter: '${fieldType}'`); console.assert(fieldName !== undefined, "checkTextField: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `checkTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}': ${fieldName}`); @@ -37,6 +37,11 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op console.assert(typeof fieldText === 'string', `checkTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}': ${fieldText}`); console.assert(allowedLinks === true || allowedLinks === false, "checkTextField: allowedLinks parameter must be either true or false"); if (!allowedLinks) console.assert(fieldText.indexOf('x-tw') < 0, `checkTextField should be allowedLinks for ${fieldType} ${fieldName} ${fieldText}`) + console.assert(optionalFieldLocation !== undefined, "checkTextField: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof optionalFieldLocation === 'string', `checkTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}': ${optionalFieldLocation}`); + console.assert(optionalFieldLocation.indexOf('true') === -1, `checkTextField: 'optionalFieldLocation' parameter should not be '${optionalFieldLocation}'`); + if (optionalCheckingOptions !== undefined) + console.assert(typeof optionalCheckingOptions === 'object', `checkTextField: 'optionalCheckingOptions' parameter should be an object not a '${typeof optionalCheckingOptions}': ${JSON.stringify(optionalCheckingOptions)}`); let result = { noticeList: [] }; @@ -53,6 +58,8 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `dBTCs addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "dBTCs addNoticePartial: 'location' parameter should be defined"); console.assert(typeof noticeObject.location === 'string', `dBTCs addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + // noticeObject.debugChain = noticeObject.debugChain ? `checkTextField(${fieldType}, ${fieldName}, ${allowedLinks}) ${noticeObject.debugChain}` : `checkTextField(${fieldType}, ${fieldName}, ${allowedLinks})`; if (fieldName.length) noticeObject.fieldName = fieldName; // Don't add the field if it's blank result.noticeList.push(noticeObject); } @@ -131,6 +138,14 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op addNoticePartial({ priority: 771, message: `Unexpected leading zero-width joiner`, characterIndex: 0, extract, location: ourLocation }); if (suggestion[0] === '\u200D') suggestion = suggestion.substring(1); } + if ((characterIndex = fieldText.indexOf('
')) >= 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 }); + } + if ((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 }); + } if (fieldText[fieldText.length - 1] === '\u2060') { const extract = fieldText.substring(0, extractLength).replace(/\u2060/g, '‼') + (fieldText.length > extractLength ? '…' : ''); @@ -154,12 +169,14 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op while (suggestion.toLowerCase().substring(0, 6) === '
') suggestion = suggestion.substring(6); } - if (fieldText[fieldText.length - 1] === ' ') { - const extract = (fieldText.length > extractLength ? '…' : '') + fieldText.substring(fieldText.length - 10).replace(/ /g, '␣'); - const notice = { priority: 95, message: "Unexpected trailing space(s)", extract, location: ourLocation }; - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = fieldText.length - 1; // characterIndex means nothing for processed USFM - addNoticePartial(notice); - } + if (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 }; + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = fieldText.length - 1; // characterIndex means nothing for processed USFM + addNoticePartial(notice); + } if ((characterIndex = fieldText.indexOf(' = 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 }); @@ -182,7 +199,7 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op if ((characterIndex = fieldText.indexOf(' ')) >= 0) { const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') const notice = { priority: 194, message: "Unexpected double spaces", extract, location: ourLocation } - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); } if ((characterIndex = fieldText.indexOf('\n')) >= 0) { @@ -203,7 +220,7 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op if ((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 }; - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); suggestion = suggestion.replace(/\u202F/g, ' '); } @@ -224,9 +241,9 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op // Check for doubled punctuation chars (international) // Doesn't check for doubled forward slash by default coz that might occur in a link, e.g., https://etc… // or doubled # coz that occurs in markdown - let doubledPunctuationCheckList = '({}<>⟨⟩:،、‒–—―…!‹›«»‐?‘’“”\';⁄·&@•^†‡°¡¿※№÷׺ª%‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿₵¢₡₢$₫₯֏₠€ƒ₣₲₴₭₺₾ℳ₥₦₧₱₰£៛₽₹₨₪৳₸₮₩¥'; + let doubledPunctuationCheckList = '({}<>⟨⟩:،、‒–—―…!‹›«»‐?‘’“”\';⁄·&@•^†‡°¡¿※№÷׺ª%‰+−=‱¶′″‴§|‖¦©℗®℠™¤₳฿₵¢₡₢$₫₯֏₠€ƒ₣₲₴₭₺₾ℳ₥₦₧₱₰£៛₽₹₨₪৳₸₮₩¥'; if (!allowedLinks) doubledPunctuationCheckList += '/[].)'; // Double square brackets can be part of markdown links, double periods can be part of a path - if (fieldType !== 'markdown') doubledPunctuationCheckList += '_*#'; // There are used for markdown formatting + if (fieldType !== 'markdown') doubledPunctuationCheckList += '_*#~'; // There are used for markdown formatting if (fieldType !== 'USFM' || fieldText.indexOf('x-morph') < 0) doubledPunctuationCheckList += ',"'; // Allowed in original language morphology fields if (fieldType !== 'YAML' || !fieldText.startsWith('--')) // NOTE: First hyphen may have been removed in preprocessing doubledPunctuationCheckList += '-'; @@ -235,9 +252,9 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op if (characterIndex >= 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 }; - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); - } + } } // Check for punctuation chars following space and at start of line // Removed ©$€₱ @@ -250,10 +267,12 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op if ((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 }; - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); - } - if ((punctChar !== '-' || fieldType !== 'YAML') && fieldText[0] === punctChar) { + } + if ((punctChar !== '-' || fieldType !== 'YAML') + && (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 }); @@ -270,21 +289,33 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op if (fieldType !== 'markdown' && fieldType !== 'USFM') beforeSpaceCheckList += '*'; // There are used for markdown formatting and USFM closing markers if (fieldType !== 'YAML') beforeSpaceCheckList += '['; for (const punctChar of beforeSpaceCheckList) { - if ((characterIndex = fieldText.indexOf(punctChar + ' '))>= 0) { + 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 }; - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); - } + } 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 }; - if (fieldType !== 'raw' || fieldName.substring(0,6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM + if (fieldType !== 'raw' || fieldName.substring(0, 6) !== 'from \\') notice.characterIndex = characterIndex; // characterIndex means nothing for processed USFM addNoticePartial(notice); - } + } + } + + // 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 }); } + // if (countOccurrences(fieldText, '(') !== countOccurrences(fieldText, ')')) { + // console.log(`checkTextField(${fieldType}, ${fieldName}, '${fieldText}', ${allowedLinks}, ${ourLocation}) found ${countOccurrences(fieldText, '(')} '(' but ${countOccurrences(fieldText, ')')} ')'`); + // addNoticePartial({ priority: 1, message: `Mismatched ( ) characters`, details: `(left=${countOccurrences(fieldText, '(').toLocaleString()}, right=${countOccurrences(fieldText, ')').toLocaleString()})`, location: ourLocation }); + // } // Check matched pairs in the field for (const punctSet of MATCHED_PUNCTUATION_PAIRS) { // Can't check '‘’' coz they might be used as apostrophe @@ -292,6 +323,7 @@ export function checkTextField(fieldType, fieldName, fieldText, allowedLinks, op // if (fieldType === 'markdown' && leftChar === '<') continue; // markdown uses this for block quote if ((fieldType === 'USFM' || fieldName.startsWith('from \\') || (fieldType === 'markdown' && fieldName === '')) && '([{“«'.indexOf(leftChar) >= 0) continue; // Start/end can be on different lines + if (fieldType === 'markdown' && leftChar === '<') continue; // > is a markdown block marker const rightChar = punctSet[1]; const leftCount = countOccurrences(fieldText, leftChar); const rightCount = countOccurrences(fieldText, rightChar); diff --git a/src/core/field-text-check.md b/src/core/field-text-check.md index a6e4ee90..bc1c2e33 100644 --- a/src/core/field-text-check.md +++ b/src/core/field-text-check.md @@ -7,6 +7,9 @@ This generic function returns a list/array of notices, that can then be post-pro This demonstration doesn't display the raw notices, but rather displays the processed and formatted lists of errors and warnings. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import { checkTextField } from './field-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; diff --git a/src/core/file-text-check.js b/src/core/file-text-check.js index 2ee0f351..c3227278 100644 --- a/src/core/file-text-check.js +++ b/src/core/file-text-check.js @@ -3,7 +3,7 @@ import { checkPlainText } from './plain-text-check'; //const FILE_TEXT_VALIDATOR_VERSION_STRING = '0.3.0'; -export function checkTextfileContents(languageCode, filename, fileText, optionalFileLocation, optionalCheckingOptions) { +export function checkTextfileContents(languageCode, fileType, filename, fileText, optionalFileLocation, optionalCheckingOptions) { // Does basic checks for small errors like mismatched punctuation pairs, etc. // (Used by ourBasicFileChecks() in checkUSFMText() in usfm-text-check.js) @@ -23,6 +23,10 @@ export function checkTextfileContents(languageCode, filename, fileText, optional // console.log(`checkTextfileContents(${filename}, ${fileText.length.toLocaleString()} chars, '${optionalFileLocation}')…`); console.assert(languageCode !== undefined, "checkTextfileContents: 'languageCode' parameter should be defined"); console.assert(typeof languageCode === 'string', `checkTextfileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + console.assert(fileType !== undefined, "checkTextfileContents: 'fileType' parameter should be defined"); + console.assert(typeof fileType === 'string', `checkTextfileContents: 'fileType' parameter should be a string not a '${typeof fileType}': ${fileType}`); + console.assert(fileType !== '', `checkTextfileContents: 'fileType' ${fileType} parameter should be not be an empty string`); + console.assert(fileType === 'markdown' || fileType === 'USFM' || fileType === 'YAML' || fileType === 'text', `checkTextfileContents: unrecognised 'fileType' parameter: '${fileType}'`); console.assert(filename !== undefined, "checkTextfileContents: 'filename' parameter should be defined"); console.assert(typeof filename === 'string', `checkTextfileContents: 'filename' parameter should be a string not a '${typeof filename}': ${filename}`); console.assert(fileText !== undefined, "checkTextfileContents: 'fileText' parameter should be defined"); @@ -42,10 +46,11 @@ export function checkTextfileContents(languageCode, filename, fileText, optional if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `dBTCs addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "dBTCs addNotice: 'location' parameter should be defined"); console.assert(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}`; result.noticeList.push(noticeObject); } - function ourCheckPlainText(textType, plainText, givenLocation, optionalCheckingOptions) { + function ourCheckPlainText(textType, textFilename, plainText, givenLocation, optionalCheckingOptions) { /** * @description - checks the given text field and processes the returned results * @param {String} plainText - the actual text of the field being checked @@ -57,13 +62,13 @@ export function checkTextfileContents(languageCode, filename, fileText, optional // We assume that checking for compulsory fields is done elsewhere // Updates the global list of notices - // console.log(`cPT ourCheckTextField(${fieldName}, (${fieldText.length}), ${fieldLocation}, …)`); - // console.assert(textName !== undefined, "cPT ourCheckTextField: 'textName' parameter should be defined"); - // console.assert(typeof textName === 'string', `cPT ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof textName}'`); - console.assert(plainText !== undefined, "cPT ourCheckTextField: 'plainText' parameter should be defined"); - console.assert(typeof plainText === 'string', `cPT ourCheckTextField: 'plainText' parameter should be a string not a '${typeof plainText}'`); + // console.log(`cPT ourCheckPlainText(${fieldName}, (${fieldText.length}), ${fieldLocation}, …)`); + // console.assert(textName !== undefined, "cPT ourCheckPlainText: 'textName' parameter should be defined"); + // console.assert(typeof textName === 'string', `cPT ourCheckPlainText: 'fieldName' parameter should be a string not a '${typeof textName}'`); + console.assert(plainText !== undefined, "cPT ourCheckPlainText: 'plainText' parameter should be defined"); + console.assert(typeof plainText === 'string', `cPT ourCheckPlainText: 'plainText' parameter should be a string not a '${typeof plainText}'`); - const resultObject = checkPlainText(textType, '', plainText, givenLocation, optionalCheckingOptions); + const resultObject = checkPlainText(textType, textFilename, plainText, givenLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -71,7 +76,7 @@ export function checkTextfileContents(languageCode, filename, fileText, optional // If we need to put everything through addNotice9, e.g., for debugging or filtering // process results line by line for (const noticeEntry of resultObject.noticeList) - addNotice({ ...noticeEntry, filename }); + addNotice({ ...noticeEntry, filename: textFilename }); } // end of ourCheckTextField function @@ -99,13 +104,14 @@ export function checkTextfileContents(languageCode, filename, fileText, optional // console.log(`Using halfLength=${halfLength}`, `halfLengthPlus=${halfLengthPlus}`); */ + /* let textType = 'raw'; const filenameLower = filename.toLowerCase(); if (filenameLower.endsWith('.usfm')) textType = 'USFM'; else if (filenameLower.endsWith('.md')) textType = 'markdown'; else if (filenameLower.endsWith('.yaml') || filenameLower.endsWith('.yml')) textType = 'YAML'; - - ourCheckPlainText(textType, fileText, ourLocation, optionalCheckingOptions); + */ + ourCheckPlainText(fileType, filename, fileText, ourLocation, optionalCheckingOptions); // // Simple check that there aren't any // ix = fileText.indexOf('://'); diff --git a/src/core/file-text-check.md b/src/core/file-text-check.md index 34975fbd..9bd985ac 100644 --- a/src/core/file-text-check.md +++ b/src/core/file-text-check.md @@ -9,6 +9,9 @@ This generic function returns a list/array of notices, that can then be post-pro This demonstration doesn't display the raw notices, but rather displays the processed and formatted lists of errors and warnings. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import { checkTextfileContents } from './file-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -24,7 +27,7 @@ const textB = `{ Peace on Earth,, const chosenTextName = "textB"; const chosenText = textB; -const rawResults = checkTextfileContents('en', 'Sample', chosenText, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkTextfileContents('en', 'text', 'Sample', chosenText, 'in '+chosenTextName+' that was supplied'); // 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/getApi.js b/src/core/getApi.js index c865af34..7e201a15 100644 --- a/src/core/getApi.js +++ b/src/core/getApi.js @@ -5,10 +5,9 @@ import { setup } from 'axios-cache-adapter'; import JSZip from 'jszip'; import * as books from './books'; import { clearCheckedArticleCache } from './tn-links-check'; -// import { consoleLogObject } from '../core/utilities'; -// const GETAPI_VERSION_STRING = '0.6.2'; +// const GETAPI_VERSION_STRING = '0.6.5'; const MAX_INDIVIDUAL_FILES_TO_DOWNLOAD = 5; // More than this and it downloads the zipfile for the entire repo @@ -72,14 +71,14 @@ export async function clearCaches() { await zipStore.clear(); await cacheStore.clear(); // This is the one used by the Axion Door43Api (above) await unzipStore.clear(); - await clearCheckedArticleCache(); // Used for checking TA and TW articles referred to by TN links + await clearCheckedArticleCache(); // Used for checking TA and TW articles referred to by TN2 links } /** * @description - Forms and returns a Door43 repoName string * @param {String} languageCode - the language code, e.g., 'en' - * @param {String} repoCode - the repo code, e.g., 'TQ' + * @param {String} repoCode - the repo code, e.g., 'TQ2' * @return {String} - the Door43 repoName string */ export function formRepoName(languageCode, repoCode) { @@ -95,14 +94,9 @@ export function formRepoName(languageCode, repoCode) { else if (repoCode === 'UGNT') repo_languageCode = 'el-x-koine'; let repoName; - if (repoCode === 'TWL' || repoCode === 'TN' || repoCode === 'TQ') - repoName = `${repo_languageCode}_translation-annotations`; - else if (repoCode === 'SN' || repoCode === 'SQ') - repoName = `${repo_languageCode}_study-annotations`; - else { - if (repoCode.endsWith('1')) repoCode = repoCode.substring(0, repoCode.length - 1); - repoName = `${repo_languageCode}_${repoCode.toLowerCase()}`; - } + + // if (repoCode.endsWith('2')) repoCode = repoCode.substring(0, repoCode.length - 1); + repoName = `${repo_languageCode}_${repoCode.toLowerCase()}`; return repoName; } @@ -145,7 +139,7 @@ async function getUnZippedFile(path) { */ // This is the function that we call the most from the outside export async function cachedGetFile({ username, repository, path, branch }) { - // if (repository==='en_ta') console.log(`cachedGetFile(${username}, ${repository}, ${path}, ${branch})…`); + // console.log(`cachedGetFile(${username}, ${repository}, ${path}, ${branch})…`); console.assert(typeof username === 'string' && username.length, `cachedGetFile: username parameter should be a string`); console.assert(typeof repository === 'string' && repository.length, `cachedGetFile: repository parameter should be a string`); console.assert(typeof path === 'string' && path.length, `cachedGetFile: path parameter should be a string`); @@ -160,7 +154,7 @@ export async function cachedGetFile({ username, repository, path, branch }) { contents = await getFileFromZip({ username, repository, path, branch }); // if (contents) - // if (filePath.indexOf('_tq/') < 0) // Don't log for TQ files coz too many + // if (filePath.indexOf('_tq/') < 0) // Don't log for TQ2 files coz too many // console.log(` cachedGetFile got ${filePath} from zipfile`); if (!contents) { contents = await cachedFetchFileFromServer({ username, repository, path, branch }); @@ -169,7 +163,7 @@ export async function cachedGetFile({ username, repository, path, branch }) { if (contents) { // save unzipped file in cache to speed later retrieval await unzipStore.setItem(filePath.toLowerCase(), contents); - // if (filePath.indexOf('_tq/') < 0) // Don't log for TQ files coz too many + // if (filePath.indexOf('_tq/') < 0) // Don't log for TQ2 files coz too many // console.log(`cachedGetFile saved ${filePath} to cache for next time`); } // else console.error(`cachedGetFile(${username}, ${repository}, ${path}, ${branch}) -- failed to get file`); @@ -222,108 +216,6 @@ export async function cachedGetBookFilenameFromManifest({ username, repository, } -/** - * Clears the caches of stale data and preloads repo zips, before running book package checks - * This allows the calling app to clear cache and start loading repos in the backgound as soon as it starts up. - * In this case it would not need to use await to wait for results. - * TRICKY: note that even if the user is super fast in selecting books and clicking next, it will not hurt anything. - * cachedGetFileFromZipOrServer() would just be fetching files directly from repo until the zips are loaded. - * After that the files would be pulled out of zipStore. - * @param {string} username - * @param {string} languageCode - * @param {Array} bookIDList - one or more books that will be checked - * @param {string} branch - optional, defaults to master - * @param {Array} repos - optional, list of repos to pre-load - * @return {Promise} resolves to true if file loads are successful - */ -/* -async function clearCacheAndPreloadRepos(username, languageCode, bookIDList, branch = 'master', repos = ['TA', 'TW', 'TQ']) { - // NOTE: We preload TA and TW by default because we are likely to have many links to those repos - // We preload TQ1 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. - console.log(`clearCacheAndPreloadRepos(${username}, ${languageCode}, ${bookIDList}, ${branch}, [${repos}])…`); - clearCaches(); // clear existing cached files so we know we have the latest - let success = true; - - const repos_ = [...repos]; - if (bookIDList && Array.isArray(bookIDList) && bookIDList.length > MAX_INDIVIDUAL_FILES_TO_DOWNLOAD) { // Fetch individually if checking less books - // make sure we have the original languages needed - for (const bookID of bookIDList) { - if (bookID !== 'OBS') { - const whichTestament = books.testament(bookID); // returns 'old' or 'new' - const origLang = whichTestament === 'old' ? 'UHB' : 'UGNT'; - if (!repos_.includes(origLang)) - repos_.unshift(origLang); - } - } - } - - // Fetch zipped versions of all the repos needing to be preloaded - console.log(`Need to preload ${repos_.length} repos: ${repos_}`) - for (const repoCode of repos_) { - const repoName = formRepoName(languageCode, repoCode); - console.log(`clearCacheAndPreloadRepos: preloading zip file for ${repoName}…`); - const zipFetchSucceeded = await cachedGetRepositoryZipFile({ username, repository: repoName, branch }); - if (!zipFetchSucceeded) { - console.log(`clearCacheAndPreloadRepos: misfetched zip file for ${repoCode} repo with ${zipFetchSucceeded}`); - success = false; - } - } - - return success; -} -*/ - - -/** - * preloads repo zips, before running book package checks. - * TRICKY: note that even if the user is super fast in selecting books and clicking next, it will not hurt anything. getFile() would just be fetching files directly from repo until the zips are loaded. After that the files would be pulled out of zipStore. - * @param {string} username - * @param {string} languageCode - * @param {Array} bookIDList - one or more books that will be preloaded - * @param {string} branch - optional, defaults to master - * @param {Array} repos - optional, list of additional repos to pre-load - * @param {boolean} loadOriginalLangs - if true will download original language books - * @return {Promise} resolves to true if file loads are successful - */ -/* -async function PreLoadRepos(username, languageCode, bookIDList, branch = 'master', repos = [], loadOriginalLangs = false) { - console.log(`PreLoadRepos(${username}, ${languageCode}, ${bookIDList}, ${branch}, ${repos}, ${loadOriginalLangs})…`); - - let success = true; - const repos_ = repos.map((repo) => (formRepoName(languageCode, repo))); - - if (loadOriginalLangs) { - // make sure we have the original languages needed - for (const origLangBibles of [ 'UHB', 'UGNT' ]) { - addToListIfMissing(repos_, formRepoName(languageCode, origLangBibles)); - } - } - - if (bookIDList && Array.isArray(bookIDList)) { - for (const bookID of bookIDList) { - if (bookID !== 'OBS') { - addToListIfMissing(repos_, formRepoName(languageCode, 'LT')); - addToListIfMissing(repos_, formRepoName(languageCode, 'ST')); - } - } - } - - // load all the repos needed - for (const repoName of repos_) { - console.log(`PreLoadRepos: preloading zip file for ${repoName}…`); - const zipFetchSucceeded = await cachedGetRepositoryZipFile({ username, repository: repoName, branch }); - if (!zipFetchSucceeded) { - console.error(`PreLoadRepos: misfetched zip file for ${repoName} repo with ${zipFetchSucceeded}`); - success = false; - } - } - - return success; -} -*/ - - /** * Preloads any necessary repo zips, before running book package checks * This allows the calling app to clear cache and start loading repos in the backgound as soon as it starts up. @@ -335,20 +227,20 @@ async function PreLoadRepos(username, languageCode, bookIDList, branch = 'master * @param {string} languageCode * @param {Array} bookIDList - one or more books that will be checked * @param {string} branch - optional, defaults to master - * @param {Array} repos - optional, list of repos to pre-load + * @param {Array} repoList - optional, list of repos to pre-load * @return {Promise} resolves to true if file loads are successful */ -export async function preloadReposIfNecessary(username, languageCode, bookIDList, branch = 'master', repos = ['TA', 'TW', 'TQ1']) { +export async function preloadReposIfNecessary(username, languageCode, bookIDList, branch, repoList) { // NOTE: We preload TA and TW by default because we are likely to have many links to those repos - // We preload TQ1 by default because it has thousands of files (17,337), so individual file fetches might be slow + // 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. - console.log(`preloadReposIfNecessary(${username}, ${languageCode}, ${bookIDList} (${typeof bookID}), ${branch}, [${repos}])…`); + console.log(`preloadReposIfNecessary(${username}, ${languageCode}, ${bookIDList} (${typeof bookID}), ${branch}, [${repoList}])…`); let success = true; - const repos_ = [...repos]; - if (bookIDList.length ===1 && bookIDList[0] === 'OBS') { + const repos_ = [...repoList]; + if (bookIDList.length === 1 && bookIDList[0] === 'OBS') { if (!repos_.includes('OBS')) - repos_.unshift('OBS'); + repos_.unshift('OBS'); // push to beginning of list } if (bookIDList && Array.isArray(bookIDList) && bookIDList.length > MAX_INDIVIDUAL_FILES_TO_DOWNLOAD) { // Fetch individually if checking less books // make sure we have the original languages needed @@ -392,9 +284,13 @@ export async function preloadReposIfNecessary(username, languageCode, bookIDList let adjustedLanguageCode = languageCode; if ((languageCode === 'hbo' && repoCode !== 'UHB') || (languageCode === 'el-x-koine' && repoCode !== 'UGNT')) adjustedLanguageCode = 'en'; // Assume English then - const repoName = formRepoName(adjustedLanguageCode, repoCode); + let adjustedBranch = branch; + let adjustedRepoCode = repoCode; + if (repoCode === 'TQ2') { adjustedRepoCode = 'TQ'; adjustedBranch = 'newFormat'; } + else if (repoCode === 'TN2') { adjustedRepoCode = 'TN'; adjustedBranch = 'newFormat'; } + const repoName = formRepoName(adjustedLanguageCode, adjustedRepoCode); // console.log(`preloadReposIfNecessary: preloading zip file for ${repoName}…`); - const zipFetchSucceeded = await cachedGetRepositoryZipFile({ username, repository: repoName, branch }); + const zipFetchSucceeded = await cachedGetRepositoryZipFile({ username, repository: repoName, branch: adjustedBranch }); if (!zipFetchSucceeded) { console.error(`preloadReposIfNecessary() misfetched zip file for ${repoCode} repo with ${zipFetchSucceeded}`); success = false; diff --git a/src/core/index.js b/src/core/index.js index d9ccaa05..044abe3a 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -8,6 +8,7 @@ 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 './plain-text-check'; export * from './tn-links-check'; diff --git a/src/core/manifest-text-check.js b/src/core/manifest-text-check.js index c7f7c8d0..fd48712b 100644 --- a/src/core/manifest-text-check.js +++ b/src/core/manifest-text-check.js @@ -1,6 +1,6 @@ +import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' import { checkYAMLText } from './yaml-text-check'; import Ajv from 'ajv'; -import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' const MANIFEST_VALIDATOR_VERSION_STRING = '0.3.3'; @@ -546,7 +546,6 @@ export function checkManifestText(textName, manifestText, givenLocation, optiona // console.log(`checkManifestText(${textName}, ${manifestText.length} chars, ${givenLocation}, ${JSON.stringify(optionalCheckingOptions)})…`); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - // if (textName) ourLocation = ` in ${textName}${ourLocation}`; let extractLength; try { @@ -580,6 +579,8 @@ export function checkManifestText(textName, manifestText, givenLocation, optiona if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cManT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "cManT addNotice: 'location' parameter should be defined"); console.assert(typeof noticeObject.location === 'string', `cManT addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + if (noticeObject.debugChain) noticeObject.debugChain = `checkManifestText ${noticeObject.debugChain}`; cmtResult.noticeList.push(noticeObject); } @@ -597,7 +598,7 @@ export function checkManifestText(textName, manifestText, givenLocation, optiona console.assert(typeof manifestText === 'string', `cManT ourYAMLTextChecks: 'manifestText' parameter should be a string not a '${typeof manifestText}'`); // console.assert( allowedLinks===true || allowedLinks===false, "cManT ourYAMLTextChecks: allowedLinks parameter must be either true or false"); - const cYtResultObject = checkYAMLText(textName, manifestText, givenLocation, optionalCheckingOptions); + const cYtResultObject = checkYAMLText('en', textName, manifestText, givenLocation, optionalCheckingOptions); // 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/manifest-text-check.md b/src/core/manifest-text-check.md index e0566917..1147b6d0 100644 --- a/src/core/manifest-text-check.md +++ b/src/core/manifest-text-check.md @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 { checkManifestText } from './manifest-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; diff --git a/src/core/markdown-file-contents-check.js b/src/core/markdown-file-contents-check.js new file mode 100644 index 00000000..f0f6eda0 --- /dev/null +++ b/src/core/markdown-file-contents-check.js @@ -0,0 +1,146 @@ +import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { checkMarkdownText } from './markdown-text-check'; +import { checkTextfileContents } from './file-text-check'; + + +const MARKDOWN_FILE_VALIDATOR_VERSION_STRING = '0.4.0'; + + +/** + * + * @param {string} languageCode + * @param {string} markdownFilename -- used for identification + * @param {string} markdownText -- the actual text to be checked + * @param {string} givenLocation + * @param {Object} optionalCheckingOptions + */ +export function checkMarkdownFileContents(languageCode, markdownFilename, markdownText, givenLocation, optionalCheckingOptions) { + /* 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 + */ + // console.log(`checkMarkdownFileContents(${languageCode}, ${markdownFilename}, ${markdownText.length}, ${givenLocation})…`); + console.assert(languageCode !== undefined, "checkMarkdownFileContents: 'languageCode' parameter should be defined"); + console.assert(typeof languageCode === 'string', `checkMarkdownFileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + console.assert(markdownFilename !== undefined, "checkMarkdownFileContents: 'markdownFilename' parameter should be defined"); + console.assert(typeof markdownFilename === 'string', `checkMarkdownFileContents: 'markdownFilename' parameter should be a string not a '${typeof markdownFilename}': ${markdownFilename}`); + console.assert(markdownText !== undefined, "checkMarkdownFileContents: 'markdownText' parameter should be defined"); + console.assert(typeof markdownText === 'string', `checkMarkdownFileContents: 'markdownText' parameter should be a string not a '${typeof markdownText}': ${markdownText}`); + console.assert(givenLocation !== undefined, "checkMarkdownFileContents: 'givenLocation' parameter should be defined"); + console.assert(typeof givenLocation === 'string', `checkMarkdownFileContents: 'givenLocation' parameter should be a string not a '${typeof givenLocation}': ${givenLocation}`); + console.assert(givenLocation.indexOf('true') === -1, `checkMarkdownFileContents: 'givenLocation' parameter should not be '${givenLocation}'`); + if (optionalCheckingOptions !== undefined) + console.assert(typeof optionalCheckingOptions === 'object', `checkMarkdownFileContents: 'optionalCheckingOptions' parameter should be an object not a '${typeof optionalCheckingOptions}': ${JSON.stringify(optionalCheckingOptions)}`); + + let ourLocation = givenLocation; + if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; + + let extractLength; + try { + extractLength = optionalCheckingOptions.extractLength; + } catch (mdtcError) { } + if (typeof extractLength !== 'number' || isNaN(extractLength)) { + extractLength = DEFAULT_EXTRACT_LENGTH; + // console.log("Using default extractLength=" + extractLength); + } + // else + // console.log("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 + // console.log("Using halfLength=" + halfLength, `halfLengthPlus=${halfLengthPlus}`); + + const result = { successList: [], noticeList: [] }; + + function addSuccessMessage(successString) { + // console.log("checkMarkdownFileContents success: " + successString); + result.successList.push(successString); + } + function addNoticePartial(noticeObject) { + // console.log(`checkMarkdownFileContents addNoticePartial: (priority=${noticeObject.priority}) ${noticeObject.message}${noticeObject.characterIndex > 0 ? ` (at character ${noticeObject.characterIndex})` : ""}${noticeObject.extract ? " " + extract : ""}${noticeObject.location}`); + console.assert(noticeObject.priority !== undefined, "cMdT addNoticePartial: 'priority' parameter should be defined"); + console.assert(typeof noticeObject.priority === 'number', `cMdT addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}': ${noticeObject.priority}`); + console.assert(noticeObject.message !== undefined, "cMdT addNoticePartial: 'message' parameter should be defined"); + console.assert(typeof noticeObject.message === 'string', `cMdT addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}': ${noticeObject.message}`); + // console.assert(characterIndex !== undefined, "cMdT addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) console.assert(typeof noticeObject.characterIndex === 'number', `cMdT addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}': ${noticeObject.characterIndex}`); + // console.assert(extract !== undefined, "cMdT addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cMdT addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); + console.assert(noticeObject.location !== undefined, "cMdT addNoticePartial: 'location' parameter should be defined"); + console.assert(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}`; + result.noticeList.push({ ...noticeObject, filename: markdownFilename }); + } + // end of addNoticePartial function + + /** + * @description - checks the given text field and processes the returned results + * @param {String} markdownText - the actual text of the file being checked + * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false + * @param {String} optionalFieldLocation - description of where the field is located + * @param {Object} optionalCheckingOptions - parameters that might affect the check + */ + function ourCheckMarkdownText(markdownText, optionalFieldLocation, optionalCheckingOptions) { + // 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 + // console.log(`cMdT ourCheckMarkdownText(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${optionalFieldLocation}, …)`); + console.assert(markdownText !== undefined, "cMdFC ourCheckMarkdownText: 'markdownText' parameter should be defined"); + console.assert(typeof markdownText === 'string', `cMdFC ourCheckMarkdownText: 'markdownText' parameter should be a string not a '${typeof markdownText}'`); + console.assert(optionalFieldLocation !== undefined, "cMdFC ourCheckMarkdownText: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof optionalFieldLocation === 'string', `cMdFC ourCheckMarkdownText: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); + + const dbtcResultObject = checkMarkdownText(languageCode, markdownFilename, markdownText, optionalFieldLocation, optionalCheckingOptions); + + // 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) + addNoticePartial(noticeEntry); + } + // end of ourCheckMarkdownText function + + + /** + * @description - checks the given text field and processes the returned results + * @param {String} markdownText - the actual text of the file being checked + * @param {String} optionalFieldLocation - description of where the field is located + * @param {Object} optionalCheckingOptions - parameters that might affect the check + */ + function ourFileTextCheck(markdownText, optionalFieldLocation, optionalCheckingOptions) { + // 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 + // console.log(`cMdT ourFileTextCheck(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${optionalFieldLocation}, …)`); + console.assert(markdownText !== undefined, "cMdFC ourFileTextCheck: 'markdownText' parameter should be defined"); + console.assert(typeof markdownText === 'string', `cMdFC ourFileTextCheck: 'markdownText' parameter should be a string not a '${typeof markdownText}'`); + + const dbtcResultObject = checkTextfileContents(languageCode, 'markdown', markdownFilename, markdownText, optionalFieldLocation, optionalCheckingOptions); + + // 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) + addNoticePartial(noticeEntry); + } + // end of ourFileTextCheck function + + + // Main code for checkMarkdownFileContents function + ourCheckMarkdownText(markdownText, givenLocation, optionalCheckingOptions); + ourFileTextCheck(markdownText, givenLocation, optionalCheckingOptions); + + addSuccessMessage(`Checked markdown file: ${markdownFilename}`); + if (result.noticeList) + 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}`) + // console.log(` checkMarkdownFileContents returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); + // console.log("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 754e8786..61e5f5dc 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -1,25 +1,40 @@ -import { checkTextField } from './field-text-check'; import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' +import { checkTextField } from './field-text-check'; -const MARKDOWN_VALIDATOR_VERSION_STRING = '0.3.5'; +const MARKDOWN_TEXT_VALIDATOR_VERSION_STRING = '0.4.2'; /** * - * @param {string} textName -- used for identification + * @param {string} languageCode + * @param {string} textOrFileName -- used for identification * @param {string} markdownText -- the actual text to be checked * @param {string} givenLocation * @param {Object} optionalCheckingOptions */ -export function checkMarkdownText(textName, markdownText, givenLocation, optionalCheckingOptions) { - /* This function is optimised for checking the entire markdown file, i.e., all lines. +export function checkMarkdownText(languageCode, textOrFileName, markdownText, givenLocation, optionalCheckingOptions) { + /* 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 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 */ // console.log(`checkMarkdownText(${textName}, ${markdownText.length}, ${givenLocation})…`); + console.assert(languageCode !== undefined, "checkMarkdownText: 'languageCode' parameter should be defined"); + console.assert(typeof languageCode === 'string', `checkMarkdownText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + console.assert(textOrFileName !== undefined, "checkMarkdownText: 'textOrFileName' parameter should be defined"); + console.assert(typeof textOrFileName === 'string', `checkMarkdownText: 'textOrFileName' parameter should be a string not a '${typeof textOrFileName}': ${textOrFileName}`); + console.assert(markdownText !== undefined, "checkMarkdownText: 'markdownText' parameter should be defined"); + console.assert(typeof markdownText === 'string', `checkMarkdownText: 'markdownText' parameter should be a string not a '${typeof markdownText}': ${markdownText}`); + console.assert(givenLocation !== undefined, "checkMarkdownText: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof givenLocation === 'string', `checkMarkdownText: 'optionalFieldLocation' parameter should be a string not a '${typeof givenLocation}': ${givenLocation}`); + console.assert(givenLocation.indexOf('true') === -1, `checkMarkdownText: 'optionalFieldLocation' parameter should not be '${givenLocation}'`); + if (optionalCheckingOptions !== undefined) + console.assert(typeof optionalCheckingOptions === 'object', `checkMarkdownText: 'optionalCheckingOptions' parameter should be an object not a '${typeof optionalCheckingOptions}': ${JSON.stringify(optionalCheckingOptions)}`); + let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; @@ -55,11 +70,13 @@ export function checkMarkdownText(textName, markdownText, givenLocation, optiona if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cMdT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "cMdT addNotice: 'location' parameter should be defined"); console.assert(typeof noticeObject.location === 'string', `cMdT addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + // noticeObject.debugChain = noticeObject.debugChain ? `checkMarkdownText(${languageCode}, ${textName}) ${noticeObject.debugChain}` : `checkMarkdownText(${languageCode}, ${textName})`; result.noticeList.push(noticeObject); // Used to have filename: textName, but that isn't always a filename !!! } // end of addNotice function - function ourCheckTextField(lineNumber, fieldText, allowedLinks, optionalFieldLocation, optionalCheckingOptions) { + function ourCheckTextField(fieldName, lineNumber, fieldText, allowedLinks, optionalFieldLocation, optionalCheckingOptions) { /** * @description - checks the given text field and processes the returned results * @param {String} fieldName - name of the field being checked @@ -74,13 +91,17 @@ export function checkMarkdownText(textName, markdownText, givenLocation, optiona // Updates the global list of notices // console.log(`cMdT ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${optionalFieldLocation}, …)`); + console.assert(fieldName !== undefined, "cMdT ourCheckTextField: 'fieldName' parameter should be defined"); + console.assert(typeof fieldName === 'string', `cMdT ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(lineNumber !== undefined, "cMdT ourCheckTextField: 'lineNumber' parameter should be defined"); console.assert(typeof lineNumber === 'number', `cMdT ourCheckTextField: 'lineNumber' parameter should be a number not a '${typeof lineNumber}'`); console.assert(fieldText !== undefined, "cMdT ourCheckTextField: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `cMdT ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "cMdT ourCheckTextField: allowedLinks parameter must be either true or false"); + console.assert(optionalFieldLocation !== undefined, "cMdT ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof optionalFieldLocation === 'string', `cMdT ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); - const dbtcResultObject = checkTextField('markdown', '', fieldText, allowedLinks, optionalFieldLocation, optionalCheckingOptions); + const dbtcResultObject = checkTextField('markdown', fieldName, fieldText, allowedLinks, optionalFieldLocation, optionalCheckingOptions); // If we need to put everything through addNotice, e.g., for debugging or filtering // process results line by line @@ -91,6 +112,13 @@ export function checkMarkdownText(textName, markdownText, givenLocation, optiona // end of ourCheckTextField function + /** + * + * @param {string} lineNumber + * @param {string} lineText -- text to be checked + * @param {string} lineLocation + * @returns {string} suggestion (may be undefined) -- suggested fixed replacement field + */ function checkMarkdownLineContents(lineNumber, lineText, lineLocation) { // console.log(`checkMarkdownLineContents for ${lineNumber} '${lineText}' at${lineLocation}`); @@ -121,8 +149,8 @@ export function checkMarkdownText(textName, markdownText, givenLocation, optiona // console.log(`After removing more leading spaces have '${thisText}'`); let suggestion; - if (thisText) - suggestion = ourCheckTextField(lineNumber, thisText, true, lineLocation, optionalCheckingOptions); + if (thisText && lineText[0] !== '|') // Doesn't really make sense to check table line entries + suggestion = ourCheckTextField(textOrFileName, lineNumber, thisText, true, lineLocation, optionalCheckingOptions); if (thisText === lineText) // i.e., we didn't premodify the field being checked return suggestion; @@ -147,7 +175,7 @@ export function checkMarkdownText(textName, markdownText, givenLocation, optiona const thisHeaderLevel = line.match(/^#*/)[0].length; // console.log(`Got thisHeaderLevel=${thisHeaderLevel} for ${line}${atString}`); if (thisHeaderLevel > headerLevel + 1 - && !textName.startsWith('TA ')) // Suppress this notice for translationAcademy subsections + && !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) headerLevel = thisHeaderLevel; @@ -178,9 +206,9 @@ export function checkMarkdownText(textName, markdownText, givenLocation, optiona addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length === 1 ? '' : 's'}${ourLocation}.`); if (result.noticeList) - addSuccessMessage(`checkMarkdownText v${MARKDOWN_VALIDATOR_VERSION_STRING} finished with ${result.noticeList.length ? result.noticeList.length.toLocaleString() : "zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); + 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_VALIDATOR_VERSION_STRING}`) + addSuccessMessage(`No errors or warnings found by checkMarkdownText v${MARKDOWN_TEXT_VALIDATOR_VERSION_STRING}`) // console.log(` checkMarkdownText returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkMarkdownText result is", JSON.stringify(result)); return result; diff --git a/src/core/markdown-text-check.md b/src/core/markdown-text-check.md index 511ca77e..8473743a 100644 --- a/src/core/markdown-text-check.md +++ b/src/core/markdown-text-check.md @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 Markdown from 'react-markdown' import { checkMarkdownText } from './markdown-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -39,7 +42,7 @@ Another paragraph. const chosenText = textSB; const chosenTextName = 'textSB'; -const rawResults = checkMarkdownText(chosenTextName, chosenText, 'that was supplied'); +const rawResults = checkMarkdownText('en', chosenTextName, chosenText, 'that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done markdown text checks"]; diff --git a/src/core/orig-quote-check.js b/src/core/orig-quote-check.js index 3aa23a9c..650e8fe6 100644 --- a/src/core/orig-quote-check.js +++ b/src/core/orig-quote-check.js @@ -5,7 +5,7 @@ import { ourParseInt } from './utilities'; // import { consoleLogObject } from '../core/utilities'; -// const QUOTE_VALIDATOR_VERSION_STRING = '0.7.0'; +// const QUOTE_VALIDATOR_VERSION_STRING = '0.7.2'; export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldText, occurrenceString, bookID, C, V, givenLocation, optionalCheckingOptions) { @@ -267,11 +267,16 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT try { verseText = optionalCheckingOptions.originalLanguageVerseText; } catch (gcVTerror) { } - if (!verseText) // not supplied, so then we need to get it ourselves - verseText = await getOriginalPassage(bookID, C, V, optionalCheckingOptions); - if (!verseText) { - addNotice({ priority: 851, message: bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation }); - return colqResult; // nothing else we can do here + if (!verseText) {// not supplied, so then we need to get it ourselves + if (optionalCheckingOptions.disableAllLinkFetchingFlag) + return colqResult; // nothing else we can do here + else { + verseText = await getOriginalPassage(bookID, C, V, optionalCheckingOptions); + if (!verseText) { + addNotice({ priority: 851, message: bookID === 'OBS' ? "Unable to load OBS story text" : "Unable to load original language verse text", location: ourLocation }); + return colqResult; // nothing else we can do here + } + } } // Now check if the quote can be found in the verse text @@ -297,7 +302,7 @@ export async function checkOriginalLanguageQuote(languageCode, fieldName, fieldT } else { // Only a single quote (no ellipsis) if (verseText.indexOf(fieldText) >= 0) { if (occurrence > 1) { - console.log(`checkOriginalLanguageQuote is checking for ${occurrence} occurrences of ${fieldText}`); + // console.log(`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 }); diff --git a/src/core/plain-text-check.js b/src/core/plain-text-check.js index 640f423e..9f1d949f 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -1,15 +1,15 @@ -import { checkTextField } from './field-text-check'; import { DEFAULT_EXTRACT_LENGTH, MATCHED_PUNCTUATION_PAIRS, PAIRED_PUNCTUATION_OPENERS, PAIRED_PUNCTUATION_CLOSERS, isWhitespace, countOccurrences } from './text-handling-functions' +import { checkTextField } from './field-text-check'; -const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.3.1'; +const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.3.4'; /** * - * @param {string} textType + * @param {string} textType 'markdown', 'USFM', 'YAML', 'text', or 'raw' * @param {string} textName - * @param {string} plainText + * @param {string} plainText -- text to be checked * @param {string} givenLocation * @param {Object} optionalCheckingOptions */ @@ -20,9 +20,9 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt Returns a result object containing a successList and a noticeList */ // console.log(`checkPlainText(${textName}, (${plainText.length} chars), ${givenLocation}, ${JSON.stringify(optionalCheckingOptions)})…`); - console.assert(textType !== undefined, "checkPlainText: 'fieldType' parameter should be defined"); - console.assert(typeof textType === 'string', `checkPlainText: 'fieldType' parameter should be a string not a '${typeof textType}': ${textType}`); - console.assert(textType === 'markdown' || textType === 'USFM' || textType === 'YAML' || textType === 'raw', `checkPlainText: unrecognised 'textType' parameter: '${textType}'`); + console.assert(textType !== undefined, "checkPlainText: 'textType' parameter should be defined"); + console.assert(typeof textType === 'string', `checkPlainText: 'textType' parameter should be a string not a '${typeof textType}': ${textType}`); + console.assert(textType === 'markdown' || textType === 'USFM' || textType === 'YAML' || textType === 'text' || textType === 'raw', `checkPlainText: unrecognised 'textType' parameter: '${textType}'`); console.assert(textName !== undefined, "checkPlainText: 'textName' parameter should be defined"); console.assert(typeof textName === 'string', `checkPlainText: 'textName' parameter should be a string not a '${typeof textName}': ${textName}`); console.assert(plainText !== undefined, "checkPlainText: 'plainText' parameter should be defined"); @@ -30,7 +30,6 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - if (textName) ourLocation = ` in ${textName}${ourLocation}`; let extractLength; try { @@ -64,6 +63,8 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cPT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "cPT addNotice: 'location' parameter should be defined"); console.assert(typeof noticeObject.location === 'string', `cPT addNotice: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); + + // noticeObject.debugChain = noticeObject.debugChain ? `checkPlainText(${textType}, ${textName}) ${noticeObject.debugChain}` : `checkPlainText(${textType}, ${textName})`; cptResult.noticeList.push(noticeObject); } @@ -87,6 +88,8 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt console.assert(fieldText !== undefined, "cPT ourCheckTextField: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `cPT ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "cPT ourCheckTextField: allowedLinks parameter must be either true or false"); + console.assert(optionalFieldLocation !== undefined, "cPT ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof optionalFieldLocation === 'string', `cPT ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); const resultObject = checkTextField(textType, '', fieldText, allowedLinks, optionalFieldLocation, optionalCheckingOptions); @@ -103,13 +106,13 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt function checkPlainLineContents(lineNumber, lineText, lineLocation) { // console.log(`checkPlainLineContents for '${lineName}', '${lineText}' at${lineLocation}`); - let thisText = lineText.trimStart(); // So we don't get "leading space" and "doubled spaces" errors + let thisText = lineText.trimStart(); // So we don't get "leading space" AND "doubled spaces" errors if (thisText) // Allow links as that's more general ourCheckTextField(lineNumber, thisText, true, lineLocation, optionalCheckingOptions); } - // end of checkPlainLine function + // end of checkPlainLineContents function // Main code for checkPlainText function @@ -118,20 +121,46 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt return cptResult; } + 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 }); + } 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 }); + } 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 }); + } + + if (!plainText.endsWith('\n')) { + 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 }); + } + 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 lines = plainText.split('\n'); // console.log(` '${location}' has ${lines.length.toLocaleString()} total lines`); - + // checking nested markers (so that we can give the line number in the notice) // let headerLevel = 0; // let lastNumLeadingSpaces = 0; // let lastLineContents; // While checking individual lines, - // checking nested markers (so that we can give the line number in the notice) const openMarkers = []; for (let n = 1; n <= lines.length; n++) { const line = lines[n - 1]; if (line) { - checkPlainLineContents(n, line, ourLocation); + if (textType === 'text' || textType === 'raw') // other file-types do these checks themselves + checkPlainLineContents(n, line, ourLocation); // Check for nested brackets and quotes, etc. for (let characterIndex = 0; characterIndex < line.length; characterIndex++) { @@ -150,17 +179,19 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt if (lastEntry.char === PAIRED_PUNCTUATION_OPENERS.charAt(closeCharacterIndex)) { // console.log(` Matched '${char}' with '${openers.charAt(which)}' ${n} ${x}`); openMarkers.pop(); - } else { + } else // something is still open and this isn't a match -- might just be consequential error + if (textType !== 'markdown' || char !== '>' || characterIndex > 2) { // Markdown uses > 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 details = `'${lastEntry.char}' opened on line ${lastEntry.n} character ${lastEntry.x + 1}`; + addNotice({ priority: 777, message: `Bad nesting: ${char} closing character doesn't match`, details, lineNumber: n, characterIndex, extract, location: ourLocation }); + // console.log(` ERROR 777: mismatched characters: ${details}`); + } + } else // Closed something unexpectedly without an opener + if (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 ? '…' : '') - const details = `'${lastEntry.char}' opened on line ${lastEntry.n} character ${lastEntry.x + 1}`; - addNotice({ priority: 777, message: `Bad nesting: ${char} closing character doesn't match`, details, lineNumber: n, characterIndex, extract, location: ourLocation }); - // console.log(` ERROR 777: mismatched characters: ${details}`); + addNotice({ priority: 774, message: `Unexpected ${char} closing character (no matching opener)`, lineNumber: n, characterIndex, extract, location: ourLocation }); + // console.log(` ERROR 774: closed with nothing open: ${char}`); } - } else { // Closed something without an opener - 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 }); - // console.log(` ERROR 774: closed with nothing open: ${char}`); - } } } @@ -171,28 +202,15 @@ export function checkPlainText(textType, textName, plainText, givenLocation, opt // lastLineContents = line; } - 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 }); - } 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 }); - } 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 }); - } - + // TODO: Is this a duplicate of the above section about nesting? // Check matched pairs in the entire file for (const punctSet of MATCHED_PUNCTUATION_PAIRS) { // Can't check '‘’' coz they might be used as apostrophe const leftChar = punctSet[0], rightChar = punctSet[1]; const leftCount = countOccurrences(plainText, leftChar); const rightCount = countOccurrences(plainText, rightChar); - if (leftCount !== rightCount) + if (leftCount !== rightCount + && (textType!=='markdown' || rightChar!=='>')) // markdown uses > as a block quote character // NOTE: These are lower priority than similar checks in a field // since they occur only within the entire file addNotice({ priority: leftChar === '“' ? 162 : 462, message: `Mismatched ${leftChar}${rightChar} characters`, details: `(left=${leftCount.toLocaleString()}, right=${rightCount.toLocaleString()})`, location: ourLocation }); diff --git a/src/core/plain-text-check.md b/src/core/plain-text-check.md index d6849eec..a70f43e7 100644 --- a/src/core/plain-text-check.md +++ b/src/core/plain-text-check.md @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 { checkPlainText } from './plain-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; diff --git a/src/core/ta-reference-check.js b/src/core/ta-reference-check.js index 8d6ac194..2f396332 100644 --- a/src/core/ta-reference-check.js +++ b/src/core/ta-reference-check.js @@ -31,7 +31,6 @@ export async function checkSupportReferenceInTA(fieldName, fieldText, givenLocat let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - // if (fieldName) ourLocation = ` in ${fieldName}${ourLocation}`; const ctarResult = { noticeList: [] }; diff --git a/src/core/tn-links-check.js b/src/core/tn-links-check.js index c431c8e5..5e9a26d9 100644 --- a/src/core/tn-links-check.js +++ b/src/core/tn-links-check.js @@ -7,7 +7,7 @@ import { ourParseInt } from './utilities'; // import { consoleLogObject } from '../core/utilities'; -// const TN_LINKS_VALIDATOR_VERSION_STRING = '0.6.1'; +// const TN_LINKS_VALIDATOR_VERSION_STRING = '0.6.3'; const DEFAULT_LANGUAGE_CODE = 'en'; const DEFAULT_BRANCH = 'master'; @@ -19,8 +19,9 @@ const TA_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/ta/man/([^ /]+?)/([^ \\]]+?)\\ const TW_REGEX = new RegExp('\\[\\[rc://([^ /]+?)/tw/dict/bible/([^ /]+?)/([^ \\]]+?)\\]\\]', 'g'); // TODO: Allow [Titus 1:9](../01/09/pzi1) -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,3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); +// TODO: 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,3})/(\\d{1,3})/(\\d{1,3})\\.md\\)', 'g'); const THIS_CHAPTER_BIBLE_REGEX = new RegExp('\\[((?:1 |2 |3 )?)((?:\\w+? )?)(?:(\\d{1,3}):)?(\\d{1,3})\\]\\(\\./(\\d{1,3})\\.md\\)', 'g'); @@ -133,6 +134,7 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cTNlnk addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "cTNlnk addNoticePartial: 'location' parameter should be defined"); console.assert(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})`; ctarResult.noticeList.push({ ...noticeObject, bookID, fieldName }); } @@ -172,7 +174,6 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f try { twRepoBranch = optionalCheckingOptions.twRepoBranch; } catch (trcBRerror) { } if (!twRepoBranch) twRepoBranch = DEFAULT_BRANCH; - let regexResultArray; // Find total links @@ -202,33 +203,35 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const filepath = `${regexResultArray[2]}/${regexResultArray[3]}/01.md`; // Other files are title.md, sub-title.md // console.log(`Got tA filepath=${filepath}`); - // console.log(`Need to check against ${taRepoName}`); - const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; - let taFileContent; // Not really used here -- just to show that we got something valid - try { - taFileContent = await getFile_(taPathParameters); - // console.log("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}` }); - } - if (!taFileContent) - addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, extract: 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}` }); - else if (optionalCheckingOptions.checkLinkedTAArticleFlag === true) { - // console.log(`checkTNLinksToOutside got ${optionalCheckingOptions.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); - if (await alreadyChecked(taPathParameters) !== true) { - // console.log(`checkTNLinksToOutside needs to check TA article: ${filepath}`); - const checkTAFileResult = checkMarkdownText(`TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, optionalCheckingOptions); - 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 + if (!optionalCheckingOptions.disableAllLinkFetchingFlag) { + // console.log(`Need to check against ${taRepoName}`); + const taPathParameters = { username: taRepoUsername, repository: taRepoName, path: filepath, branch: taRepoBranch }; + let taFileContent; + try { + taFileContent = await getFile_(taPathParameters); + // console.log("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}` }); + } + if (!taFileContent) + addNoticePartial({ priority: 886, message: `Unable to find ${fieldName} TA link`, extract: 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}` }); + else if (optionalCheckingOptions.checkLinkedTAArticleFlag === true) { + // console.log(`checkTNLinksToOutside got ${optionalCheckingOptions.checkLinkedTAArticleFlag} so checking TA article: ${filepath}`); + if (await alreadyChecked(taPathParameters) !== true) { + // console.log(`checkTNLinksToOutside needs to check TA article: ${filepath}`); + const checkTAFileResult = checkMarkdownText(languageCode, `TA ${regexResultArray[3]}.md`, taFileContent, ourLocation, optionalCheckingOptions); + 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 + } } } } @@ -248,34 +251,36 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f const filepath = `bible/${regexResultArray[2]}/${regexResultArray[3]}.md`; // Other files are title.md, sub-title.md // console.log(`Got tW filepath=${filepath}`); - // console.log(`Need to check against ${twRepoName}`); - const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; - let twFileContent; - try { - twFileContent = await getFile_(twPathParameters); - // console.log("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}` }); - } - if (!twFileContent) - addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, extract: 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}` }); - else if (optionalCheckingOptions.checkLinkedTWArticleFlag === true) { - // console.log(`checkTNLinksToOutside got ${optionalCheckingOptions.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); - if (await alreadyChecked(twPathParameters) !== true) { - // console.log(`checkTNLinksToOutside needs to check TW article: ${filepath}`); - const checkTWFileResult = checkMarkdownText(`TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, optionalCheckingOptions); - 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 + if (!optionalCheckingOptions.disableAllLinkFetchingFlag) { + // console.log(`Need to check against ${twRepoName}`); + const twPathParameters = { username: twRepoUsername, repository: twRepoName, path: filepath, branch: twRepoBranch }; + let twFileContent; + try { + twFileContent = await getFile_(twPathParameters); + // console.log("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}` }); + } + if (!twFileContent) + addNoticePartial({ priority: 883, message: `Unable to find ${fieldName} TW link`, extract: 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}` }); + else if (optionalCheckingOptions.checkLinkedTWArticleFlag === true) { + // console.log(`checkTNLinksToOutside got ${optionalCheckingOptions.checkLinkedTWArticleFlag} so checking TW article: ${filepath}`); + if (await alreadyChecked(twPathParameters) !== true) { + // console.log(`checkTNLinksToOutside needs to check TW article: ${filepath}`); + const checkTWFileResult = checkMarkdownText(languageCode, `TW ${regexResultArray[3]}.md`, twFileContent, ourLocation, optionalCheckingOptions); + 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 + } } } } @@ -309,13 +314,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (ourParseInt(C1) !== chapterInt) addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don't match", details: `${C1} vs ${chapterInt}`, extract: totalLink, location: ourLocation }); } catch (ccError) { - console.error(`TN Link Check couldn't compare chapter numbers: ${ccError}`); + console.error(`TN2 Link Check couldn't compare chapter numbers: ${ccError}`); } try { if (ourParseInt(V1) !== ourParseInt(verseInt)) addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don't match", details: `${V1} vs ${verseInt}`, extract: totalLink, location: ourLocation }); } catch (vvError) { - console.error(`TN Link Check couldn't compare verse numbers: ${vvError}`); + console.error(`TN2 Link Check couldn't compare verse numbers: ${vvError}`); } if (linkBookCode) { // then we know which Bible book this link is to @@ -361,13 +366,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (ourParseInt(C1) !== chapterInt) addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don't match", details: `${C1} vs ${chapterInt}`, extract: totalLink, location: ourLocation }); } catch (ccError) { - console.error(`TN Link Check couldn't compare chapter numbers: ${ccError}`); + console.error(`TN2 Link Check couldn't compare chapter numbers: ${ccError}`); } try { if (ourParseInt(V1) !== ourParseInt(verseInt)) addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don't match", details: `${V1} vs ${verseInt}`, extract: totalLink, location: ourLocation }); } catch (vvError) { - console.error(`TN Link Check couldn't compare verse numbers: ${vvError}`); + console.error(`TN2 Link Check couldn't compare verse numbers: ${vvError}`); } if (linkBookCode) { // then we know which Bible book this link is to @@ -413,13 +418,13 @@ export async function checkTNLinksToOutside(bookID, givenC, givenV, fieldName, f if (ourParseInt(C1) !== chapterInt) addNoticePartial({ priority: 743, message: "Chapter numbers of markdown Bible link don't match", details: `${C1} vs ${chapterInt}`, extract: totalLink, location: ourLocation }); } catch (ccError) { - console.error(`TN Link Check couldn't compare chapter numbers: ${ccError}`); + console.error(`TN2 Link Check couldn't compare chapter numbers: ${ccError}`); } try { if (ourParseInt(V1) !== ourParseInt(verseInt)) addNoticePartial({ priority: 742, message: "Verse numbers of markdown Bible link don't match", details: `${V1} vs ${verseInt}`, extract: totalLink, location: ourLocation }); } catch (vvError) { - console.error(`TN Link Check couldn't compare verse numbers: ${vvError}`); + console.error(`TN2 Link Check couldn't compare verse numbers: ${vvError}`); } if (linkBookCode) { // then we know which Bible book this link is to diff --git a/src/core/tn-table-row-check.js b/src/core/tn-table-row-check.js index 3c349bb0..b820ee91 100644 --- a/src/core/tn-table-row-check.js +++ b/src/core/tn-table-row-check.js @@ -7,21 +7,23 @@ import { checkTNLinksToOutside } from './tn-links-check'; import { checkOriginalLanguageQuote } from './orig-quote-check'; -// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.0'; +// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.6.3'; 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'; +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 (TN) + * @description - Checks one TSV data row of translation notes (TN2) * @param {String} languageCode - the language code, e.g., 'en' - * @param {String} annotationType - TN, TQ, TWL, SN, or SQ -- allows more specific checks + * @param {String} annotationType - 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 @@ -87,6 +89,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `checkTN_TSVDataRow addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "checkTN_TSVDataRow addNoticePartial: 'location' parameter should be defined"); console.assert(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'; // Also uses the given bookID,C,V, parameters from the main function call drResult.noticeList.push({ ...noticeObject, bookID, C: givenC, V: givenV }); } @@ -118,9 +121,11 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv console.assert(fieldText !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "checkTN_TSVDataRow ourMarkdownTextChecks: allowedLinks parameter must be either true or false"); + console.assert(rowLocation !== undefined, "checkTN_TSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be defined"); + console.assert(typeof rowLocation === 'string', `checkTN_TSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); console.assert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourMarkdownTextChecks: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); - const omtcResultObject = checkMarkdownText(fieldName, fieldText, rowLocation, optionalCheckingOptions); + const omtcResultObject = checkMarkdownText(languageCode, fieldName, fieldText, rowLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -164,6 +169,8 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv console.assert(fieldText !== undefined, "checkTN_TSVDataRow ourCheckTextField: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `checkTN_TSVDataRow ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "checkTN_TSVDataRow ourCheckTextField: allowedLinks parameter must be either true or false"); + console.assert(rowLocation !== undefined, "checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be defined"); + console.assert(typeof rowLocation === 'string', `checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be a string not a '${typeof rowLocation}'`); console.assert(rowLocation.indexOf(fieldName) < 0, `checkTN_TSVDataRow ourCheckTextField: 'rowLocation' parameter should be not contain fieldName=${fieldName}`); const fieldType = fieldName === 'OccurrenceNote' ? 'markdown' : 'raw'; @@ -267,7 +274,7 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv // 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 TN check + 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 }); @@ -396,22 +403,22 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv 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); + 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_PLUS_DIGITS.indexOf(rowID[0]) < 0) - addNoticePartial({ priority: 176, message: "Row ID should start with a lowercase letter or digit", characterIndex: 0, rowID, fieldName: 'ID', extract: rowID, location: ourRowLocation }); + } 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.indexOf(rowID[1]) < 0) + 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.indexOf(rowID[2]) < 0) + 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 (supportReference.length) { // need to check TN against TA + 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 { // More than just whitespace @@ -422,7 +429,8 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv && supportReference !== 'guidelines-sonofgodprinciples') addNoticePartial({ priority: 788, message: "Only 'Just-In-Time Training' TA articles allowed here", fieldName: 'SupportReference', extract: supportReference, rowID, location: ourRowLocation }); SRSuggestion = ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, optionalCheckingOptions); - await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); + if (!optionalCheckingOptions.disableAllLinkFetchingFlag) + await ourCheckSupportReferenceInTA(rowID, 'SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); 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 }); } @@ -501,10 +509,10 @@ export async function checkTN_TSVDataRow(languageCode, line, bookID, givenC, giv 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}`; + 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}`; if (suggestion !== line) { - // console.log(`Had TN ${line}`); - // console.log(`Sug TN ${suggestion}`); + // console.log(`Had TN2 ${line}`); + // console.log(`Sug TN2 ${suggestion}`); drResult.suggestion = suggestion; } diff --git a/src/core/tn-table-text-check.js b/src/core/tn-table-text-check.js index 1e927c37..a166373d 100644 --- a/src/core/tn-table-text-check.js +++ b/src/core/tn-table-text-check.js @@ -3,7 +3,7 @@ import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' import { checkTN_TSVDataRow } from './tn-table-row-check'; -const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.2.5'; +const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.2.6'; 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'; @@ -31,7 +31,6 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - // if (bookID) ourLocation = ` in ${bookID}${ourLocation}`; const ttResult = { successList: [], noticeList: [] }; @@ -55,6 +54,7 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `TSV addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "TSV addNoticePartial: 'location' parameter should be defined"); console.assert(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}`; ttResult.noticeList.push({ ...noticeObject, bookID, filename }); } @@ -113,7 +113,7 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, // 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 TN check + if (drNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN2 check ttResult.noticeList.push(drNoticeEntry); // Just copy the complete notice as is else addNoticePartial({ ...drNoticeEntry, lineNumber: n + 1 }); @@ -226,6 +226,10 @@ export async function checkTN_TSVText(languageCode, bookID, filename, tableText, } } } + + if (optionalCheckingOptions.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 (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'}`); diff --git a/src/core/tn-tsv-table-row-check.md b/src/core/tn-tsv-table-row-check.md index 49426284..4b2dea01 100644 --- a/src/core/tn-tsv-table-row-check.md +++ b/src/core/tn-tsv-table-row-check.md @@ -1,4 +1,4 @@ -## TN TSV Table Row Check Sandbox +## TN2 TSV Table Row Check Sandbox This function checks one TranslationNotes tab-separated line for typical formatting errors. @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 { checkTN_TSVDataRow } from './tn-table-row-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -58,7 +61,8 @@ function CheckTNTSVRow(props) { (async () => { // Display our "waiting" message setResults(

Checking {tableLineName} {bookID}

); - const rawResults = await checkTN_TSVDataRow(languageCode, tableLine, bookID, C, V, givenLocation); + // (Final unused parameter is optionalCheckingOptions) + const rawResults = await checkTN_TSVDataRow(languageCode, tableLine, bookID, C, V, givenLocation, {}); setResults(
Check {tableLineName}: "{tableLine.substr(0,256)}…"

diff --git a/src/core/tn-tsv-table-text-check.md b/src/core/tn-tsv-table-text-check.md index 61eafe07..26c8a667 100644 --- a/src/core/tn-tsv-table-text-check.md +++ b/src/core/tn-tsv-table-text-check.md @@ -1,4 +1,4 @@ -## TN TSV Table Text Check Sandbox +## TN2 TSV Table Text Check Sandbox This function checks the given block of TranslationNote TSV table lines for typical formatting errors. @@ -7,6 +7,9 @@ It returns a list of success messages and a list of notice components. (There is 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 { checkTN_TSVText } from './tn-table-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -56,7 +59,8 @@ function CheckTNTSVText(props) { (async () => { // Display our "waiting" message setResults(

Checking {tableTextName} {bookID}

); - const rawResults = await checkTN_TSVText(languageCode, bookID, filename, tableText, givenLocation); + // (Final unused parameter is optionalCheckingOptions) + const rawResults = await checkTN_TSVText(languageCode, bookID, filename, tableText, givenLocation, {}); setResults(
Check {tableTextName}: "{tableText.substr(0,256)}…"

diff --git a/src/core/usfm-js-check.js b/src/core/usfm-js-check.js index 755a28dd..24eb27b5 100644 --- a/src/core/usfm-js-check.js +++ b/src/core/usfm-js-check.js @@ -1,4 +1,5 @@ import { toJSON } from 'usfm-js'; +import * as books from '../core/books/books'; export function runUsfmJsCheck(fileText, convertOptions) { @@ -29,10 +30,21 @@ export function checkUSFMToJSON(bookID, filename, givenText, givenLocation, opti Returns a result object containing a successList and a noticeList */ // console.log(`checkUSFMToJSON(${givenText.length.toLocaleString()} chars, '${givenLocation}')…`); + console.assert(bookID !== undefined, "checkUSFMToJSON: 'bookID' parameter should be defined"); + console.assert(typeof bookID === 'string', `checkUSFMToJSON: 'bookID' parameter should be a string not a '${typeof bookID}': ${bookID}`); + console.assert(bookID.length === 3, `checkUSFMToJSON: 'bookID' parameter should be three characters long not ${bookID.length}`); + console.assert(bookID.toUpperCase() === bookID, `checkUSFMToJSON: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + console.assert(books.isValidBookID(bookID), `checkUSFMToJSON: '${bookID}' is not a valid USFM book identifier`); + console.assert(filename !== undefined, "checkUSFMToJSON: 'filename' parameter should be defined"); + console.assert(typeof filename === 'string', `checkUSFMToJSON: 'filename' parameter should be a string not a '${typeof filename}': ${filename}`); + console.assert(givenText !== undefined, "checkUSFMToJSON: 'givenText' parameter should be defined"); + console.assert(typeof givenText === 'string', `checkUSFMToJSON: 'givenText' parameter should be a string not a '${typeof givenText}': ${givenText}`); + console.assert(givenLocation !== undefined, "checkUSFMToJSON: 'givenRowLocation' parameter should be defined"); + console.assert(typeof givenLocation === 'string', `checkUSFMToJSON: 'givenRowLocation' parameter should be a string not a '${typeof givenLocation}'`); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - if (filename) ourLocation = ` in ${filename}${ourLocation}`; + // if (filename) ourLocation = ` in ${filename}${ourLocation}`; const result = { successList: [], noticeList: [] }; diff --git a/src/core/usfm-js-check.md b/src/core/usfm-js-check.md index ef89943b..99f66f9d 100644 --- a/src/core/usfm-js-check.md +++ b/src/core/usfm-js-check.md @@ -9,6 +9,9 @@ Our packaged function returns a list of success messages and a list of (prioriti 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 { checkUSFMToJSON } from './usfm-js-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -181,7 +184,7 @@ const textB = `\\id GEN Bad USFM test const chosenTextName = 'textH'; const chosenText = textH; -const rawResults = checkUSFMToJSON(chosenTextName, chosenText, 'that was supplied'); +const rawResults = checkUSFMToJSON('GEN', chosenTextName, chosenText, 'that was supplied'); <> Check diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index c330c4ef..a0e78986 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -1,5 +1,5 @@ -import * as books from '../core/books/books'; import { DEFAULT_EXTRACT_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'; import { runUsfmJsCheck } from './usfm-js-check'; @@ -7,9 +7,11 @@ import { runBCSGrammarCheck } from './BCS-usfm-grammar-check'; import { ourParseInt } from './utilities'; -// const USFM_VALIDATOR_VERSION_STRING = '0.7.0'; +// const USFM_VALIDATOR_VERSION_STRING = '0.7.2'; +const VALID_LINE_START_CHARACTERS = `([“‘`; // '{' gets added for STs + // See http://ubsicap.github.io/usfm/master/index.html const COMPULSORY_MARKERS = ['id', 'ide']; const EXPECTED_MARKERS = ['usfm', 'mt1']; @@ -118,7 +120,7 @@ const MATCHED_CHARACTER_FORMATTING_PAIRS = [ -export function checkUSFMText(languageCode, bookID, filename, givenText, givenLocation, optionalCheckingOptions) { +export function checkUSFMText(languageCode, repoCode, bookID, filename, givenText, givenLocation, optionalCheckingOptions) { /* This function is optimised for checking the entire file, i.e., all lines. bookID is a three-character UPPERCASE USFM book identifier. @@ -130,13 +132,15 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo // console.log(`checkUSFMText(${languageCode}, ${bookID}, ${givenText.length.toLocaleString()} chars, '${givenLocation}', ${JSON.stringify(optionalCheckingOptions)})…`); console.assert(languageCode !== undefined, "checkUSFMText: 'languageCode' parameter should be defined"); console.assert(typeof languageCode === 'string', `checkUSFMText: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + console.assert(repoCode !== undefined, "checkUSFMText: 'repoCode' parameter should be defined"); + console.assert(typeof repoCode === 'string', `checkUSFMText: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); console.assert(bookID !== undefined, "checkUSFMText: 'bookID' parameter should be defined"); console.assert(typeof bookID === 'string', `checkUSFMText: 'bookID' parameter should be a string not a '${typeof bookID}'`); console.assert(bookID.length === 3, `checkUSFMText: 'bookID' parameter should be three characters long not ${bookID.length}`); console.assert(bookID.toUpperCase() === bookID, `checkUSFMText: 'bookID' parameter should be UPPERCASE not '${bookID}'`); console.assert(bookID === 'OBS' || books.isValidBookID(bookID), `checkUSFMText: '${bookID}' is not a valid USFM book identifier`); - console.assert(filename !== undefined, "checkUSFMText: 'line' parameter should be defined"); - console.assert(typeof filename === 'string', `checkUSFMText: 'line' parameter should be a string not a '${typeof filename}'`); + console.assert(filename !== undefined, "checkUSFMText: 'filename' parameter should be defined"); + console.assert(typeof filename === 'string', `checkUSFMText: 'filename' parameter should be a string not a '${typeof filename}'`); console.assert(givenLocation !== undefined, "checkUSFMText: 'givenRowLocation' parameter should be defined"); console.assert(typeof givenLocation === 'string', `checkUSFMText: 'givenRowLocation' parameter should be a string not a '${typeof givenLocation}'`); @@ -159,6 +163,9 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo const lowercaseBookID = bookID.toLowerCase(); + let validLineStartCharacters = VALID_LINE_START_CHARACTERS; + if (repoCode==='ST') validLineStartCharacters += '{'; + const result = { successList: [], noticeList: [] }; function addSuccessMessage(successString) { @@ -185,6 +192,7 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo // Doublecheck -- we don't want "Mismatched {}" per line, only per file console.assert(noticeObject.message.indexOf("Mismatched {}") < 0 || noticeObject.lineNumber === undefined, `checkUSFMText addNoticePartial: got bad notice: ${JSON.stringify(noticeObject)}`); + if (noticeObject.debugChain) noticeObject.debugChain = `checkUSFMText ${noticeObject.debugChain}`; result.noticeList.push({ ...noticeObject, bookID, filename }); } @@ -466,6 +474,8 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo console.assert(fieldText !== undefined, "cUSFM ourCheckTextField: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `cUSFM ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "cUSFM ourCheckTextField: allowedLinks parameter must be either true or false"); + console.assert(fieldLocation !== undefined, "cUSFM ourCheckTextField: 'fieldLocation' parameter should be defined"); + console.assert(typeof fieldLocation === 'string', `cUSFM ourCheckTextField: 'fieldLocation' parameter should be a string not a '${typeof fieldLocation}'`); const dbtcResultObject = checkTextField(fieldType, fieldName, fieldText, allowedLinks, fieldLocation, optionalCheckingOptions); @@ -492,7 +502,7 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo console.assert(fileText !== undefined, "cUSFM ourBasicFileChecks: 'fileText' parameter should be defined"); console.assert(typeof fileText === 'string', `cUSFM ourBasicFileChecks: 'fileText' parameter should be a string not a '${typeof fileText}'`); - const resultObject = checkTextfileContents(languageCode, filename, fileText, fileLocation, optionalCheckingOptions); + const resultObject = checkTextfileContents(languageCode, 'USFM', filename, fileText, fileLocation, optionalCheckingOptions); // If we need to put everything through addNoticePartial, e.g., for debugging or filtering // process results line by line @@ -699,31 +709,36 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo // end of checkUSFMLineText function - function checkUSFMLineInternals(lineNumber, C, V, marker, rest, lineLocation, optionalCheckingOptions) { - // Handles character formatting within the line contents - // console.log(`checkUSFMLineInternals(${lineNumber}, ${C}:${V}, ${marker}='${rest}', ${lineLocation}, ${JSON.stringify(optionalCheckingOptions)})…`); + function checkUSFMLineContents(lineNumber, C, V, marker, rest, lineLocation, optionalCheckingOptions) { + // 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 - if (marker === 'c' && isNaN(rest)) - addNoticePartial({ priority: 822, message: "Expected \\c field to contain an integer", lineNumber, C, V, characterIndex: 3, extract: `\\c ${rest}`, location: lineLocation }); - if (marker === 'v') { - let Vstr = (rest) ? rest.split(' ', 1)[0] : '?'; - if (isNaN(Vstr) && Vstr.indexOf('-') < 0) - addNoticePartial({ priority: 822, C, V, message: "Expected \\v field to contain an integer", characterIndex: 3, extract: `\\v ${rest}`, location: lineLocation }); - } + function checkUSFMLineInternals(lineNumber, C, V, marker, rest, lineLocation, optionalCheckingOptions) { + // Handles character formatting within the line contents + // console.log(`checkUSFMLineInternals(${lineNumber}, ${C}:${V}, ${marker}='${rest}', ${lineLocation}, ${JSON.stringify(optionalCheckingOptions)})…`); - if (rest) checkUSFMLineText(lineNumber, C, V, marker, rest, lineLocation, optionalCheckingOptions); + 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 }); + 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 }); + } + 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 }); - 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") - && rest.indexOf('x-tw') >= 0; - if (rest) ourCheckTextField(lineNumber, C, V, 'USFM', `\\${marker}`, rest, allowedLinks, lineLocation, optionalCheckingOptions); - } - // end of checkUSFMLineInternals function + if (rest) checkUSFMLineText(lineNumber, C, V, marker, rest, lineLocation, optionalCheckingOptions); + 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") + && rest.indexOf('x-tw') >= 0; + if (rest) ourCheckTextField(lineNumber, C, V, 'USFM', `\\${marker}`, rest, allowedLinks, lineLocation, optionalCheckingOptions); + } + // end of checkUSFMLineInternals function - function checkUSFMLineContents(lineNumber, C, V, marker, rest, lineLocation, optionalCheckingOptions) { - // 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 + + // Main code for checkUSFMLineContents() if (ALLOWED_LINE_START_MARKERS.indexOf(marker) >= 0 || marker === 'SPECIAL1') { if (rest && MARKERS_WITHOUT_CONTENT.indexOf(marker) >= 0) if (isWhitespace(rest)) @@ -811,7 +826,7 @@ export function checkUSFMText(languageCode, bookID, filename, givenText, givenLo // NOTE: Some unfoldingWord USFM Bibles commonly have this // so it's not necessarily either an error or a warning rest = line; - if (`([“‘`.indexOf(line[0]) < 0) { // These are the often expected characters + 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 : 280, C, V, message: "Expected line to start with backslash", lineNumber: n, characterIndex: 0, extract: line[0], location: ourLocation }); if (line[1] === '\\') { // Let's drop the leading punctuation and try to check the rest of the line diff --git a/src/core/usfm-text-check.md b/src/core/usfm-text-check.md index b0128c90..428868bf 100644 --- a/src/core/usfm-text-check.md +++ b/src/core/usfm-text-check.md @@ -13,6 +13,9 @@ Note that unfoldingWord has three distinct forms of USFM files (and these functi 1. Some of our USFM Bible books simply contain the (normal) Bible text. (Of course, these files are much smaller and quicker to validate.) ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import { checkUSFMText } from './usfm-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -180,8 +183,9 @@ const textB = `\\id GEN Bad USFM test // (to demonstrate differing results) const chosenText = textH; -// Second (unused) parameter is filename -const rawResults = checkUSFMText('en', 'GEN', '', chosenText, 'that was supplied'); +// Second (unused) parameter is repoCode +// Fourth (unused) parameter is filename +const rawResults = checkUSFMText('en', '', 'GEN', '', chosenText, 'that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done USFM text checks"]; diff --git a/src/core/yaml-text-check.js b/src/core/yaml-text-check.js index e03f5d89..2ae83d92 100644 --- a/src/core/yaml-text-check.js +++ b/src/core/yaml-text-check.js @@ -1,12 +1,12 @@ import { DEFAULT_EXTRACT_LENGTH } from './text-handling-functions' import yaml from 'yaml'; import { checkTextField } from './field-text-check'; +import { checkTextfileContents } from './file-text-check'; +const YAML_VALIDATOR_VERSION_STRING = '0.4.0'; -const YAML_VALIDATOR_VERSION_STRING = '0.3.0'; - -export function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckingOptions) { +export function checkYAMLText(languageCode, textName, YAMLText, givenLocation, optionalCheckingOptions) { /* This function is optimised for checking the entire file, i.e., all lines. Returns a result object containing a successList and a noticeList, @@ -14,9 +14,21 @@ export function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckin */ // console.log(`checkYAMLText(${textName}, ${YAMLText.length}, ${givenLocation})…`); + console.assert(languageCode !== undefined, "checkYAMLText: 'languageCode' parameter should be defined"); + console.assert(typeof languageCode === 'string', `checkYAMLText: 'languageCode' parameter should be a string not a '${typeof languageCode}': ${languageCode}`); + console.assert(textName !== undefined, "checkYAMLText: 'textName' parameter should be defined"); + console.assert(typeof textName === 'string', `checkYAMLText: 'textName' parameter should be a string not a '${typeof textName}': ${textName}`); + console.assert(YAMLText !== undefined, "checkYAMLText: 'YAMLText' parameter should be defined"); + console.assert(typeof YAMLText === 'string', `checkYAMLText: 'YAMLText' parameter should be a string not a '${typeof YAMLText}': ${YAMLText}`); + console.assert(givenLocation !== undefined, "checkYAMLText: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof givenLocation === 'string', `checkYAMLText: 'optionalFieldLocation' parameter should be a string not a '${typeof givenLocation}': ${givenLocation}`); + console.assert(givenLocation.indexOf('true') === -1, `checkYAMLText: 'optionalFieldLocation' parameter should not be '${givenLocation}'`); + if (optionalCheckingOptions !== undefined) + console.assert(typeof optionalCheckingOptions === 'object', `checkYAMLText: 'optionalCheckingOptions' parameter should be an object not a '${typeof optionalCheckingOptions}': ${JSON.stringify(optionalCheckingOptions)}`); + let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - if (textName) ourLocation = ` in ${textName}${ourLocation}`; + // if (textName) ourLocation = ` in ${textName}${ourLocation}`; let extractLength; try { @@ -50,6 +62,7 @@ export function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckin if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cManT addNotice: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "cYt addNotice: 'location' parameter should be defined"); console.assert(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}`; cytResult.noticeList.push(noticeObject); } @@ -71,6 +84,8 @@ export function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckin console.assert(fieldText !== undefined, "cYt ourCheckTextField: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `cYt ourCheckTextField: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); console.assert(allowedLinks === true || allowedLinks === false, "cYt ourCheckTextField: allowedLinks parameter must be either true or false"); + console.assert(optionalFieldLocation !== undefined, "cYt ourCheckTextField: 'optionalFieldLocation' parameter should be defined"); + console.assert(typeof optionalFieldLocation === 'string', `cYt ourCheckTextField: 'optionalFieldLocation' parameter should be a string not a '${typeof optionalFieldLocation}'`); const resultObject = checkTextField('YAML', '', fieldText, allowedLinks, optionalFieldLocation, optionalCheckingOptions); @@ -107,6 +122,29 @@ export function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckin // end of checkYAMLLine function + function ourBasicFileChecks(filename, fileText, fileLocation, optionalCheckingOptions) { + // 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 + console.assert(filename !== undefined, "cYT ourBasicFileChecks: 'filename' parameter should be defined"); + console.assert(typeof filename === 'string', `cYT ourBasicFileChecks: 'filename' parameter should be a string not a '${typeof filename}'`); + console.assert(fileText !== undefined, "cYT ourBasicFileChecks: 'fileText' parameter should be defined"); + console.assert(typeof fileText === 'string', `cYT ourBasicFileChecks: 'fileText' parameter should be a string not a '${typeof fileText}'`); + + const resultObject = checkTextfileContents(languageCode, 'YAML', filename, fileText, fileLocation, optionalCheckingOptions); + + // 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) { + console.assert(Object.keys(noticeEntry).length >= 5, `USFM ourBasicFileChecks notice length=${Object.keys(noticeEntry).length}`); + addNotice(noticeEntry); + } + } + // end of ourBasicFileChecks function + + // Main code for checkYAMLText function const lines = YAMLText.split('\n'); // console.log(` '${location}' has ${lines.length.toLocaleString()} total lines`); @@ -144,6 +182,9 @@ export function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckin // lastNumLeadingSpaces = numLeadingSpaces; } + // Do basic file checks + ourBasicFileChecks(textName, YAMLText, givenLocation, optionalCheckingOptions); + addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length === 1 ? '' : 's'}${ourLocation}.`); if (cytResult.noticeList) addSuccessMessage(`checkYAMLText v${YAML_VALIDATOR_VERSION_STRING} finished with ${cytResult.noticeList.length ? cytResult.noticeList.length.toLocaleString() : "zero"} notice${cytResult.noticeList.length === 1 ? '' : 's'}`); diff --git a/src/core/yaml-text-check.md b/src/core/yaml-text-check.md index 98a42871..58d9af60 100644 --- a/src/core/yaml-text-check.md +++ b/src/core/yaml-text-check.md @@ -9,6 +9,9 @@ These raw notice components can then be filtered and/or sorted as required by th Note that we have a more specialised function for checking `manifest.yaml` files. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import { checkYAMLText } from './yaml-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; @@ -217,7 +220,7 @@ projects: const chosenText = textG2; const chosenTextName = 'textG2'; -const rawResults = checkYAMLText(chosenTextName, chosenText, 'in YAML data that was supplied'); +const rawResults = checkYAMLText('en', chosenTextName, chosenText, 'in YAML data that was supplied'); <> YAML contents: diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index abdb577d..335c24f9 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -5,7 +5,7 @@ import React from 'react'; import MaterialTable from 'material-table'; -// const RENDER_PROCESSED_RESULTS_VERSION = '0.5.3'; +// const RENDER_PROCESSED_RESULTS_VERSION = '0.5.4'; export function RenderSuccesses({ username, results }) { @@ -29,12 +29,12 @@ export function RenderTotals({ rawNoticeListLength, results }) { return (

    Finished in with {rawNoticeListLength === 0 ? 'no' : rawNoticeListLength.toLocaleString()} notice{rawNoticeListLength === 1 ? '' : 's'}.

); } +/** +* @description - Displays a given piece of text (which can include newline characters) +* @param {String} text - text to render as numbered lines +* @return {String} - rendered HTML for the numbered list of lines +*/ export function RenderLines({ text }) { - /** - * @description - Displays a given piece of text (which can include newline characters) - * @param {String} text - text to render as numbered lines - * @return {String} - rendered HTML for the numbered list of lines - */ return
    {text.split('\n').map(function (line, index) { return
  1. {line}
  2. ; @@ -44,13 +44,13 @@ export function RenderLines({ text }) { const MAX_ARRAY_ITEMS_TO_DISPLAY = 8; // Or do we want this as a parameter? +/** +* @description - Displays whatever is in the object +* @param {Object} thisObject - object to render +* @param {Array} excludeList - optional list of object property names to be ignored +* @return {String} - rendered HTML for list of thisObject properties +*/ export function RenderObject({ thisObject, excludeList }) { - /** - * @description - Displays whatever is in the object - * @param {Object} thisObject - object to render - * @param {Array} excludeList - optional list of object property names to be ignored - * @return {String} - rendered HTML for list of thisObject properties - */ // console.log("In RenderObject"); // consoleLogObject('RenderObject settings', settings); return
      @@ -72,12 +72,12 @@ export function RenderObject({ thisObject, excludeList }) { } +/** +* @description - Displays the raw noticeList in a table +* @param {Object} results - object containing noticeList +* @return {String} - rendered HTML for table of notices +*/ export function RenderRawResults({ results }) { - /** - * @description - Displays the raw noticeList in a table - * @param {Object} results - object containing noticeList - * @return {String} - rendered HTML for table of notices - */ // This function is flexible enough to handle notice objects: // including bookID,C,V or not // including repoName, filename, lineNumber or not @@ -167,14 +167,14 @@ export function RenderRawResults({ results }) { } +/** +* @description - Displays the message plus details if specified +* @param {String} color - color field for the message style +* @param {String} message - notice text +* @param {String} details - (optional) extra notice text +* @return {String} - rendered HTML for the given reference +*/ function RenderMessage({ color, message, details }) { - /** - * @description - Displays the message plus details if specified - * @param {String} color - color field for the message style - * @param {String} message - notice text - * @param {String} details - (optional) extra notice text - * @return {String} - rendered HTML for the given reference - */ let detailsString = ''; if (details && details.length) detailsString = ' with ' + (details[0] === '(' ? details : `'${details}'`); @@ -182,14 +182,14 @@ function RenderMessage({ color, message, details }) { } +/** +* @description - Displays the bookcode and chapter/verse details if specified +* @param {String} bookID - (optional) 3-character UPPERCASE USFM bookcode or 'OBS'. +* @param {String} C - (optional) chapter info +* @param {String} V - (optional) verse info +* @return {String} - rendered HTML for the given reference +*/ function RenderBCV({ bookID, C, V }) { - /** - * @description - Displays the bookcode and chapter/verse details if specified - * @param {String} bookID - (optional) 3-character UPPERCASE USFM bookcode or 'OBS'. - * @param {String} C - (optional) chapter info - * @param {String} V - (optional) verse info - * @return {String} - rendered HTML for the given reference - */ // These are all optional parameters - they may be undefined or blank if irrelevant // console.log(`RenderBCV(${bookID}, ${C}, ${V})`); if (!bookID && !C && !V) return null; // They're all undefined or blank! @@ -203,17 +203,17 @@ function RenderBCV({ bookID, C, V }) { return null; } +/** +* @description - Displays the repoName and filename/lineNumber details if specified +* @param {String} username - (optional) username/orgName string +* @param {String} repoName - (optional) repo name string +* @param {String} filename - (optional) filename string +* @param {Number} lineNumber - (optional) line number integer (1-based) +* @param {String} rowID - (optional) 4-character ID field +* @param {String} fieldName - (optional) name of field +* @return {String} - rendered HTML for the given reference +*/ function RenderFileDetails({ username, repoName, filename, lineNumber, rowID, fieldName }) { - /** - * @description - Displays the repoName and filename/lineNumber details if specified - * @param {String} username - (optional) username/orgName string - * @param {String} repoName - (optional) repo name string - * @param {String} filename - (optional) filename string - * @param {Number} lineNumber - (optional) line number integer (1-based) - * @param {String} rowID - (optional) 4-character ID field - * @param {String} fieldName - (optional) name of field - * @return {String} - rendered HTML for the given reference - */ // These are all optional parameters - they may be undefined or blank if irrelevant // console.log(`RenderFileDetails(${repoName}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); if (!repoName && !filename && !lineNumber && !rowID && !fieldName) @@ -272,6 +272,10 @@ function RenderSuccessesColored({ results }) { * @param {Object} props.entry -- the given notice entry object */ function RenderPriority({ entry }) { + // Also displays the debugChain (after the priority) if the debugChain string exists + if (entry.debugChain) + return ({entry.priority >= 0 ? "Priority " + entry.priority : ""}) [{entry.debugChain}] + else return ({entry.priority >= 0 ? "Priority " + entry.priority : ""}) } diff --git a/src/demos/all-book-packages-check/AllBookPackagesCheck.js b/src/demos/all-book-packages-check/AllBookPackagesCheck.js index 8db8ced0..a569d991 100644 --- a/src/demos/all-book-packages-check/AllBookPackagesCheck.js +++ b/src/demos/all-book-packages-check/AllBookPackagesCheck.js @@ -67,8 +67,8 @@ function AllBookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { // Or this allows the parameters to be specified as a BookPackagesCheck property if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); - let preloadList = ['TA', 'TW', 'TQ']; - if (bookIDList.length > 5) { preloadList.push('LT'); preloadList.push('ST'); preloadList.push('TN'); } + let repoPreloadList = ['TA', 'TW', 'TQ', 'TQ2']; + if (bookIDList.length > 5) { repoPreloadList.push('LT'); repoPreloadList.push('ST'); repoPreloadList.push('TN'); repoPreloadList.push('TN2'); } useEffect(() => { // console.log("BookPackagesCheck.useEffect() called with ", JSON.stringify(props)); @@ -93,7 +93,7 @@ function AllBookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { else await clearCheckedArticleCache(); setResultValue(

      Preloading repos for {username} {languageCode} ready for all book packages check…

      ); - const successFlag = await preloadReposIfNecessary(username, languageCode, bookIDList, branch, preloadList); + const successFlag = await preloadReposIfNecessary(username, languageCode, bookIDList, branch, repoPreloadList); if (!successFlag) console.log(`AllBookPackagesCheck error: Failed to pre-load all repos`) diff --git a/src/demos/all-book-packages-check/README.md b/src/demos/all-book-packages-check/README.md index fb47ba77..49e759b7 100644 --- a/src/demos/all-book-packages-check/README.md +++ b/src/demos/all-book-packages-check/README.md @@ -9,14 +9,17 @@ The code below requests some info and then checks the requested Bible books—NT **Note**: This demonstration uses saved (cached) copies of files stored inside the local browser. This makes reruns of the checks faster, but it won't notice if you have recently updated the files on Door43. If you want to clear the local caches, use either the `reloadAllFilesFirst` variable below, or the `Clear Cache` function from the menu. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import AllBookPackagesCheck from './AllBookPackagesCheck'; ``` - - diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 7fd556c9..4acbe272 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 { consoleLogObject } from '../../core/utilities'; -// const BP_VALIDATOR_VERSION_STRING = '0.3.1'; +// const BP_VALIDATOR_VERSION_STRING = '0.3.3'; function BookPackageCheck(/*username, languageCode, bookID,*/ props) { @@ -35,16 +35,21 @@ function BookPackageCheck(/*username, languageCode, bookID,*/ props) { let checkingOptions = { // Uncomment any of these to test them dataSet: dataSet, // Can be 'OLD' (Markdown, etc.), 'NEW' (TSV only), or 'BOTH' - // extractLength: 25, + // extractLength: 25, // default is 15 checkManifestFlag: true, + checkReadmeFlag: true, + checkLicenseFlag: true, }; // Or this allows the parameters to be specified as a BookPackageCheck property if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + 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'; // console.log(`checkingOptions.checkLinkedTAArticleFlag ${checkingOptions.checkLinkedTAArticleFlag} from '${props.checkLinkedTAArticleFlag}'`); // console.log(`checkingOptions.checkLinkedTWArticleFlag ${checkingOptions.checkLinkedTWArticleFlag} from '${props.checkLinkedTWArticleFlag}'`); + const repoPreloadList = ['TA', 'TW', 'TQ', 'TQ2']; + useEffect(() => { // const newProps = { bookID, branch, checkingOptions, languageCode, cutoffPriorityLevel: props.cutoffPriorityLevel, displayType: props.displayType, errorPriorityLevel: props.errorPriorityLevel, maximumSimilarMessages: props.maximumSimilarMessages, sortBy: props.sortBy, username}; // console.log("BookPackageCheck.useEffect() called with ", JSON.stringify(newProps)); @@ -78,7 +83,7 @@ function BookPackageCheck(/*username, languageCode, bookID,*/ props) { // if (bookID !== 'OBS') { // Preload the reference repos setResultValue(

      Preloading repos for {username} {languageCode} ready for {bookID} book package check…

      ); - const successFlag = await preloadReposIfNecessary(username, languageCode, [bookID], branch); + const successFlag = await preloadReposIfNecessary(username, languageCode, [bookID], branch, repoPreloadList); if (!successFlag) console.error(`BookPackageCheck error: Failed to pre-load all repos`) // } diff --git a/src/demos/book-package-check/README.md b/src/demos/book-package-check/README.md index 02545f82..6e6f69b9 100644 --- a/src/demos/book-package-check/README.md +++ b/src/demos/book-package-check/README.md @@ -13,238 +13,43 @@ Note that `OBS` can also be entered here as a *pseudo book identifier* in order **Note**: This demonstration uses saved (cached) copies of files stored inside the local browser. This makes reruns of the checks faster, but it won't notice if you have recently updated the files on Door43. If you want to clear the local caches, use either the `reloadAllFilesFirst` variable below, or the `Clear Cache` function from the menu. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import BookPackageCheck from './BookPackageCheck'; ``` - - diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index b0f10bf5..60e93d97 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -5,156 +5,11 @@ import { checkFileContents } from '../file-check/checkFileContents'; import { checkRepo } from '../repo-check/checkRepo'; -//const BP_VALIDATOR_VERSION_STRING = '0.4.5'; +//const BP_VALIDATOR_VERSION_STRING = '0.5.1'; const MANIFEST_FILENAME = 'manifest.yaml'; -/* - checkTQMarkdownBook -*/ -/** - * - * @param {string} username - * @param {string} languageCode - * @param {string} repoName - * @param {string} branch - * @param {string} bookID -- 3-character USFM book ID or 'OBS' - * @param {Object} checkingOptions - * @return {Object} - containing successList and noticeList - */ -async function checkTQMarkdownBook(username, languageCode, repoName, branch, bookID, checkingOptions) { - // console.log(`checkTQMarkdownBook(${username}, ${repoName}, ${branch}, ${bookID}, ${JSON.stringify(checkingOptions)})…`) - const repoCode = 'TQ1'; - const generalLocation = ` in ${username} (${branch})`; - - const ctqResult = { successList: [], noticeList: [] }; - - function addSuccessMessage(successString) { - // console.log(`checkBookPackage success: ${successString}`); - ctqResult.successList.push(successString); - } - - function addNoticePartial(noticeObject) { - // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. - // console.log(`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}`); - console.assert(noticeObject.priority !== undefined, "cTQ addNoticePartial: 'priority' parameter should be defined"); - console.assert(typeof noticeObject.priority === 'number', `cTQ addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}'`); - console.assert(noticeObject.message !== undefined, "cTQ addNoticePartial: 'message' parameter should be defined"); - console.assert(typeof noticeObject.message === 'string', `cTQ addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}'`); - console.assert(noticeObject.bookID !== undefined, "cTQ addNoticePartial: 'bookID' parameter should be defined"); - console.assert(typeof noticeObject.bookID === 'string', `cTQ addNoticePartial: 'bookID' parameter should be a string not a '${typeof noticeObject.bookID}'`); - console.assert(noticeObject.bookID.length === 3, `cTQ addNoticePartial: 'bookID' parameter should be three characters long not ${noticeObject.bookID.length}`); - console.assert(books.isValidBookID(noticeObject.bookID), `cTQ addNoticePartial: '${noticeObject.bookID}' is not a valid USFM book identifier`); - // console.assert(C !== undefined, "cTQ addNoticePartial: 'C' parameter should be defined"); - if (noticeObject.C) console.assert(typeof noticeObject.C === 'string', `cTQ addNoticePartial: 'C' parameter should be a string not a '${typeof noticeObject.C}'`); - // console.assert(V !== undefined, "cTQ addNoticePartial: 'V' parameter should be defined"); - if (noticeObject.V) console.assert(typeof noticeObject.V === 'string', `cTQ addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}'`); - // console.assert(characterIndex !== undefined, "cTQ addNoticePartial: 'characterIndex' parameter should be defined"); - if (noticeObject.characterIndex) console.assert(typeof noticeObject.characterIndex === 'number', `cTQ addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}'`); - // console.assert(extract !== undefined, "cTQ addNoticePartial: 'extract' parameter should be defined"); - if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cTQ addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}'`); - console.assert(noticeObject.location !== undefined, "cTQ addNoticePartial: 'location' parameter should be defined"); - console.assert(typeof noticeObject.location === 'string', `cTQ addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); - console.assert(noticeObject.extra !== undefined, "cTQ addNoticePartial: 'extra' parameter should be defined"); - console.assert(typeof noticeObject.extra === 'string', `cTQ addNoticePartial: 'extra' parameter should be a string not a '${typeof noticeObject.extra}'`); - ctqResult.noticeList.push({ ...noticeObject, username, repoCode, repoName, bookID }); - } - - - async function ourCheckTQFileContents(repoCode, bookID, C, V, cfFilename, fileContent, fileLocation, optionalCheckingOptions) { - // console.log(`checkBookPackage ourCheckTQFileContents(${cfFilename})`); - - // Updates the global list of notices - console.assert(repoCode !== undefined, "cTQ ourCheckTQFileContents: 'repoCode' parameter should be defined"); - console.assert(typeof repoCode === 'string', `cTQ ourCheckTQFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); - console.assert(cfFilename !== undefined, "cTQ ourCheckTQFileContents: 'cfFilename' parameter should be defined"); - console.assert(typeof cfFilename === 'string', `cTQ ourCheckTQFileContents: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); - console.assert(fileContent !== undefined, "cTQ ourCheckTQFileContents: 'fileContent' parameter should be defined"); - console.assert(typeof fileContent === 'string', `cTQ ourCheckTQFileContents: 'fileContent' parameter should be a string not a '${typeof fileContent}'`); - console.assert(fileLocation !== undefined, "cTQ ourCheckTQFileContents: 'fileLocation' parameter should be defined"); - console.assert(typeof fileLocation === 'string', `cTQ ourCheckTQFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - - const cfResultObject = await checkFileContents(languageCode, cfFilename, fileContent, fileLocation, optionalCheckingOptions); - // console.log("checkFileContents() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); - // for (const successEntry of cfResultObject.successList) console.log(" ourCheckTQFileContents:", successEntry); - - // 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 - // console.assert(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 }); - } - } - // end of ourCheckTQFileContents function - - - // Main code for checkTQMarkdownBook - // We need to find and check all the markdown folders/files for this book - const getFileListFromZip_ = checkingOptions && checkingOptions.getFileListFromZip ? checkingOptions.getFileListFromZip : getFileListFromZip; - let checkedFileCount = 0, checkedFilenames = [], checkedFilenameExtensions = new Set(), totalCheckedSize = 0; - const pathList = await getFileListFromZip_({ username, repository: repoName, branch, optionalPrefix: `${bookID.toLowerCase()}/` }); - if (!Array.isArray(pathList) || !pathList.length) { - // console.error("checkTQrepo failed to load", username, repoName, branch); - const details = `username=${username}`; - if (! await repositoryExistsOnDoor43({ username, repository: repoName })) - ctqResult.noticeList.push({ priority: 997, message: "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode }); - else - addNoticePartial({ priority: 996, message: "Unable to load", details, bookID, location: generalLocation, extra: repoCode }); - } else { - - // console.log(` Got ${pathList.length} pathList entries`) - for (const thisPath of pathList) { - // console.log("checkTQMarkdownBook: Try to load", username, repoName, thisPath, branch); - - console.assert(thisPath.endsWith('.md'), `Expected ${thisPath} to end with .md`); - // const filename = thisPath.split('/').pop(); - const pathParts = thisPath.slice(0, -3).split('/'); - const C = pathParts[pathParts.length - 2].replace(/^0+(?=\d)/, ''); // Remove leading zeroes - const V = pathParts[pathParts.length - 1].replace(/^0+(?=\d)/, ''); // Remove leading zeroes - - const getFile_ = (checkingOptions && checkingOptions.getFile) ? checkingOptions.getFile : cachedGetFile; - let tqFileContent; - try { - tqFileContent = await getFile_({ username, repository: repoName, path: thisPath, branch }); - // console.log("Fetched fileContent for", repoName, thisPath, typeof tqFileContent, tqFileContent.length); - checkedFilenames.push(thisPath); - totalCheckedSize += tqFileContent.length; - } catch (tQerror) { - console.error("checkTQMarkdownBook failed to load", username, repoName, thisPath, branch, tQerror + ''); - let details = `username=${username}`; - if (! await repositoryExistsOnDoor43({ username, repository: repoName })) - ctqResult.noticeList.push({ priority: 997, message: "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode }); - else { - // eslint-disable-next-line eqeqeq - if (tQerror != 'TypeError: repoFileContent is null') details += ` error=${tQerror}`; - addNoticePartial({ priority: 996, message: "Unable to load", details, bookID, C, V, filename: thisPath, location: `${generalLocation} ${thisPath}`, extra: repoCode }); - } - } - if (tqFileContent) { - // We use the generalLocation here (does not include repo name) - // so that we can adjust the returned strings ourselves - // NOTE: We pass thisPath here coz the actual filename by itself is useless (so many '01.md') - await ourCheckTQFileContents(repoCode, bookID, C, V, thisPath, tqFileContent, generalLocation, checkingOptions); // Adds the notices to checkBookPackageResult - checkedFileCount += 1; - checkedFilenameExtensions.add('md'); - // addSuccessMessage(`Checked ${repoCode.toUpperCase()} file: ${thisPath}`); - } - } - addSuccessMessage(`Checked ${checkedFileCount.toLocaleString()} ${repoCode.toUpperCase()} file${checkedFileCount === 1 ? '' : 's'}`); - } - - ctqResult.checkedFileCount = checkedFileCount; - ctqResult.checkedFilenames = checkedFilenames; - ctqResult.checkedFilenameExtensions = [...checkedFilenameExtensions]; // convert Set to Array - ctqResult.checkedFilesizes = totalCheckedSize; - // console.log(` checkTQMarkdownBook returning ${JSON.stringify(ctqResult)}`); - return ctqResult; -} -// end of checkTQMarkdownBook function - - /* checkBookPackage */ @@ -174,6 +29,16 @@ export async function checkBookPackage(username, languageCode, bookID, setResult Note that bookID here can also be the 'OBS' pseudo bookID. */ // console.log(`checkBookPackage(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)})…`) + console.assert(username !== undefined, "checkBookPackage: 'username' parameter should be defined"); + console.assert(typeof username === 'string', `checkBookPackage: 'username' parameter should be a string not a '${typeof username}'`); + console.assert(languageCode !== undefined, "checkBookPackage: 'languageCode' parameter should be defined"); + console.assert(typeof languageCode === 'string', `checkBookPackage: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + console.assert(bookID !== undefined, "checkBookPackage: 'bookID' parameter should be defined"); + console.assert(typeof bookID === 'string', `checkBookPackage: 'bookID' parameter should be a string not a '${typeof bookID}'`); + console.assert(bookID.length === 3, `checkBookPackage: 'bookID' parameter should be three characters long not ${bookID.length}`); + console.assert(bookID.toUpperCase() === bookID, `checkBookPackage: 'bookID' parameter should be UPPERCASE not '${bookID}'`); + console.assert(bookID === 'OBS' || books.isValidBookID(bookID), `checkBookPackage: '${bookID}' is not a valid USFM book identifier`); + let abortFlag = false; const startTime = new Date(); bookID = bookID.toUpperCase(); // normalise to USFM standard @@ -181,8 +46,8 @@ export async function checkBookPackage(username, languageCode, bookID, setResult let checkedFileCount = 0, checkedFilenames = [], checkedFilenameExtensions = new Set(), totalCheckedSize = 0, checkedRepoNames = new Set(); let checkBookPackageResult = { successList: [], noticeList: [] }; - let dataSet = checkingOptions.dataSet; // Can be 'OLD' (Markdown, etc.), 'NEW' (TSV only), or 'BOTH' - if (!dataSet) dataSet = 'OLD'; + let dataSet = checkingOptions.dataSet; // Can be 'DEFAULT', 'OLD' (Markdown, etc.), 'NEW' (TSV only), or 'BOTH' + if (!dataSet) dataSet = 'OLD'; // TODO: Change back to DEFAULT const newCheckingOptions = checkingOptions ? { ...checkingOptions } : {}; // clone before modify const getFile_ = newCheckingOptions.getFile ? newCheckingOptions.getFile : cachedGetFile; // default to using caching of files @@ -228,6 +93,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult console.assert(typeof noticeObject.location === 'string', `cBP addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); console.assert(noticeObject.extra !== undefined, "cBP addNoticePartial: 'extra' parameter should be defined"); console.assert(typeof noticeObject.extra === 'string', `cBP addNoticePartial: 'extra' parameter should be a string not a '${typeof noticeObject.extra}'`); + if (noticeObject.debugChain) noticeObject.debugChain = `checkBookPackage ${noticeObject.debugChain}`; checkBookPackageResult.noticeList.push({ ...noticeObject, bookID, username }); } @@ -245,18 +111,18 @@ export async function checkBookPackage(username, languageCode, bookID, setResult console.assert(fileLocation !== undefined, "cBP ourCheckBPFileContents: 'fileLocation' parameter should be defined"); console.assert(typeof fileLocation === 'string', `cBP ourCheckBPFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - const cfcResultObject = await checkFileContents(languageCode, cfFilename, fileContent, fileLocation, optionalCheckingOptions); + const cfcResultObject = await checkFileContents(languageCode, repoCode, cfFilename, fileContent, fileLocation, optionalCheckingOptions); // console.log("checkFileContents() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); // for (const successEntry of cfResultObject.successList) console.log(" ourCheckBPFileContents:", successEntry); // console.log("cfcResultObject", JSON.stringify(cfcResultObject)); // Process noticeList line by line, appending the repoCode as an extra field as we go for (const cfcNoticeEntry of cfcResultObject.noticeList) // noticeEntry is an object - if (cfcNoticeEntry.extra) // it must be an indirect check on a TA or TW article from a TN check + 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 }); - // The following is needed coz we might be checking the linked TA and/or TW articles from TN TSV files + // 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; addSuccessMessage(`Checked ${cfcResultObject.checkedFileCount} linked TA/TW articles`); @@ -330,15 +196,72 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // end of ourCheckManifest function + /** + * + * @param {string} repoCode, e.g., TA + * @param {string} repoName, e.g., en_ta + * @param {string} filename, e.g., README.md + * @param {string} manifestLocation + * @param {Object} optionalCheckingOptions + */ + async function ourCheckMarkdown(repoCode, repoName, filename, manifestLocation, optionalCheckingOptions) { + // Updates the global list of notices + // console.log(`checkBookPackage ourCheckMarkdown(${repoCode}, ${repoName}, ${manifestLocation}, ${JSON.stringify(optionalCheckingOptions)})…`); + console.assert(repoCode !== undefined, "cBP ourCheckMarkdown: 'repoCode' parameter should be defined"); + console.assert(typeof repoCode === 'string', `cBP ourCheckMarkdown: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + console.assert(manifestLocation !== undefined, "cBP ourCheckMarkdown: 'manifestLocation' parameter should be defined"); + console.assert(typeof manifestLocation === 'string', `cBP ourCheckMarkdown: 'manifestLocation' parameter should be a string not a '${typeof manifestLocation}'`); + + let manifestFileContent; + try { + // console.log("checkBookPackage ourCheckMarkdown about to fetch manifest", username, repoName, branch); + manifestFileContent = await getFile_({ username, repository: repoName, path: filename, branch }); + // console.log("checkBookPackage ourCheckMarkdown fetched content for manifest", username, repoName, branch, typeof manifestFileContent, manifestFileContent.length); + // console.log(manifestFileContent); + } catch (cBPgfError) { + console.error(`checkBookPackage ourCheckMarkdown(${username}, ${languageCode}, ${bookID}, (fn), ${JSON.stringify(checkingOptions)}) failed to load manifest`, username, repoName, branch, 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 }); + } + } + if (manifestFileContent) { + const cmtResultObject = checkManifestText('Manifest', manifestFileContent, manifestLocation, optionalCheckingOptions); + // console.log(`ourCheckMarkdown checkManifestText(${repoName}) returned ${cmtResultObject.successList.length} success message(s) and ${cmtResultObject.noticeList.length} notice(s)`); + // console.log(`ourCheckMarkdown checkManifestText(${repoName}) returned ${JSON.stringify(cmtResultObject)}`); + // NOTE: We ignore the returned success messages here + // for (const successEntry of cfResultObject.successList) console.log(" ourCheckBPFileContents:", successEntry); + // console.log("cfcResultObject", JSON.stringify(cfcResultObject)); + + // 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` }); + } + 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` }); + return 0; + } + // end of ourCheckMarkdown function + + // Main code for checkBookPackage() - // NOTE: TN1 and TQ1 are used here for the old resource formats, e.g., 9-column TSV TN and markdown TQ - // The TN, TQ, SN, and SQ repoCodes refer to the new 7-column annotation TSV format. + // 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. // console.log("checkBookPackage() main code…"); let repoCodeList; let bookNumberAndName, whichTestament; if (bookID === 'OBS') { - // NOTE: No code below to handle OBS TN1 and TQ1 which are markdown repos - repoCodeList = ['TWL', 'OBS', 'TN', 'TQ', 'SN', 'SQ']; + // NOTE: No code below to handle OBS TN and TQ which are markdown repos + repoCodeList = ['TWL', 'OBS', 'TN2', 'TQ2', 'SN', 'SQ']; } else { // not OBS // We also need to know the number for USFM books try { @@ -355,12 +278,14 @@ 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 === 'OLD') - repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'LT', 'ST', 'TN1', 'TQ1'] : [origLangRepoCode, 'LT', 'ST', 'TN1', 'TQ1']; + if (dataSet === 'DEFAULT') + repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ2'] : [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') - repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'TWL', 'LT', 'ST', 'TN', 'TQ', 'SN', 'SQ'] : [origLangRepoCode, 'LT', 'ST', 'TN1', 'TQ1']; + repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'TWL', 'LT', 'ST', 'TN2', 'TQ2', 'SN', 'SQ'] : [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ']; else // assume BOTH - repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'TWL', 'LT', 'ST', 'TN', 'TN1', 'TQ', 'TQ1', 'SN', 'SQ'] : [origLangRepoCode, 'LT', 'ST', 'TN1', 'TQ1']; + repoCodeList = languageCode === 'en' ? [origLangRepoCode, 'TWL', 'LT', 'ST', 'TN2', 'TN', 'TQ2', 'TQ', 'SN', 'SQ'] : [origLangRepoCode, 'LT', 'ST', 'TN', 'TQ']; } @@ -374,32 +299,34 @@ export async function checkBookPackage(username, languageCode, bookID, setResult const adjustedRepoCode = (repoCode.endsWith('1') ? repoCode.substring(0, repoCode.length - 1) : repoCode).toLowerCase(); if (bookID === 'OBS' && repoCode !== 'OBS' && repoName === `${languageCode}_${adjustedRepoCode}`) repoName = `${languageCode}_obs-${adjustedRepoCode}`; - console.log(`checkBookPackage: check ${bookID} in ${repoCode} (${languageCode} ${bookID} from ${username} ${repoName})`); + console.log(`checkBookPackage: check ${languageCode} ${bookID} in ${repoCode} from ${username} ${repoName}`); // Update our "waiting" message setResultValue(

      Checking {username} {languageCode} {bookID} book package in {repoCode} (checked {numCheckedRepos}/{repoCodeList.length} repos)…

      ); let filename; if (repoCode === 'UHB' || repoCode === 'UGNT' || repoCode === 'LT' || repoCode === 'ST') { - // TODO: Might we need specific releases/tags for some of these (e.g., from the TN manifest)??? + // TODO: Might we need specific releases/tags for some of these (e.g., from the TN2 manifest)??? // TODO: Do we need to hard-code where to find the UHB and UGNT??? filename = `${bookNumberAndName}.usfm`; } - else if (repoCode === 'TWL' || repoCode === 'TN' || repoCode === 'TQ') { // in translation-annotations repo - filename = `${bookID}_${repoCode.toLowerCase()}.tsv` + else if (repoCode === 'TWL' || repoCode === 'TN2' || repoCode === 'TQ2') { + let adjustedRepoCode = repoCode; + if (adjustedRepoCode.endsWith('2')) adjustedRepoCode = adjustedRepoCode.substring(0, adjustedRepoCode.length - 1); + filename = `${bookID}_${adjustedRepoCode.toLowerCase()}.tsv` } - else if (repoCode === 'SN' || repoCode === 'SQ') { // in study-annotations repo + else if (repoCode === 'SN' || repoCode === 'SQ') { filename = `${bookID}_${repoCode.toLowerCase()}.tsv` } - else if (repoCode === 'TN1') { + else if (repoCode === 'TN') { try { filename = await cachedGetBookFilenameFromManifest({ username, repository: repoName, branch, bookID: bookID.toLowerCase() }); - console.assert(filename.startsWith(`${languageCode}_`), `Expected TN filename '${filename}' to start with the language code '${languageCode}_'`); + console.assert(filename.startsWith(`${languageCode}_`), `Expected TN2 filename '${filename}' to start with the language code '${languageCode}_'`); } catch (e) { // console.error(`cachedGetBookFilenameFromManifest failed with: ${e}`); filename = `${languageCode}_tn_${bookNumberAndName}.tsv`; // Take a guess } - console.assert(filename.endsWith('.tsv'), `Expected TN filename '${filename}' to end with '.tsv'`); + console.assert(filename.endsWith('.tsv'), `Expected TN2 filename '${filename}' to end with '.tsv'`); } if (repoCode === 'OBS') { @@ -408,7 +335,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult // console.log(`checkRepo() returned ${checkBookPackageResult.successList.length} success message(s) and ${checkBookPackageResult.noticeList.length} notice(s)`); // console.log("crResultObject keys", JSON.stringify(Object.keys(checkBookPackageResult))); addSuccessMessage(`Checked ${languageCode} OBS repo from ${username}`); - } else if (repoCode === 'TQ1') { + } else if (repoCode === 'TQ') { // This is the old markdown resource with hundreds/thousands of files const tqResultObject = await checkTQMarkdownBook(username, languageCode, repoName, branch, bookID, newCheckingOptions); checkBookPackageResult.successList = checkBookPackageResult.successList.concat(tqResultObject.successList); @@ -420,7 +347,7 @@ export async function checkBookPackage(username, languageCode, bookID, setResult totalCheckedSize += tqResultObject.totalCheckedSize; checkedRepoNames.add(repoName); } - } else { // For repos other than OBS and TQ1, we only have one file to check + } 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; @@ -451,20 +378,39 @@ export async function checkBookPackage(username, languageCode, bookID, setResult addSuccessMessage(`Checked ${repoCode.toUpperCase()} file: ${filename}`); } - // 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 (checkingOptions.checkManifestFlag) { - if (!checkedManifestDetails.includes(repoName)) { // Don't want to check more than once, esp. for annotations repos - checkedManifestDetails.push(repoName); // Remember that we checked this one - // console.log("BEFORE", checkBookPackageResult.noticeList.length); - const numCheckedCharacters = await ourCheckManifest(repoCode, repoName, generalLocation, newCheckingOptions); - // console.log("AFTER", checkBookPackageResult.noticeList.length); - if (numCheckedCharacters > 0) { - checkedFileCount += 1; - checkedFilenames.push('manifest.yaml'); - checkedFilenameExtensions.add('yaml'); - totalCheckedSize += numCheckedCharacters; - addSuccessMessage(`Checked ${repoName} manifest file`); + 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 (checkingOptions.checkManifestFlag) { + if (!checkedManifestDetails.includes(repoName)) { // Don't want to check more than once, esp. for annotations repos + checkedManifestDetails.push(repoName); // Remember that we checked this one + // console.log("BEFORE", checkBookPackageResult.noticeList.length); + const numCheckedCharacters = await ourCheckManifest(repoCode, repoName, generalLocation, newCheckingOptions); + // console.log("AFTER", checkBookPackageResult.noticeList.length); + if (numCheckedCharacters > 0) { + checkedFileCount += 1; + checkedFilenames.push('manifest.yaml'); + checkedFilenameExtensions.add('yaml'); + totalCheckedSize += numCheckedCharacters; + addSuccessMessage(`Checked ${repoName} manifest file`); + } + } + } + // We can also check the README file for each repo if requested + if (checkingOptions.checkReadmeFlag) { + if (!checkedManifestDetails.includes(repoName)) { // Don't want to check more than once, esp. for annotations repos + checkedManifestDetails.push(repoName); // Remember that we checked this one + // console.log("BEFORE", checkBookPackageResult.noticeList.length); + const filename = 'README.md'; + const numCheckedCharacters = await ourCheckMarkdown(repoCode, repoName, filename, generalLocation, newCheckingOptions); + // console.log("AFTER", checkBookPackageResult.noticeList.length); + if (numCheckedCharacters > 0) { + checkedFileCount += 1; + checkedFilenames.push(filename); + checkedFilenameExtensions.add('md'); + totalCheckedSize += numCheckedCharacters; + addSuccessMessage(`Checked ${repoName} README file`); + } } } } @@ -487,3 +433,148 @@ export async function checkBookPackage(username, languageCode, bookID, setResult return checkBookPackageResult; }; // end of checkBookPackage() + + +/* + checkTQMarkdownBook +*/ +/** + * + * @param {string} username + * @param {string} languageCode + * @param {string} repoName + * @param {string} branch + * @param {string} bookID -- 3-character USFM book ID or 'OBS' + * @param {Object} checkingOptions + * @return {Object} - containing successList and noticeList + */ +async function checkTQMarkdownBook(username, languageCode, repoName, branch, bookID, checkingOptions) { + // console.log(`checkTQMarkdownBook(${username}, ${repoName}, ${branch}, ${bookID}, ${JSON.stringify(checkingOptions)})…`) + const repoCode = 'TQ'; + const generalLocation = ` in ${username} (${branch})`; + + const ctqResult = { successList: [], noticeList: [] }; + + function addSuccessMessage(successString) { + // console.log(`checkBookPackage success: ${successString}`); + ctqResult.successList.push(successString); + } + + function addNoticePartial(noticeObject) { + // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. + // console.log(`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}`); + console.assert(noticeObject.priority !== undefined, "cTQ addNoticePartial: 'priority' parameter should be defined"); + console.assert(typeof noticeObject.priority === 'number', `cTQ addNoticePartial: 'priority' parameter should be a number not a '${typeof noticeObject.priority}'`); + console.assert(noticeObject.message !== undefined, "cTQ addNoticePartial: 'message' parameter should be defined"); + console.assert(typeof noticeObject.message === 'string', `cTQ addNoticePartial: 'message' parameter should be a string not a '${typeof noticeObject.message}'`); + console.assert(noticeObject.bookID !== undefined, "cTQ addNoticePartial: 'bookID' parameter should be defined"); + console.assert(typeof noticeObject.bookID === 'string', `cTQ addNoticePartial: 'bookID' parameter should be a string not a '${typeof noticeObject.bookID}'`); + console.assert(noticeObject.bookID.length === 3, `cTQ addNoticePartial: 'bookID' parameter should be three characters long not ${noticeObject.bookID.length}`); + console.assert(books.isValidBookID(noticeObject.bookID), `cTQ addNoticePartial: '${noticeObject.bookID}' is not a valid USFM book identifier`); + // console.assert(C !== undefined, "cTQ addNoticePartial: 'C' parameter should be defined"); + if (noticeObject.C) console.assert(typeof noticeObject.C === 'string', `cTQ addNoticePartial: 'C' parameter should be a string not a '${typeof noticeObject.C}'`); + // console.assert(V !== undefined, "cTQ addNoticePartial: 'V' parameter should be defined"); + if (noticeObject.V) console.assert(typeof noticeObject.V === 'string', `cTQ addNoticePartial: 'V' parameter should be a string not a '${typeof noticeObject.V}'`); + // console.assert(characterIndex !== undefined, "cTQ addNoticePartial: 'characterIndex' parameter should be defined"); + if (noticeObject.characterIndex) console.assert(typeof noticeObject.characterIndex === 'number', `cTQ addNoticePartial: 'characterIndex' parameter should be a number not a '${typeof noticeObject.characterIndex}'`); + // console.assert(extract !== undefined, "cTQ addNoticePartial: 'extract' parameter should be defined"); + if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cTQ addNoticePartial: 'extract' parameter should be a string not a '${typeof noticeObject.extract}'`); + console.assert(noticeObject.location !== undefined, "cTQ addNoticePartial: 'location' parameter should be defined"); + console.assert(typeof noticeObject.location === 'string', `cTQ addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); + console.assert(noticeObject.extra !== undefined, "cTQ addNoticePartial: 'extra' parameter should be defined"); + console.assert(typeof noticeObject.extra === 'string', `cTQ addNoticePartial: 'extra' parameter should be a string not a '${typeof noticeObject.extra}'`); + ctqResult.noticeList.push({ ...noticeObject, username, repoCode, repoName, bookID }); + } + + + async function ourCheckTQFileContents(repoCode, bookID, C, V, cfFilename, fileContent, fileLocation, optionalCheckingOptions) { + // console.log(`checkBookPackage ourCheckTQFileContents(${cfFilename})`); + + // Updates the global list of notices + console.assert(repoCode !== undefined, "cTQ ourCheckTQFileContents: 'repoCode' parameter should be defined"); + console.assert(typeof repoCode === 'string', `cTQ ourCheckTQFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + console.assert(cfFilename !== undefined, "cTQ ourCheckTQFileContents: 'cfFilename' parameter should be defined"); + console.assert(typeof cfFilename === 'string', `cTQ ourCheckTQFileContents: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); + console.assert(fileContent !== undefined, "cTQ ourCheckTQFileContents: 'fileContent' parameter should be defined"); + console.assert(typeof fileContent === 'string', `cTQ ourCheckTQFileContents: 'fileContent' parameter should be a string not a '${typeof fileContent}'`); + console.assert(fileLocation !== undefined, "cTQ ourCheckTQFileContents: 'fileLocation' parameter should be defined"); + console.assert(typeof fileLocation === 'string', `cTQ ourCheckTQFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); + + const cfResultObject = await checkFileContents(languageCode, repoCode, cfFilename, fileContent, fileLocation, optionalCheckingOptions); + // console.log("checkFileContents() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); + // for (const successEntry of cfResultObject.successList) console.log(" ourCheckTQFileContents:", successEntry); + + // 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 + // console.assert(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 }); + } + } + // end of ourCheckTQFileContents function + + + // Main code for checkTQMarkdownBook + // We need to find and check all the markdown folders/files for this book + const getFileListFromZip_ = checkingOptions && checkingOptions.getFileListFromZip ? checkingOptions.getFileListFromZip : getFileListFromZip; + let checkedFileCount = 0, checkedFilenames = [], checkedFilenameExtensions = new Set(), totalCheckedSize = 0; + const pathList = await getFileListFromZip_({ username, repository: repoName, branch, optionalPrefix: `${bookID.toLowerCase()}/` }); + if (!Array.isArray(pathList) || !pathList.length) { + // console.error("checkTQrepo failed to load", username, repoName, branch); + const details = `username=${username}`; + if (! await repositoryExistsOnDoor43({ username, repository: repoName })) + ctqResult.noticeList.push({ priority: 997, message: "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode }); + else + addNoticePartial({ priority: 996, message: "Unable to load", details, bookID, location: generalLocation, extra: repoCode }); + } else { + + // console.log(` Got ${pathList.length} pathList entries`) + for (const thisPath of pathList) { + // console.log("checkTQMarkdownBook: Try to load", username, repoName, thisPath, branch); + + console.assert(thisPath.endsWith('.md'), `Expected ${thisPath} to end with .md`); + // const filename = thisPath.split('/').pop(); + const pathParts = thisPath.slice(0, -3).split('/'); + const C = pathParts[pathParts.length - 2].replace(/^0+(?=\d)/, ''); // Remove leading zeroes + const V = pathParts[pathParts.length - 1].replace(/^0+(?=\d)/, ''); // Remove leading zeroes + + const getFile_ = (checkingOptions && checkingOptions.getFile) ? checkingOptions.getFile : cachedGetFile; + let tqFileContent; + try { + tqFileContent = await getFile_({ username, repository: repoName, path: thisPath, branch }); + // console.log("Fetched fileContent for", repoName, thisPath, typeof tqFileContent, tqFileContent.length); + checkedFilenames.push(thisPath); + totalCheckedSize += tqFileContent.length; + } catch (tQerror) { + console.error("checkTQMarkdownBook failed to load", username, repoName, thisPath, branch, tQerror + ''); + let details = `username=${username}`; + if (! await repositoryExistsOnDoor43({ username, repository: repoName })) + ctqResult.noticeList.push({ priority: 997, message: "Repository doesn't exist", details, username, repoCode, repoName, location: generalLocation, extra: repoCode }); + else { + // eslint-disable-next-line eqeqeq + if (tQerror != 'TypeError: repoFileContent is null') details += ` error=${tQerror}`; + addNoticePartial({ priority: 996, message: "Unable to load", details, bookID, C, V, filename: thisPath, location: `${generalLocation} ${thisPath}`, extra: repoCode }); + } + } + if (tqFileContent) { + // We use the generalLocation here (does not include repo name) + // so that we can adjust the returned strings ourselves + // NOTE: We pass thisPath here coz the actual filename by itself is useless (so many '01.md') + await ourCheckTQFileContents(repoCode, bookID, C, V, thisPath, tqFileContent, generalLocation, checkingOptions); // Adds the notices to checkBookPackageResult + checkedFileCount += 1; + checkedFilenameExtensions.add('md'); + // addSuccessMessage(`Checked ${repoCode.toUpperCase()} file: ${thisPath}`); + } + } + addSuccessMessage(`Checked ${checkedFileCount.toLocaleString()} ${repoCode.toUpperCase()} file${checkedFileCount === 1 ? '' : 's'}`); + } + + ctqResult.checkedFileCount = checkedFileCount; + ctqResult.checkedFilenames = checkedFilenames; + ctqResult.checkedFilenameExtensions = [...checkedFilenameExtensions]; // convert Set to Array + ctqResult.checkedFilesizes = totalCheckedSize; + // console.log(` checkTQMarkdownBook returning ${JSON.stringify(ctqResult)}`); + return ctqResult; +} +// end of checkTQMarkdownBook function diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index 392b1c6d..8d9dbdfb 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -45,8 +45,8 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { // Or this allows the parameters to be specified as a BookPackagesCheck property if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); - let preloadList = ['TA', 'TW', 'TQ']; - if (bookIDList.length > 5) { preloadList.push('LT'); preloadList.push('ST'); preloadList.push('TN'); } + let repoPreloadList = ['TA', 'TW', 'TQ', 'TQ2']; + if (bookIDList.length > 5) { repoPreloadList.push('LT'); repoPreloadList.push('ST'); repoPreloadList.push('TN'); repoPreloadList.push('TN2'); } useEffect(() => { // console.log("BookPackagesCheck.useEffect() called with ", JSON.stringify(props)); @@ -71,7 +71,7 @@ function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { else await clearCheckedArticleCache(); setResultValue(

      Preloading repos for {username} {languageCode} ready for book packages check…

      ); - const successFlag = await preloadReposIfNecessary(username, languageCode, bookIDList, branch, preloadList); + const successFlag = await preloadReposIfNecessary(username, languageCode, bookIDList, branch, repoPreloadList); if (!successFlag) console.error(`BookPackagesCheck error: Failed to pre-load all repos`) diff --git a/src/demos/book-packages-check/README.md b/src/demos/book-packages-check/README.md index 84ca8fc8..2bd69735 100644 --- a/src/demos/book-packages-check/README.md +++ b/src/demos/book-packages-check/README.md @@ -13,230 +13,32 @@ Note that `OBS` can also be entered here as a *pseudo book identifier* in order **Note**: This demonstration uses saved (cached) copies of files stored inside the local browser. This makes reruns of the checks faster, but it won't notice if you have recently updated the files on Door43. If you want to clear the local caches, use either the `reloadAllFilesFirst` variable below, or the `Clear Cache` function from the menu. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import BookPackagesCheck from './BookPackagesCheck'; ``` - - diff --git a/src/demos/book-packages-check/checkBookPackages.js b/src/demos/book-packages-check/checkBookPackages.js index cb4f68b9..3ebe76fe 100644 --- a/src/demos/book-packages-check/checkBookPackages.js +++ b/src/demos/book-packages-check/checkBookPackages.js @@ -69,14 +69,17 @@ export async function checkBookPackages(username, languageCode, bookIDList, setR } // We only want to check the manifest files for ONE Bible BP AND for OBS - let checkManifestFlag = false; - if (bookID === 'OBS') checkManifestFlag = true; + let checkManifestFlag = false, checkReadmeFlag =false, checkLicenseFlag = false; +; + if (bookID === 'OBS') { checkManifestFlag = true; checkReadmeFlag =true; checkLicenseFlag = true; } else // it's a Bible book if (!checkedBibleBPManifestFlag) { - checkManifestFlag = true; + checkManifestFlag = true; checkReadmeFlag =true; checkLicenseFlag=true; checkedBibleBPManifestFlag = true; // so we only do it once for Bible books } checkingOptions.checkManifestFlag = checkManifestFlag; + checkingOptions.checkReadmeFlag = checkReadmeFlag; + checkingOptions.checkLicenseFlag = checkLicenseFlag; // We use the generalLocation here (does not include repo name) // so that we can adjust the returned strings ourselves diff --git a/src/demos/clear-cache/README.md b/src/demos/clear-cache/README.md index 52051e7e..a085b23d 100644 --- a/src/demos/clear-cache/README.md +++ b/src/demos/clear-cache/README.md @@ -11,6 +11,9 @@ Unless you use this `ClearCache` function below, these demos can cache files for Simply change `N` to `Y` below to clear the internal caches. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import ClearCache from './ClearCache'; */} return ( diff --git a/src/demos/file-check/README.md b/src/demos/file-check/README.md index 85672598..bf5c418f 100644 --- a/src/demos/file-check/README.md +++ b/src/demos/file-check/README.md @@ -6,19 +6,23 @@ and then validates the content of one file selected from the repo. **Note**: This demonstration uses saved (cached) copies of files stored inside the local browser. This makes reruns of the checks faster, but it won't notice if you have recently updated the files on Door43. If you want to clear the local caches, use either the `reloadAllFilesFirst` variable below, or the `Clear Cache` function from the menu. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + ``` - - diff --git a/src/demos/file-check/checkFileContents.js b/src/demos/file-check/checkFileContents.js index 190543b6..d6952d36 100644 --- a/src/demos/file-check/checkFileContents.js +++ b/src/demos/file-check/checkFileContents.js @@ -1,8 +1,8 @@ import * as books from '../../core/books/books'; -import { checkUSFMText, checkMarkdownText, checkPlainText, checkYAMLText, checkManifestText, checkTN_TSVText, checkAnnotationRows } from '../../core'; +import { checkUSFMText, checkMarkdownFileContents, checkPlainText, checkYAMLText, checkManifestText, checkTN_TSVText, checkAnnotationRows } from '../../core'; -// const CHECK_FILE_CONTENTS_VERSION_STRING = '0.2.2'; +// const CHECK_FILE_CONTENTS_VERSION_STRING = '0.2.3'; /** @@ -13,10 +13,21 @@ import { checkUSFMText, checkMarkdownText, checkPlainText, checkYAMLText, checkM * @param {string} givenLocation * @param {Object} checkingOptions */ -export async function checkFileContents(languageCode, filename, fileContent, givenLocation, checkingOptions) { +export async function checkFileContents(languageCode, repoCode, filename, fileContent, givenLocation, checkingOptions) { // Determine the file type from the filename extension // and return the results of checking that kind of file text // console.log(`checkFileContents(${languageCode}, ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)})…`); + console.assert(languageCode !== undefined, "checkFileContents: 'languageCode' parameter should be defined"); + console.assert(typeof languageCode === 'string', `checkFileContents: 'languageCode' parameter should be a string not a '${typeof languageCode}'`); + console.assert(repoCode !== undefined, "checkFileContents: 'repoCode' parameter should be defined"); + console.assert(typeof repoCode === 'string', `checkFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + console.assert(filename !== undefined, "checkFileContents: 'filename' parameter should be defined"); + console.assert(typeof filename === 'string', `checkFileContents: 'filename' parameter should be a string not a '${typeof filename}'`); + console.assert(fileContent !== undefined, "checkFileContents: 'fileContent' parameter should be defined"); + console.assert(typeof fileContent === 'string', `checkFileContents: 'fileContent' parameter should be a string not a '${typeof fileContent}'`); + console.assert(givenLocation !== undefined, "checkFileContents: 'givenRowLocation' parameter should be defined"); + console.assert(typeof givenLocation === 'string', `checkFileContents: 'givenRowLocation' parameter should be a string not a '${typeof givenLocation}'`); + const startTime = new Date(); let ourCFLocation = givenLocation; @@ -44,22 +55,22 @@ export async function checkFileContents(languageCode, filename, fileContent, giv const bookID = filenameMain.substring(filenameMain.length - 3); // console.log(`Have USFM bookcode=${bookID}`); console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); - checkFileResult = checkUSFMText(languageCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkUSFMText(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filenameLower.endsWith('.sfm')) { const filenameMain = filename.substring(0, filename.length - 4); // drop .sfm console.log(`checkFileContents have SFM filenameMain=${filenameMain}`); const bookID = filenameMain.substring(2, 5); console.log(`checkFileContents have SFM bookcode=${bookID}`); console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); - checkFileResult = checkUSFMText(languageCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkUSFMText(languageCode, repoCode, bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filenameLower.endsWith('.md')) - checkFileResult = checkMarkdownText(filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkMarkdownFileContents(languageCode, filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower.endsWith('.txt')) - checkFileResult = checkPlainText('raw', filename, fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkPlainText('text', filename, fileContent, ourCFLocation, checkingOptions); else if (filenameLower === 'manifest.yaml') checkFileResult = checkManifestText('', fileContent, ourCFLocation, checkingOptions); else if (filenameLower.endsWith('.yaml')) - checkFileResult = checkYAMLText('', fileContent, ourCFLocation, checkingOptions); + checkFileResult = checkYAMLText(languageCode, filename, fileContent, ourCFLocation, checkingOptions); else { checkFileResult = checkPlainText('raw', filename, fileContent, ourCFLocation, checkingOptions); checkFileResult.noticeList.unshift({ priority: 995, message: "File extension is not recognized, so treated as plain text.", filename, location: filename }); @@ -67,7 +78,11 @@ export async function checkFileContents(languageCode, filename, fileContent, giv // console.log(`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(notice) { return notice.extra ? notice : { ...notice, filename }; } // Might be an indirect check on a TA or TW article + 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 + } checkFileResult.noticeList = checkFileResult.noticeList.map(addFilenameField); // Add some extra fields to our checkFileResult object diff --git a/src/demos/gl-book-package-check/GlBookPackageCheck.js b/src/demos/gl-book-package-check/GlBookPackageCheck.js index e067b4ef..49bb0eeb 100644 --- a/src/demos/gl-book-package-check/GlBookPackageCheck.js +++ b/src/demos/gl-book-package-check/GlBookPackageCheck.js @@ -8,7 +8,7 @@ import { checkBookPackage } from '../book-package-check/checkBookPackage'; // import { consoleLogObject } from '../../core/utilities'; -// const GL_BP_VALIDATOR_VERSION_STRING = '0.1.4'; +// const GL_BP_VALIDATOR_VERSION_STRING = '0.1.5'; function GlBookPackageCheck(/*username, languageCode, bookIDs,*/ props) { @@ -35,10 +35,14 @@ function GlBookPackageCheck(/*username, languageCode, bookIDs,*/ props) { let checkingOptions = { // Uncomment any of these to test them // extractLength: 25, checkManifestFlag: true, + checkReadmeFlag: true, + checkLicenseFlag: true, }; // Or this allows the parameters to be specified as a GlBookPackageCheck property if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + const repoPreloadList = ['TA', 'TW', 'TQ', 'TQ2']; + useEffect(() => { // console.log("GlBookPackageCheck.useEffect() called with ", JSON.stringify(props)); @@ -70,7 +74,7 @@ function GlBookPackageCheck(/*username, languageCode, bookIDs,*/ props) { else await clearCheckedArticleCache(); setResultValue(

      Preloading repos for {username} {languageCode} ready for GL book package check…

      ); - const successFlag = await preloadReposIfNecessary(username, languageCode, [bookID], branch); + const successFlag = await preloadReposIfNecessary(username, languageCode, [bookID], branch, repoPreloadList); if (!successFlag) console.error(`AllBookPackagesCheck error: Failed to pre-load all repos`) diff --git a/src/demos/gl-book-package-check/README.md b/src/demos/gl-book-package-check/README.md index dabb40d6..1223eebe 100644 --- a/src/demos/gl-book-package-check/README.md +++ b/src/demos/gl-book-package-check/README.md @@ -13,6 +13,9 @@ Note that `OBS` can also be entered here as a *pseudo book identifier* in order **Note**: This demonstration uses saved (cached) copies of files stored inside the local browser. This makes reruns of the checks faster, but it won't notice if you have recently updated the files on Door43. If you want to clear the local caches, use either the `reloadAllFilesFirst` variable below, or the `Clear Cache` function from the menu. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import { clearCheckedArticleCache } from '../../core'; import GlBookPackageCheck from './GlBookPackageCheck'; @@ -25,11 +28,11 @@ clearCheckedArticleCache(); originalLanguagesUsername='unfoldingWord' // repo organisation name for work-in-progress Door43 UHB and UGNT versions // Uncomment or change ONE of the following lines - // otherLanguageUsername='Door43-Catalog' // repo organisation name for all published Door43 LT, ST, TN, etc. versions + // otherLanguageUsername='Door43-Catalog' // repo organisation name for all published Door43 LT, ST, TN2, etc. versions // otherLanguageUsername='unfoldingWord' // repo organisation name for work-in-progress en Door43 ULT, UST, UTN, etc. versions - // otherLanguageUsername='Es-419_gl' // repo organisation name for work-in-progress es-419 Door43 LT, ST, TN, etc. versions - // otherLanguageUsername='translationCore-Create-BCS' // repo organisation name for work-in-progress hi/kn Door43 LT, ST, TN, etc. versions - otherLanguageUsername='ru_gl' // repo organisation name for work-in-progress ru Door43 LT, ST, TN, etc. versions + // otherLanguageUsername='Es-419_gl' // repo organisation name for work-in-progress es-419 Door43 LT, ST, TN2, etc. versions + // otherLanguageUsername='translationCore-Create-BCS' // repo organisation name for work-in-progress hi/kn Door43 LT, ST, TN2, etc. versions + otherLanguageUsername='ru_gl' // repo organisation name for work-in-progress ru Door43 LT, ST, TN2, etc. versions // Of course, this languageCode has to match the chosen otherLanguageUsername above languageCode='ru' // Tested with es-419, hi, kn, ru @@ -42,211 +45,10 @@ clearCheckedArticleCache(); // Alternatives are `SevereMediumLow', 'SingleList' displayType='SingleList' + // Lines starting with // are ignored -- you can add or remove // as desired // Specifying maximumSimilarMessages and extractLength is just to show off options // —those fields are not necessary (or normal) here maximumSimilarMessages='2' // Default is 3 (0 means don't suppress) // extractLength='13' // Default is 15 /> ``` - - diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index 1e6c1a7d..b513b2f4 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -2,7 +2,7 @@ import { isDisabledNotice } from './disabled-notices'; // import { displayPropertyNames, consoleLogObject } from './utilities'; -// const NOTICE_PROCESSOR_VERSION_STRING = '0.8.4'; +// const NOTICE_PROCESSOR_VERSION_STRING = '0.8.10'; // All of the following can be overriden with optionalProcessingOptions const DEFAULT_MAXIMUM_SIMILAR_MESSAGES = 3; // Zero means no suppression of similar messages @@ -21,18 +21,12 @@ const DEFAULT_MEDIUM_PRIORITY_LEVEL = 600; // This level or higher becomes a med /** - * - * @param {Object} givenNoticeObject - * @param {Object} optionalProcessingOptions - * @return {Array} containing three items: remainingNoticeList, allTotals, resultObject - */ +* @description - Preprocesses the successList and noticeList +* @param {Object} givenNoticeObject - must contain a noticeList array +* @param {Object} optionalProcessingOptions - may contain parameters +* @return {Array} containing three items: remainingNoticeList, allTotals, resultObject +*/ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { - /** - * @description - Preprocesses the successList and noticeList - * @param {Object} givenNoticeObject - must contain a noticeList array - * @param {Object} optionalProcessingOptions - may contain parameters - * @return {Array} - noticeList, countObject, preResultObject - */ /* Expects to get an object with: successList: a list of strings describing what has been checked @@ -102,6 +96,42 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { const standardisedNoticeList = givenNoticeObject.noticeList; + // Check for duplicate notices in the noticeList + // This might indicate that a function is being called twice unnecessarily + // This entire section may be commented out of production code + // It only really makes sense if the debugChain is enabled + if (givenNoticeObject.noticeList && givenNoticeObject.noticeList.length) { + console.log("Checking for duplicate notices…") + const uniqueList = []; + function uniqueListContains(item) { // returns -1 or the index of the first match + for (let ix = 0; ix < uniqueList.length; ix++) { + const thisUniqueNotice = uniqueList[ix]; + if ( // compare as few essentialfields as possible to find matches + thisUniqueNotice.priority === item.priority + && thisUniqueNotice.message === item.message + && (thisUniqueNotice.details === item.details || thisUniqueNotice.details === undefined || item.details === undefined) + && (thisUniqueNotice.repoCode === item.repoCode || thisUniqueNotice.repoCode === undefined || item.repoCode === undefined) + && (thisUniqueNotice.filename === item.filename || thisUniqueNotice.filename === undefined || item.filename === undefined) + && (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) + ) + return ix; + } + return -1; + } + for (const thisGivenNotice of standardisedNoticeList) { + let xx; + if ((xx = uniqueListContains(thisGivenNotice)) === -1) // wasn't found + uniqueList.push(thisGivenNotice); + else console.log(`Duplicate notices:\n${JSON.stringify(thisGivenNotice)}\nwhen had\n${JSON.stringify(uniqueList[xx])}`); + } + if (uniqueList.length !== givenNoticeObject.noticeList.length) + console.log(`Here with ${givenNoticeObject.noticeList.length.toLocaleString()} notices and ${uniqueList.length.toLocaleString()} unique notices`); + } + + // Run a check through the noticeList to help discover any programming errors that need fixing // This entire section may be commented out of production code if (givenNoticeObject.noticeList && givenNoticeObject.noticeList.length) { @@ -126,6 +156,8 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { && !thisMsg.startsWith('Unexpected content after \\') && !thisMsg.startsWith('USFMGrammar: ') && !thisMsg.endsWith(' character after space') + && !thisMsg.endsWith(' character at start of line') + && !thisMsg.endsWith(' character at end of line') && !thisMsg.endsWith(' marker at start of line') && !thisMsg.endsWith(' closing character (no matching opener)') && !thisMsg.endsWith(' closing character doesn\'t match') @@ -232,7 +264,7 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { const NotesRegex = /\d\d-(\w\w\w).tsv/; // "Checked EN_TN_01-GEN.TSV file: en_tn_01-GEN.tsv" const manifestRegex = /Checked ([\w\-_]{2,25}) manifest file/; resultObject.successList = []; - const UHBBookList = [], UGNTBookList = [], LTBookList = [], STBookList = [], TNBookList = []; + const UHBBookList = [], UGNTBookList = [], LTBookList = [], STBookList = [], TNBookList = [], TN2BookList = [], TQ2BookList = []; const USFMBookList = [], TSVNotesList = [], manifestsList = []; const TNList = [], TQList = [], TWLList = []; for (const thisParticularSuccessMsg of givenNoticeObject.successList) { @@ -248,9 +280,13 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { STBookList.push(thisParticularSuccessMsg.substring(17, thisParticularSuccessMsg.length)) else if (thisParticularSuccessMsg.startsWith('Checked TN file: ')) TNBookList.push(thisParticularSuccessMsg.substring(17, thisParticularSuccessMsg.length)) - else if (thisParticularSuccessMsg.startsWith('Checked TN ') && thisParticularSuccessMsg.substring(14, 20) === ' file:') + else if (thisParticularSuccessMsg.startsWith('Checked TN2 file: ')) + TN2BookList.push(thisParticularSuccessMsg.substring(17, thisParticularSuccessMsg.length)) + else if (thisParticularSuccessMsg.startsWith('Checked TQ2 file: ')) + TQ2BookList.push(thisParticularSuccessMsg.substring(17, thisParticularSuccessMsg.length)) + else if (thisParticularSuccessMsg.startsWith('Checked TN2 ') && thisParticularSuccessMsg.substring(14, 20) === ' file:') TNList.push(thisParticularSuccessMsg.substring(21, thisParticularSuccessMsg.length)) - else if (thisParticularSuccessMsg.startsWith('Checked TQ ') && thisParticularSuccessMsg.substring(14, 20) === ' file:') + else if (thisParticularSuccessMsg.startsWith('Checked TQ2 ') && thisParticularSuccessMsg.substring(14, 20) === ' file:') TQList.push(thisParticularSuccessMsg.substring(21, thisParticularSuccessMsg.length)) else if (thisParticularSuccessMsg.startsWith('Checked TWL ') && thisParticularSuccessMsg.substring(15, 21) === ' file:') TWLList.push(thisParticularSuccessMsg.substring(22, thisParticularSuccessMsg.length)) @@ -278,14 +314,18 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { resultObject.successList.push(`Checked ST file: ${STBookList[0]}`); if (TNBookList.length === 1) resultObject.successList.push(`Checked TN file: ${TNBookList[0]}`); + if (TN2BookList.length === 1) + resultObject.successList.push(`Checked TN2 file: ${TN2BookList[0]}`); + if (TQ2BookList.length === 1) + resultObject.successList.push(`Checked TQ2 file: ${TQ2BookList[0]}`); if (USFMBookList.length === 1) resultObject.successList.push(`Checked ${USFMBookList[0]} file`); if (TSVNotesList.length === 1) resultObject.successList.push(`Checked ${TSVNotesList[0]} file`); if (TNList.length === 1) - resultObject.successList.push(`Checked TN file: ${TNList[0]}`); + resultObject.successList.push(`Checked TN2 file: ${TNList[0]}`); if (TQList.length === 1) - resultObject.successList.push(`Checked TQ file: ${TQList[0]}`); + resultObject.successList.push(`Checked TQ2 file: ${TQList[0]}`); if (TWLList.length === 1) resultObject.successList.push(`Checked TWL file: ${TWLList[0]}`); if (manifestsList.length === 1) @@ -301,9 +341,13 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { if (TWLList.length > 1) resultObject.successList.unshift(`Checked ${TWLList.length} TWL files: ${TWLList.join(', ')}`); if (TQList.length > 1) - resultObject.successList.unshift(`Checked ${TQList.length} TQ files: ${TQList.join(', ')}`); + resultObject.successList.unshift(`Checked ${TQList.length} TQ2 files: ${TQList.join(', ')}`); if (TNList.length > 1) resultObject.successList.unshift(`Checked ${TNList.length} TN files: ${TNList.join(', ')}`); + if (TQ2BookList.length > 1) + resultObject.successList.unshift(`Checked ${TQ2BookList.length} TQ2 files: ${TQ2BookList.join(', ')}`); + if (TN2BookList.length > 1) + resultObject.successList.unshift(`Checked ${TN2BookList.length} TN2 files: ${TN2BookList.join(', ')}`); if (TNBookList.length > 1) resultObject.successList.unshift(`Checked ${TNBookList.length} TN files: ${TNBookList.join(', ')}`); if (STBookList.length > 1) diff --git a/src/demos/notice-processing1.md b/src/demos/notice-processing1.md index a7ad1749..d8f75ecf 100644 --- a/src/demos/notice-processing1.md +++ b/src/demos/notice-processing1.md @@ -20,6 +20,9 @@ Note below that the optional `processOptions` object allows the user to adjust t Although this demonstration here formats and colours the error and warning lists, it's expected that the encapsulating program will format and use the fields as desired. Because they are returned as an array of fields rather than simply strings, it's certainly possible for the encapsulating program to sort or filter the messages 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 { checkTextField } from '../core/field-text-check'; import { processNoticesToErrorsWarnings } from './notice-processing-functions'; import { RenderRawResults, RenderObject, RenderSuccessesErrorsWarnings } from '../demos/RenderProcessedResults'; diff --git a/src/demos/notice-processing2.md b/src/demos/notice-processing2.md index 86e4728a..8da1af4b 100644 --- a/src/demos/notice-processing2.md +++ b/src/demos/notice-processing2.md @@ -20,6 +20,9 @@ Note below that the optional `processOptions` object allows the user to adjust t Although this demonstration here formats and colours the error and warning lists, it's expected that the encapsulating program will format and use the fields as desired. Because they are returned as an array of fields rather than simply strings, it's certainly possible for the encapsulating program to sort or filter the messages 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 { checkTextField } from '../core/field-text-check'; import { processNoticesToSevereMediumLow } from './notice-processing-functions'; import { RenderRawResults, RenderObject, RenderSuccessesSevereMediumLow } from '../demos/RenderProcessedResults'; diff --git a/src/demos/notice-processing3.md b/src/demos/notice-processing3.md index b8a363cb..3397ba7b 100644 --- a/src/demos/notice-processing3.md +++ b/src/demos/notice-processing3.md @@ -20,6 +20,9 @@ Note below that the optional `processOptions` object allows the user to adjust t Although this demonstration here formats and colour the warning list, it's expected that the encapsulating program will format and use the fields as desired. Because they are returned as an array of fields rather than simply strings, it's certainly possible for the encapsulating program to sort or filter the messages 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 { checkTextField } from '../core/field-text-check'; import { processNoticesToSingleList } from './notice-processing-functions'; import { RenderRawResults, RenderObject, RenderSuccessesWarningsGradient } from '../demos/RenderProcessedResults'; diff --git a/src/demos/repo-check/README.md b/src/demos/repo-check/README.md index e913c552..72fef0b0 100644 --- a/src/demos/repo-check/README.md +++ b/src/demos/repo-check/README.md @@ -7,28 +7,31 @@ The code below requests some info and then checks a Door43 repository.You can en **Note**: This demonstration uses saved (cached) copies of files stored inside the local browser. This makes reruns of the checks faster, but it won't notice if you have recently updated the files on Door43. If you want to clear the local caches, use either the `reloadAllFilesFirst` variable below, or the `Clear Cache` function from the menu. ```js +// The code in this box is editable for changing settings— +// Simply click inside here and add, change, or delete text as required. + import RepoCheck from './RepoCheck'; ``` - - diff --git a/src/demos/repo-check/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index fa3a03ef..97c088e7 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -7,7 +7,7 @@ import { checkRepo } from './checkRepo'; // import { consoleLogObject, displayPropertyNames } from '../../core/utilities'; -//const REPO_VALIDATOR_VERSION_STRING = '0.1.4'; +//const REPO_VALIDATOR_VERSION_STRING = '0.1.5'; function RepoCheck(/*username, languageCode,*/ props) { @@ -78,15 +78,15 @@ function RepoCheck(/*username, languageCode,*/ props) { let [languageCode, repoCode] = repoName.split('_'); repoCode = repoCode.toUpperCase(); - if (repoCode === 'TN') repoCode = 'TN1'; - else if (repoCode === 'TQ') repoCode = 'TQ1'; + if (repoCode === 'TN2') repoCode = 'TN'; + else if (repoCode === 'TQ2') repoCode = 'TQ'; // console.log(`RepoCheck languageCode='${languageCode}' repoCode='${repoCode}'`); setResultValue(

      Preloading repos for {username} {languageCode} ready for {repoName} repo check…

      ); - const repoList = ['TW']; - if (repoCode !== 'UHB' && repoCode !== 'UGNT') repoList.push('TA'); // Original languages only have TW links - if (repoCode !== 'TA' && repoCode !== 'TW') repoList.push(repoCode); - const successFlag = await preloadReposIfNecessary(username, languageCode, [], branch, repoList); + const repoPreloadList = ['TW']; + if (repoCode !== 'UHB' && repoCode !== 'UGNT') repoPreloadList.push('TA'); // Original languages only have TW links + if (repoCode !== 'TA' && repoCode !== 'TW') repoPreloadList.push(repoCode); + const successFlag = await preloadReposIfNecessary(username, languageCode, [], branch, repoPreloadList); if (!successFlag) console.error(`RepoCheck error: Failed to pre-load all repos`) @@ -111,9 +111,11 @@ function RepoCheck(/*username, languageCode,*/ props) { rawCRResults.languageCode = languageCode; rawCRResults.checkedOptions = checkingOptions; + // Because we know here that we're only checking one repo, we don't need the repoName field in the notices - function deleteRepoNameField(notice) { delete notice.repoName; return notice; } - rawCRResults.noticeList = rawCRResults.noticeList.map(deleteRepoNameField); + // WRONG: We want the repoName so we can make the line numbers into live links + // function deleteRepoNameField(notice) { delete notice.repoName; return notice; } + // rawCRResults.noticeList = rawCRResults.noticeList.map(deleteRepoNameField); // console.log("Here with RC rawCRResults", typeof rawCRResults); // Now do our final handling of the result -- we have some options available diff --git a/src/demos/repo-check/checkRepo.js b/src/demos/repo-check/checkRepo.js index 7acbe207..1fbd36d3 100644 --- a/src/demos/repo-check/checkRepo.js +++ b/src/demos/repo-check/checkRepo.js @@ -4,7 +4,7 @@ import { repositoryExistsOnDoor43, getFileListFromZip, cachedGetFile, cachedGetR import { checkFileContents } from '../file-check/checkFileContents'; -// const REPO_VALIDATOR_VERSION_STRING = '0.4.2'; +// const REPO_VALIDATOR_VERSION_STRING = '0.4.3'; /* @@ -17,13 +17,22 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe noticeList: an array of 9 (i.e., with extra bookOrFileCode parameter at end) notice components */ // console.log(`checkRepo(${username}, ${repoName}, ${branch}, ${givenLocation}, (fn), ${JSON.stringify(checkingOptions)})…`); + console.assert(username !== undefined, "checkRepo: 'username' parameter should be defined"); + console.assert(typeof username === 'string', `checkRepo: 'username' parameter should be a string not a '${typeof username}'`); + console.assert(repoName !== undefined, "checkRepo: 'repoName' parameter should be defined"); + console.assert(typeof repoName === 'string', `checkRepo: 'repoName' parameter should be a string not a '${typeof repoName}'`); + console.assert(branch !== undefined, "checkRepo: 'branch' parameter should be defined"); + console.assert(typeof branch === 'string', `checkRepo: 'branch' parameter should be a string not a '${typeof branch}'`); + console.assert(givenLocation !== undefined, "checkRepo: 'givenRowLocation' parameter should be defined"); + console.assert(typeof givenLocation === 'string', `checkRepo: 'givenRowLocation' parameter should be a string not a '${typeof givenLocation}'`); + let abortFlag = false; const startTime = new Date(); let [languageCode, repoCode] = repoName.split('_'); repoCode = repoCode.toUpperCase(); - if (repoCode === 'TN') repoCode = 'TN1'; - else if (repoCode === 'TQ') repoCode = 'TQ1'; + if (repoCode === 'TN2') repoCode = 'TN'; + else if (repoCode === 'TQ2') repoCode = 'TQ'; // console.log("checkRepo languageCode", languageCode); if (branch === undefined) branch = 'master'; // Ideally we should ask what the default branch is @@ -66,8 +75,9 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe console.assert(typeof noticeObject.location === 'string', `cR addNoticePartial: 'location' parameter should be a string not a '${typeof noticeObject.location}'`); // console.assert(noticeObject.extra !== undefined, "cR addNoticePartial: 'extra' parameter should be defined"); console.assert(typeof noticeObject.extra === 'string', `cR addNoticePartial: 'extra' parameter should be a string not a '${typeof noticeObject.extra}'`); + if (noticeObject.debugChain) noticeObject.debugChain = `checkRepo ${noticeObject.debugChain}`; // Add in the repoName from the outer scope - checkRepoResult.noticeList.push({ ...noticeObject, repoCode, repoName }); + checkRepoResult.noticeList.push({ ...noticeObject, username, repoCode, repoName }); } @@ -92,7 +102,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe console.assert(fileLocation !== undefined, "ourCheckRepoFileContents: 'fileLocation' parameter should be defined"); console.assert(typeof fileLocation === 'string', `ourCheckRepoFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - const cfcResultObject = await checkFileContents(languageCode, filename, fileContent, fileLocation, optionalCheckingOptions); + const cfcResultObject = await checkFileContents(languageCode, repoCode, filename, fileContent, fileLocation, optionalCheckingOptions); // console.log("checkFileContents() returned", resultObject.successList.length, "success message(s) and", resultObject.noticeList.length, "notice(s)"); // for (const successEntry of resultObject.successList) // console.log(" ", successEntry); @@ -113,7 +123,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe // as we don't enable TA or TW checking per repo anyway // Anyway, not sure that the following code was working yet if (repoName.endsWith('_tn')) { - // The following is needed coz we might be checking the linked TA and/or TW articles from TN TSV files + // The following is needed coz we might be checking the linked TA and/or TW articles from TN2 TSV files console.log("cfcResultObject", JSON.stringify({ ...cfcResultObject, noticeList: "deleted" })); if (cfcResultObject.checkedFileCount && cfcResultObject.checkedFileCount > 0) { checkRepoResult.checkedFileCount += cfcResultObject.checkedFileCount; @@ -208,9 +218,10 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe else if (thisFilenameExtension === 'tsv') { // const filenameMain = thisFilename.substring(0, thisFilename.length - 4); // drop .tsv // console.log(`Have TSV filenameMain=${bookOrFileCode}`); - const bookID = bookOrFileCode.substring(bookOrFileCode.length - 3).toUpperCase(); + let bookID; + bookID = bookOrFileCode.length === 6 ? bookOrFileCode.substring(0, 3) : bookOrFileCode.slice(-3).toUpperCase(); // console.log(`Have TSV bookcode=${bookID}`); - console.assert(books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for TSV)`); + console.assert(bookID !== 'OBS' && books.isValidBookID(bookID), `checkRepo: '${bookID}' is not a valid USFM book identifier (for TSV)`); bookOrFileCode = bookID; ourBookID = bookID; } diff --git a/styleguide.config.js b/styleguide.config.js index ea4e996e..ef2d5c51 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -128,7 +128,7 @@ let sections = [ // description: '' }, { - name: 'TN TSV table check', + name: 'TN2 TSV table check', content: 'src/core/tn-tsv-table-text-check.md', // description: '' }, @@ -202,7 +202,7 @@ let sections = [ // description: '' }, { - name: 'TN TSV table row check', + name: 'TN2 TSV table row check', content: 'src/core/tn-tsv-table-row-check.md', // description: '' }, diff --git a/yarn.lock b/yarn.lock index e15544dc..b6beedec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@babel/cli@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.1.tgz#e08a0b1cb6fcd4b9eb6a606ba5602c5c0fe24a0c" - integrity sha512-eRJREyrfAJ2r42Iaxe8h3v6yyj1wu9OyosaUHW6UImjGf9ahGL9nsFNh7OCopvtcPL8WnEo7tp78wrZaZ6vG9g== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.7.tgz#63a3c38bddff02a1c633c70f2fd03019af6bf977" + integrity sha512-vE1fidQsaWnQVs4SItkuCdi3+uXqjbhw4cIKp8aawKxOnTnlvxYMzXSeMAqo6alldQRFQYb198YQfW0Sp1jl5Q== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -16,7 +16,7 @@ slash "^2.0.0" source-map "^0.5.0" optionalDependencies: - "@nicolo-ribaudo/chokidar-2" "^2.1.8" + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents" chokidar "^3.4.0" "@babel/code-frame@7.5.5": @@ -40,10 +40,10 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.9.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9" - integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg== +"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7", "@babel/compat-data@^7.9.0": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== "@babel/core@7.9.0": version "7.9.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.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" - integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.7.tgz#bf55363c08c8352a37691f7216ec30090bf7e3bf" + integrity sha512-tRKx9B53kJe8NCGGIxEQb2Bkr0riUIEuN7Sc1fxhs5H8lKlCWUvQCSNMVIB0Meva7hcbCRJ76de15KoLltdoqw== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.1" + "@babel/generator" "^7.12.5" "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.1" - "@babel/parser" "^7.12.3" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.7" + "@babel/types" "^7.12.7" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -89,7 +89,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.12.5", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": +"@babel/generator@^7.12.5", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== @@ -113,7 +113,7 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.12.1": +"@babel/helper-builder-react-jsx-experimental@^7.12.4": version "7.12.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48" integrity sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og== @@ -130,7 +130,7 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.12.1", "@babel/helper-compilation-targets@^7.8.7": +"@babel/helper-compilation-targets@^7.12.5", "@babel/helper-compilation-targets@^7.8.7": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== @@ -152,12 +152,11 @@ "@babel/helper-split-export-declaration" "^7.10.4" "@babel/helper-create-regexp-features-plugin@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" - integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.1" "@babel/helper-define-map@^7.10.4": @@ -200,13 +199,13 @@ "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" - integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== dependencies: - "@babel/types" "^7.12.1" + "@babel/types" "^7.12.7" -"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.8.3": +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5", "@babel/helper-module-imports@^7.8.3": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== @@ -229,24 +228,17 @@ lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" - integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.7.tgz#7f94ae5e08721a49467346aa04fd22f750033b9c" + integrity sha512-I5xc9oSJ2h59OwyUqjv95HRyzxj53DAubUERgQMrpcCEYQyToeHA+NEcUEsVWB4j53RDeskeBJ0SgRAYHDBckw== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.7" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-regex@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" - integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== - dependencies: - lodash "^4.17.19" - "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" @@ -307,7 +299,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.12.1", "@babel/helpers@^7.9.0": +"@babel/helpers@^7.12.5", "@babel/helpers@^7.9.0": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== @@ -325,10 +317,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" - integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.7", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056" + integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg== "@babel/plugin-proposal-async-generator-functions@^7.12.1", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.12.1" @@ -420,10 +412,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.12.1", "@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz#b1ce757156d40ed79d59d467cb2b154a5c4149ba" - integrity sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g== +"@babel/plugin-proposal-numeric-separator@^7.12.7", "@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" @@ -453,10 +445,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz#cce122203fc8a32794296fc377c6dedaf4363797" - integrity sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw== +"@babel/plugin-proposal-optional-chaining@^7.12.7", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" @@ -817,12 +809,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx-development@^7.12.5", "@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.5.tgz#677de5b96da310430d6cfb7fee16a1603afa3d56" - integrity sha512-1JJusg3iPgsZDthyWiCr3KQiGs31ikU/mSf2N2dSYEAO0GEImmVUbWf0VoSDGDFTAn5Dj4DUiR6SdIXHY7tELA== +"@babel/plugin-transform-react-jsx-development@^7.12.7", "@babel/plugin-transform-react-jsx-development@^7.9.0": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.7.tgz#4c2a647de79c7e2b16bfe4540677ba3121e82a08" + integrity sha512-Rs3ETtMtR3VLXFeYRChle5SsP/P9Jp/6dsewBQfokDSzKJThlsuFcnzLTDRALiUmTC48ej19YD9uN1mupEeEDg== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.12.1" + "@babel/helper-builder-react-jsx-experimental" "^7.12.4" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.12.1" @@ -840,13 +832,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.12.5", "@babel/plugin-transform-react-jsx@^7.9.1": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz#39ede0e30159770561b6963be143e40af3bde00c" - integrity sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ== +"@babel/plugin-transform-react-jsx@^7.12.7", "@babel/plugin-transform-react-jsx@^7.9.1": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.7.tgz#8b14d45f6eccd41b7f924bcb65c021e9f0a06f7f" + integrity sha512-YFlTi6MEsclFAPIDNZYiCRbneg1MFGao9pPG9uD5htwE0vDbPaMUMeYd6itWjw7K4kro4UbdQf3ljmFl9y48dQ== dependencies: "@babel/helper-builder-react-jsx" "^7.10.4" - "@babel/helper-builder-react-jsx-experimental" "^7.12.1" + "@babel/helper-builder-react-jsx-experimental" "^7.12.4" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.12.1" @@ -907,13 +899,12 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" -"@babel/plugin-transform-sticky-regex@^7.12.1", "@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz#5c24cf50de396d30e99afc8d1c700e8bce0f5caf" - integrity sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ== +"@babel/plugin-transform-sticky-regex@^7.12.7", "@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-regex" "^7.10.4" "@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.8.3": version "7.12.1" @@ -1020,13 +1011,13 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.4.5": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.1.tgz#9c7e5ca82a19efc865384bb4989148d2ee5d7ac2" - integrity sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.7.tgz#54ea21dbe92caf6f10cb1a0a576adc4ebf094b55" + integrity sha512-OnNdfAr1FUQg7ksb7bmbKoby4qFOHw6DKWWUNB9KqnnCldxhxJlP+21dpyaWFmf2h0rTbOkXJtAGevY3XW1eew== dependencies: - "@babel/compat-data" "^7.12.1" - "@babel/helper-compilation-targets" "^7.12.1" - "@babel/helper-module-imports" "^7.12.1" + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-validator-option" "^7.12.1" "@babel/plugin-proposal-async-generator-functions" "^7.12.1" @@ -1036,10 +1027,10 @@ "@babel/plugin-proposal-json-strings" "^7.12.1" "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-numeric-separator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" "@babel/plugin-proposal-object-rest-spread" "^7.12.1" "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" "@babel/plugin-proposal-private-methods" "^7.12.1" "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" @@ -1081,14 +1072,14 @@ "@babel/plugin-transform-reserved-words" "^7.12.1" "@babel/plugin-transform-shorthand-properties" "^7.12.1" "@babel/plugin-transform-spread" "^7.12.1" - "@babel/plugin-transform-sticky-regex" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" "@babel/plugin-transform-template-literals" "^7.12.1" "@babel/plugin-transform-typeof-symbol" "^7.12.1" "@babel/plugin-transform-unicode-escapes" "^7.12.1" "@babel/plugin-transform-unicode-regex" "^7.12.1" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.1" - core-js-compat "^3.6.2" + "@babel/types" "^7.12.7" + core-js-compat "^3.7.0" semver "^5.5.0" "@babel/preset-modules@^0.1.3": @@ -1115,14 +1106,14 @@ "@babel/plugin-transform-react-jsx-source" "^7.9.0" "@babel/preset-react@^7.0.0", "@babel/preset-react@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.5.tgz#d45625f65d53612078a43867c5c6750e78772c56" - integrity sha512-jcs++VPrgyFehkMezHtezS2BpnUlR7tQFAyesJn1vGTO9aTFZrgIQrA5YydlTwxbcjMwkFY6i04flCigRRr3GA== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.7.tgz#36d61d83223b07b6ac4ec55cf016abb0f70be83b" + integrity sha512-wKeTdnGUP5AEYCYQIMeXMMwU7j+2opxrG0WzuZfxuuW9nhKvvALBjl67653CWamZJVefuJGI219G591RSldrqQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-display-name" "^7.12.1" - "@babel/plugin-transform-react-jsx" "^7.12.5" - "@babel/plugin-transform-react-jsx-development" "^7.12.5" + "@babel/plugin-transform-react-jsx" "^7.12.7" + "@babel/plugin-transform-react-jsx-development" "^7.12.7" "@babel/plugin-transform-react-jsx-self" "^7.12.1" "@babel/plugin-transform-react-jsx-source" "^7.12.1" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" @@ -1150,41 +1141,41 @@ dependencies: 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.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.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@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.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.4", "@babel/template@^7.3.3", "@babel/template@^7.4.0", "@babel/template@^7.8.6": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== +"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.3.3", "@babel/template@^7.4.0", "@babel/template@^7.8.6": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" - integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.7", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.7.tgz#572a722408681cef17d6b0bef69ef2e728ca69f1" + integrity sha512-nMWaqsQEeSvMNypswUDzjqQ+0rR6pqCtoQpsqGJC4/Khm9cISwPTSpai57F6/jDaOoEGz8yE/WxcO3PV6tKSmQ== dependencies: "@babel/code-frame" "^7.10.4" "@babel/generator" "^7.12.5" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@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.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" - integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@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.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.7.tgz#6039ff1e242640a29452c9ae572162ec9a8f5d13" + integrity sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" @@ -1213,7 +1204,7 @@ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== -"@date-io/core@1.x", "@date-io/core@^1.3.13": +"@date-io/core@^1.1.0": version "1.3.13" resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa" integrity sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA== @@ -1223,12 +1214,12 @@ resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.10.6.tgz#1a6e671b590a08af8bd0784f3a93670e5d2d5bd7" integrity sha512-MGYt4GEB/4ZMdSbj6FS7/gPBvuhHUwnn5O6t8PlkSqGF1310qxypVyK4CZg5RQgev25L3R5eLVdNTyYrJOL8Rw== -"@date-io/date-fns@^1.1.0": - version "1.3.13" - resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-1.3.13.tgz#7798844041640ab393f7e21a7769a65d672f4735" - integrity sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA== +"@date-io/date-fns@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-1.1.0.tgz#91cd7703042513a6a0056a344b25cd74a4df643e" + integrity sha512-FMRhYWfoGiIXdN4xWAArpkdEbqsg2Fr+6Yda7Np2eVWCNx6gSMYsHIM51IIcI+3762ajYbhoEYjHYXVFNZIk1g== dependencies: - "@date-io/core" "^1.3.13" + "@date-io/core" "^1.1.0" "@emotion/hash@^0.8.0": version "0.8.0" @@ -1627,17 +1618,17 @@ dependencies: "@babel/runtime" "^7.4.4" -"@material-ui/pickers@^3.2.2": - version "3.2.10" - resolved "https://registry.yarnpkg.com/@material-ui/pickers/-/pickers-3.2.10.tgz#19df024895876eb0ec7cd239bbaea595f703f0ae" - integrity sha512-B8G6Obn5S3RCl7hwahkQj9sKUapwXWFjiaz/Bsw1fhYFdNMnDUolRiWQSoKPb1/oKe37Dtfszoywi1Ynbo3y8w== +"@material-ui/pickers@3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@material-ui/pickers/-/pickers-3.2.2.tgz#9b7a67f5a8f21f8183853ebc1848e5d8dd680d4c" + integrity sha512-on/J1yyKeJ4CkLnItpf/jPDKMZVWvHDklkh5FS7wkZ0s1OPoqTsPubLWfA7eND6xREnVRyLFzVTlE3VlWYdQWw== dependencies: - "@babel/runtime" "^7.6.0" - "@date-io/core" "1.x" + "@babel/runtime" "^7.2.0" "@types/styled-jsx" "^2.2.8" clsx "^1.0.2" react-transition-group "^4.0.0" rifm "^0.7.0" + tslib "^1.9.3" "@material-ui/styles@^4.10.0": version "4.10.0" @@ -1693,12 +1684,22 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nicolo-ribaudo/chokidar-2@^2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8.tgz#eef8d9b47e8dc589499f14d656e8d2dd978c3d14" - integrity sha512-FohwULwAebCUKi/akMFyGi7jfc7JXTeMHzKxuP3umRd9mK/2Y7/SMBSI2jX+YLopPXi+PF9l307NmpfxTdCegA== +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": + version "2.1.8-no-fsevents" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" + integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== dependencies: - chokidar "2.1.8" + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" "@nodelib/fs.stat@^1.1.2": version "1.1.3" @@ -1841,9 +1842,9 @@ "@babel/types" "^7.0.0" "@types/babel__template@*": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.3.tgz#b8aaeba0a45caca7b56a5de9459872dde3727214" - integrity sha512-uCoznIPDmnickEi6D0v11SBpW0OuVqHJCa7syXqQHy5uktSCreIlt0iglsCnmvz8yCb38hGcWeseA8cWJSwv5Q== + version "7.4.0" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.0.tgz#0c888dd70b3ee9eebb6e4f200e809da0076262be" + integrity sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1932,9 +1933,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" - integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== + version "14.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.9.tgz#04afc9a25c6ff93da14deabd65dc44485b53c8d6" + integrity sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1974,9 +1975,9 @@ "@types/react" "*" "@types/react@*": - version "16.9.56" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0" - integrity sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ== + version "17.0.0" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8" + integrity sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -2032,9 +2033,9 @@ "@types/yargs-parser" "*" "@types/yargs@^15.0.0": - version "15.0.9" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.9.tgz#524cd7998fe810cdb02f26101b699cccd156ff19" - integrity sha512-HmU8SeIRhZCWcnRskCs36Q1Q00KBV6Cqh/ora8WN1+22dY07AZdn6Gel8QZ3t26XYPImtcL8WV/eqjhVmMEw4g== + version "15.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.10.tgz#0fe3c8173a0d5c3e780b389050140c3f5ea6ea74" + integrity sha512-z8PNtlhrj7eJNLmrAivM7rjBESG6JwC5xP3RVk12i/8HVP7Xnx/sEmERnRImyEuUaJfO942X0qMOYsoupaJbZQ== dependencies: "@types/yargs-parser" "*" @@ -2683,20 +2684,22 @@ array-unique@^0.3.2: integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" - integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" array.prototype.flatmap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" - integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" + integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" function-bind "^1.1.1" arrify@^1.0.1: @@ -2820,9 +2823,9 @@ aws4@^1.8.0: integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== axe-core@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.0.2.tgz#c7cf7378378a51fcd272d3c09668002a4990b1cb" - integrity sha512-arU1h31OGFu+LPrOLGZ7nB45v940NMDMEJeNmbutu57P+UFDVnkZg3e+J1I2HJRZ9hT7gO8J91dn/PMrAiKakA== + version "4.1.1" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.1.tgz#70a7855888e287f7add66002211a423937063eaf" + integrity sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ== axios-cache-adapter@^2.5.0: version "2.5.0" @@ -3071,9 +3074,9 @@ base64-arraybuffer@^0.2.0: integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ== base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: version "0.11.2" @@ -3132,7 +3135,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== -bn.js@^5.1.1: +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== @@ -3250,11 +3253,11 @@ browserify-des@^1.0.0: safe-buffer "^5.1.2" browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: - bn.js "^4.1.0" + bn.js "^5.0.0" randombytes "^2.0.1" browserify-sign@^4.0.0: @@ -3299,14 +3302,15 @@ browserslist@4.7.0: node-releases "^1.1.29" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.14.6, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.9.1: - version "4.14.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.6.tgz#97702a9c212e0c6b6afefad913d3a1538e348457" - integrity sha512-zeFYcUo85ENhc/zxHbiIp0LGzzTrE2Pv2JhxvS7kpUb9Q9D38kUX6Bie7pGutJ/5iF5rOxE7CepAuWD56xJ33A== + version "4.14.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6" + integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ== dependencies: - caniuse-lite "^1.0.30001154" - electron-to-chromium "^1.3.585" + caniuse-lite "^1.0.30001157" + colorette "^1.2.1" + electron-to-chromium "^1.3.591" escalade "^3.1.1" - node-releases "^1.1.65" + node-releases "^1.1.66" bser@2.1.1: version "2.1.1" @@ -3522,10 +3526,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" 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.30001154: - version "1.0.30001156" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001156.tgz#75c20937b6012fe2b02ab58b30d475bf0718de97" - integrity sha512-z7qztybA2eFZTB6Z3yvaQBIoJpQtsewRD74adw2UbRWwsRq3jIPvgrQGawBMbfafekQaD21FWuXNcywtTDGGCw== +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.30001157: + version "1.0.30001159" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz#bebde28f893fa9594dadcaa7d6b8e2aa0299df20" + integrity sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA== canvg@^3.0.6: version "3.0.7" @@ -3619,7 +3623,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chokidar@2.1.8, chokidar@^2.0.4, chokidar@^2.1.8: +chokidar@^2.0.4, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -3693,7 +3697,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.6: +classnames@2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -4071,7 +4075,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.6.2, core-js-compat@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.7.0.tgz#8479c5d3d672d83f1f5ab94cf353e57113e065ed" integrity sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg== @@ -4314,11 +4318,11 @@ css-tree@1.0.0-alpha.37: source-map "^0.6.1" css-tree@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0.tgz#21993fa270d742642a90409a2c0cb3ac0298adf6" - integrity sha512-CdVYz/Yuqw0VdKhXPBIgi8DO3NicJVYZNWeX9XcIuSp9ZoFT5IcleVRW07O5rMjdcx1mb+MEJPknTTEW7DdsYw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.1.tgz#30b8c0161d9fb4e9e2141d762589b6ec2faebd2e" + integrity sha512-NVN42M2fjszcUNpDbdkvutgQSlFYsr1z7kqeuCagHnNLBfYor6uP1WL1KrkmdYZ5Y1vTBCIOI/C/+8T98fJ71w== dependencies: - mdn-data "2.0.12" + mdn-data "2.0.14" source-map "^0.6.1" css-vendor@^2.0.8: @@ -4433,9 +4437,9 @@ cssnano@^4.1.10: postcss "^7.0.0" csso@^4.0.2: - version "4.1.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.1.0.tgz#1d31193efa99b87aa6bad6c0cef155e543d09e8b" - integrity sha512-h+6w/W1WqXaJA4tb1dk7r5tVbOm97MsKxzwnvOR04UQ6GILroryjMWu3pmCCtL2mLaEStQ0fZgeGiy99mo7iyg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.1.1.tgz#e0cb02d6eb3af1df719222048e4359efd662af13" + integrity sha512-Rvq+e1e0TFB8E8X+8MQjHSY6vtol45s5gxtLI/018UsAn2IBMmwNEZRM/h+HVnAJRHjasLIKKUO3uvoMM28LvA== dependencies: css-tree "^1.0.0" @@ -4464,14 +4468,14 @@ cssstyle@^2.2.0: cssom "~0.3.6" csstype@^2.5.2: - version "2.6.13" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f" - integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A== + version "2.6.14" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.14.tgz#004822a4050345b55ad4dcc00be1d9cf2f4296de" + integrity sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A== csstype@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.4.tgz#b156d7be03b84ff425c9a0a4b1e5f4da9c5ca888" - integrity sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA== + version "3.0.5" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.5.tgz#7fdec6a28a67ae18647c51668a9ff95bb2fa7bb8" + integrity sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ== cyclist@^1.0.1: version "1.0.1" @@ -4516,12 +4520,12 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-fns@^2.0.0-alpha.27: - version "2.16.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b" - integrity sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ== +date-fns@2.0.0-alpha.27: + version "2.0.0-alpha.27" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0-alpha.27.tgz#5ecd4204ef0e7064264039570f6e8afbc014481c" + integrity sha512-cqfVLS+346P/Mpj2RpDrBv0P4p2zZhWWvfY5fuWrXNR/K38HaAGEkeOwb47hIpQP9Jr/TIxjZ2/sNMQwdXuGMg== -debounce@^1.2.0: +debounce@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg== @@ -4534,16 +4538,16 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: ms "2.0.0" debug@^3.1.1, debug@^3.2.5: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" @@ -4926,10 +4930,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.585: - version "1.3.591" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.591.tgz#a18892bf1acb93f7b6e4da402705d564bc235017" - integrity sha512-ol/0WzjL4NS4Kqy9VD6xXQON91xIihDT36sYCew/G/bnd1v0/4D+kahp26JauQhgFUjrdva3kRSo7URcUmQ+qw== +electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.591: + version "1.3.603" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.603.tgz#1b71bec27fb940eccd79245f6824c63d5f7e8abf" + integrity sha512-J8OHxOeJkoSLgBXfV9BHgKccgfLMHh+CoeRo6wJsi6m0k3otaxS/5vrHpMNSEYY4MISwewqanPOuhAtuE8riQQ== elliptic@^6.5.3: version "6.5.3" @@ -6731,6 +6735,13 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indefinite-observable@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/indefinite-observable/-/indefinite-observable-2.0.1.tgz#574af29bfbc17eb5947793797bddc94c9d859400" + integrity sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ== + dependencies: + symbol-observable "1.2.0" + indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -6975,7 +6986,7 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.0.0: +is-core-module@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== @@ -8381,72 +8392,73 @@ jss-nested@^6.0.1: warning "^3.0.0" jss-plugin-camel-case@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.4.0.tgz#46c75ff7fd61c304984c21af5817823f0f501ceb" - integrity sha512-9oDjsQ/AgdBbMyRjc06Kl3P8lDCSEts2vYZiPZfGAxbGCegqE4RnMob3mDaBby5H9vL9gWmyyImhLRWqIkRUCw== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.0.tgz#4b0a9c85e65e5eb72cbfba59373686c604d88f72" + integrity sha512-GSjPL0adGAkuoqeYiXTgO7PlIrmjv5v8lA6TTBdfxbNYpxADOdGKJgIEkffhlyuIZHlPuuiFYTwUreLUmSn7rg== dependencies: "@babel/runtime" "^7.3.1" hyphenate-style-name "^1.0.3" - jss "10.4.0" + jss "10.5.0" jss-plugin-default-unit@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.4.0.tgz#2b10f01269eaea7f36f0f5fd1cfbfcc76ed42854" - integrity sha512-BYJ+Y3RUYiMEgmlcYMLqwbA49DcSWsGgHpVmEEllTC8MK5iJ7++pT9TnKkKBnNZZxTV75ycyFCR5xeLSOzVm4A== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.0.tgz#e9f2e89741b0118ba15d52b4c13bda2b27262373" + integrity sha512-rsbTtZGCMrbcb9beiDd+TwL991NGmsAgVYH0hATrYJtue9e+LH/Gn4yFD1ENwE+3JzF3A+rPnM2JuD9L/SIIWw== dependencies: "@babel/runtime" "^7.3.1" - jss "10.4.0" + jss "10.5.0" jss-plugin-global@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.4.0.tgz#19449425a94e4e74e113139b629fd44d3577f97d" - integrity sha512-b8IHMJUmv29cidt3nI4bUI1+Mo5RZE37kqthaFpmxf5K7r2aAegGliAw4hXvA70ca6ckAoXMUl4SN/zxiRcRag== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.5.0.tgz#eb357ccd35cb4894277fb2117a78d1e498668ad6" + integrity sha512-FZd9+JE/3D7HMefEG54fEC0XiQ9rhGtDHAT/ols24y8sKQ1D5KIw6OyXEmIdKFmACgxZV2ARQ5pAUypxkk2IFQ== dependencies: "@babel/runtime" "^7.3.1" - jss "10.4.0" + jss "10.5.0" jss-plugin-nested@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.4.0.tgz#017d0c02c0b6b454fd9d7d3fc33470a15eea9fd1" - integrity sha512-cKgpeHIxAP0ygeWh+drpLbrxFiak6zzJ2toVRi/NmHbpkNaLjTLgePmOz5+67ln3qzJiPdXXJB1tbOyYKAP4Pw== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.5.0.tgz#790c506432a23a63c71ceb5044e2ac85f0958702" + integrity sha512-ejPlCLNlEGgx8jmMiDk/zarsCZk+DV0YqXfddpgzbO9Toamo0HweCFuwJ3ZO40UFOfqKwfpKMVH/3HUXgxkTMg== dependencies: "@babel/runtime" "^7.3.1" - jss "10.4.0" + jss "10.5.0" tiny-warning "^1.0.2" jss-plugin-props-sort@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.4.0.tgz#7110bf0b6049cc2080b220b506532bf0b70c0e07" - integrity sha512-j/t0R40/2fp+Nzt6GgHeUFnHVY2kPGF5drUVlgkcwYoHCgtBDOhTTsOfdaQFW6sHWfoQYgnGV4CXdjlPiRrzwA== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.0.tgz#5bcc3bd8e68cd3e2dafb47d67db28fd5a4fcf102" + integrity sha512-kTLRvrOetFKz5vM88FAhLNeJIxfjhCepnvq65G7xsAQ/Wgy7HwO1BS/2wE5mx8iLaAWC6Rj5h16mhMk9sKdZxg== dependencies: "@babel/runtime" "^7.3.1" - jss "10.4.0" + jss "10.5.0" jss-plugin-rule-value-function@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.4.0.tgz#7cff4a91e84973536fa49b6ebbdbf7f339b01c82" - integrity sha512-w8504Cdfu66+0SJoLkr6GUQlEb8keHg8ymtJXdVHWh0YvFxDG2l/nS93SI5Gfx0fV29dO6yUugXnKzDFJxrdFQ== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.0.tgz#60ee8240dfe60418e1ba4729adee893cbe9be7a3" + integrity sha512-jXINGr8BSsB13JVuK274oEtk0LoooYSJqTBCGeBu2cG/VJ3+4FPs1gwLgsq24xTgKshtZ+WEQMVL34OprLidRA== dependencies: "@babel/runtime" "^7.3.1" - jss "10.4.0" + jss "10.5.0" tiny-warning "^1.0.2" jss-plugin-vendor-prefixer@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.4.0.tgz#2a78f3c5d57d1e024fe7ad7c41de34d04e72ecc0" - integrity sha512-DpF+/a+GU8hMh/948sBGnKSNfKkoHg2p9aRFUmyoyxgKjOeH9n74Ht3Yt8lOgdZsuWNJbPrvaa3U4PXKwxVpTQ== + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.0.tgz#01f04cfff31f43f153f5d71972f5800b10a2eb84" + integrity sha512-rux3gmfwDdOKCLDx0IQjTwTm03IfBa+Rm/hs747cOw5Q7O3RaTUIMPKjtVfc31Xr/XI9Abz2XEupk1/oMQ7zRA== dependencies: "@babel/runtime" "^7.3.1" css-vendor "^2.0.8" - jss "10.4.0" + jss "10.5.0" -jss@10.4.0, jss@^10.0.3: - version "10.4.0" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.4.0.tgz#473a6fbe42e85441020a07e9519dac1e8a2e79ca" - integrity sha512-l7EwdwhsDishXzqTc3lbsbyZ83tlUl5L/Hb16pHCvZliA9lRDdNBZmHzeJHP0sxqD0t1mrMmMR8XroR12JBYzw== +jss@10.5.0, jss@^10.0.3: + version "10.5.0" + resolved "https://registry.yarnpkg.com/jss/-/jss-10.5.0.tgz#0c2de8a29874b2dc8162ab7f34ef6573a87d9dd3" + integrity sha512-B6151NvG+thUg3murLNHRPLxTLwQ13ep4SH5brj4d8qKtogOx/jupnpfkPGSHPqvcwKJaCLctpj2lEk+5yGwMw== dependencies: "@babel/runtime" "^7.3.1" csstype "^3.0.2" + indefinite-observable "^2.0.1" is-in-browser "^1.1.3" tiny-warning "^1.0.2" @@ -8782,7 +8794,7 @@ longest-streak@^2.0.1: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -8888,21 +8900,21 @@ markdown-to-jsx@^6.9.3: unquote "^1.1.0" material-table@^1.69.1: - version "1.69.1" - resolved "https://registry.yarnpkg.com/material-table/-/material-table-1.69.1.tgz#8d1c8b23207f18bd3328cae1b5775ede284682e6" - integrity sha512-7MA8kMtr8ToPE6gNUbOGIb4g+RGOLWK8s9gXZYNwFtg6fGAjWEJ+iqBrMmdq7fkMmTRcyOd7/sC/5OPPY8CNGg== - dependencies: - "@date-io/date-fns" "^1.1.0" - "@material-ui/pickers" "^3.2.2" - classnames "^2.2.6" - date-fns "^2.0.0-alpha.27" - debounce "^1.2.0" + version "1.69.2" + resolved "https://registry.yarnpkg.com/material-table/-/material-table-1.69.2.tgz#d5cf35d9814c30e6e8d00cd00c98756296259b57" + integrity sha512-OFst2Dzo5EZHk5mTPVR9cILFT9BcDSVVlFii0UOgvWE8ho/sn0euV1B2MfoTLKSX6pMkH0I/f3QTLX0AXhlUzQ== + dependencies: + "@date-io/date-fns" "1.1.0" + "@material-ui/pickers" "3.2.2" + classnames "2.2.6" + date-fns "2.0.0-alpha.27" + debounce "1.2.0" fast-deep-equal "2.0.1" filefy "0.1.10" jspdf "2.1.0" jspdf-autotable "3.5.9" - prop-types "^15.6.2" - react-beautiful-dnd "^13.0.0" + prop-types "15.6.2" + react-beautiful-dnd "13.0.0" react-double-scrollbar "0.0.15" md5.js@^1.3.4: @@ -8928,10 +8940,10 @@ mdast-util-compact@^1.0.0: dependencies: unist-util-visit "^1.1.0" -mdn-data@2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.12.tgz#bbb658d08b38f574bbb88f7b83703defdcc46844" - integrity sha512-ULbAlgzVb8IqZ0Hsxm6hHSlQl3Jckst2YEQS7fODu9ilNWy2LvcoSY7TRFIktABP2mdppBioc66va90T+NUs8Q== +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== mdn-data@2.0.4: version "2.0.4" @@ -9376,10 +9388,10 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.29, node-releases@^1.1.52, node-releases@^1.1.65: - version "1.1.66" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.66.tgz#609bd0dc069381015cd982300bae51ab4f1b1814" - integrity sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg== +node-releases@^1.1.29, node-releases@^1.1.52, node-releases@^1.1.66: + version "1.1.67" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" + integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -9689,9 +9701,9 @@ p-each-series@^1.0.0: p-reduce "^1.0.0" p-each-series@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" - integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== p-finally@^1.0.0: version "1.0.0" @@ -10833,6 +10845,14 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +prop-types@15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== + dependencies: + loose-envify "^1.3.1" + object-assign "^4.1.1" + prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" @@ -11028,7 +11048,7 @@ react-app-polyfill@^1.0.6: regenerator-runtime "^0.13.3" whatwg-fetch "^3.0.0" -react-beautiful-dnd@^13.0.0: +react-beautiful-dnd@13.0.0: version "13.0.0" resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz#f70cc8ff82b84bc718f8af157c9f95757a6c3b40" integrity sha512-87It8sN0ineoC3nBW0SbQuTFXM6bUqM62uJGY4BtTf0yzPl8/3+bHMWkgIe0Z6m8e+gJgjWxefGRVfpE3VcdEg== @@ -11795,11 +11815,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.18.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" - integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: - is-core-module "^2.0.0" + is-core-module "^2.1.0" path-parse "^1.0.6" restore-cursor@^2.0.0: @@ -12217,7 +12237,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.2: +side-channel@^1.0.2, side-channel@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3" integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g== @@ -12482,14 +12502,16 @@ stable@^0.1.8: integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.3.tgz#db7a475733b5b8bf6521907b18891d29006f7751" + integrity sha512-WldO+YmqhEpjp23eHZRhOT1NQF51STsbxZ+/AdpFD+EhheFxAe5d0WoK4DQVJkSHacPrJJX3OqRAl9CgHf78pg== + dependencies: + escape-string-regexp "^2.0.0" stack-utils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" - integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== dependencies: escape-string-regexp "^2.0.0" @@ -12614,32 +12636,33 @@ string-width@^4.1.0, string-width@^4.2.0: strip-ansi "^6.0.0" string.prototype.matchall@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" - integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" + integrity sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0" + es-abstract "^1.18.0-next.1" has-symbols "^1.0.1" internal-slot "^1.0.2" regexp.prototype.flags "^1.3.0" - side-channel "^1.0.2" + side-channel "^1.0.3" string.prototype.trimend@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" - integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== + 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== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" string.prototype.trimstart@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" - integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -12832,7 +12855,7 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-observable@^1.1.0, symbol-observable@^1.2.0: +symbol-observable@1.2.0, symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== @@ -13123,7 +13146,7 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -13618,23 +13641,23 @@ warning@^3.0.0: dependencies: loose-envify "^1.0.0" -watchpack-chokidar2@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" - integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" watchpack@^1.6.0, watchpack@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" - integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" optionalDependencies: chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.0" + watchpack-chokidar2 "^2.0.1" wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3"