From 4e1ff5b100f1702c9e9fa8d849c36c7ecc1a226b Mon Sep 17 00:00:00 2001 From: Robert Hunt Date: Fri, 11 Sep 2020 11:57:51 +1200 Subject: [PATCH 1/5] Add optional rowID field to notices --- noticeList.txt | 25 +++--- src/core/annotation-row-check.js | 114 ++++++++++++++----------- src/core/annotation-table-check.js | 16 ++-- src/core/tn-table-row-check.js | 128 ++++++++++++++++------------ src/core/tn-table-text-check.js | 16 ++-- src/demos/RenderProcessedResults.js | 9 +- 6 files changed, 171 insertions(+), 137 deletions(-) diff --git a/noticeList.txt b/noticeList.txt index 1aac2f0f..e6b115c0 100644 --- a/noticeList.txt +++ b/noticeList.txt @@ -92,8 +92,8 @@ Got 201 notices: 790, C,V, "Missing verse number", lineNumber:n+1, location:` after ${C}:${lastV}${withString}`} 779, "Missing ID field", location:ourRowLocation} 779, "Missing ID field", location:ourRowLocation} - 778, "ID should be exactly 4 characters", location:` (not ${fieldID.length})`} - 778, "ID should be exactly 4 characters", location:` (not ${fieldID.length})`} + 778, "ID should be exactly 4 characters", location:` (not ${rowID.length})`} + 778, "ID should be exactly 4 characters", location:` (not ${rowID.length})`} 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:atString} 765, 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:atString} 765, "Unexpected link", characterIndex, extract, location:ourAtString} @@ -128,8 +128,8 @@ Got 201 notices: 733, C,V, `Receding '${V}' verse number after '${lastV}'`, lineNumber:n+1, location:withString} 730, C,V, "Missing ID", lineNumber:n+1, location:withString} 730, C,V, "Missing ID", lineNumber:n+1, location:withString} - 729, C,V, `Duplicate '${fieldID}' ID`, lineNumber:n+1, location:withString} - 729, C,V, `Duplicate '${fieldID}' ID`, lineNumber:n+1, location:withString} + 729, C,V, `Duplicate '${rowID}' ID`, lineNumber:n+1, location:withString} + 729, C,V, `Duplicate '${rowID}' ID`, lineNumber:n+1, location:withString} 724, C, V, "Unable to convert chapter number to integer", lineNumber:n, characterIndex:3, extract:`${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location:atString} 723, C, V, "Unable to convert verse number to integer", lineNumber:n, characterIndex:3, extract:`${rest.substring(0, halfLength)}${rest.length > halfLength ? '…' : ''}`, location:atString} 722, "Unable to find original language quote in verse text", extract, location:ourLocation} @@ -179,14 +179,14 @@ Got 201 notices: 179, "Unexpected space before ellipse character", characterIndex, extract, location:ourAtString} 178, "Unexpected space after ellipse character", characterIndex, extract, location:ourAtString} 177, `Unexpected doubled ${punctChar} characters`, characterIndex, extract, location:ourAtString} - 176, "ID should start with a lowercase letter or digit", characterIndex:0, location:` (not '${fieldID[0]}')`} - 176, "ID should start with a lowercase letter or digit", characterIndex:0, location:` (not '${fieldID[0]}')`} - 175, "ID should end with a lowercase letter or digit", characterIndex:3, location:` (not '${fieldID[3]}')`} - 175, "ID should end with a lowercase letter or digit", characterIndeX:3, location:` (not '${fieldID[3]}')`} - 174, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, location:` (not '${fieldID[1]}')`} - 174, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, location:` (not '${fieldID[1]}')`} - 173, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, location:` (not '${fieldID[2]}')`} - 173, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, location:` (not '${fieldID[2]}')`} + 176, "ID should start with a lowercase letter or digit", characterIndex:0, location:` (not '${rowID[0]}')`} + 176, "ID should start with a lowercase letter or digit", characterIndex:0, location:` (not '${rowID[0]}')`} + 175, "ID should end with a lowercase letter or digit", characterIndex:3, location:` (not '${rowID[3]}')`} + 175, "ID should end with a lowercase letter or digit", characterIndeX:3, location:` (not '${rowID[3]}')`} + 174, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, location:` (not '${rowID[1]}')`} + 174, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, location:` (not '${rowID[1]}')`} + 173, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, location:` (not '${rowID[2]}')`} + 173, "ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, location:` (not '${rowID[2]}')`} 172, "Header levels should only increment by one", lineNumber:n, characterIndex:0, location:atString} 163, `Mismatched ${leftChar}${rightChar} characters`, extract:`(left=${lCount.toLocaleString()}, right=${rCount.toLocaleString()})`, location:ourAtString} 159, "Should use proper ellipse character (not periods)", characterIndex, extract, location:ourLocation} @@ -201,4 +201,3 @@ Got 201 notices: 103, `USFMGrammar: ${warningString.trim()}`, location} 102, `USFMGrammar: ${warningString}`, location:fileLocation} 101, `USFMGrammar: ${warningString}`, location:ourLocation} - \ No newline at end of file diff --git a/src/core/annotation-row-check.js b/src/core/annotation-row-check.js index 57937ea2..7dc501ec 100644 --- a/src/core/annotation-row-check.js +++ b/src/core/annotation-row-check.js @@ -61,11 +61,12 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv let adrResult = { noticeList: [] }; - function addNotice6to9({priority, message, lineNumber, characterIndex, extract, location}) { + function addNotice6to9({priority, message, rowID, lineNumber, characterIndex, extract, location}) { /** * @description - adds a new notice entry, adding bookID,C,V to the given fields * @param {Number} priority - notice priority from 1 (lowest) to 999 (highest) * @param {String} message - the text of the notice message + * @param {String} rowID - 4-character row ID field * @param {Number} lineNumber - one-based line number * @param {Number} characterIndex - zero-based index of where the issue occurs in the line * @param {String} extract - short extract from the line centred on the problem (if available) @@ -85,12 +86,13 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv console.assert(location !== undefined, "cATSVrow addNotice6to9: 'location' parameter should be defined"); console.assert(typeof location === 'string', `cATSVrow addNotice6to9: 'location' parameter should be a string not a '${typeof location}': ${location}`); // Also uses the given bookID,C,V, parameters from the main function call - adrResult.noticeList.push({ priority, message, bookID, C, V, lineNumber, characterIndex, extract, location }); + adrResult.noticeList.push({ priority, message, bookID, C, V, rowID, lineNumber, characterIndex, extract, location }); } - function ourMarkdownTextChecks(fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { + function ourMarkdownTextChecks(rowID, fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { /** * @description - checks the given markdown field and processes the returned results + * @param {String} rowID - 4-character row ID field * @param {String} fieldName - name of the field being checked * @param {String} fieldText - the actual text of the field being checked * @param {} allowedLinks - true if links are allowed in the field, otherwise false @@ -106,6 +108,8 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // We don't currently use the allowedLinks parameter // console.log(`cATSVrow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cATSVrow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cATSVrow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cATSVrow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cATSVrow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "cATSVrow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); @@ -121,14 +125,15 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of cmtResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourMarkdownTextChecks function - function ourCheckTextField(fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { + function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { /** * @description - checks the given text field and processes the returned results + * @param {String} rowID - 4-character row ID field * @param {String} fieldName - name of the field being checked * @param {String} fieldText - the actual text of the field being checked * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false @@ -142,6 +147,8 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // Updates the global list of notices // console.log(`cATSVrow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cATSVrow ourCheckTextField: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cATSVrow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cATSVrow ourCheckTextField: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cATSVrow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "cATSVrow ourCheckTextField: 'fieldText' parameter should be defined"); @@ -157,19 +164,22 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of dbtcResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTextField function - async function ourCheckTAReference(fieldName, taLinkText, rowLocation, optionalCheckingOptions) { + + async function ourCheckTAReference(rowID, fieldName, taLinkText, rowLocation, optionalCheckingOptions) { // Checks that the TA reference can be found // Updates the global list of notices // console.log(`cATSVrow ourCheckTAReference(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - console.assert(fieldName !== undefined, "cATSVrow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); - console.assert(typeof fieldName === 'string', `cATSVrow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + console.assert(rowID !== undefined, "cATSVrow ourCheckTAReference: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cATSVrow ourCheckTAReference: 'rowID' parameter should be a string not a '${typeof rowID}'`); + console.assert(fieldName !== undefined, "cATSVrow ourCheckTAReference: 'fieldName' parameter should be defined"); + console.assert(typeof fieldName === 'string', `cATSVrow ourCheckTAReference: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(taLinkText !== undefined, "cATSVrow ourCheckTAReference: 'taLinkText' parameter should be defined"); console.assert(typeof taLinkText === 'string', `cATSVrow ourCheckTAReference: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); @@ -182,12 +192,12 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTAReference notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTAReference function - async function ourCheckTNOriginalLanguageQuote(fieldName, fieldText, rowLocation, optionalCheckingOptions) { + async function ourCheckTNOriginalLanguageQuote(rowID, fieldName, fieldText, rowLocation, optionalCheckingOptions) { // Checks that the Hebrew/Greek quote can be found in the original texts // Uses the bookID,C,V values from the main function call @@ -195,12 +205,14 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // Updates the global list of notices // console.log(`cATSVrow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cATSVrow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cATSVrow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cATSVrow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cATSVrow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "cATSVrow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); console.assert(typeof fieldText === 'string', `cATSVrow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldText}'`); - const coqResultObject = await checkOriginalLanguageQuote(fieldName, fieldText, bookID, C, V, rowLocation, optionalCheckingOptions); + const coqResultObject = await checkOriginalLanguageQuote(fieldName,fieldText, bookID,C,V, rowLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field @@ -209,17 +221,19 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTNOriginalLanguageQuote function - async function ourCheckTNLinks(fieldName, taLinkText, rowLocation, optionalCheckingOptions) { + async function ourCheckTNLinks(rowID, fieldName, taLinkText, rowLocation, optionalCheckingOptions) { // Checks that the TA reference can be found // Updates the global list of notices // console.log(`cATSVrow ourCheckTNLinks(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cATSVrow ourCheckTNLinks: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cATSVrow ourCheckTNLinks: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cATSVrow ourCheckTNLinks: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cATSVrow ourCheckTNLinks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(taLinkText !== undefined, "cATSVrow ourCheckTNLinks: 'taLinkText' parameter should be defined"); @@ -234,7 +248,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNLinks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTNLinks function @@ -273,10 +287,10 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv let fields = line.split('\t'); if (fields.length === NUM_EXPECTED_TSV_FIELDS) { - const [reference, fieldID, tags, supportReference, quote, occurrence, annotation] = fields; - // let withString = ` with '${fieldID}'${inString}`; + const [reference, rowID, tags, supportReference, quote, occurrence, annotation] = fields; + // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; - // let atString = ` at ${B} ${C}:${V} (${fieldID})${inString}`; + // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; // Check the fields one-by-one const [C, V] = reference.split(':') @@ -286,12 +300,12 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv else if (/^\d+$/.test(C)) { let intC = Number(C); if (intC === 0) { - addNotice6to9({priority:824, message:`Invalid zero chapter number`, extract:C, location:ourRowLocation}); + addNotice6to9({priority:824, message:`Invalid zero chapter number`, extract:C, rowID, location:ourRowLocation}); haveGoodChapterNumber = false; } // TODO: Does this next section need rewriting (see verse check below)??? else if (intC > numChaptersThisBook) { - addNotice6to9({priority:823, message:`Invalid large chapter number`, extract:C, location:ourRowLocation}); + addNotice6to9({priority:823, message:`Invalid large chapter number`, extract:C, rowID, location:ourRowLocation}); haveGoodChapterNumber = false; } try { @@ -301,88 +315,88 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv if (!haveBibleBookID) // addNotice6to9({priority:500, message:"Invalid chapter number", rowLocation); // else - addNotice6to9({priority:822, message:"Unable to check chapter number", location:` '${C}'${ourRowLocation}`}); + addNotice6to9({priority:822, message:"Unable to check chapter number", rowID, location:` '${C}'${ourRowLocation}`}); haveGoodChapterNumber = false; } } else - addNotice6to9({priority:821, message:"Bad chapter number", location:` '${C}' with${ourRowLocation}`}); + addNotice6to9({priority:821, message:"Bad chapter number", rowID, location:` '${C}' with${ourRowLocation}`}); } else - addNotice6to9({priority:820, message:"Missing chapter number", location:` ?:${V}${ourRowLocation}`}); + addNotice6to9({priority:820, message:"Missing chapter number", rowID, location:` ?:${V}${ourRowLocation}`}); if (V.length) { if (V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0) - addNotice6to9({priority:814, message:`Invalid zero '${V}' verse number`, location:ourRowLocation}); + addNotice6to9({priority:814, message:`Invalid zero '${V}' verse number`, rowID, location:ourRowLocation}); else { if (haveGoodChapterNumber) { if (intV > numVersesThisChapter) - addNotice6to9({priority:813, message:`Invalid large '${V}' verse number`, location:` for chapter ${C}${ourRowLocation}`}); + addNotice6to9({priority:813, message:`Invalid large '${V}' verse number`, rowID, location:` for chapter ${C}${ourRowLocation}`}); } else - addNotice6to9({priority:812, message:"Unable to check verse number", location:` '${V}'${ourRowLocation}`}); + addNotice6to9({priority:812, message:"Unable to check verse number", rowID, location:` '${V}'${ourRowLocation}`}); } } else - addNotice6to9({priority:811, message:"Bad verse number", location:` '${V}'${ourRowLocation}`}); + addNotice6to9({priority:811, message:"Bad verse number", rowID, location:` '${V}'${ourRowLocation}`}); } else - addNotice6to9({priority:810, message:"Missing verse number", location:` after ${C}:?${ourRowLocation}`}); + addNotice6to9({priority:810, message:"Missing verse number", rowID, location:` after ${C}:?${ourRowLocation}`}); - if (!fieldID.length) + if (!rowID.length) addNotice6to9({priority:779, message:"Missing ID field", location:ourRowLocation}); else { - if (fieldID.length !== 4) - addNotice6to9({priority:778, message:"ID should be exactly 4 characters", location:` (not ${fieldID.length})${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[0]) < 0) - addNotice6to9({priority:176, message:"ID should start with a lowercase letter or digit", characterIndex:0, location:` (not '${fieldID[0]}')${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[3]) < 0) - addNotice6to9({priority:175, message:"ID should end with a lowercase letter or digit", characterIndex:3, location:` (not '${fieldID[3]}')${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[1]) < 0) - addNotice6to9({priority:174, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, location:` (not '${fieldID[1]}')${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[2]) < 0) - addNotice6to9({priority:173, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, location:` (not '${fieldID[2]}')${ourRowLocation}`}); + if (rowID.length !== 4) + addNotice6to9({priority:778, message:"ID should be exactly 4 characters", rowID, location:` (not ${rowID.length})${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[0]) < 0) + addNotice6to9({priority:176, message:"ID should start with a lowercase letter or digit", characterIndex:0, rowID, location:` (not '${rowID[0]}')${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[3]) < 0) + addNotice6to9({priority:175, message:"ID should end with a lowercase letter or digit", characterIndex:3, rowID, location:` (not '${rowID[3]}')${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[1]) < 0) + addNotice6to9({priority:174, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, rowID, location:` (not '${rowID[1]}')${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[2]) < 0) + addNotice6to9({priority:173, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, rowID, location:` (not '${rowID[2]}')${ourRowLocation}`}); } if (tags.length) ; if (supportReference.length) { // need to check UTN against UTA - ourCheckTextField('SupportReference', supportReference, true, ourRowLocation, optionalCheckingOptions); - await ourCheckTAReference('SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); + ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, optionalCheckingOptions); + await ourCheckTAReference(rowID, 'SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); } // else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? // addNotice6to9({priority:277, message:"Missing SupportReference field", location:ourRowLocation}); if (quote.length) { // need to check UTN against UHB and UGNT - ourCheckTextField('Quote', quote, false, ourRowLocation, optionalCheckingOptions); - await ourCheckTNOriginalLanguageQuote('Quote', quote, ourRowLocation, optionalCheckingOptions); + ourCheckTextField(rowID, 'Quote', quote, false, ourRowLocation, optionalCheckingOptions); + await ourCheckTNOriginalLanguageQuote(rowID, 'Quote', quote, ourRowLocation, optionalCheckingOptions); } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (V !== 'intro') - addNotice6to9({priority:276, message:"Missing Quote field", location:ourRowLocation}); + addNotice6to9({priority:276, message:"Missing Quote field", rowID, location:ourRowLocation}); if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn't occur if (quote.length) - addNotice6to9({priority:550, message:"Invalid zero occurrence field when we have an original quote", location:ourRowLocation}); + addNotice6to9({priority:550, message:"Invalid zero occurrence field when we have an original quote", rowID, location:ourRowLocation}); // if (V !== 'intro') - // addNotice6to9({priority:500, message:"Invalid zero occurrence field", location:rowLocation); + // addNotice6to9({priority:500, message:"Invalid zero occurrence field", rowID, location:rowLocation); } else if (occurrence === '-1') // TODO check the special conditions when this can occur??? ; else if ('12345'.indexOf(occurrence) < 0) // it's not one of these integers - addNotice6to9({priority:792, message:`Invalid '${occurrence}' occurrence field`, location:ourRowLocation}); + addNotice6to9({priority:792, message:`Invalid '${occurrence}' occurrence field`, rowID, location:ourRowLocation}); } if (annotation.length) { - ourMarkdownTextChecks('Annotation', annotation, true, ourRowLocation, optionalCheckingOptions); - await ourCheckTNLinks('Annotation', annotation, ourRowLocation, optionalCheckingOptions); + ourMarkdownTextChecks(rowID, 'Annotation', annotation, true, ourRowLocation, optionalCheckingOptions); + await ourCheckTNLinks(rowID, 'Annotation', annotation, ourRowLocation, optionalCheckingOptions); } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - addNotice6to9({priority:274, message:`Missing ${annotationType} Annotation field`, location:ourRowLocation}); + addNotice6to9({priority:274, message:`Missing ${annotationType} Annotation field`, rowID, location:ourRowLocation}); } else addNotice6to9({priority:861, message:`Found wrong number of TSV fields (expected ${NUM_EXPECTED_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, location:ourRowLocation}); diff --git a/src/core/annotation-table-check.js b/src/core/annotation-table-check.js index ac5293f6..e64644c4 100644 --- a/src/core/annotation-table-check.js +++ b/src/core/annotation-table-check.js @@ -80,7 +80,7 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // console.log(` '${location}' has ${lines.length.toLocaleString()} total lines (expecting ${NUM_EXPECTED_TN_FIELDS} fields in each line)`); let lastC = '', lastV = ''; - let fieldID_list = []; + let rowID_list = []; let numVersesThisChapter = 0; for (let n= 0; n < lines.length; n++) { // console.log(`CheckAnnotationRows checking line ${n}: ${JSON.stringify(lines[n])}`); @@ -95,11 +95,11 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat let fields = lines[n].split('\t'); if (fields.length === NUM_EXPECTED_TN_FIELDS) { // eslint-disable-next-line no-unused-vars - const [reference, fieldID, tags, _support_reference, _quote, _occurrence, _annotation] = fields; + const [reference, rowID, tags, _support_reference, _quote, _occurrence, _annotation] = fields; const [C, V] = reference.split(':') - const withString = ` with ID '${fieldID}'${ourLocation}`; + const withString = ` with ID '${rowID}'${ourLocation}`; // let CV_withString = ` ${C}:${V}${withString}`; - // let atString = ` at ${Annotation} ${C}:${V} (${fieldID})${inString}`; + // let atString = ` at ${Annotation} ${C}:${V} (${rowID})${inString}`; // Use the row check to do most basic checks const firstResult = await checkAnnotationTSVDataRow(annotationType, lines[n], bookID,C,V, withString, optionalCheckingOptions); @@ -159,15 +159,15 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat else addNoticeCV8({priority:790, C,V, message:"Missing verse number", lineNumber:n+1, location:` after ${C}:${lastV}${withString}`}); - if (fieldID) { - if (fieldID_list.indexOf(fieldID) >= 0) - addNoticeCV8({priority:729, C,V, message:`Duplicate '${fieldID}' ID`, lineNumber:n+1, location:withString}); + if (rowID) { + if (rowID_list.indexOf(rowID) >= 0) + addNoticeCV8({priority:729, C,V, message:`Duplicate '${rowID}' ID`, lineNumber:n+1, location:withString}); } else addNoticeCV8({priority:730, C,V, message:"Missing ID", lineNumber:n+1, location:withString}); if (C !== lastC || V !== lastV) { - fieldID_list = []; // ID's only need to be unique within each verse + rowID_list = []; // ID's only need to be unique within each verse lastC = C; lastV = V; } diff --git a/src/core/tn-table-row-check.js b/src/core/tn-table-row-check.js index c4e2e12d..8f695886 100644 --- a/src/core/tn-table-row-check.js +++ b/src/core/tn-table-row-check.js @@ -51,20 +51,24 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional let drResult = { noticeList: [] }; - function addNotice6to9({priority, message, lineNumber, characterIndex, extract, location}) { + function addNotice6to9({priority, message, rowID, lineNumber, characterIndex, extract, location}) { /** * @description - adds a new notice entry, adding bookID,C,V to the given fields * @param {Number} priority - notice priority from 1 (lowest) to 999 (highest) * @param {String} message - the text of the notice message - * @param {Number} characterIndex - where the issue occurs in the line + * @param {String} rowID - 4-character row ID field + * @param {Number} lineNumber - one-based line number + * @param {Number} characterIndex - zero-based index of where the issue occurs in the line * @param {String} extract - short extract from the line centred on the problem (if available) * @param {String} location - description of where the issue is located */ - // console.log(`TSV Row addNotice6to9: (priority=${priority}) ${message}, ${characterIndex}, ${extract}, ${location}`); + // console.log(`Annotation TSV Row Notice: (priority=${priority}) ${message}, ${characterIndex}, ${extract}, ${location}`); console.assert(priority !== undefined, "cTSVrow addNotice6to9: 'priority' parameter should be defined"); console.assert(typeof priority === 'number', `cTSVrow addNotice6to9: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); console.assert(message !== undefined, "cTSVrow addNotice6to9: 'message' parameter should be defined"); console.assert(typeof message === 'string', `cTSVrow addNotice6to9: 'message' parameter should be a string not a '${typeof message}': ${message}`); + // console.assert(lineNumber !== undefined, "cTSVrow addNotice6to9: 'lineNumber' parameter should be defined"); + // console.assert(typeof lineNumber === 'number', `cTSVrow addNotice6to9: 'lineNumber' parameter should be a number not a '${typeof lineNumber}': ${lineNumber}`); // console.assert(characterIndex !== undefined, "cTSVrow addNotice6to9: 'characterIndex' parameter should be defined"); if (characterIndex) console.assert(typeof characterIndex === 'number', `cTSVrow addNotice6to9: 'characterIndex' parameter should be a number not a '${typeof characterIndex}': ${characterIndex}`); // console.assert(extract !== undefined, "cTSVrow addNotice6to9: 'extract' parameter should be defined"); @@ -72,12 +76,13 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional console.assert(location !== undefined, "cTSVrow addNotice6to9: 'location' parameter should be defined"); console.assert(typeof location === 'string', `cTSVrow addNotice6to9: 'location' parameter should be a string not a '${typeof location}': ${location}`); // Also uses the given bookID,C,V, parameters from the main function call - drResult.noticeList.push({priority, message, bookID, C, V, lineNumber, characterIndex, extract, location}); + drResult.noticeList.push({ priority, message, bookID, C, V, rowID, lineNumber, characterIndex, extract, location }); } - function ourMarkdownTextChecks(fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { + function ourMarkdownTextChecks(rowID, fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { /** * @description - checks the given markdown field and processes the returned results + * @param {String} rowID - 4-character row ID field * @param {String} fieldName - name of the field being checked * @param {String} fieldText - the actual text of the field being checked * @param {} allowedLinks - true if links are allowed in the field, otherwise false @@ -92,7 +97,9 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // We don't currently use the allowedLinks parameter - // console.log(`cTSVrow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${fieldLocation}, …)`); + // console.log(`cTSVrow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cTSVrow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cTSVrow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cTSVrow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cTSVrow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "cTSVrow ourMarkdownTextChecks: 'fieldText' parameter should be defined"); @@ -108,14 +115,15 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of cmtResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourMarkdownTextChecks function - function ourCheckTextField(fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { + function ourCheckTextField(rowID, fieldName, fieldText, allowedLinks, rowLocation, optionalCheckingOptions) { /** * @description - checks the given text field and processes the returned results + * @param {String} rowID - 4-character row ID field * @param {String} fieldName - name of the field being checked * @param {String} fieldText - the actual text of the field being checked * @param {boolean} allowedLinks - true if links are allowed in the field, otherwise false @@ -129,6 +137,8 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // Updates the global list of notices // console.log(`cTSVrow ourCheckTextField(${fieldName}, (${fieldText.length}), ${allowedLinks}, ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cTSVrow ourCheckTextField: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cTSVrow ourCheckTextField: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cTSVrow ourCheckTextField: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cTSVrow ourCheckTextField: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "cTSVrow ourCheckTextField: 'fieldText' parameter should be defined"); @@ -144,19 +154,21 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of dbtcResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTextField function - async function ourCheckTAReference(fieldName, taLinkText, rowLocation, optionalCheckingOptions) { + async function ourCheckTAReference(rowID, fieldName, taLinkText, rowLocation, optionalCheckingOptions) { // Checks that the TA reference can be found // Updates the global list of notices // console.log(`cTSVrow ourCheckTAReference(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); - console.assert(fieldName !== undefined, "cTSVrow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); - console.assert(typeof fieldName === 'string', `cTSVrow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); + console.assert(rowID !== undefined, "cTSVrow ourCheckTAReference: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cTSVrow ourCheckTAReference: 'rowID' parameter should be a string not a '${typeof rowID}'`); + console.assert(fieldName !== undefined, "cTSVrow ourCheckTAReference: 'fieldName' parameter should be defined"); + console.assert(typeof fieldName === 'string', `cTSVrow ourCheckTAReference: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(taLinkText !== undefined, "cTSVrow ourCheckTAReference: 'taLinkText' parameter should be defined"); console.assert(typeof taLinkText === 'string', `cTSVrow ourCheckTAReference: 'taLinkText' parameter should be a string not a '${typeof taLinkText}'`); @@ -169,12 +181,12 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTAReference notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTAReference function - async function ourCheckTNOriginalLanguageQuote(fieldName, fieldText, rowLocation, optionalCheckingOptions) { + async function ourCheckTNOriginalLanguageQuote(rowID, fieldName, fieldText, rowLocation, optionalCheckingOptions) { // Checks that the Hebrew/Greek quote can be found in the original texts // Uses the bookID,C,V values from the main function call @@ -182,6 +194,8 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // Updates the global list of notices // console.log(`cTSVrow ourCheckTNOriginalLanguageQuote(${fieldName}, (${fieldText.length}) '${fieldText}', ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cTSVrow ourMarkdownTextChecks: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cTSVrow ourMarkdownTextChecks: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cTSVrow ourMarkdownTextChecks: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cTSVrow ourMarkdownTextChecks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "cTSVrow ourCheckTNOriginalLanguageQuote: 'fieldText' parameter should be defined"); @@ -196,17 +210,19 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTNOriginalLanguageQuote function - async function ourCheckTNLinks(fieldName, taLinkText, rowLocation, optionalCheckingOptions) { + async function ourCheckTNLinks(rowID, fieldName, taLinkText, rowLocation, optionalCheckingOptions) { // Checks that the TA reference can be found // Updates the global list of notices // console.log(`cTSVrow ourCheckTNLinks(${fieldName}, (${taLinkText.length}) '${taLinkText}', ${rowLocation}, …)`); + console.assert(rowID !== undefined, "cTSVrow ourCheckTNLinks: 'rowID' parameter should be defined"); + console.assert(typeof rowID === 'string', `cTSVrow ourCheckTNLinks: 'rowID' parameter should be a string not a '${typeof rowID}'`); console.assert(fieldName !== undefined, "cTSVrow ourCheckTNLinks: 'fieldName' parameter should be defined"); console.assert(typeof fieldName === 'string', `cTSVrow ourCheckTNLinks: 'fieldName' parameter should be a string not a '${typeof fieldName}'`); console.assert(taLinkText !== undefined, "cTSVrow ourCheckTNLinks: 'taLinkText' parameter should be defined"); @@ -221,7 +237,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNLinks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({priority:noticeEntry.priority, message:noticeEntry.message, characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, location:noticeEntry.location}); + addNotice6to9({ ...noticeEntry, rowID }); } } // end of ourCheckTNLinks function @@ -256,18 +272,18 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional let fields = line.split('\t'); if (fields.length === NUM_EXPECTED_TSV_FIELDS) { - const [B, C, V, fieldID, supportReference, origQuote, occurrence, GLQuote, occurrenceNote] = fields; - // let withString = ` with '${fieldID}'${inString}`; + const [B, C, V, rowID, supportReference, origQuote, occurrence, GLQuote, occurrenceNote] = fields; + // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; - // let atString = ` at ${B} ${C}:${V} (${fieldID})${inString}`; + // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; // Check the fields one-by-one if (B.length) { if (B !== bookID) - addNotice6to9({priority:978, message:`Wrong '${B}' book identifier`, location:` (expected '${bookID}')${ourRowLocation}`}); + addNotice6to9({priority:978, message:`Wrong '${B}' book identifier`, rowID, location:` (expected '${bookID}')${ourRowLocation}`}); } else - addNotice6to9({priority:977, message:"Missing book identifier", characterIndex:0, location:ourRowLocation}); + addNotice6to9({priority:977, message:"Missing book identifier", characterIndex:0, rowID, location:ourRowLocation}); let numVersesThisChapter, haveGoodChapterNumber; if (C.length) { @@ -275,12 +291,12 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional else if (/^\d+$/.test(C)) { let intC = Number(C); if (intC === 0) { - addNotice6to9({priority:824, message:`Invalid zero chapter number`, extract:C, location:ourRowLocation}); + addNotice6to9({priority:824, message:`Invalid zero chapter number`, extract:C, rowID, location:ourRowLocation}); haveGoodChapterNumber = false; } // TODO: Does this next section need rewriting (see verse check below)??? else if (intC > numChaptersThisBook) { - addNotice6to9({priority:823, message:`Invalid large chapter number`, extract:C, location:ourRowLocation}); + addNotice6to9({priority:823, message:`Invalid large chapter number`, extract:C, rowID, location:ourRowLocation}); haveGoodChapterNumber = false; } try { @@ -290,93 +306,93 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional if (!haveGoodBookID) // addNotice6to9({priority:500, "Invalid chapter number", rowLocation); // else - addNotice6to9({priority:822, message:"Unable to check chapter number", location:` '${C}'${ourRowLocation}`}); + addNotice6to9({priority:822, message:"Unable to check chapter number", rowID, location:` '${C}'${ourRowLocation}`}); haveGoodChapterNumber = false; } } else - addNotice6to9({priority:821, message:"Bad chapter number", location:` '${C}' with${ourRowLocation}`}); + addNotice6to9({priority:821, message:"Bad chapter number", rowID, location:` '${C}' with${ourRowLocation}`}); } else - addNotice6to9({priority:820, message:"Missing chapter number", location:` ?:${V}${ourRowLocation}`}); + addNotice6to9({priority:820, message:"Missing chapter number", rowID, location:` ?:${V}${ourRowLocation}`}); if (V.length) { if (V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0) - addNotice6to9({priority:814, message:`Invalid zero '${V}' verse number`, location:ourRowLocation}); + addNotice6to9({priority:814, message:`Invalid zero '${V}' verse number`, rowID, location:ourRowLocation}); else { if (haveGoodChapterNumber) { if (intV > numVersesThisChapter) - addNotice6to9({priority:813, message:`Invalid large '${V}' verse number`, location:` for chapter ${C}${ourRowLocation}`}); + addNotice6to9({priority:813, message:`Invalid large '${V}' verse number`, rowID, location:` for chapter ${C}${ourRowLocation}`}); } else - addNotice6to9({priority:812, message:"Unable to check verse number", location:` '${V}'${ourRowLocation}`}); + addNotice6to9({priority:812, message:"Unable to check verse number", rowID, location:` '${V}'${ourRowLocation}`}); } } else - addNotice6to9({priority:811, message:"Bad verse number", location:` '${V}'${ourRowLocation}`}); + addNotice6to9({priority:811, message:"Bad verse number", rowID, location:` '${V}'${ourRowLocation}`}); } else - addNotice6to9({priority:810, message:"Missing verse number", location:` after ${C}:?${ourRowLocation}`}); + addNotice6to9({priority:810, message:"Missing verse number", rowID, location:` after ${C}:?${ourRowLocation}`}); - if (!fieldID.length) + if (!rowID.length) addNotice6to9({priority:779, message:"Missing ID field", location:ourRowLocation}); else { - if (fieldID.length !== 4) - addNotice6to9({priority:778, message:"ID should be exactly 4 characters", location:` (not ${fieldID.length})${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[0]) < 0) - addNotice6to9({priority:176, message:"ID should start with a lowercase letter or digit", characterIndex:0, location:` (not '${fieldID[0]}')${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[3]) < 0) - addNotice6to9({priority:175, message:"ID should end with a lowercase letter or digit", characterIndeX:3, location:` (not '${fieldID[3]}')${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[1]) < 0) - addNotice6to9({priority:174, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, location:` (not '${fieldID[1]}')${ourRowLocation}`}); - else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(fieldID[2]) < 0) - addNotice6to9({priority:173, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, location:` (not '${fieldID[2]}')${ourRowLocation}`}); + if (rowID.length !== 4) + addNotice6to9({priority:778, message:"ID should be exactly 4 characters", rowID, location:` (not ${rowID.length})${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[0]) < 0) + addNotice6to9({priority:176, message:"ID should start with a lowercase letter or digit", characterIndex:0, rowID, location:` (not '${rowID[0]}')${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[3]) < 0) + addNotice6to9({priority:175, message:"ID should end with a lowercase letter or digit", characterIndeX:3, rowID, location:` (not '${rowID[3]}')${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[1]) < 0) + addNotice6to9({priority:174, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:1, rowID, location:` (not '${rowID[1]}')${ourRowLocation}`}); + else if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(rowID[2]) < 0) + addNotice6to9({priority:173, message:"ID characters should only be lowercase letters, digits, or hypen", characterIndex:2, rowID, location:` (not '${rowID[2]}')${ourRowLocation}`}); } if (supportReference.length) { // need to check UTN against UTA - ourCheckTextField('SupportReference', supportReference, true, ourRowLocation, optionalCheckingOptions); - await ourCheckTAReference('SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); + ourCheckTextField(rowID, 'SupportReference', supportReference, true, ourRowLocation, optionalCheckingOptions); + await ourCheckTAReference(rowID, 'SupportReference', supportReference, ourRowLocation, optionalCheckingOptions); } // else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? // addNotice6to9({priority:277, message:"Missing SupportReference field", location:ourRowLocation}); if (origQuote.length) { // need to check UTN against UHB and UGNT - ourCheckTextField('OrigQuote', origQuote, false, ourRowLocation, optionalCheckingOptions); - await ourCheckTNOriginalLanguageQuote('OrigQuote', origQuote, ourRowLocation, optionalCheckingOptions); + ourCheckTextField(rowID, 'OrigQuote', origQuote, false, ourRowLocation, optionalCheckingOptions); + await ourCheckTNOriginalLanguageQuote(rowID, 'OrigQuote', origQuote, ourRowLocation, optionalCheckingOptions); } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (V !== 'intro') - addNotice6to9({priority:276, message:"Missing OrigQuote field", location:ourRowLocation}); + addNotice6to9({priority:276, message:"Missing OrigQuote field", rowID, location:ourRowLocation}); if (occurrence.length) { // This should usually be a digit if (occurrence === '0') { // zero means that it doesn't occur if (origQuote.length) - addNotice6to9({priority:550, message:"Invalid zero occurrence field when we have an original quote", location:ourRowLocation}); + addNotice6to9({priority:550, message:"Invalid zero occurrence field when we have an original quote", rowID, location:ourRowLocation}); // if (V !== 'intro') - // addNotice6to9({priority:500, message:"Invalid zero occurrence field", location:rowLocation); + // addNotice6to9({priority:500, message:"Invalid zero occurrence field", rowID, location:rowLocation); } else if (occurrence === '-1') // TODO check the special conditions when this can occur??? ; else if ('12345'.indexOf(occurrence) < 0) // it's not one of these integers - addNotice6to9({priority:792, message:`Invalid '${occurrence}' occurrence field`, location:ourRowLocation}); + addNotice6to9({priority:792, message:`Invalid '${occurrence}' occurrence field`, rowID, location:ourRowLocation}); } if (GLQuote.length) { // TODO: need to check UTN against ULT if (V !== 'intro') - ourCheckTextField('GLQuote', GLQuote, false, ourRowLocation, optionalCheckingOptions); + ourCheckTextField(rowID, 'GLQuote', GLQuote, false, ourRowLocation, optionalCheckingOptions); } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? if (V !== 'intro') - addNotice6to9({priority:275, message:"Missing GLQuote field", location:ourRowLocation}); + addNotice6to9({priority:275, message:"Missing GLQuote field", rowID, location:ourRowLocation}); if (occurrenceNote.length) { - ourMarkdownTextChecks('OccurrenceNote', occurrenceNote, true, ourRowLocation, optionalCheckingOptions); - await ourCheckTNLinks('OccurrenceNote', occurrenceNote, ourRowLocation, optionalCheckingOptions); + ourMarkdownTextChecks(rowID, 'OccurrenceNote', occurrenceNote, true, ourRowLocation, optionalCheckingOptions); + await ourCheckTNLinks(rowID, 'OccurrenceNote', occurrenceNote, ourRowLocation, optionalCheckingOptions); } else // TODO: Find out if these fields are really compulsory (and when they're not, e.g., for 'intro') ??? - addNotice6to9({priority:274, message:"Missing OccurrenceNote field", location:ourRowLocation}); + addNotice6to9({priority:274, message:"Missing OccurrenceNote field", rowID, location:ourRowLocation}); } else addNotice6to9({priority:861, message:`Found wrong number of TSV fields (expected ${NUM_EXPECTED_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, location:ourRowLocation}); diff --git a/src/core/tn-table-text-check.js b/src/core/tn-table-text-check.js index d3ae1b34..a1ebe22e 100644 --- a/src/core/tn-table-text-check.js +++ b/src/core/tn-table-text-check.js @@ -78,7 +78,7 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin // console.log(` '${location}' has ${lines.length.toLocaleString()} total lines (expecting ${NUM_EXPECTED_TN_FIELDS} fields in each line)`); let lastB = '', lastC = '', lastV = ''; - let fieldID_list = []; + let rowID_list = []; let numVersesThisChapter = 0; for (let n= 0; n < lines.length; n++) { // console.log(`checkTN_TSVText checking line ${n}: ${JSON.stringify(lines[n])}`); @@ -93,10 +93,10 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin let fields = lines[n].split('\t'); if (fields.length === NUM_EXPECTED_TN_FIELDS) { // eslint-disable-next-line no-unused-vars - const [B, C, V, fieldID, _support_reference, _orig_quote, _occurrence, _GL_quote, _occurrenceNote] = fields; - const withString = ` with ID '${fieldID}'${ourLocation}`; + const [B, C, V, rowID, _support_reference, _orig_quote, _occurrence, _GL_quote, _occurrenceNote] = fields; + const withString = ` with ID '${rowID}'${ourLocation}`; // let CV_withString = ` ${C}:${V}${withString}`; - // let atString = ` at ${B} ${C}:${V} (${fieldID})${inString}`; + // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; // Use the row check to do most basic checks const firstResult = await checkTN_TSVDataRow(lines[n], bookID,C,V, withString, optionalCheckingOptions); @@ -163,15 +163,15 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin else addNoticeCV8({priority:790, C,V, message:"Missing verse number", lineNumber:n+1, location:` after ${C}:${lastV}${withString}`}); - if (fieldID) { - if (fieldID_list.indexOf(fieldID) >= 0) - addNoticeCV8({priority:729, C,V, message:`Duplicate '${fieldID}' ID`, lineNumber:n+1, location:withString}); + if (rowID) { + if (rowID_list.indexOf(rowID) >= 0) + addNoticeCV8({priority:729, C,V, message:`Duplicate '${rowID}' ID`, lineNumber:n+1, location:withString}); } else addNoticeCV8({priority:730, C,V, message:"Missing ID", lineNumber:n+1, location:withString}); if (B !== lastB || C !== lastC || V !== lastV) { - fieldID_list = []; // ID's only need to be unique within each verse + rowID_list = []; // ID's only need to be unique within each verse lastB = B; lastC = C; lastV = V; } diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index d4ec245f..717405ba 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -7,6 +7,9 @@ import MaterialTable from 'material-table'; // import { consoleLogObject, displayPropertyNames } from '../core/utilities'; +// Note from RJH: I commented out these fields because 1/ they seemed to cause warnings/errors, +// 2/ I didn't understand what they do anyway. +// so feel free to uncomment it if it makes the table work better. /* const tableIcons = { Add: forwardRef((props, ref) => ), @@ -139,9 +142,11 @@ export function RenderRawResults({ results }) { { title: VName, field: 'V' } ]); } - if (allPropertiesSet.has('lineNumber')) headerData = headerData.concat([{ title: 'Line', field: 'lineNumber' }]); - if (allPropertiesSet.has('filename')) headerData = headerData.concat([{ title: 'Filename', field: 'filename' }]); + if (allPropertiesSet.has('rowID')) headerData = headerData.concat([{ title: 'ID', field: 'rowID' }]); if (allPropertiesSet.has('repoName')) headerData = headerData.concat([{ title: 'Repo', field: 'repoName' }]); + if (allPropertiesSet.has('filename')) headerData = headerData.concat([{ title: 'Filename', field: 'filename' }]); + if (allPropertiesSet.has('fieldName')) headerData = headerData.concat([{ title: 'Field', field: 'fieldName' }]); + if (allPropertiesSet.has('lineNumber')) headerData = headerData.concat([{ title: 'Line', field: 'lineNumber' }]); if (allPropertiesSet.has('characterIndex')) headerData = headerData.concat([{ title: 'CharIndex', field: 'characterIndex' }]); if (allPropertiesSet.has('extract')) headerData = headerData.concat([{ title: 'Extract', field: 'extract' }]); if (allPropertiesSet.has('location')) headerData = headerData.concat([{ title: 'Location', field: 'location' }]); From 31226f4266cc561c121dc4c3b40c366de9e67ef7 Mon Sep 17 00:00:00 2001 From: Robert Hunt Date: Fri, 11 Sep 2020 11:58:22 +1200 Subject: [PATCH 2/5] Move notice processing from core to demos --- README.md | 2 +- src/core/field-link-check.md | 2 +- src/core/index.js | 1 - src/demos/book-package-check/BookPackageCheck.js | 2 +- src/demos/book-packages-check/BookPackagesCheck.js | 2 +- src/demos/file-check/FileCheck.js | 2 +- src/demos/index.js | 1 + src/{core => demos}/notice-processing-functions.js | 0 src/{core => demos}/notice-processing1.md | 2 +- src/{core => demos}/notice-processing2.md | 2 +- src/{core => demos}/notice-processing3.md | 2 +- src/demos/repo-check/RepoCheck.js | 2 +- styleguide.config.js | 8 ++++---- yarn.lock | 12 ++++++------ 14 files changed, 20 insertions(+), 20 deletions(-) rename src/{core => demos}/notice-processing-functions.js (100%) rename src/{core => demos}/notice-processing1.md (98%) rename src/{core => demos}/notice-processing2.md (98%) rename src/{core => demos}/notice-processing3.md (98%) diff --git a/README.md b/README.md index 110a1409..d2e74a4c 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ All of the following fields may be missing or undefined, i.e., they're all optio 1. `extract`: An extract (if available) of the checked text which indicates the area containing the problem. Where helpful, some character substitutions have already been made, for example, if the notice is about spaces, it is generally helpful to display spaces as a visible character in an attempt to best highlight the issue to the user. (The length of the extract defaults to ten characters, but is settable as an option.) 1. `location`: A string indicating the context of the notice, e.g., "in line 17 of 'someBook.usfm'". (Still not completely sure what should be left in this string now that we have added optional `filename`, `repoName`, `lineNumber` fields.) -Keeping our notices in this format, rather than the simplicity of just saving an array of single strings, allows the above *notice components* to be processed at a higher level, e.g., to allow user-controlled filtering, sorting, etc. The default is to funnel them all through the supplied `processNoticesToErrorsWarnings` function (in core/notice-processing-functions.fs) which does the following: +Keeping our notices in this format, rather than the simplicity of just saving an array of single strings, allows the above *notice components* to be processed at a higher level, e.g., to allow user-controlled filtering, sorting, etc. The default is to funnel them all through the supplied `processNoticesToErrorsWarnings` function (in demos/notice-processing-functions.fs) which does the following: 1. Removes excess repeated errors. For example, if there's a systematic error in a file, say with unneeded leading spaces in every field, rather than returning with hundreds of errors, only the first several errors will be returned, followed by an "errors suppressed" message. (The number of each error displayed is settable as an option -- zero means display all errors with no suppression.) 1. Separates notices into error and warning lists based on the priority number. (The switch-over point is settable as an option.) diff --git a/src/core/field-link-check.md b/src/core/field-link-check.md index bab0da8a..62e73c57 100644 --- a/src/core/field-link-check.md +++ b/src/core/field-link-check.md @@ -4,7 +4,7 @@ This function is for checking text fields that are links, or that contain links. ```js import checkFieldLinks from './field-link-check'; -import { processNoticesToErrorsWarnings } from './notice-processing-functions'; +import { processNoticesToErrorsWarnings } from '../demos/notice-processing-functions'; import { RenderLines, RenderRawResults, RenderSuccessesErrorsWarnings } from '../demos/RenderProcessedResults'; // Empty, space, link, RC, good, and bad text samples diff --git a/src/core/index.js b/src/core/index.js index dd007b0b..abd0dcaa 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -10,5 +10,4 @@ export * from './tn-table-text-check'; export * from './annotation-row-check'; export * from './annotation-table-check'; export * from './usfm-text-check'; -export * from './notice-processing-functions'; export * from './book-package-check'; diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 1ea478b9..6c312b3a 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; // import { withStyles } from '@material-ui/core/styles'; import * as books from '../../core/books/books'; import { checkBookPackage } from '../../core'; -import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../../core/notice-processing-functions'; +import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index ef2d8414..f04f2f02 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; // import { withStyles } from '@material-ui/core/styles'; import * as books from '../../core/books/books'; import checkBookPackages from './checkBookPackages'; -import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../../core/notice-processing-functions'; +import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 6b517dc0..9ed484a7 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -6,7 +6,7 @@ import React, { useEffect, useState } from 'react'; import { withStyles } from '@material-ui/core/styles'; // import { getFile } from '../../core/getApi'; import { getFile, checkFile } from '../../core'; -import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../../core/notice-processing-functions'; +import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; diff --git a/src/demos/index.js b/src/demos/index.js index d74b260a..5b4bf877 100644 --- a/src/demos/index.js +++ b/src/demos/index.js @@ -2,4 +2,5 @@ export * from './file-check'; export * from './book-package-check'; export * from './book-packages-check'; export * from './repo-check'; +export * from './notice-processing-functions'; export * from './RenderProcessedResults'; \ No newline at end of file diff --git a/src/core/notice-processing-functions.js b/src/demos/notice-processing-functions.js similarity index 100% rename from src/core/notice-processing-functions.js rename to src/demos/notice-processing-functions.js diff --git a/src/core/notice-processing1.md b/src/demos/notice-processing1.md similarity index 98% rename from src/core/notice-processing1.md rename to src/demos/notice-processing1.md index bc56e9db..a62211f0 100644 --- a/src/core/notice-processing1.md +++ b/src/demos/notice-processing1.md @@ -20,7 +20,7 @@ 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 -import checkTextField from './field-text-check'; +import checkTextField from '../core/field-text-check'; import { processNoticesToErrorsWarnings } from './notice-processing-functions'; import { RenderRawResults, RenderObject, RenderSuccessesErrorsWarnings } from '../demos/RenderProcessedResults'; diff --git a/src/core/notice-processing2.md b/src/demos/notice-processing2.md similarity index 98% rename from src/core/notice-processing2.md rename to src/demos/notice-processing2.md index 65bc3de2..0b30f813 100644 --- a/src/core/notice-processing2.md +++ b/src/demos/notice-processing2.md @@ -20,7 +20,7 @@ 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 -import checkTextField from './field-text-check'; +import checkTextField from '../core/field-text-check'; import { processNoticesToSevereMediumLow } from './notice-processing-functions'; import { RenderRawResults, RenderObject, RenderSuccessesSevereMediumLow } from '../demos/RenderProcessedResults'; diff --git a/src/core/notice-processing3.md b/src/demos/notice-processing3.md similarity index 98% rename from src/core/notice-processing3.md rename to src/demos/notice-processing3.md index bcef9f25..f7847876 100644 --- a/src/core/notice-processing3.md +++ b/src/demos/notice-processing3.md @@ -20,7 +20,7 @@ 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 -import checkTextField from './field-text-check'; +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/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index 008e81e5..c288e6f8 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { withStyles } from '@material-ui/core/styles'; import { checkRepo } from '../../core'; -import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../../core/notice-processing-functions'; +import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject, displayPropertyNames } from '../../core/utilities'; diff --git a/styleguide.config.js b/styleguide.config.js index e389ed43..05747922 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -70,24 +70,24 @@ let sections = [ } }, { - // The difficulty with displaying core functions this way + // The difficulty with displaying the various functions this way // is that they all appear and run on a SINGLE web-page. name: 'Sample Notice Processing Functions', content: 'src/core/README.md', sections: [ { name: 'Process notices -> Errors/Warnings', - content: 'src/core/notice-processing1.md', + content: 'src/demos/notice-processing1.md', // description: '' }, { name: 'Process notices -> Severe/Medium/Low', - content: 'src/core/notice-processing2.md', + content: 'src/demos/notice-processing2.md', // description: '' }, { name: 'Process notices -> colour gradient', - content: 'src/core/notice-processing3.md', + content: 'src/demos/notice-processing3.md', // description: '' } ] diff --git a/yarn.lock b/yarn.lock index 636c9ed1..693b3b06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1719,9 +1719,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.6.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a" - integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ== + version "14.10.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.0.tgz#15815dff82c8dc30827f6b1286f865902945095a" + integrity sha512-SOIyrdADB4cq6eY1F+9iU48iIomFAPltu11LCvA9PKcyEwHadjCFzNVPotAR+oEJA0bCP4Xvvgy+vwu1ZjVh8g== "@types/parse-json@^4.0.0": version "4.0.0" @@ -4761,9 +4761,9 @@ eslint-plugin-react-hooks@^1.6.1: integrity sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA== eslint-plugin-react-hooks@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.0.tgz#6323fbd5e650e84b2987ba76370523a60f4e7925" - integrity sha512-36zilUcDwDReiORXmcmTc6rRumu9JIM3WjSvV0nclHoUQ0CNrX866EwONvLR/UqaeqFutbAnVu8PEmctdo2SRQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.1.tgz#b37e1ff622b7800cd673901de32db1103d48411d" + integrity sha512-vFJNwsf4MLYS0lHYfz9LqxQ+GccYsGGeKPHDxgkIaKbAhNuTLnST+q44pt81MzJZyFU5K4XLF6WiCGv3Yb6tCg== eslint-plugin-react@7.19.0: version "7.19.0" From 2a57171ecfc44590121f98563736951c8e8b8df2 Mon Sep 17 00:00:00 2001 From: Robert Hunt Date: Fri, 11 Sep 2020 12:03:16 +1200 Subject: [PATCH 3/5] Add optional fieldName to notices --- src/core/annotation-row-check.js | 10 +++++----- src/core/tn-table-row-check.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/annotation-row-check.js b/src/core/annotation-row-check.js index 7dc501ec..452c0cfe 100644 --- a/src/core/annotation-row-check.js +++ b/src/core/annotation-row-check.js @@ -125,7 +125,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of cmtResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourMarkdownTextChecks function @@ -164,7 +164,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of dbtcResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTextField function @@ -192,7 +192,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTAReference notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTAReference function @@ -221,7 +221,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTNOriginalLanguageQuote function @@ -248,7 +248,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNLinks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTNLinks function diff --git a/src/core/tn-table-row-check.js b/src/core/tn-table-row-check.js index 8f695886..12199273 100644 --- a/src/core/tn-table-row-check.js +++ b/src/core/tn-table-row-check.js @@ -115,7 +115,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of cmtResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourMarkdownTextChecks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourMarkdownTextChecks function @@ -154,7 +154,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of dbtcResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTextField notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTextField function @@ -181,7 +181,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTAReference notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTAReference function @@ -210,7 +210,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNOriginalLanguageQuote notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTNOriginalLanguageQuote function @@ -237,7 +237,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional // process results line by line for (const noticeEntry of coqResultObject.noticeList) { // console.assert(Object.keys(noticeEntry).length === 5, `TL ourCheckTNLinks notice length=${Object.keys(noticeEntry).length}`); - addNotice6to9({ ...noticeEntry, rowID }); + addNotice6to9({ ...noticeEntry, rowID, fieldName }); } } // end of ourCheckTNLinks function From 1edf50e023f16d96bef65807905bd4c42dbb2709 Mon Sep 17 00:00:00 2001 From: Robert Hunt Date: Fri, 11 Sep 2020 13:41:23 +1200 Subject: [PATCH 4/5] Tidyup up check version strings, esp. duplicated one --- package.json | 2 +- src/core/BCS-usfm-grammar-check.js | 2 +- src/core/annotation-row-check.js | 8 ++- src/core/annotation-table-check.js | 58 +++++++++---------- src/core/field-link-check.js | 6 +- src/core/field-text-check.js | 2 +- src/core/file-text-check.js | 2 +- src/core/manifest-text-check.js | 6 +- src/core/markdown-text-check.js | 6 +- src/core/plain-text-check.js | 6 +- src/core/quote-check.js | 4 +- src/core/ta-reference-check.js | 4 +- src/core/tn-links-check.js | 4 +- src/core/tn-table-row-check.js | 8 +-- src/core/tn-table-text-check.js | 12 ++-- src/core/usfm-text-check.js | 3 +- src/core/yaml-text-check.js | 6 +- .../book-package-check/BookPackageCheck.js | 4 +- .../book-package-check/checkBookPackage.js | 4 +- .../book-packages-check/BookPackagesCheck.js | 4 +- .../book-packages-check/checkBookPackages.js | 4 +- src/demos/file-check/FileCheck.js | 3 +- src/demos/notice-processing-functions.js | 2 +- src/demos/repo-check/RepoCheck.js | 4 +- 24 files changed, 82 insertions(+), 82 deletions(-) diff --git a/package.json b/package.json index 2c58182f..3a537a6a 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.8.8", + "version": "0.8.9_alpha1", "private": false, "homepage": "https://unfoldingword.github.io/uw-content-validation/", "repository": { diff --git a/src/core/BCS-usfm-grammar-check.js b/src/core/BCS-usfm-grammar-check.js index ec7ba31e..aedf2628 100644 --- a/src/core/BCS-usfm-grammar-check.js +++ b/src/core/BCS-usfm-grammar-check.js @@ -2,7 +2,7 @@ import grammar from 'usfm-grammar'; import * as books from '../core/books/books'; -export const USFM_GRAMMAR_VALIDATOR_VERSION = '0.3.1'; +// const USFM_GRAMMAR_VALIDATOR_VERSION_STRING = '0.3.1'; const DEFAULT_EXTRACT_LENGTH = 10; diff --git a/src/core/annotation-row-check.js b/src/core/annotation-row-check.js index 452c0cfe..b4f1fcbc 100644 --- a/src/core/annotation-row-check.js +++ b/src/core/annotation-row-check.js @@ -6,7 +6,9 @@ import checkTNLinks from './tn-links-check'; import checkOriginalLanguageQuote from './quote-check'; -const NUM_EXPECTED_TSV_FIELDS = 7; // so expects 6 tabs per line +// const ANNOTATION_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.4.1'; + +const NUM_EXPECTED_ANNOTATION_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -286,7 +288,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv const haveBibleBookID = numChaptersThisBook !== undefined; let fields = line.split('\t'); - if (fields.length === NUM_EXPECTED_TSV_FIELDS) { + if (fields.length === NUM_EXPECTED_ANNOTATION_TSV_FIELDS) { const [reference, rowID, tags, supportReference, quote, occurrence, annotation] = fields; // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; @@ -399,7 +401,7 @@ async function checkAnnotationTSVDataRow(annotationType, line, bookID, C, V, giv addNotice6to9({priority:274, message:`Missing ${annotationType} Annotation field`, rowID, location:ourRowLocation}); } else - addNotice6to9({priority:861, message:`Found wrong number of TSV fields (expected ${NUM_EXPECTED_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, location:ourRowLocation}); + addNotice6to9({priority:861, message:`Found wrong number of TSV fields (expected ${NUM_EXPECTED_ANNOTATION_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, location:ourRowLocation}); // console.log(` checkAnnotationTSVDataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkAnnotationTSVDataRow result is", JSON.stringify(drResult)); diff --git a/src/core/annotation-table-check.js b/src/core/annotation-table-check.js index e64644c4..684dd839 100644 --- a/src/core/annotation-table-check.js +++ b/src/core/annotation-table-check.js @@ -2,9 +2,9 @@ import * as books from './books/books'; import checkAnnotationTSVDataRow from './annotation-row-check'; -const TABLE_TEXT_VALIDATOR_VERSION = '0.2.1'; +const ANNOTATION_TABLE_VALIDATOR_VERSION_STRING = '0.2.2'; -const NUM_EXPECTED_TN_FIELDS = 7; // so expects 6 tabs per line +const NUM_EXPECTED_ANNOTATION_TSV_FIELDS = 7; // so expects 6 tabs per line const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\tOccurrence\tAnnotation'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -30,7 +30,7 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // console.log(`CheckAnnotationRows success: ${successString}`); result.successList.push(successString); } - function addNoticeCV8({priority,message, C,V, lineNumber, characterIndex, extract, location}) { + function addNoticeCV8({ priority, message, C, V, lineNumber, characterIndex, extract, location }) { // console.log(`CheckAnnotationRows notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); console.assert(priority !== undefined, "ATSV addNoticeCV8: 'priority' parameter should be defined"); console.assert(typeof priority === 'number', `TSV addNoticeCV8: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); @@ -46,11 +46,11 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat if (extract) console.assert(typeof extract === 'string', `TSV addNoticeCV8: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); console.assert(location !== undefined, "ATSV addNoticeCV8: 'location' parameter should be defined"); console.assert(typeof location === 'string', `TSV addNoticeCV8: 'location' parameter should be a string not a '${typeof location}': ${location}`); - result.noticeList.push({priority,message, bookID,C,V, lineNumber, characterIndex, extract, location}); + result.noticeList.push({ priority, message, bookID, C, V, lineNumber, characterIndex, extract, location }); } - addNoticeCV8({priority:997, message:"CheckAnnotationRows() is still a placeholder -- not completed yet", location:ourLocation}); + addNoticeCV8({ priority: 997, message: "CheckAnnotationRows() is still a placeholder -- not completed yet", location: ourLocation }); let extractLength; try { @@ -61,7 +61,7 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // console.log(`Using default extractLength=${extractLength}`); } // else - // console.log(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); + // 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}`); @@ -73,7 +73,7 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticeCV8({priority:747, message:"Bad function call: should be given a valid book abbreviation", extract:bookID, location:` (not '${bookID}')${ourLocation}`}); + addNoticeCV8({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); } let lines = tableText.split('\n'); @@ -82,19 +82,19 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat let lastC = '', lastV = ''; let rowID_list = []; let numVersesThisChapter = 0; - for (let n= 0; n < lines.length; n++) { + for (let n = 0; n < lines.length; n++) { // console.log(`CheckAnnotationRows checking line ${n}: ${JSON.stringify(lines[n])}`); if (n === 0) { if (lines[0] === EXPECTED_TN_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); else - addNoticeCV8({priority:746, message:"Bad TSV header", lineNumber:n+1, location:`${ourLocation}: '${lines[0]}'`}); + addNoticeCV8({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); } else // not the header { let fields = lines[n].split('\t'); - if (fields.length === NUM_EXPECTED_TN_FIELDS) { - // eslint-disable-next-line no-unused-vars + if (fields.length === NUM_EXPECTED_ANNOTATION_TSV_FIELDS) { + // eslint-disable-next-line no-unused-vars const [reference, rowID, tags, _support_reference, _quote, _occurrence, _annotation] = fields; const [C, V] = reference.split(':') const withString = ` with ID '${rowID}'${ourLocation}`; @@ -102,14 +102,14 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // let atString = ` at ${Annotation} ${C}:${V} (${rowID})${inString}`; // Use the row check to do most basic checks - const firstResult = await checkAnnotationTSVDataRow(annotationType, lines[n], bookID,C,V, withString, optionalCheckingOptions); + const firstResult = await checkAnnotationTSVDataRow(annotationType, lines[n], bookID, C, V, withString, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); // If we need to put everything through addNoticeCV8, e.g., for debugging or filtering // process results line by line for (const noticeEntry of firstResult.noticeList) - addNoticeCV8({ ...noticeEntry, lineNumber:n+1}); + addNoticeCV8({ ...noticeEntry, lineNumber: n + 1 }); // So here we only have to check against the previous and next fields for out-of-order problems if (C) { @@ -119,51 +119,51 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat if (C !== lastC) numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticeCV8({priority:551, C,V, message:`Invalid zero '${C}' chapter number`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 551, C, V, message: `Invalid zero '${C}' chapter number`, lineNumber: n + 1, location: withString }); if (intC > numChaptersThisBook) - addNoticeCV8({priority:737, C,V, message:`Invalid large '${C}' chapter number`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 737, C, V, message: `Invalid large '${C}' chapter number`, lineNumber: n + 1, location: withString }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) - addNoticeCV8({priority:736, C,V, message:`Receding '${C}' chapter number after '${lastC}'`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 736, C, V, message: `Receding '${C}' chapter number after '${lastC}'`, lineNumber: n + 1, location: withString }); else if (intC > lastintC + 1) - addNoticeCV8({priority:735, C,V, message:`Advancing '${C}' chapter number after '${lastC}'`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 735, C, V, message: `Advancing '${C}' chapter number after '${lastC}'`, lineNumber: n + 1, location: withString }); } } else - addNoticeCV8({priority:734, C,V, message:"Bad chapter number", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 734, C, V, message: "Bad chapter number", lineNumber: n + 1, location: withString }); } else - addNoticeCV8({priority:739, C,V, message:"Missing chapter number", lineNumber:n+1, location:` after ${lastC}:${V}${withString}`}); + addNoticeCV8({ priority: 739, C, V, message: "Missing chapter number", lineNumber: n + 1, location: ` after ${lastC}:${V}${withString}` }); if (V) { if (V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0) - addNoticeCV8({priority:552, C,V, message:`Invalid zero '${V}' verse number`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 552, C, V, message: `Invalid zero '${V}' verse number`, lineNumber: n + 1, location: withString }); if (intV > numVersesThisChapter) - addNoticeCV8({priority:734, C,V, message:`Invalid large '${V}' verse number for chapter ${C}`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 734, C, V, message: `Invalid large '${V}' verse number for chapter ${C}`, lineNumber: n + 1, location: withString }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (intV < lastintV) - addNoticeCV8({priority:733, C,V, message:`Receding '${V}' verse number after '${lastV}'`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 733, C, V, message: `Receding '${V}' verse number after '${lastV}'`, lineNumber: n + 1, location: withString }); // else if (intV > lastintV + 1) // addNoticeCV8({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } } else - addNoticeCV8({priority:738, C,V, message:"Bad verse number", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 738, C, V, message: "Bad verse number", lineNumber: n + 1, location: withString }); } else - addNoticeCV8({priority:790, C,V, message:"Missing verse number", lineNumber:n+1, location:` after ${C}:${lastV}${withString}`}); + addNoticeCV8({ priority: 790, C, V, message: "Missing verse number", lineNumber: n + 1, location: ` after ${C}:${lastV}${withString}` }); if (rowID) { if (rowID_list.indexOf(rowID) >= 0) - addNoticeCV8({priority:729, C,V, message:`Duplicate '${rowID}' ID`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 729, C, V, message: `Duplicate '${rowID}' ID`, lineNumber: n + 1, location: withString }); } else - addNoticeCV8({priority:730, C,V, message:"Missing ID", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 730, C, V, message: "Missing ID", lineNumber: n + 1, location: withString }); if (C !== lastC || V !== lastV) { @@ -176,14 +176,14 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // console.log(` Line ${n}: Has ${fields.length} field(s) instead of ${NUM_EXPECTED_TN_FIELDS}: ${EXPECTED_TN_HEADING_LINE.replace(/\t/g, ', ')}`); // else if (n !== lines.length - 1) // it's not the last line - addNoticeCV8({priority:988, message:`Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_FIELDS})`, extract:`Found ${fields.length} field${fields.length===1?'':'s'}`, lineNumber:n+1, location:ourLocation}); + addNoticeCV8({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_ANNOTATION_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, lineNumber: n + 1, location: ourLocation }); } } addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); if (result.noticeList) - addSuccessMessage(`CheckAnnotationRows v${TABLE_TEXT_VALIDATOR_VERSION} finished with ${result.noticeList.length?result.noticeList.length.toLocaleString():"zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`CheckAnnotationRows v${ANNOTATION_TABLE_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 CheckAnnotationRows v${TABLE_TEXT_VALIDATOR_VERSION}`) + addSuccessMessage(`No errors or warnings found by CheckAnnotationRows v${ANNOTATION_TABLE_VALIDATOR_VERSION_STRING}`) // console.log(` CheckAnnotationRows returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); // console.log("CheckAnnotationRows result is", JSON.stringify(result)); return result; diff --git a/src/core/field-link-check.js b/src/core/field-link-check.js index 9db3fdd2..3fabdb51 100644 --- a/src/core/field-link-check.js +++ b/src/core/field-link-check.js @@ -2,7 +2,7 @@ import { checkTextField } from './field-text-check' import { cachedGetURL } from './getApi'; -export const LINK_VALIDATOR_VERSION = '0.3.2'; +const LINK_VALIDATOR_VERSION_STRING = '0.3.2'; // const DEFAULT_EXTRACT_LENGTH = 10; @@ -11,7 +11,7 @@ async function startLiveLinksCheck(linksList, existingNoticeList, callbackFuncti // This (slow) function checks the targets of the given links // to ensure that they actually exist // NOTE: no caching yet - console.log(`startLiveLinksCheck v${LINK_VALIDATOR_VERSION} for ${linksList.length} link(s)…`) + console.log(`startLiveLinksCheck v${LINK_VALIDATOR_VERSION_STRING} for ${linksList.length} link(s)…`) // console.log(`startLiveLinksCheck was given ${existingNoticeList.length} warnings.`) let result = { noticeList: existingNoticeList }; @@ -141,7 +141,7 @@ function checkFieldLinks(fieldName, fieldText, linkOptions, optionalFieldLocatio console.log("checkFieldLinks now returning initial result…"); } - console.log(` checkFieldLinks returning with ${result.noticeList.length} notices.`); + console.log(` checkFieldLinks v${LINK_VALIDATOR_VERSION_STRING} returning with ${result.noticeList.length} notices.`); return result; } // end of checkFieldLinks function diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index cb837aac..f3937ec8 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -1,6 +1,6 @@ import { isWhitespace, countOccurrences } from './text-handling-functions' -//const CHECKER_VERSION_STRING = '0.1.1'; +//const VALIDATOR_VERSION_STRING = '0.1.1'; const DEFAULT_EXTRACT_LENGTH = 10; diff --git a/src/core/file-text-check.js b/src/core/file-text-check.js index bacc702d..612c978c 100644 --- a/src/core/file-text-check.js +++ b/src/core/file-text-check.js @@ -1,6 +1,6 @@ import { isWhitespace, countOccurrences } from './text-handling-functions' -//const CHECKER_VERSION_STRING = '0.1.1'; +//const VALIDATOR_VERSION_STRING = '0.1.1'; const DEFAULT_EXTRACT_LENGTH = 10; diff --git a/src/core/manifest-text-check.js b/src/core/manifest-text-check.js index 00387256..a44f536e 100644 --- a/src/core/manifest-text-check.js +++ b/src/core/manifest-text-check.js @@ -2,7 +2,7 @@ import checkYAMLText from './yaml-text-check'; import * as books from './books'; -const MANIFEST_VALIDATOR_VERSION = '0.2.1'; +const MANIFEST_VALIDATOR_VERSION_STRING = '0.2.1'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -114,9 +114,9 @@ function checkManifestText(textName, manifestText, givenLocation, optionalChecki // addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length==1?'':'s'}${ourLocation}.`); if (cmtResult.noticeList) - addSuccessMessage(`checkManifestText v${MANIFEST_VALIDATOR_VERSION} finished with ${cmtResult.noticeList.length ? cmtResult.noticeList.length.toLocaleString() : "zero"} notice${cmtResult.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkManifestText v${MANIFEST_VALIDATOR_VERSION_STRING} finished with ${cmtResult.noticeList.length ? cmtResult.noticeList.length.toLocaleString() : "zero"} notice${cmtResult.noticeList.length === 1 ? '' : 's'}`); else - addSuccessMessage(`No errors or warnings found by checkManifestText v${MANIFEST_VALIDATOR_VERSION}`) + addSuccessMessage(`No errors or warnings found by checkManifestText v${MANIFEST_VALIDATOR_VERSION_STRING}`) // console.log(` checkManifestText returning with ${cmtResult.successList.length.toLocaleString()} success(es), ${cmtResult.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkManifestText result is", JSON.stringify(result)); return cmtResult; diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index 7268fc60..d83f010f 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -1,7 +1,7 @@ import checkTextField from './field-text-check'; -export const MARKDOWN_VALIDATOR_VERSION = '0.3.1'; +const MARKDOWN_VALIDATOR_VERSION_STRING = '0.3.1'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -159,9 +159,9 @@ function checkMarkdownText(textName, markdownText, givenLocation, optionalChecki addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length === 1 ? '' : 's'}${ourLocation}.`); if (result.noticeList) - addSuccessMessage(`checkMarkdownText v${MARKDOWN_VALIDATOR_VERSION} finished with ${result.noticeList.length ? result.noticeList.length.toLocaleString() : "zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkMarkdownText v${MARKDOWN_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) + addSuccessMessage(`No errors or warnings found by checkMarkdownText v${MARKDOWN_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/plain-text-check.js b/src/core/plain-text-check.js index 2f88c0e3..6bdbf33d 100644 --- a/src/core/plain-text-check.js +++ b/src/core/plain-text-check.js @@ -1,7 +1,7 @@ import checkTextField from './field-text-check'; -export const PLAIN_TEXT_VALIDATOR_VERSION = '0.1.1'; +const PLAIN_TEXT_VALIDATOR_VERSION_STRING = '0.1.1'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -127,9 +127,9 @@ function checkPlainText(textName, plainText, givenLocation, optionalCheckingOpti addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length===1?'':'s'}${ourLocation}.`); if (cptResult.noticeList) - addSuccessMessage(`checkPlainText v${PLAIN_TEXT_VALIDATOR_VERSION} finished with ${cptResult.noticeList.length?cptResult.noticeList.length.toLocaleString():"zero"} notice${cptResult.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkPlainText v${PLAIN_TEXT_VALIDATOR_VERSION_STRING} finished with ${cptResult.noticeList.length?cptResult.noticeList.length.toLocaleString():"zero"} notice${cptResult.noticeList.length === 1 ? '' : 's'}`); else - addSuccessMessage(`No errors or warnings found by checkPlainText v${PLAIN_TEXT_VALIDATOR_VERSION}`) + addSuccessMessage(`No errors or warnings found by checkPlainText v${PLAIN_TEXT_VALIDATOR_VERSION_STRING}`) // console.log(` checkPlainText returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkPlainText result is", JSON.stringify(result)); return cptResult; diff --git a/src/core/quote-check.js b/src/core/quote-check.js index f9493c99..e9dc3cf5 100644 --- a/src/core/quote-check.js +++ b/src/core/quote-check.js @@ -3,7 +3,7 @@ import { getFile } from '../core/getApi'; // import { consoleLogObject } from '../core/utilities'; -export const QUOTE_VALIDATOR_VERSION = '0.3.1'; +// const QUOTE_VALIDATOR_VERSION_STRING = '0.3.1'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -20,7 +20,7 @@ async function checkOriginalLanguageQuote(fieldName, fieldText, bookID, C, V, gi // (UHB or UGNT will be used for the repo name) // optionalCheckingOptions.originalLanguageRepoBranch (or tag) - // console.log(`checkOriginalLanguageQuote v${QUOTE_VALIDATOR_VERSION} (${fieldName}, (${fieldText.length}) '${fieldText}', ${bookID} ${C}:${V} ${givenLocation}, …)`); + // console.log(`checkOriginalLanguageQuote v${QUOTE_VALIDATOR_VERSION_STRING} (${fieldName}, (${fieldText.length}) '${fieldText}', ${bookID} ${C}:${V} ${givenLocation}, …)`); console.assert(fieldName !== undefined, "checkOriginalLanguageQuote: 'fieldText' parameter should be defined"); console.assert(typeof fieldName === 'string', `checkOriginalLanguageQuote: 'fieldText' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "checkOriginalLanguageQuote: 'fieldText' parameter should be defined"); diff --git a/src/core/ta-reference-check.js b/src/core/ta-reference-check.js index 9495dd9f..0bbdaf28 100644 --- a/src/core/ta-reference-check.js +++ b/src/core/ta-reference-check.js @@ -2,7 +2,7 @@ import { getFile } from '../core/getApi'; // import { consoleLogObject } from '../core/utilities'; -export const TA_REFERENCE_VALIDATOR_VERSION = '0.2.1'; +// const TA_REFERENCE_VALIDATOR_VERSION_STRING = '0.2.1'; // const DEFAULT_EXTRACT_LENGTH = 10; @@ -18,7 +18,7 @@ async function checkTAReference(fieldName, fieldText, givenLocation, optionalChe // optionalCheckingOptions.taRepoLanguageCode // optionalCheckingOptions.taRepoSectionName - // console.log(`checkTAReference v${TA_REFERENCE_VALIDATOR_VERSION} (${fieldName}, (${fieldText.length}) '${fieldText}', ${givenLocation}, …)`); + // console.log(`checkTAReference v${TA_REFERENCE_VALIDATOR_VERSION_STRING} (${fieldName}, (${fieldText.length}) '${fieldText}', ${givenLocation}, …)`); console.assert(fieldName !== undefined, "checkTAReference: 'fieldText' parameter should be defined"); console.assert(typeof fieldName === 'string', `checkTAReference: 'fieldText' parameter should be a string not a '${typeof fieldName}'`); console.assert(fieldText !== undefined, "checkTAReference: 'fieldText' parameter should be defined"); diff --git a/src/core/tn-links-check.js b/src/core/tn-links-check.js index 32df7f1d..285a3e05 100644 --- a/src/core/tn-links-check.js +++ b/src/core/tn-links-check.js @@ -4,7 +4,7 @@ import { ourParseInt } from './utilities'; // import { consoleLogObject } from '../core/utilities'; -export const TN_LINKS_VALIDATOR_VERSION = '0.2.1'; +// const TN_LINKS_VALIDATOR_VERSION_STRING = '0.2.1'; // const DEFAULT_EXTRACT_LENGTH = 10; @@ -25,7 +25,7 @@ async function checkTNLinks(bookID, fieldName, fieldText, givenLocation, optiona // optionalCheckingOptions.taRepoDefaultLanguageCode */ - // console.log(`checkTNLinks v${TN_LINKS_VALIDATOR_VERSION} ${bookID} (${fieldName}, (${fieldText.length}) '${fieldText}', ${givenLocation}, …)`); + // console.log(`checkTNLinks v${TN_LINKS_VALIDATOR_VERSION_STRING} ${bookID} (${fieldName}, (${fieldText.length}) '${fieldText}', ${givenLocation}, …)`); console.assert(bookID !== undefined, "checkTNLinks: 'bookID' parameter should be defined"); console.assert(typeof bookID === 'string', `checkTNLinks: 'bookID' parameter should be a string not a '${typeof bookID}'`); console.assert(bookID.length === 3, `checkTNLinks: 'bookID' parameter should be three characters long not ${bookID.length}`); diff --git a/src/core/tn-table-row-check.js b/src/core/tn-table-row-check.js index 12199273..cfd7f4ee 100644 --- a/src/core/tn-table-row-check.js +++ b/src/core/tn-table-row-check.js @@ -6,9 +6,9 @@ import checkTNLinks from './tn-links-check'; import checkOriginalLanguageQuote from './quote-check'; -export const TABLE_LINE_VALIDATOR_VERSION = '0.3.3'; +// const TN_TABLE_ROW_VALIDATOR_VERSION_STRING = '0.4.1'; -const NUM_EXPECTED_TSV_FIELDS = 9; // so expects 8 tabs per line +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 DEFAULT_EXTRACT_LENGTH = 10; @@ -271,7 +271,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional const haveGoodBookID = numChaptersThisBook !== undefined; let fields = line.split('\t'); - if (fields.length === NUM_EXPECTED_TSV_FIELDS) { + if (fields.length === NUM_EXPECTED_TN_TSV_FIELDS) { const [B, C, V, rowID, supportReference, origQuote, occurrence, GLQuote, occurrenceNote] = fields; // let withString = ` with '${rowID}'${inString}`; // let CV_withString = ` ${C}:${V}${withString}`; @@ -395,7 +395,7 @@ async function checkTN_TSVDataRow(line, bookID, C, V, givenRowLocation, optional addNotice6to9({priority:274, message:"Missing OccurrenceNote field", rowID, location:ourRowLocation}); } else - addNotice6to9({priority:861, message:`Found wrong number of TSV fields (expected ${NUM_EXPECTED_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, location:ourRowLocation}); + addNotice6to9({priority:861, message:`Found wrong number of TSV fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, location:ourRowLocation}); // console.log(` checkTN_TSVDataRow returning with ${drResult.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkTN_TSVDataRow result is", JSON.stringify(drResult)); diff --git a/src/core/tn-table-text-check.js b/src/core/tn-table-text-check.js index a1ebe22e..e84d268d 100644 --- a/src/core/tn-table-text-check.js +++ b/src/core/tn-table-text-check.js @@ -2,9 +2,9 @@ import * as books from './books/books'; import checkTN_TSVDataRow from './tn-table-row-check'; -const TABLE_TEXT_VALIDATOR_VERSION = '0.2.1'; +const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.2.2'; -const NUM_EXPECTED_TN_FIELDS = 9; // so expects 8 tabs per line +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 DEFAULT_EXTRACT_LENGTH = 10; @@ -91,7 +91,7 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin else // not the header { let fields = lines[n].split('\t'); - if (fields.length === NUM_EXPECTED_TN_FIELDS) { + if (fields.length === NUM_EXPECTED_TN_TSV_FIELDS) { // eslint-disable-next-line no-unused-vars const [B, C, V, rowID, _support_reference, _orig_quote, _occurrence, _GL_quote, _occurrenceNote] = fields; const withString = ` with ID '${rowID}'${ourLocation}`; @@ -180,14 +180,14 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin // console.log(` Line ${n}: Has ${fields.length} field(s) instead of ${NUM_EXPECTED_TN_FIELDS}: ${EXPECTED_TN_HEADING_LINE.replace(/\t/g, ', ')}`); // else if (n !== lines.length - 1) // it's not the last line - addNoticeCV8({priority:988, message:`Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_FIELDS})`, extract:`Found ${fields.length} field${fields.length===1?'':'s'}`, lineNumber:n+1, location:ourLocation}); + addNoticeCV8({priority:988, message:`Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length===1?'':'s'}`, lineNumber:n+1, location:ourLocation}); } } addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); if (result.noticeList) - addSuccessMessage(`checkTN_TSVText v${TABLE_TEXT_VALIDATOR_VERSION} finished with ${result.noticeList.length?result.noticeList.length.toLocaleString():"zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkTN_TSVText v${TN_TABLE_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 checkTN_TSVText v${TABLE_TEXT_VALIDATOR_VERSION}`) + addSuccessMessage(`No errors or warnings found by checkTN_TSVText v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING}`) // console.log(` checkTN_TSVText returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkTN_TSVText result is", JSON.stringify(result)); return result; diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 570e252d..60c044d0 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -5,10 +5,9 @@ import checkFileText from './file-text-check'; import { runUsfmJsCheck } from './usfm-js-check'; import { runBCSGrammarCheck } from './BCS-usfm-grammar-check'; import { ourParseInt } from './utilities'; -// import { consoleLogObject } from './utilities'; -export const USFM_VALIDATOR_VERSION = '0.6.1'; +// const USFM_VALIDATOR_VERSION_STRING = '0.6.1'; const DEFAULT_EXTRACT_LENGTH = 10; diff --git a/src/core/yaml-text-check.js b/src/core/yaml-text-check.js index e04b946f..4ee187cc 100644 --- a/src/core/yaml-text-check.js +++ b/src/core/yaml-text-check.js @@ -3,7 +3,7 @@ import yaml from 'yaml'; import checkTextField from './field-text-check'; -export const YAML_VALIDATOR_VERSION = '0.1.1'; +const YAML_VALIDATOR_VERSION_STRING = '0.1.1'; const DEFAULT_EXTRACT_LENGTH = 10; @@ -156,9 +156,9 @@ function checkYAMLText(textName, YAMLText, givenLocation, optionalCheckingOption addSuccessMessage(`Checked all ${lines.length.toLocaleString()} line${lines.length===1?'':'s'}${ourLocation}.`); if (cytResult.noticeList) - addSuccessMessage(`checkYAMLText v${YAML_VALIDATOR_VERSION} finished with ${cytResult.noticeList.length?cytResult.noticeList.length.toLocaleString():"zero"} notice${cytResult.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkYAMLText v${YAML_VALIDATOR_VERSION_STRING} finished with ${cytResult.noticeList.length?cytResult.noticeList.length.toLocaleString():"zero"} notice${cytResult.noticeList.length === 1 ? '' : 's'}`); else - addSuccessMessage(`No errors or warnings found by checkYAMLText v${YAML_VALIDATOR_VERSION}`) + addSuccessMessage(`No errors or warnings found by checkYAMLText v${YAML_VALIDATOR_VERSION_STRING}`) // console.log(` checkYAMLText returning with ${cytResult.successList.length.toLocaleString()} success(es), ${cytResult.noticeList.length.toLocaleString()} notice(s).`); // console.log("checkYAMLText result is", JSON.stringify(result)); return cytResult; diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index 6c312b3a..d442ba8e 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -8,14 +8,14 @@ import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; -//const CHECKER_VERSION_STRING = '0.1.3'; +//const VALIDATOR_VERSION_STRING = '0.1.3'; function BookPackageCheck(/*username, language_code, bookID,*/ props) { // Check a single Bible book across many repositories const [result, setResultValue] = useState("Waiting-CheckBookPackage"); - // console.log(`I'm here in BookPackageCheck v${CHECKER_VERSION_STRING}`); + // console.log(`I'm here in BookPackageCheck v${VALIDATOR_VERSION_STRING}`); // consoleLogObject("props", props); // consoleLogObject("props.classes", props.classes); diff --git a/src/demos/book-package-check/checkBookPackage.js b/src/demos/book-package-check/checkBookPackage.js index 7c0c707f..43bf4c9b 100644 --- a/src/demos/book-package-check/checkBookPackage.js +++ b/src/demos/book-package-check/checkBookPackage.js @@ -7,7 +7,7 @@ // import { consoleLogObject } from '../../core/utilities'; -// const CHECKER_VERSION_STRING = '0.3.1'; +// const VALIDATOR_VERSION_STRING = '0.3.1'; // let cachedUnzippedFiles = {}; @@ -165,7 +165,7 @@ // async function checkBookPackageDemo(username, language_code, bookID, setResultValue, checkingOptions) { // // Note that bookID here can also be the 'OBS' pseudo bookID. -// // console.log(`I'm here in checkBookPackage v${CHECKER_VERSION_STRING} +// // console.log(`I'm here in checkBookPackage v${VALIDATOR_VERSION_STRING} // // with ${username}, ${language_code}, ${bookID}, ${JSON.stringify(checkingOptions)}`); // const startTime = new Date(); diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index f04f2f02..f60986d0 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -8,14 +8,14 @@ import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; -//const CHECKER_VERSION_STRING = '0.0.3'; +//const VALIDATOR_VERSION_STRING = '0.0.3'; function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { // Check a single Bible book across many repositories const [result, setResultValue] = useState("Waiting-CheckBookPackages"); - // console.log(`I'm here in BookPackagesCheck v${CHECKER_VERSION_STRING}`); + // console.log(`I'm here in BookPackagesCheck v${VALIDATOR_VERSION_STRING}`); // consoleLogObject("props", props); // consoleLogObject("props.classes", props.classes); diff --git a/src/demos/book-packages-check/checkBookPackages.js b/src/demos/book-packages-check/checkBookPackages.js index f0feb4af..fa99eb0b 100644 --- a/src/demos/book-packages-check/checkBookPackages.js +++ b/src/demos/book-packages-check/checkBookPackages.js @@ -4,11 +4,11 @@ import { checkBookPackage } from '../../core'; // import { getFile } from '../../core/getApi'; // import { consoleLogObject } from '../../core/utilities'; -//const CHECKER_VERSION_STRING = '0.2.1'; +//const VALIDATOR_VERSION_STRING = '0.2.1'; async function checkBookPackages(username, language_code, bookIDList, setResultValue, checkingOptions) { - // console.log(`I'm here in checkBookPackages v${CHECKER_VERSION_STRING} + // console.log(`I'm here in checkBookPackages v${VALIDATOR_VERSION_STRING} // with ${username}, ${language_code}, ${bookIDList}, ${JSON.stringify(checkingOptions)}`); const startTime = new Date(); diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 9ed484a7..12fa1dbc 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -4,7 +4,6 @@ import React, { useEffect, useState } from 'react'; // import { Paper, Button } from '@material-ui/core'; // import { RepositoryContext, FileContext } from 'gitea-react-toolkit'; import { withStyles } from '@material-ui/core/styles'; -// import { getFile } from '../../core/getApi'; import { getFile, checkFile } from '../../core'; import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; @@ -12,7 +11,7 @@ import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; -export const FILE_CHECK_VERSION_STRING = '0.1.3'; +// const FILE_CHECK_VERSION_STRING = '0.1.3'; function FileCheck(props) { diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index 878fd920..3bfafd5c 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -1,7 +1,7 @@ // import { displayPropertyNames, consoleLogObject } from './utilities'; -export const NOTICE_PROCESSOR_VERSION_STRING = '0.6.1'; +// const NOTICE_PROCESSOR_VERSION_STRING = '0.6.1'; // All of the following can be overriden with optionalProcessingOptions const DEFAULT_MAXIMUM_SIMILAR_MESSAGES = 3; // Zero means no suppression of similar messages diff --git a/src/demos/repo-check/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index c288e6f8..787ea9a8 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -7,7 +7,7 @@ import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject, displayPropertyNames } from '../../core/utilities'; -//const CHECKER_VERSION_STRING = '0.1.2'; +//const VALIDATOR_VERSION_STRING = '0.1.2'; function RepoCheck(/*username, languageCode,*/ props) { @@ -18,7 +18,7 @@ function RepoCheck(/*username, languageCode,*/ props) { and then checks all the individual files */ - // console.log(`I'm here in RepoCheck v${CHECKER_VERSION_STRING}`); + // console.log(`I'm here in RepoCheck v${VALIDATOR_VERSION_STRING}`); // consoleLogObject("props", props); // consoleLogObject("props.classes", props.classes); From fc9c05ecc15819221aee3a42370631f8130784a9 Mon Sep 17 00:00:00 2001 From: Robert Hunt Date: Fri, 11 Sep 2020 18:48:08 +1200 Subject: [PATCH 5/5] Many fixes to get demos working again --- src/core/annotation-table-check.js | 53 +- src/core/annotation-table-check.md | 5 +- src/core/book-package-check.js | 235 ++++---- src/core/book-package-check.md | 12 +- src/core/field-text-check.js | 47 +- src/core/file-check.md | 12 +- src/core/file-text-check.js | 20 +- src/core/file-text-check.md | 6 +- src/core/markdown-text-check.js | 2 +- src/core/tn-table-text-check.js | 57 +- src/core/tn-tsv-table-text-check.md | 5 +- src/core/usfm-text-check.js | 8 +- src/core/utilities.js | 16 + src/demos/RenderProcessedResults.js | 18 +- .../book-package-check/BookPackageCheck.js | 52 +- src/demos/book-package-check/README.md | 4 +- .../book-package-check/checkBookPackage.js | 102 ++-- .../book-packages-check/BookPackagesCheck.js | 112 ++-- src/demos/book-packages-check/README.md | 6 +- .../book-packages-check/checkBookPackages.js | 18 +- src/demos/clear-cache/ClearCache.js | 2 +- src/demos/file-check/FileCheck.js | 9 +- src/demos/file-check/checkFile.js | 12 +- src/demos/notice-processing-functions.js | 537 +++++++++--------- src/demos/repo-check/RepoCheck.js | 7 +- src/demos/repo-check/checkRepo.js | 36 +- styleguide.config.js | 2 +- 27 files changed, 727 insertions(+), 668 deletions(-) diff --git a/src/core/annotation-table-check.js b/src/core/annotation-table-check.js index 684dd839..71500903 100644 --- a/src/core/annotation-table-check.js +++ b/src/core/annotation-table-check.js @@ -2,7 +2,7 @@ import * as books from './books/books'; import checkAnnotationTSVDataRow from './annotation-row-check'; -const ANNOTATION_TABLE_VALIDATOR_VERSION_STRING = '0.2.2'; +const ANNOTATION_TABLE_VALIDATOR_VERSION_STRING = '0.2.3'; 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'; @@ -10,7 +10,7 @@ const EXPECTED_TN_HEADING_LINE = 'Reference\tID\tTags\tSupportReference\tQuote\t const DEFAULT_EXTRACT_LENGTH = 10; -async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocation, optionalCheckingOptions) { +async function CheckAnnotationRows(annotationType, bookID, filename, tableText, givenLocation, optionalCheckingOptions) { /* This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -30,23 +30,23 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // console.log(`CheckAnnotationRows success: ${successString}`); result.successList.push(successString); } - function addNoticeCV8({ priority, message, C, V, lineNumber, characterIndex, extract, location }) { + function addNoticeCV8({ priority, message, C, V, rowID, lineNumber, characterIndex, extract, location }) { // console.log(`CheckAnnotationRows notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); console.assert(priority !== undefined, "ATSV addNoticeCV8: 'priority' parameter should be defined"); - console.assert(typeof priority === 'number', `TSV addNoticeCV8: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); + console.assert(typeof priority === 'number', `ATSV addNoticeCV8: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); console.assert(message !== undefined, "ATSV addNoticeCV8: 'message' parameter should be defined"); - console.assert(typeof message === 'string', `TSV addNoticeCV8: 'message' parameter should be a string not a '${typeof message}': ${message}`); + console.assert(typeof message === 'string', `ATSV addNoticeCV8: 'message' parameter should be a string not a '${typeof message}': ${message}`); // console.assert(C !== undefined, "ATSV addNoticeCV8: 'C' parameter should be defined"); - if (C) console.assert(typeof C === 'string', `TSV addNoticeCV8: 'C' parameter should be a string not a '${typeof C}': ${C}`); + if (C) console.assert(typeof C === 'string', `ATSV addNoticeCV8: 'C' parameter should be a string not a '${typeof C}': ${C}`); // console.assert(V !== undefined, "ATSV addNoticeCV8: 'V' parameter should be defined"); - if (V) console.assert(typeof V === 'string', `TSV addNoticeCV8: 'V' parameter should be a string not a '${typeof V}': ${V}`); + if (V) console.assert(typeof V === 'string', `ATSV addNoticeCV8: 'V' parameter should be a string not a '${typeof V}': ${V}`); // console.assert(characterIndex !== undefined, "ATSV addNoticeCV8: 'characterIndex' parameter should be defined"); - if (characterIndex) console.assert(typeof characterIndex === 'number', `TSV addNoticeCV8: 'characterIndex' parameter should be a number not a '${typeof characterIndex}': ${characterIndex}`); + if (characterIndex) console.assert(typeof characterIndex === 'number', `ATSV addNoticeCV8: 'characterIndex' parameter should be a number not a '${typeof characterIndex}': ${characterIndex}`); // console.assert(extract !== undefined, "ATSV addNoticeCV8: 'extract' parameter should be defined"); - if (extract) console.assert(typeof extract === 'string', `TSV addNoticeCV8: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); + if (extract) console.assert(typeof extract === 'string', `ATSV addNoticeCV8: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); console.assert(location !== undefined, "ATSV addNoticeCV8: 'location' parameter should be defined"); - console.assert(typeof location === 'string', `TSV addNoticeCV8: 'location' parameter should be a string not a '${typeof location}': ${location}`); - result.noticeList.push({ priority, message, bookID, C, V, lineNumber, characterIndex, extract, location }); + console.assert(typeof location === 'string', `ATSV addNoticeCV8: 'location' parameter should be a string not a '${typeof location}': ${location}`); + result.noticeList.push({ priority, message, bookID, C, V, filename, rowID, lineNumber, characterIndex, extract, location }); } @@ -97,12 +97,9 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat // eslint-disable-next-line no-unused-vars const [reference, rowID, tags, _support_reference, _quote, _occurrence, _annotation] = fields; const [C, V] = reference.split(':') - const withString = ` with ID '${rowID}'${ourLocation}`; - // let CV_withString = ` ${C}:${V}${withString}`; - // let atString = ` at ${Annotation} ${C}:${V} (${rowID})${inString}`; // Use the row check to do most basic checks - const firstResult = await checkAnnotationTSVDataRow(annotationType, lines[n], bookID, C, V, withString, optionalCheckingOptions); + const firstResult = await checkAnnotationTSVDataRow(annotationType, lines[n], bookID, C, V, ourLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); @@ -119,51 +116,51 @@ async function CheckAnnotationRows(annotationType, bookID, tableText, givenLocat if (C !== lastC) numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticeCV8({ priority: 551, C, V, message: `Invalid zero '${C}' chapter number`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 551, C, V, message: `Invalid zero '${C}' chapter number`, rowID, lineNumber: n + 1, location: ourLocation }); if (intC > numChaptersThisBook) - addNoticeCV8({ priority: 737, C, V, message: `Invalid large '${C}' chapter number`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 737, C, V, message: `Invalid large '${C}' chapter number`, rowID, lineNumber: n + 1, location: ourLocation }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) - addNoticeCV8({ priority: 736, C, V, message: `Receding '${C}' chapter number after '${lastC}'`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 736, C, V, message: `Receding '${C}' chapter number after '${lastC}'`, rowID, lineNumber: n + 1, location: ourLocation }); else if (intC > lastintC + 1) - addNoticeCV8({ priority: 735, C, V, message: `Advancing '${C}' chapter number after '${lastC}'`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 735, C, V, message: `Advancing '${C}' chapter number after '${lastC}'`, rowID, lineNumber: n + 1, location: ourLocation }); } } else - addNoticeCV8({ priority: 734, C, V, message: "Bad chapter number", lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 734, C, V, message: "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({ priority: 739, C, V, message: "Missing chapter number", lineNumber: n + 1, location: ` after ${lastC}:${V}${withString}` }); + addNoticeCV8({ priority: 739, C, V, message: "Missing chapter number", rowID, lineNumber: n + 1, location: ` after ${lastC}:${V}${ourLocation}` }); if (V) { if (V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0) - addNoticeCV8({ priority: 552, C, V, message: `Invalid zero '${V}' verse number`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 552, C, V, message: `Invalid zero '${V}' verse number`, rowID, lineNumber: n + 1, location: ourLocation }); if (intV > numVersesThisChapter) - addNoticeCV8({ priority: 734, C, V, message: `Invalid large '${V}' verse number for chapter ${C}`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 734, C, V, message: `Invalid large '${V}' verse number for chapter ${C}`, rowID, lineNumber: n + 1, location: ourLocation }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (intV < lastintV) - addNoticeCV8({ priority: 733, C, V, message: `Receding '${V}' verse number after '${lastV}'`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 733, C, V, message: `Receding '${V}' verse number after '${lastV}'`, rowID, lineNumber: n + 1, location: ourLocation }); // else if (intV > lastintV + 1) // addNoticeCV8({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } } else - addNoticeCV8({ priority: 738, C, V, message: "Bad verse number", lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 738, C, V, message: "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({ priority: 790, C, V, message: "Missing verse number", lineNumber: n + 1, location: ` after ${C}:${lastV}${withString}` }); + addNoticeCV8({ priority: 790, C, V, message: "Missing verse number", rowID, lineNumber: n + 1, location: ` after ${C}:${lastV}${ourLocation}` }); if (rowID) { if (rowID_list.indexOf(rowID) >= 0) - addNoticeCV8({ priority: 729, C, V, message: `Duplicate '${rowID}' ID`, lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 729, C, V, message: `Duplicate '${rowID}' ID`, rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({ priority: 730, C, V, message: "Missing ID", lineNumber: n + 1, location: withString }); + addNoticeCV8({ priority: 730, C, V, message: "Missing ID", lineNumber: n + 1, location: ourLocation }); if (C !== lastC || V !== lastV) { diff --git a/src/core/annotation-table-check.md b/src/core/annotation-table-check.md index c43f6f5a..70a10201 100644 --- a/src/core/annotation-table-check.md +++ b/src/core/annotation-table-check.md @@ -40,11 +40,12 @@ const data = { tableTextName : 'textG', tableText : textG, bookID : 'GEN', + filename: 'dummyFilename', givenLocation : 'that was supplied', } function CheckAnnotationRows(props) { - const { annotationType, bookID, tableText, tableTextName, givenLocation } = props.data; + const { annotationType, bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -55,7 +56,7 @@ function CheckAnnotationRows(props) { (async () => { // Display our "waiting" message setResults(

Waiting for {annotationType} check results for {tableTextName} {bookID}

); - const rawResults = await checkAnnotationTSVText(annotationType, bookID, tableText, givenLocation); + const rawResults = await checkAnnotationTSVText(annotationType, bookID, filename, tableText, givenLocation); setResults(
Check {tableTextName}: "{tableText.substr(0,256)}…"

diff --git a/src/core/book-package-check.js b/src/core/book-package-check.js index b295b03c..01800953 100644 --- a/src/core/book-package-check.js +++ b/src/core/book-package-check.js @@ -1,5 +1,7 @@ import React from 'react'; import * as books from './books'; +import { getRepoName } from './utilities'; +import { getFilelistFromZip, getFile, getFileCached, fetchRepositoryZipFile } from './getApi'; import checkUSFMText from './usfm-text-check'; import checkMarkdownText from './markdown-text-check'; import checkPlainText from './plain-text-check'; @@ -7,7 +9,6 @@ import checkYAMLText from './yaml-text-check'; import checkManifestText from './manifest-text-check'; import checkTN_TSVText from './tn-table-text-check'; -import {getFilelistFromZip, getFile, getFileCached, fetchRepositoryZipFile} from './getApi'; /* @@ -21,7 +22,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe successList: an array of strings to tell the use exactly what has been checked noticeList: an array of 9 (i.e., with extra bookOrFileCode parameter at end) notice components */ - // console.log(`I'm here in checkRepo v${CHECK_REPO_VERSION_STRING} + // console.log(`I'm here in checkRepo // with ${username}, ${repoName}, ${branch}, ${givenLocation}, ${JSON.stringify(checkingOptions)}`); const startTime = new Date(); @@ -37,7 +38,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe // console.log(`checkRepo success: ${successString}`); checkRepoResult.successList.push(successString); } - function addNotice10({priority, message, filename, bookID, C, V, lineNumber, characterIndex, extract, location, extra}) { + function addNotice10({ priority, message, filename, bookID, C, V, lineNumber, characterIndex, extract, location, extra }) { // Adds the notices to the result that we will later return // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. // Note that bookID,C,V might all be empty strings (as some repos don't have BCV) @@ -64,41 +65,37 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe console.assert(typeof location === 'string', `cR addNotice10: 'location' parameter should be a string not a '${typeof location}'`); console.assert(extra !== undefined, "cR addNotice10: 'extra' parameter should be defined"); console.assert(typeof extra === 'string', `cR addNotice10: 'extra' parameter should be a string not a '${typeof extra}'`); - checkRepoResult.noticeList.push({ priority,message, bookID, C, V, repoName, filename, lineNumber, characterIndex, extract, location, extra }); + checkRepoResult.noticeList.push({ priority, message, bookID, C, V, repoName, filename, lineNumber, characterIndex, extract, location, extra }); } - async function ourCheckFile(bookOrFileCode, cfBookID, filename, file_content, fileLocation, optionalCheckingOptions) { + async function ourCheckFileContents(bookOrFileCode, cfBookID, filename, file_content, fileLocation, optionalCheckingOptions) { // We assume that checking for compulsory fields is done elsewhere - // console.log(`checkRepo ourCheckFile(${filename})…`); + // console.log(`checkRepo ourCheckFileContents(${filename})…`); // Updates the global list of notices - console.assert(bookOrFileCode !== undefined, "ourCheckFile: 'bookOrFileCode' parameter should be defined"); - console.assert(typeof bookOrFileCode === 'string', `ourCheckFile: 'bookOrFileCode' parameter should be a string not a '${typeof bookOrFileCode}'`); - console.assert(cfBookID !== undefined, "ourCheckFile: 'cfBookID' parameter should be defined"); - console.assert(typeof cfBookID === 'string', `ourCheckFile: 'cfBookID' parameter should be a string not a '${typeof cfBookID}'`); - console.assert(filename !== undefined, "ourCheckFile: 'filename' parameter should be defined"); - console.assert(typeof filename === 'string', `ourCheckFile: 'filename' parameter should be a string not a '${typeof filename}'`); - console.assert(file_content !== undefined, "ourCheckFile: 'file_content' parameter should be defined"); - console.assert(typeof file_content === 'string', `ourCheckFile: 'file_content' parameter should be a string not a '${typeof file_content}'`); - console.assert(fileLocation !== undefined, "ourCheckFile: 'fileLocation' parameter should be defined"); - console.assert(typeof fileLocation === 'string', `ourCheckFile: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - - const resultObject = await checkFile(filename, file_content, fileLocation, optionalCheckingOptions); - // console.log("checkFile() returned", resultObject.successList.length, "success message(s) and", resultObject.noticeList.length, "notice(s)"); + console.assert(bookOrFileCode !== undefined, "ourCheckFileContents: 'bookOrFileCode' parameter should be defined"); + console.assert(typeof bookOrFileCode === 'string', `ourCheckFileContents: 'bookOrFileCode' parameter should be a string not a '${typeof bookOrFileCode}'`); + console.assert(cfBookID !== undefined, "ourCheckFileContents: 'cfBookID' parameter should be defined"); + console.assert(typeof cfBookID === 'string', `ourCheckFileContents: 'cfBookID' parameter should be a string not a '${typeof cfBookID}'`); + console.assert(filename !== undefined, "ourCheckFileContents: 'filename' parameter should be defined"); + console.assert(typeof filename === 'string', `ourCheckFileContents: 'filename' parameter should be a string not a '${typeof filename}'`); + console.assert(file_content !== undefined, "ourCheckFileContents: 'file_content' parameter should be defined"); + console.assert(typeof file_content === 'string', `ourCheckFileContents: 'file_content' parameter should be a string not a '${typeof file_content}'`); + console.assert(fileLocation !== undefined, "ourCheckFileContents: 'fileLocation' parameter should be defined"); + console.assert(typeof fileLocation === 'string', `ourCheckFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); + + const resultObject = await checkFileContents(filename, file_content, 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); // Process results line by line, appending the bookOrFileCode as an extra field as we go for (const noticeEntry of resultObject.noticeList) // We add the bookOrFileCode as an extra value - addNotice10({priority:noticeEntry.priority, message:noticeEntry.message, - bookID:noticeEntry.bookID, C:noticeEntry.C, V:noticeEntry.V, - filename, lineNumber:noticeEntry.lineNumber, - characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, - location:noticeEntry.location, extra:bookOrFileCode}); + addNotice10({ ...noticeEntry, bookID:cfBookID, extra:bookOrFileCode }); } - // end of ourCheckFile function + // end of ourCheckFileContents function // Main code for checkRepo() @@ -107,7 +104,7 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; // if (ourLocation.indexOf(username) < 0) - ourLocation = ` in ${username} ${repoName} ${givenLocation}` + // ourLocation = ` in ${username} ${repoName} ${givenLocation}` // Update our "waiting" message setResultValue(

Fetching zipped files from {username}/{repoName} repository…

); @@ -170,12 +167,12 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe // console.log("Fetched file_content for", repoName, thisPath, typeof repoFileContent, repoFileContent.length); } catch (cRgfError) { console.log("Failed to load", username, repoName, thisFilepath, branch, `${cRgfError}`); - addNotice10({priority:996, message:"Failed to load", bookID:ourBookID, filename:thisFilename, location:`${givenLocation} ${thisFilepath}: ${cRgfError}`, extra:repoName}); + addNotice10({ priority: 996, message: "Failed to load", bookID: ourBookID, filename: thisFilename, location: `${givenLocation} ${thisFilepath}: ${cRgfError}`, extra: repoName }); return; } if (repoFileContent) { // console.log(`checkRepo checking ${thisFilename}`); - await ourCheckFile(bookOrFileCode, ourBookID, thisFilename, repoFileContent, ourLocation, checkingOptions); + await ourCheckFileContents(bookOrFileCode, ourBookID, thisFilename, repoFileContent, ourLocation, checkingOptions); checkedFileCount += 1; checkedFilenames.push(thisFilename); checkedFilenameExtensions.add(thisFilenameExtension); @@ -188,9 +185,9 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe // Check that we processed a license and a manifest if (checkedFilenames.indexOf('LICENSE.md') < 0) - addNotice10({priority:946, message:"Missing LICENSE.md", location:ourLocation, extra:'LICENSE'}); + addNotice10({ priority: 946, message: "Missing LICENSE.md", location: ourLocation, extra: 'LICENSE' }); if (checkedFilenames.indexOf('manifest.yaml') < 0) - addNotice10({priority:947, message:"Missing manifest.yaml", location:ourLocation, extra:'MANIFEST'}); + addNotice10({ priority: 947, message: "Missing manifest.yaml", location: ourLocation, extra: 'MANIFEST' }); // Add some extra fields to our checkRepoResult object // in case we need this information again later @@ -217,12 +214,12 @@ export async function checkRepo(username, repoName, branch, givenLocation, setRe /* - checkFile + checkFileContents */ -export async function checkFile(filename, fileContent, givenLocation, checkingOptions) { +export async function checkFileContents(filename, fileContent, givenLocation, checkingOptions) { // Determine the file type from the filename extension - // and return the results of checking that kind of file - // console.log(`I'm here in checkFile v${CHECK_FILE_VERSION_STRING} + // and return the results of checking that kind of file text + // console.log(`I'm here in checkFileContents // with ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)}`); const startTime = new Date(); @@ -235,22 +232,22 @@ export async function checkFile(filename, fileContent, givenLocation, checkingOp // console.log(`Have TSV filenameMain=${filenameMain}`); const bookID = filenameMain.substring(filenameMain.length - 3); // console.log(`Have TSV bookcode=${bookID}`); - console.assert(books.isValidBookID(bookID), `checkFile: '${bookID}' is not a valid USFM book identifier`); - checkFileResult = await checkTN_TSVText(bookID, fileContent, ourCFLocation, checkingOptions); + console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); + checkFileResult = await checkTN_TSVText(bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filename.toLowerCase().endsWith('.usfm')) { const filenameMain = filename.substring(0, filename.length - 5); // drop .usfm // console.log(`Have USFM filenameMain=${filenameMain}`); const bookID = filenameMain.substring(filenameMain.length - 3); // console.log(`Have USFM bookcode=${bookID}`); - console.assert(books.isValidBookID(bookID), `checkFile: '${bookID}' is not a valid USFM book identifier`); + console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); checkFileResult = checkUSFMText(bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filename.toLowerCase().endsWith('.sfm')) { const filenameMain = filename.substring(0, filename.length - 4); // drop .sfm console.log(`Have SFM filenameMain=${filenameMain}`); const bookID = filenameMain.substring(2, 5); console.log(`Have SFM bookcode=${bookID}`); - console.assert(books.isValidBookID(bookID), `checkFile: '${bookID}' is not a valid USFM book identifier`); + console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); checkFileResult = checkUSFMText(bookID, filename, fileContent, ourCFLocation, checkingOptions); } else if (filename.toLowerCase().endsWith('.md')) checkFileResult = checkMarkdownText(filename, fileContent, ourCFLocation, checkingOptions); @@ -264,7 +261,7 @@ export async function checkFile(filename, fileContent, givenLocation, checkingOp checkFileResult = checkPlainText(filename, fileContent, ourCFLocation, checkingOptions); checkFileResult.noticeList.unshift([995, "File extension is not recognized, so treated as plain text.", -1, '', filename]); } - // console.log(`checkFile got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); + // console.log(`checkFileContents got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); // Add some extra fields to our checkFileResult object // in case we need this information again later @@ -274,15 +271,17 @@ export async function checkFile(filename, fileContent, givenLocation, checkingOp checkFileResult.checkedOptions = checkingOptions; checkFileResult.elapsedSeconds = (new Date() - startTime) / 1000; // seconds + // console.log(`checkFileResult: ${JSON.stringify(checkFileResult)}`); return checkFileResult; }; -// end of checkFile() +// end of checkFileContents() /* checkTQbook */ export async function checkTQbook(username, repoName, branch, bookID, checkingOptions) { + // console.log(`checkTQbook(${username}, ${repoName}, ${branch}, ${bookID}, ${JSON.stringify(checkingOptions)})…`) const repoCode = 'TQ'; const generalLocation = `in ${username} ${repoName} (${branch})`; @@ -293,7 +292,7 @@ export async function checkTQbook(username, repoName, branch, bookID, checkingOp ctqResult.successList.push(successString); } - function addNotice10({priority, message, bookID, C, V, lineNumber, characterIndex, extract, location, extra}) { + function addNotice10({ priority, message, bookID, C, V, filename, lineNumber, characterIndex, extract, location, extra }) { // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. // console.log(`checkTQbook addNotice10: (priority=${priority}) ${bookID} ${C}:${V} ${message}${characterIndex > 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); console.assert(priority !== undefined, "cTQ addNotice10: 'priority' parameter should be defined"); @@ -316,40 +315,36 @@ export async function checkTQbook(username, repoName, branch, bookID, checkingOp console.assert(typeof location === 'string', `cTQ addNotice10: 'location' parameter should be a string not a '${typeof location}'`); console.assert(extra !== undefined, "cTQ addNotice10: 'extra' parameter should be defined"); console.assert(typeof extra === 'string', `cTQ addNotice10: 'extra' parameter should be a string not a '${typeof extra}'`); - ctqResult.noticeList.push({priority, message, bookID, C, V, lineNumber, characterIndex, extract, location, extra}); + ctqResult.noticeList.push({ priority, message, bookID, C, V, filename, lineNumber, characterIndex, extract, location, extra }); } - async function ourCheckFile(repoCode, bookID, C, V, cfFilename, file_content, fileLocation, optionalCheckingOptions) { - // console.log(`checkBookPackage ourCheckFile(${cfFilename})`); + async function ourCheckFileContents(repoCode, bookID, C, V, cfFilename, file_content, fileLocation, optionalCheckingOptions) { + // console.log(`checkBookPackage ourCheckFileContents(${cfFilename})`); // Updates the global list of notices - console.assert(repoCode !== undefined, "cTQ ourCheckFile: 'repoCode' parameter should be defined"); - console.assert(typeof repoCode === 'string', `cTQ ourCheckFile: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); - console.assert(cfFilename !== undefined, "cTQ ourCheckFile: 'cfFilename' parameter should be defined"); - console.assert(typeof cfFilename === 'string', `cTQ ourCheckFile: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); - console.assert(file_content !== undefined, "cTQ ourCheckFile: 'file_content' parameter should be defined"); - console.assert(typeof file_content === 'string', `cTQ ourCheckFile: 'file_content' parameter should be a string not a '${typeof file_content}'`); - console.assert(fileLocation !== undefined, "cTQ ourCheckFile: 'fileLocation' parameter should be defined"); - console.assert(typeof fileLocation === 'string', `cTQ ourCheckFile: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - - const cfResultObject = await checkFile(cfFilename, file_content, fileLocation, optionalCheckingOptions); - // console.log("checkFile() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); - // for (const successEntry of cfResultObject.successList) console.log(" ourCheckFile:", successEntry); + console.assert(repoCode !== undefined, "cTQ ourCheckFileContents: 'repoCode' parameter should be defined"); + console.assert(typeof repoCode === 'string', `cTQ ourCheckFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + console.assert(cfFilename !== undefined, "cTQ ourCheckFileContents: 'cfFilename' parameter should be defined"); + console.assert(typeof cfFilename === 'string', `cTQ ourCheckFileContents: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); + console.assert(file_content !== undefined, "cTQ ourCheckFileContents: 'file_content' parameter should be defined"); + console.assert(typeof file_content === 'string', `cTQ ourCheckFileContents: 'file_content' parameter should be a string not a '${typeof file_content}'`); + console.assert(fileLocation !== undefined, "cTQ ourCheckFileContents: 'fileLocation' parameter should be defined"); + console.assert(typeof fileLocation === 'string', `cTQ ourCheckFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); + + const cfResultObject = await checkFileContents(cfFilename, file_content, 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(" ourCheckFileContents:", successEntry); // Process results 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 ourCheckFile notice length=${Object.keys(noticeEntry).length}`); + // console.assert(Object.keys(noticeEntry).length === 5, `cTQ ourCheckFileContents notice length=${Object.keys(noticeEntry).length}`); // We add the repoCode as an extra value - addNotice10({priority:noticeEntry.priority, message:noticeEntry.message, - bookID, C, V, - filename: cfFilename, lineNumber:noticeEntry.lineNumber, - characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, - location:noticeEntry.location, extra:repoCode}); + addNotice10({ ...noticeEntry, bookID, C,V, extra:repoCode }); } } - // end of ourCheckFile function + // end of ourCheckFileContents function // Main code for checkTQbook @@ -361,9 +356,9 @@ export async function checkTQbook(username, repoName, branch, bookID, checkingOp // console.log("checkTQbook: Try to load", username, repoName, thisPath, branch); console.assert(thisPath.endsWith('.md'), `Expected ${thisPath} to end with .md`); - const pathParts = thisPath.slice(0,-3).split('/'); - const C = pathParts[pathParts.length-2].replace(/^0+(?=\d)/, ''); - const V = pathParts[pathParts.length-1].replace(/^0+(?=\d)/, ''); + const pathParts = thisPath.slice(0, -3).split('/'); + const C = pathParts[pathParts.length - 2].replace(/^0+(?=\d)/, ''); + const V = pathParts[pathParts.length - 1].replace(/^0+(?=\d)/, ''); const getFile_ = (checkingOptions && checkingOptions.getFile) ? checkingOptions.getFile : getFile; let tqFileContent; @@ -374,13 +369,13 @@ export async function checkTQbook(username, repoName, branch, bookID, checkingOp totalCheckedSize += tqFileContent.length; } catch (tQerror) { console.log("checkTQbook failed to load", username, repoName, thisPath, branch, tQerror + ''); - addNotice10({priority:996, bookID, C, V, message:"Failed to load", location:`${generalLocation} ${thisPath}: ${tQerror}`, extra:repoCode}); + addNotice10({ priority: 996, bookID, C, V, message: "Failed to load", location: `${generalLocation} ${thisPath}: ${tQerror}`, extra: repoCode }); continue; } // We use the generalLocation here (does not include repo name) // so that we can adjust the returned strings ourselves - await ourCheckFile(repoCode, bookID, C, V, thisPath, tqFileContent, generalLocation, checkingOptions); // Adds the notices to checkBookPackageResult + await ourCheckFileContents(repoCode, bookID, C, V, thisPath, tqFileContent, generalLocation, checkingOptions); // Adds the notices to checkBookPackageResult checkedFileCount += 1; // addSuccessMessage(`Checked ${repoCode.toUpperCase()} file: ${thisPath}`); } @@ -396,29 +391,21 @@ export async function checkTQbook(username, repoName, branch, bookID, checkingOp // end of checkTQbook function -function getRepoName(language_code, repoCode) { - let repo_language_code = language_code; - if (repoCode === 'UHB') repo_language_code = 'hbo'; - else if (repoCode === 'UGNT') repo_language_code = 'el-x-koine'; - const repoName = `${repo_language_code}_${repoCode.toLowerCase()}`; - return repoName; - } - - /* checkBookPackage */ -export async function checkBookPackage(username, language_code, bookID, setResultValue, checkingOptions) { +export async function checkBookPackage(username, languageCode, bookID, setResultValue, checkingOptions) { /* Note: You may want to run clearCaches() before running this function??? Note that bookID here can also be the 'OBS' pseudo bookID. */ + // console.log(`checkBookPackage(${username}, ${languageCode}, ${bookID}, …)…`) const startTime = new Date(); let checkBookPackageResult = { successList: [], noticeList: [] }; - const newCheckingOptions = checkingOptions ? { ...checkingOptions } : { }; // clone before modify + const newCheckingOptions = checkingOptions ? { ...checkingOptions } : {}; // clone before modify const getFile_ = newCheckingOptions.getFile ? newCheckingOptions.getFile : getFileCached; // default to using caching of files newCheckingOptions.getFile = getFile_; // use same getFile_ when we call core functions @@ -427,7 +414,7 @@ export async function checkBookPackage(username, language_code, bookID, setResul checkBookPackageResult.successList.push(successString); } - function addNotice10({priority, message, bookID, C, V, lineNumber, characterIndex, extract, location, extra}) { + function addNotice10({ priority, message, bookID, C, V, rowID, repoName, filename, lineNumber, fieldName, characterIndex, extract, location, extra }) { // bookID is a three-character UPPERCASE USFM book identifier or 'OBS'. // console.log(`checkBookPackage addNotice10: (priority=${priority}) ${bookID} ${C}:${V} ${message}${characterIndex > 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); console.assert(priority !== undefined, "cBP addNotice10: 'priority' parameter should be defined"); @@ -452,40 +439,37 @@ export async function checkBookPackage(username, language_code, bookID, setResul console.assert(typeof location === 'string', `cBP addNotice10: 'location' parameter should be a string not a '${typeof location}'`); console.assert(extra !== undefined, "cBP addNotice10: 'extra' parameter should be defined"); console.assert(typeof extra === 'string', `cBP addNotice10: 'extra' parameter should be a string not a '${typeof extra}'`); - checkBookPackageResult.noticeList.push({priority, message, bookID, C, V, lineNumber, characterIndex, extract, location, extra}); + checkBookPackageResult.noticeList.push({ priority, message, bookID, C, V, rowID, repoName, filename, lineNumber, fieldName, characterIndex, extract, location, extra }); } - async function ourCheckFile(repoCode, cfFilename, file_content, fileLocation, optionalCheckingOptions) { - // console.log(`checkBookPackage ourCheckFile(${cfFilename})`); + async function ourCheckFileContents(repoCode, cfFilename, file_content, fileLocation, optionalCheckingOptions) { + // console.log(`checkBookPackage ourCheckFileContents(${cfFilename})`); // Updates the global list of notices - console.assert(repoCode !== undefined, "cBP ourCheckFile: 'repoCode' parameter should be defined"); - console.assert(typeof repoCode === 'string', `cBP ourCheckFile: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); - console.assert(cfFilename !== undefined, "cBP ourCheckFile: 'cfFilename' parameter should be defined"); - console.assert(typeof cfFilename === 'string', `cBP ourCheckFile: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); - console.assert(file_content !== undefined, "cBP ourCheckFile: 'file_content' parameter should be defined"); - console.assert(typeof file_content === 'string', `cBP ourCheckFile: 'file_content' parameter should be a string not a '${typeof file_content}'`); - console.assert(fileLocation !== undefined, "cBP ourCheckFile: 'fileLocation' parameter should be defined"); - console.assert(typeof fileLocation === 'string', `cBP ourCheckFile: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - - const cfResultObject = await checkFile(cfFilename, file_content, fileLocation, optionalCheckingOptions); - // console.log("checkFile() returned", cfResultObject.successList.length, "success message(s) and", cfResultObject.noticeList.length, "notice(s)"); - // for (const successEntry of cfResultObject.successList) console.log(" ourCheckFile:", successEntry); + console.assert(repoCode !== undefined, "cBP ourCheckFileContents: 'repoCode' parameter should be defined"); + console.assert(typeof repoCode === 'string', `cBP ourCheckFileContents: 'repoCode' parameter should be a string not a '${typeof repoCode}'`); + console.assert(cfFilename !== undefined, "cBP ourCheckFileContents: 'cfFilename' parameter should be defined"); + console.assert(typeof cfFilename === 'string', `cBP ourCheckFileContents: 'cfFilename' parameter should be a string not a '${typeof cfFilename}'`); + console.assert(file_content !== undefined, "cBP ourCheckFileContents: 'file_content' parameter should be defined"); + console.assert(typeof file_content === 'string', `cBP ourCheckFileContents: 'file_content' parameter should be a string not a '${typeof file_content}'`); + console.assert(fileLocation !== undefined, "cBP ourCheckFileContents: 'fileLocation' parameter should be defined"); + console.assert(typeof fileLocation === 'string', `cBP ourCheckFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); + + const cfResultObject = await checkFileContents(cfFilename, file_content, 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(" ourCheckFileContents:", successEntry); // Process results line by line, appending the repoCode as an extra field as we go for (const noticeEntry of cfResultObject.noticeList) // noticeEntry is an object // We add the repoCode as an extra value - addNotice10({priority:noticeEntry.priority, message:noticeEntry.message, - bookID:noticeEntry.bookID, C:noticeEntry.C, V:noticeEntry.V, lineNumber:noticeEntry.lineNumber, - characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, - location:noticeEntry.location, extra:repoCode}); + addNotice10({ ...noticeEntry, extra:repoCode }); } - // end of ourCheckFile function + // end of ourCheckFileContents function // Main code for checkBookPackage() - const generalLocation = ` ${language_code} ${bookID} book package from ${username}`; + const generalLocation = ` in ${languageCode} ${bookID} book package from ${username}`; // No point in passing the branch through as a parameter // coz if it's not 'master', it's unlikely to be common for all the repos @@ -495,7 +479,7 @@ export async function checkBookPackage(username, language_code, bookID, setResul // We use the generalLocation here (does not include repo name) // so that we can adjust the returned strings ourselves // console.log("Calling OBS checkRepo()…"); - checkBookPackageResult = await checkRepo(username, `${language_code}_obs`, branch, generalLocation, setResultValue, newCheckingOptions); // Adds the notices to checkBookPackageResult + checkBookPackageResult = await checkRepo(username, `${languageCode}_obs`, branch, generalLocation, setResultValue, newCheckingOptions); // Adds the notices to checkBookPackageResult // 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))); @@ -503,7 +487,7 @@ export async function checkBookPackage(username, language_code, bookID, setResul // checkBookPackageResult.successList = checkBookPackageResult.successList.concat(crResultObject.successList); // checkBookPackageResult.noticeList = checkBookPackageResult.noticeList.concat(crResultObject.noticeList); // checkedFileCount += crResultObject.fileCount; - addSuccessMessage(`Checked ${language_code} OBS repo from ${username}`); + addSuccessMessage(`Checked ${languageCode} OBS repo from ${username}`); } else { // not OBS // We also need to know the number for USFM books let bookNumberAndName, whichTestament; @@ -514,9 +498,11 @@ export async function checkBookPackage(username, language_code, bookID, setResul if (books.isValidBookID(bookID)) // must be in FRT, BAK, etc. whichTestament = 'other' else { - addNotice10({priority:902, message:"Bad function call: should be given a valid book abbreviation", - bookID, - extract:bookID, location:` (not '${bookID}')${generalLocation}`}); + addNotice10({ + priority: 902, message: "Bad function call: should be given a valid book abbreviation", + bookID, + extract: bookID, location: ` (not '${bookID}')${generalLocation}` + }); return checkBookPackageResult; } } @@ -527,19 +513,22 @@ export async function checkBookPackage(username, language_code, bookID, setResul const getFile_ = (checkingOptions && checkingOptions.getFile) ? checkingOptions.getFile : getFile; let checkedFileCount = 0, checkedFilenames = [], checkedFilenameExtensions = new Set(), totalCheckedSize = 0, checkedRepoNames = []; const origLang = whichTestament === 'old' ? 'UHB' : 'UGNT'; - for (const repoCode of [origLang, 'TA', 'TW']) { - const repoName = getRepoName(language_code, repoCode); - console.log(`Loading zip file for ${repoName}…`); - const zipFetchSucceeded = await fetchRepositoryZipFile({ username, repository: repoName, branch }); - if (!zipFetchSucceeded) - console.log(`checkRepo: misfetched zip file for repo with ${zipFetchSucceeded}`); - } - for (const repoCode of [origLang, 'ULT', 'UST', 'TN', 'TQ']) { - console.log(`Check ${bookID} in ${repoCode} (${language_code} ${bookID} from ${username})`); - const repoLocation = ` in ${repoCode.toUpperCase()}${generalLocation}`; - const repoName = getRepoName(language_code, repoCode); - - // const fullRepoName = username + '/' + repoName; + + // NOTE: The following code probably needs to be in/controlled-by the calling program + // for (const repoCode of [origLang, 'TA', 'TW']) { + // const repoName = getRepoName(languageCode, repoCode); + // console.log(`Preloading zip file for ${repoName}…`); + // const zipFetchSucceeded = await fetchRepositoryZipFile({ username, repository: repoName, branch }); + // if (!zipFetchSucceeded) + // console.log(`checkRepo: misfetched zip file for repo with ${zipFetchSucceeded}`); + // } + + for (const repoCode of [origLang, 'ULT', 'UST', 'TN', 'TQ']) { + console.log(`Check ${bookID} in ${repoCode} (${languageCode} ${bookID} from ${username})`); + const repoLocation = ` in ${repoCode.toUpperCase()}${generalLocation}`; + const repoName = getRepoName(languageCode, repoCode); + + // const fullRepoName = username + '/' + repoName; // console.log("Let's try1", bookID, "from", fullRepoName); let filename; @@ -548,7 +537,7 @@ export async function checkBookPackage(username, language_code, bookID, setResul checkedFilenameExtensions.add('usfm'); } else if (repoCode === 'TN') { - filename = `${language_code}_tn_${bookNumberAndName}.tsv`; + filename = `${languageCode}_tn_${bookNumberAndName}.tsv`; checkedFilenameExtensions.add('tsv'); } @@ -573,19 +562,19 @@ export async function checkBookPackage(username, language_code, bookID, setResul checkedRepoNames.push(repoCode); } catch (cBPgfError) { console.log("ERROR: Failed to load", username, repoName, filename, branch, cBPgfError + ''); - addNotice10({priority:996, message:"Failed to load", bookID, repoName, filename, location:`${repoLocation} ${filename}: ${cBPgfError}`, extra:repoCode}); + addNotice10({ priority: 996, message: "Failed to load", bookID, repoName, filename, location: `${repoLocation} ${filename}: ${cBPgfError}`, extra: repoCode }); continue; } // We use the generalLocation here (does not include repo name) // so that we can adjust the returned strings ourselves - await ourCheckFile(repoCode, filename, repoFileContent, generalLocation, newCheckingOptions); // Adds the notices to checkBookPackageResult + await ourCheckFileContents(repoCode, filename, repoFileContent, generalLocation, newCheckingOptions); // Adds the notices to checkBookPackageResult checkedFileCount += 1; addSuccessMessage(`Checked ${repoCode.toUpperCase()} file: ${filename}`); } // Update our "waiting" message - setResultValue(

Waiting for check results for {username} {language_code} {bookID} book package: checked {checkedRepoNames.length.toLocaleString()}/5 repos…

); + setResultValue(

Waiting for check results for {username} {languageCode} {bookID} book package: checked {checkedRepoNames.length.toLocaleString()}/5 repos…

); } // Add some extra fields to our checkFileResult object diff --git a/src/core/book-package-check.md b/src/core/book-package-check.md index 9ddc1d90..a37e5427 100644 --- a/src/core/book-package-check.md +++ b/src/core/book-package-check.md @@ -12,7 +12,7 @@ See a list of valid book identifiers [here](http://ubsicap.github.io/usfm/identi Note that `OBS` can also be entered here as a *pseudo book identifier* in order to check an **Open Bible Stories** repo. -`Book Package Check` calls `checkBookPackage()` which then calls `checkFile()` for the book file in each repo (or calls `checkRepo()` for **OBS**). +`Book Package Check` calls `checkBookPackage()` which then calls `checkFileContents()` for the book file in each repo (or calls `checkRepo()` for **OBS**). **Warning**: Some book packages contain many files and/or very large files, and downloading them all and then checking them might slow down your browser -- maybe even causing pop-up messages asking to confirm that you want to keep waiting. @@ -26,14 +26,14 @@ import { RenderRawResults } from '../demos/RenderProcessedResults'; // You can put your own data into the following fields: const data = { username: 'unfoldingWord', - language_code : 'en', + languageCode : 'en', bookID : 'RUT', givenLocation : 'that was supplied', checkingOptions: {}, } function CheckBookPackage(props) { - const { username, language_code, bookID, givenLocation, checkingOptions } = props.data; + const { username, languageCode, bookID, givenLocation, checkingOptions } = props.data; const [results, setResults] = useState(null); @@ -43,11 +43,11 @@ function CheckBookPackage(props) { // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 (async () => { // Display our "waiting" message - setResults(

Waiting for {username} {language_code} {bookID} check results…

); - const rawResults = await checkBookPackage(username, language_code, bookID, setResults, checkingOptions); + setResults(

Waiting for {username} {languageCode} {bookID} check results…

); + const rawResults = await checkBookPackage(username, languageCode, bookID, setResults, checkingOptions); setResults(
- Checked Door43 {username} {language_code} {bookID}

+ Checked Door43 {username} {languageCode} {bookID}

); diff --git a/src/core/field-text-check.js b/src/core/field-text-check.js index f3937ec8..2b74f3f7 100644 --- a/src/core/field-text-check.js +++ b/src/core/field-text-check.js @@ -53,14 +53,11 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField return result; // Create our more detailed location string by prepending the fieldName - let ourAtString = ` in '${fieldName}'`; - if (optionalFieldLocation) { - if (optionalFieldLocation[0] !== ' ') ourAtString += ' '; - ourAtString += optionalFieldLocation; - } + let ourLocation = optionalFieldLocation; + if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; if (isWhitespace(fieldText)) { - addNotice6({ priority: 638, message: "Only found whitespace", location: ourAtString }); + addNotice6({ priority: 638, message: "Only found whitespace", location: ourLocation }); return result; } @@ -82,66 +79,66 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField if (characterIndex >= 0) { const iy = characterIndex + halfLength; // Want extract to focus more on what follows const extract = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 993, message: "Unresolved GIT conflict", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 993, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); } else { characterIndex = fieldText.indexOf('======='); if (characterIndex >= 0) { const iy = characterIndex + halfLength; // Want extract to focus more on what follows const extract = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 992, message: "Unresolved GIT conflict", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 992, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); } else { characterIndex = fieldText.indexOf('>>>>>>>>'); if (characterIndex >= 0) { const iy = characterIndex + halfLength; // Want extract to focus more on what follows const extract = (iy > halfLength ? '…' : '') + fieldText.substring(iy - halfLength, iy + halfLengthPlus).replace(/ /g, '␣') + (iy + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 991, message: "Unresolved GIT conflict", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 991, message: "Unresolved GIT conflict", characterIndex, extract, location: ourLocation }); } } } if (fieldText[0] === ' ') { const extract = fieldText.substring(0, extractLength).replace(/ /g, '␣') + (fieldText.length > extractLength ? '…' : ''); - addNotice6({ priority: 106, message: `Unexpected leading space${fieldText[1] === ' ' ? "s" : ""}`, characterIndex: 0, extract, location: ourAtString }); + addNotice6({ priority: 106, message: `Unexpected leading space${fieldText[1] === ' ' ? "s" : ""}`, characterIndex: 0, extract, location: ourLocation }); } if (fieldText.substring(0, 4) === '
' || fieldText.substring(0, 5) === '
' || fieldText.substring(0, 6) === '
') { const extract = fieldText.substring(0, extractLength) + (fieldText.length > extractLength ? '…' : ''); - addNotice6({ priority: 107, message: "Unexpected leading break", characterIndex: 0, extract, location: ourAtString }); + addNotice6({ priority: 107, message: "Unexpected leading break", characterIndex: 0, extract, location: ourLocation }); } if (fieldText[fieldText.length - 1] === ' ') { const extract = (fieldText.length > extractLength ? '…' : '') + fieldText.substring(fieldText.length - 10).replace(/ /g, '␣'); - addNotice6({ priority: 105, message: "Unexpected trailing space(s)", characterIndex: fieldText.length - 1, extract, location: ourAtString }); + addNotice6({ priority: 105, message: "Unexpected trailing space(s)", characterIndex: fieldText.length - 1, extract, location: ourLocation }); } if (fieldText.substring(fieldText.length - 4) === '
' || fieldText.substring(fieldText.length - 5) === '
' || fieldText.substring(fieldText.length - 6) === '
') { const extract = (fieldText.length > extractLength ? '…' : '') + fieldText.substring(fieldText.length - 10); - addNotice6({ priority: 104, message: "Unexpected trailing break", characterIndex: fieldText.length - 1, extract, location: ourAtString }); + addNotice6({ priority: 104, message: "Unexpected trailing break", characterIndex: fieldText.length - 1, extract, location: ourLocation }); } if ((characterIndex = fieldText.indexOf(' ')) >= 0) { const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/ /g, '␣') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 194, message: "Unexpected double spaces", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 194, message: "Unexpected double spaces", characterIndex, extract, location: ourLocation }); } if ((characterIndex = fieldText.indexOf('\n')) >= 0) { const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 583, message: "Unexpected newLine character", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 583, message: "Unexpected newLine character", characterIndex, extract, location: ourLocation }); } if ((characterIndex = fieldText.indexOf('\r')) >= 0) { const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 582, message: "Unexpected carriageReturn character", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 582, message: "Unexpected carriageReturn character", characterIndex, extract, location: ourLocation }); } if ((characterIndex = fieldText.indexOf('\xA0')) >= 0) { // non-break space const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus).replace(/\xA0/g, '⍽') + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 581, message: "Unexpected non-break space character", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 581, message: "Unexpected non-break space character", characterIndex, extract, location: ourLocation }); } 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 ? '…' : '') - addNotice6({ priority: 580, message: "Unexpected narrow non-break space character", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 580, message: "Unexpected narrow non-break space character", characterIndex, extract, location: ourLocation }); } if ((characterIndex = fieldText.indexOf(' …')) >= 0) { const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 179, message: "Unexpected space before ellipse character", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 179, message: "Unexpected space before ellipse character", characterIndex, extract, location: ourLocation }); } if ((characterIndex = fieldText.indexOf('… ')) >= 0) { const extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 178, message: "Unexpected space after ellipse character", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 178, message: "Unexpected space after ellipse character", characterIndex, extract, location: ourLocation }); } // Check for doubled punctuation chars (international) // Doesn't check for doubled forward slash coz that might occur in a link, e.g., https://etc… @@ -152,7 +149,7 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField characterIndex = fieldText.indexOf(punctChar + punctChar); if (characterIndex >= 0) { let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 177, message: `Unexpected doubled ${punctChar} characters`, characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 177, message: `Unexpected doubled ${punctChar} characters`, characterIndex, extract, location: ourLocation }); } } // Check for punctuation chars following space @@ -160,7 +157,7 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField characterIndex = fieldText.indexOf(' ' + punctChar); if (characterIndex >= 0) { let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 191, message: `Unexpected ${punctChar} character after space`, characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 191, message: `Unexpected ${punctChar} character after space`, characterIndex, extract, location: ourLocation }); } } // Check for punctuation chars before space @@ -169,7 +166,7 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField characterIndex = fieldText.indexOf(punctChar + ' '); if (characterIndex >= 0) { let extract = (characterIndex > halfLength ? '…' : '') + fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus) + (characterIndex + halfLengthPlus < fieldText.length ? '…' : '') - addNotice6({ priority: 192, message: `Unexpected space after ${punctChar} character`, characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 192, message: `Unexpected space after ${punctChar} character`, characterIndex, extract, location: ourLocation }); } } @@ -182,7 +179,7 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField const lCount = countOccurrences(fieldText, leftChar); const rCount = countOccurrences(fieldText, rightChar); if (lCount !== rCount) - addNotice6({ priority: 663, message: `Mismatched ${leftChar}${rightChar} characters`, extract: `(left=${lCount.toLocaleString()}, right=${rCount.toLocaleString()})`, location: ourAtString }); + addNotice6({ priority: 663, message: `Mismatched ${leftChar}${rightChar} characters`, extract: `(left=${lCount.toLocaleString()}, right=${rCount.toLocaleString()})`, location: ourLocation }); } if (!allowedLinks) { @@ -197,7 +194,7 @@ export function checkTextField(fieldName, fieldText, allowedLinks, optionalField if (characterIndex === -1) characterIndex = fieldText.indexOf('.bible'); if (characterIndex >= 0) { let extract = `${characterIndex > halfLength ? '…' : ''}${fieldText.substring(characterIndex - halfLength, characterIndex + halfLengthPlus)}${characterIndex + halfLengthPlus < fieldText.length ? '…' : ''}` - addNotice6({ priority: 765, message: "Unexpected link", characterIndex, extract, location: ourAtString }); + addNotice6({ priority: 765, message: "Unexpected link", characterIndex, extract, location: ourLocation }); } } return result; diff --git a/src/core/file-check.md b/src/core/file-check.md index 16f4c107..81aea7d3 100644 --- a/src/core/file-check.md +++ b/src/core/file-check.md @@ -8,7 +8,7 @@ These raw notice components can then be filtered and/or sorted as required by th ```js import React, { useState, useEffect } from 'react'; -import { checkFile } from './book-package-check'; +import { checkFileContents } from './book-package-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; const sampleUSFM = `\\id GEN EN_ULT en_English_ltr unfoldingWord Literal Text Thu Jul 25 2019 09:33:56 GMT-0400 (EDT) tc @@ -44,19 +44,19 @@ const data = { checkingOptions: {}, } -function CheckFile(props) { +function CheckFileContents(props) { const { filename, fileContent, givenLocation, checkingOptions } = props.data; const [results, setResults] = useState(null); - // We need the following construction because checkFile is an ASYNC function + // We need the following construction because checkFileContents is an ASYNC function useEffect(() => { // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 (async () => { // Display our "waiting" message setResults(

Waiting for {filename} check results…

); - const rawResults = await checkFile(filename, fileContent, givenLocation, checkingOptions); + const rawResults = await checkFileContents(filename, fileContent, givenLocation, checkingOptions); setResults(
Checked {filename}: "{fileContent.substr(0,256)}…"

@@ -67,7 +67,7 @@ function CheckFile(props) { }, []); // end of useEffect part return results; -} // end of CheckFile function +} // end of CheckFileContents function - + ``` diff --git a/src/core/file-text-check.js b/src/core/file-text-check.js index 612c978c..2e52d472 100644 --- a/src/core/file-text-check.js +++ b/src/core/file-text-check.js @@ -5,7 +5,7 @@ import { isWhitespace, countOccurrences } from './text-handling-functions' const DEFAULT_EXTRACT_LENGTH = 10; -export function checkFileText(filename, fileText, optionalFileLocation, optionalCheckingOptions) { +export function checkFileContents(filename, fileText, optionalFileLocation, optionalCheckingOptions) { // Does basic checks for small errors like mismatched punctuation pairs, etc. // (Used by usfm-text-check) @@ -24,12 +24,12 @@ export function checkFileText(filename, fileText, optionalFileLocation, optional // extract: a short extract of the string containing the error (or empty-string if irrelevant) // location: the detailed location string // (Returned in this way for more intelligent processing at a higher level) - // console.log(`checkFileText(${filename}, ${fileText.length.toLocaleString()} chars, ${allowedLinks}, '${optionalFileLocation}')…`); - console.assert(filename !== undefined, "checkFileText: 'filename' parameter should be defined"); - console.assert(typeof filename === 'string', `checkFileText: 'filename' parameter should be a number not a '${typeof filename}': ${filename}`); - console.assert(fileText !== undefined, "checkFileText: 'fileText' parameter should be defined"); - console.assert(typeof fileText === 'string', `checkFileText: 'fileText' parameter should be a number not a '${typeof fileText}': ${fileText}`); - // console.assert( allowedLinks===true || allowedLinks===false, "checkFileText: allowedLinks parameter must be either true or false"); + // console.log(`checkFileContents(${filename}, ${fileText.length.toLocaleString()} chars, ${allowedLinks}, '${optionalFileLocation}')…`); + console.assert(filename !== undefined, "checkFileContents: 'filename' parameter should be defined"); + console.assert(typeof filename === 'string', `checkFileContents: 'filename' parameter should be a number not a '${typeof filename}': ${filename}`); + console.assert(fileText !== undefined, "checkFileContents: 'fileText' parameter should be defined"); + console.assert(typeof fileText === 'string', `checkFileContents: 'fileText' parameter should be a number not a '${typeof fileText}': ${fileText}`); + // console.assert( allowedLinks===true || allowedLinks===false, "checkFileContents: allowedLinks parameter must be either true or false"); let result = { noticeList: [] }; @@ -49,7 +49,7 @@ export function checkFileText(filename, fileText, optionalFileLocation, optional } - // Main code for checkFileText() + // Main code for checkFileContents() if (!fileText) // Nothing to check return result; @@ -123,6 +123,6 @@ export function checkFileText(filename, fileText, optionalFileLocation, optional // } return result; } -// end of checkFileText function +// end of checkFileContents function -export default checkFileText; +export default checkFileContents; diff --git a/src/core/file-text-check.md b/src/core/file-text-check.md index 1921123e..f29b823d 100644 --- a/src/core/file-text-check.md +++ b/src/core/file-text-check.md @@ -1,6 +1,6 @@ ## Basic File Check Sandbox -This `checkFileText()` function can be passed a text and checks for global errors like mismatching punctuation pairs. +This `checkFileContents()` function can be passed a text and checks for global errors like mismatching punctuation pairs. Note that it's not always wise to call this function. If punctuation pairs, etc., are already constrained to, and checked for, in certain fields/parts of the file, then this function may just confuse the user with duplicated warnings. @@ -9,7 +9,7 @@ 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 -import checkFileText from './file-text-check'; +import checkFileContents from './file-text-check'; import { RenderLines, RenderRawResults } from '../demos/RenderProcessedResults'; // Empty, space, good, and bad samples @@ -24,7 +24,7 @@ const textB = `{ Peace on Earth,, const chosenTextName = "textB"; const chosenText = textB; -const rawResults = checkFileText('Sample', chosenText, 'in '+chosenTextName+' that was supplied'); +const rawResults = checkFileContents('Sample', chosenText, 'in '+chosenTextName+' that was supplied'); if (!rawResults.successList || !rawResults.successList.length) rawResults.successList = ["Done basic file checks"]; diff --git a/src/core/markdown-text-check.js b/src/core/markdown-text-check.js index d83f010f..04bb8fac 100644 --- a/src/core/markdown-text-check.js +++ b/src/core/markdown-text-check.js @@ -16,7 +16,7 @@ function checkMarkdownText(textName, markdownText, givenLocation, optionalChecki // console.log(`checkMarkdownText(${textName}, ${markdownText.length}, ${givenLocation})…`); let ourLocation = givenLocation; if (ourLocation && ourLocation[0] !== ' ') ourLocation = ` ${ourLocation}`; - if (textName) ourLocation = ` in ${textName}${ourLocation}`; + // if (textName) ourLocation = ` in ${textName}${ourLocation}`; let extractLength; try { diff --git a/src/core/tn-table-text-check.js b/src/core/tn-table-text-check.js index e84d268d..b418fb69 100644 --- a/src/core/tn-table-text-check.js +++ b/src/core/tn-table-text-check.js @@ -2,7 +2,7 @@ import * as books from './books/books'; import checkTN_TSVDataRow from './tn-table-row-check'; -const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.2.2'; +const TN_TABLE_TEXT_VALIDATOR_VERSION_STRING = '0.2.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'; @@ -10,7 +10,7 @@ const EXPECTED_TN_HEADING_LINE = 'Book\tChapter\tVerse\tID\tSupportReference\tOr const DEFAULT_EXTRACT_LENGTH = 10; -async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckingOptions) { +async function checkTN_TSVText(bookID, filename, tableText, givenLocation, optionalCheckingOptions) { /* This function is optimised for checking the entire file, i.e., all rows. It also has the advantage of being able to compare one row with the previous one. @@ -30,7 +30,7 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin // console.log(`checkTN_TSVText success: ${successString}`); result.successList.push(successString); } - function addNoticeCV8({priority,message, C,V, lineNumber, characterIndex, extract, location}) { + function addNoticeCV8({ priority, message, C, V, rowID, lineNumber, characterIndex, extract, location }) { // console.log(`checkTN_TSVText notice: (priority=${priority}) ${message}${characterIndex > 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); console.assert(priority !== undefined, "TSV addNoticeCV8: 'priority' parameter should be defined"); console.assert(typeof priority === 'number', `TSV addNoticeCV8: 'priority' parameter should be a number not a '${typeof priority}': ${priority}`); @@ -46,7 +46,7 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin if (extract) console.assert(typeof extract === 'string', `TSV addNoticeCV8: 'extract' parameter should be a string not a '${typeof extract}': ${extract}`); console.assert(location !== undefined, "TSV addNoticeCV8: 'location' parameter should be defined"); console.assert(typeof location === 'string', `TSV addNoticeCV8: 'location' parameter should be a string not a '${typeof location}': ${location}`); - result.noticeList.push({priority,message, bookID,C,V, lineNumber, characterIndex, extract, location}); + result.noticeList.push({ priority, message, bookID, C, V, filename, rowID, lineNumber, characterIndex, extract, location }); } @@ -59,7 +59,7 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin // console.log(`Using default extractLength=${extractLength}`); } // else - // console.log(`Using supplied extractLength=${extractLength}`, `cf. default=${DEFAULT_EXTRACT_LENGTH}`); + // 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}`); @@ -71,7 +71,7 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin } catch { if (!books.isValidBookID(bookID)) // must not be in FRT, BAK, etc. - addNoticeCV8({priority:747, message:"Bad function call: should be given a valid book abbreviation", extract:bookID, location:` (not '${bookID}')${ourLocation}`}); + addNoticeCV8({ priority: 747, message: "Bad function call: should be given a valid book abbreviation", extract: bookID, location: ` (not '${bookID}')${ourLocation}` }); } let lines = tableText.split('\n'); @@ -80,13 +80,13 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin let lastB = '', lastC = '', lastV = ''; let rowID_list = []; let numVersesThisChapter = 0; - for (let n= 0; n < lines.length; n++) { + for (let n = 0; n < lines.length; n++) { // console.log(`checkTN_TSVText checking line ${n}: ${JSON.stringify(lines[n])}`); if (n === 0) { if (lines[0] === EXPECTED_TN_HEADING_LINE) addSuccessMessage(`Checked TSV header ${ourLocation}`); else - addNoticeCV8({priority:746, message:"Bad TSV header", lineNumber:n+1, location:`${ourLocation}: '${lines[0]}'`}); + addNoticeCV8({ priority: 746, message: "Bad TSV header", lineNumber: n + 1, location: `${ourLocation}: '${lines[0]}'` }); } else // not the header { @@ -94,27 +94,24 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin if (fields.length === NUM_EXPECTED_TN_TSV_FIELDS) { // eslint-disable-next-line no-unused-vars const [B, C, V, rowID, _support_reference, _orig_quote, _occurrence, _GL_quote, _occurrenceNote] = fields; - const withString = ` with ID '${rowID}'${ourLocation}`; - // let CV_withString = ` ${C}:${V}${withString}`; - // let atString = ` at ${B} ${C}:${V} (${rowID})${inString}`; // Use the row check to do most basic checks - const firstResult = await checkTN_TSVDataRow(lines[n], bookID,C,V, withString, optionalCheckingOptions); + const firstResult = await checkTN_TSVDataRow(lines[n], bookID, C, V, ourLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field // result.noticeList = result.noticeList.concat(firstResult.noticeList); // If we need to put everything through addNoticeCV8, e.g., for debugging or filtering // process results line by line for (const noticeEntry of firstResult.noticeList) - addNoticeCV8({ ...noticeEntry, lineNumber:n+1}); + addNoticeCV8({ ...noticeEntry, lineNumber: n + 1 }); // So here we only have to check against the previous and next fields for out-of-order problems if (B) { if (B !== bookID) - addNoticeCV8({priority:745, C,V, message:`Wrong '${B}' book identifier (expected '${bookID}')`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 745, C, V, message: `Wrong '${B}' book identifier (expected '${bookID}')`, rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({priority:744, C,V, message:"Missing book identifier", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 744, C, V, message: "Missing book identifier", rowID, lineNumber: n + 1, location: ourLocation }); if (C) { if (C === 'front') { } @@ -123,51 +120,51 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin if (C !== lastC) numVersesThisChapter = books.versesInChapter(lowercaseBookID, intC); if (intC === 0) - addNoticeCV8({priority:551, C,V, message:`Invalid zero '${C}' chapter number`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 551, C, V, message: `Invalid zero '${C}' chapter number`, rowID, lineNumber: n + 1, location: ourLocation }); if (intC > numChaptersThisBook) - addNoticeCV8({priority:737, C,V, message:`Invalid large '${C}' chapter number`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 737, C, V, message: `Invalid large '${C}' chapter number`, rowID, lineNumber: n + 1, location: ourLocation }); if (/^\d+$/.test(lastC)) { let lastintC = Number(lastC); if (intC < lastintC) - addNoticeCV8({priority:736, C,V, message:`Receding '${C}' chapter number after '${lastC}'`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 736, C, V, message: `Receding '${C}' chapter number after '${lastC}'`, rowID, lineNumber: n + 1, location: ourLocation }); else if (intC > lastintC + 1) - addNoticeCV8({priority:735, C,V, message:`Advancing '${C}' chapter number after '${lastC}'`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 735, C, V, message: `Advancing '${C}' chapter number after '${lastC}'`, rowID, lineNumber: n + 1, location: ourLocation }); } } else - addNoticeCV8({priority:734, C,V, message:"Bad chapter number", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 734, C, V, message: "Bad chapter number", rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({priority:739, C,V, message:"Missing chapter number", lineNumber:n+1, location:` after ${lastC}:${V}${withString}`}); + addNoticeCV8({ priority: 739, C, V, message: "Missing chapter number", rowID, lineNumber: n + 1, location: ` after ${lastC}:${V}${ourLocation}` }); if (V) { if (V === 'intro') { } else if (/^\d+$/.test(V)) { let intV = Number(V); if (intV === 0) - addNoticeCV8({priority:552, C,V, message:`Invalid zero '${V}' verse number`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 552, C, V, message: `Invalid zero '${V}' verse number`, rowID, lineNumber: n + 1, location: ourLocation }); if (intV > numVersesThisChapter) - addNoticeCV8({priority:734, C,V, message:`Invalid large '${V}' verse number for chapter ${C}`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 734, C, V, message: `Invalid large '${V}' verse number for chapter ${C}`, rowID, lineNumber: n + 1, location: ourLocation }); if (/^\d+$/.test(lastV)) { let lastintV = Number(lastV); if (intV < lastintV) - addNoticeCV8({priority:733, C,V, message:`Receding '${V}' verse number after '${lastV}'`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 733, C, V, message: `Receding '${V}' verse number after '${lastV}'`, rowID, lineNumber: n + 1, location: ourLocation }); // else if (intV > lastintV + 1) // addNoticeCV8({priority:556, `Skipped verses with '${V}' verse number after '${lastV}'${withString}`); } } else - addNoticeCV8({priority:738, C,V, message:"Bad verse number", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 738, C, V, message: "Bad verse number", rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({priority:790, C,V, message:"Missing verse number", lineNumber:n+1, location:` after ${C}:${lastV}${withString}`}); + addNoticeCV8({ priority: 790, C, V, message: "Missing verse number", rowID, lineNumber: n + 1, location: ` after ${C}:${lastV}${ourLocation}` }); if (rowID) { if (rowID_list.indexOf(rowID) >= 0) - addNoticeCV8({priority:729, C,V, message:`Duplicate '${rowID}' ID`, lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 729, C, V, message: `Duplicate '${rowID}' ID`, rowID, lineNumber: n + 1, location: ourLocation }); } else - addNoticeCV8({priority:730, C,V, message:"Missing ID", lineNumber:n+1, location:withString}); + addNoticeCV8({ priority: 730, C, V, message: "Missing ID", lineNumber: n + 1, location: ourLocation }); if (B !== lastB || C !== lastC || V !== lastV) { @@ -180,12 +177,12 @@ async function checkTN_TSVText(bookID, tableText, givenLocation, optionalCheckin // console.log(` Line ${n}: Has ${fields.length} field(s) instead of ${NUM_EXPECTED_TN_FIELDS}: ${EXPECTED_TN_HEADING_LINE.replace(/\t/g, ', ')}`); // else if (n !== lines.length - 1) // it's not the last line - addNoticeCV8({priority:988, message:`Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, extract:`Found ${fields.length} field${fields.length===1?'':'s'}`, lineNumber:n+1, location:ourLocation}); + addNoticeCV8({ priority: 988, message: `Wrong number of tabbed fields (expected ${NUM_EXPECTED_TN_TSV_FIELDS})`, extract: `Found ${fields.length} field${fields.length === 1 ? '' : 's'}`, lineNumber: n + 1, location: ourLocation }); } } addSuccessMessage(`Checked all ${(lines.length - 1).toLocaleString()} data line${lines.length - 1 === 1 ? '' : 's'}${ourLocation}.`); if (result.noticeList) - addSuccessMessage(`checkTN_TSVText v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING} finished with ${result.noticeList.length?result.noticeList.length.toLocaleString():"zero"} notice${result.noticeList.length === 1 ? '' : 's'}`); + addSuccessMessage(`checkTN_TSVText v${TN_TABLE_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 checkTN_TSVText v${TN_TABLE_TEXT_VALIDATOR_VERSION_STRING}`) // console.log(` checkTN_TSVText returning with ${result.successList.length.toLocaleString()} success(es), ${result.noticeList.length.toLocaleString()} notice(s).`); diff --git a/src/core/tn-tsv-table-text-check.md b/src/core/tn-tsv-table-text-check.md index 98d26d37..f9ed5967 100644 --- a/src/core/tn-tsv-table-text-check.md +++ b/src/core/tn-tsv-table-text-check.md @@ -39,11 +39,12 @@ const data = { tableTextName : 'textG', tableText : textG, bookID : 'GEN', + filename: 'dummyFilename', givenLocation : 'that was supplied', } function CheckTNTSVText(props) { - const { bookID, tableText, tableTextName, givenLocation } = props.data; + const { bookID, filename, tableText, tableTextName, givenLocation } = props.data; const [results, setResults] = useState(null); @@ -54,7 +55,7 @@ function CheckTNTSVText(props) { (async () => { // Display our "waiting" message setResults(

Waiting for check results for {tableTextName} {bookID}

); - const rawResults = await checkTN_TSVText(bookID, tableText, givenLocation); + const rawResults = await checkTN_TSVText(bookID, filename, tableText, givenLocation); setResults(
Check {tableTextName}: "{tableText.substr(0,256)}…"

diff --git a/src/core/usfm-text-check.js b/src/core/usfm-text-check.js index 60c044d0..7a03ccad 100644 --- a/src/core/usfm-text-check.js +++ b/src/core/usfm-text-check.js @@ -1,7 +1,7 @@ import * as books from '../core/books/books'; import { isWhitespace, countOccurrences } from './text-handling-functions' import checkTextField from './field-text-check'; -import checkFileText from './file-text-check'; +import checkFileContents from './file-text-check'; import { runUsfmJsCheck } from './usfm-js-check'; import { runBCSGrammarCheck } from './BCS-usfm-grammar-check'; import { ourParseInt } from './utilities'; @@ -126,9 +126,7 @@ function checkUSFMText(bookID, filename, givenText, givenLocation, optionalCheck if (noticeObject.extract) console.assert(typeof noticeObject.extract === 'string', `cUSFM addNoticeCV8: 'extract' parameter should be a string not a '${typeof noticeObject.extract}': ${noticeObject.extract}`); console.assert(noticeObject.location !== undefined, "cUSFM addNoticeCV8: 'location' parameter should be defined"); console.assert(typeof noticeObject.location === 'string', `cUSFM addNoticeCV8: 'location' parameter should be a string not a '${typeof noticeObject.location}': ${noticeObject.location}`); - if (bookID && bookID.length) noticeObject.bookID = bookID; - if (filename && filename.length) noticeObject.filename = filename; - result.noticeList.push(noticeObject); + result.noticeList.push({ ...noticeObject, bookID, filename }); } @@ -381,7 +379,7 @@ function checkUSFMText(bookID, filename, givenText, givenLocation, optionalCheck 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 = checkFileText(filename, fileText, fileLocation, optionalCheckingOptions); + const resultObject = checkFileContents(filename, fileText, fileLocation, optionalCheckingOptions); // Choose only ONE of the following // This is the fast way of append the results from this field diff --git a/src/core/utilities.js b/src/core/utilities.js index 8830a723..455a3f73 100644 --- a/src/core/utilities.js +++ b/src/core/utilities.js @@ -68,6 +68,22 @@ export function ourParseInt(givenString) { } +export function getRepoName(languageCode, repoCode) { + /** + * @description - Creates and returns a Door43 repoName string + * @param {String} languageCode - the language code, e.g., 'en' + * @param {String} repoCode - the repo code, e.g., 'TQ' + * @return {String} - the Door43 repoName string + */ +// console.log(`getRepoName('${languageCode}', '${repoCode}')…`); + let repo_languageCode = languageCode; + if (repoCode === 'UHB') repo_languageCode = 'hbo'; + else if (repoCode === 'UGNT') repo_languageCode = 'el-x-koine'; + const repoName = `${repo_languageCode}_${repoCode.toLowerCase()}`; + return repoName; +} + + /* // function to convert an array to an object // with keys being 0..n diff --git a/src/demos/RenderProcessedResults.js b/src/demos/RenderProcessedResults.js index 717405ba..3710e364 100644 --- a/src/demos/RenderProcessedResults.js +++ b/src/demos/RenderProcessedResults.js @@ -188,22 +188,26 @@ export function RenderBCV({ bookID, C, V }) { return null; } -export function RenderFileDetails({ repoName, filename, lineNumber }) { +export function RenderFileDetails({ repoName, filename, lineNumber, rowID, fieldName }) { /** * @description - Displays the repoName and filename/lineNumber details if specified * @param {String} repoName - (optional) repo name string * @param {String} filename - (optional) filename string - * @param {String} lineNumber - (optional) line number integer (1-based) + * @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})`); + // console.log(`RenderFileDetails(${repoName}, ${filename}, ${lineNumber}, ${rowID}, ${fieldName})`); if (!repoName && !filename && !lineNumber) return null; // They're all undefined or blank! // console.log(`RenderFileDetails2 ${repoName}, ${filename}, ${lineNumber}`); let result = ''; if (repoName && repoName.length) result += ` in ${repoName} repository`; - if (filename && filename.length) result += ` in ${filename}`; + if (filename && filename.length) result += ` in file ${filename}`; if (lineNumber) result += ` on line ${lineNumber.toLocaleString()}`; + if (rowID && rowID.length) result += ` with ID ${rowID}`; + if (fieldName && fieldName.length) result += ` in ${fieldName} field`; return result; } @@ -252,7 +256,7 @@ export function RenderProcessedArray({ arrayType, results }) { return
  • {listEntry.message} - + {listEntry.characterIndex > 0 ? " (at character " + (listEntry.characterIndex + 1) + ")" : ""} {listEntry.extract ? " around '" + listEntry.extract + "'" : ""} {listEntry.location} @@ -280,7 +284,7 @@ export function RenderGivenArray({ array, colour }) { return
  • {listEntry.message} - + {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} {listEntry.extract ? " around '" + listEntry.extract + "'" : ""} {listEntry.location} @@ -318,7 +322,7 @@ export function RenderWarningsGradient({ results }) { return
  • {listEntry.message} - + {listEntry.characterIndex !== undefined && listEntry.characterIndex >= 0 ? " (at character " + (listEntry.characterIndex + 1) + " of line)" : ""} {listEntry.extract ? " around '" + listEntry.extract + "'" : ""} {listEntry.location} diff --git a/src/demos/book-package-check/BookPackageCheck.js b/src/demos/book-package-check/BookPackageCheck.js index d442ba8e..fae99a27 100644 --- a/src/demos/book-package-check/BookPackageCheck.js +++ b/src/demos/book-package-check/BookPackageCheck.js @@ -1,28 +1,27 @@ import React, { useState, useEffect } from 'react'; // import { withStyles } from '@material-ui/core/styles'; import * as books from '../../core/books/books'; -import { checkBookPackage } from '../../core'; +import { getRepoName, ourParseInt, fetchRepositoryZipFile, checkBookPackage } from '../../core'; import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; -import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; -//const VALIDATOR_VERSION_STRING = '0.1.3'; +// const BP_VALIDATOR_VERSION_STRING = '0.2.1'; -function BookPackageCheck(/*username, language_code, bookID,*/ props) { +function BookPackageCheck(/*username, languageCode, bookID,*/ props) { // Check a single Bible book across many repositories const [result, setResultValue] = useState("Waiting-CheckBookPackage"); - // console.log(`I'm here in BookPackageCheck v${VALIDATOR_VERSION_STRING}`); + // console.log(`I'm here in BookPackageCheck v${BP_VALIDATOR_VERSION_STRING}`); // consoleLogObject("props", props); // consoleLogObject("props.classes", props.classes); let username = props.username; // console.log(`username='${username}'`); - let language_code = props.language_code; - // console.log(`language_code='${language_code}'`); + let languageCode = props.languageCode; + // console.log(`languageCode='${languageCode}'`); let bookID = props.bookID; // console.log(`bookID='${bookID}'`); let branch = props.branch; @@ -38,24 +37,42 @@ function BookPackageCheck(/*username, language_code, bookID,*/ props) { if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); useEffect(() => { - const newProps = { bookID, branch, checkingOptions, language_code, cutoffPriorityLevel: props.cutoffPriorityLevel, displayType: props.displayType, errorPriorityLevel: props.errorPriorityLevel, maximumSimilarMessages: props.maximumSimilarMessages, sortBy: props.sortBy, username}; - console.log("useEffect() called with ", newProps); + // 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)); // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 (async () => { - // console.log("Started unnamedFunction()"); + // console.log("Started BookPackageCheck.unnamedFunction()"); + + // NOTE from RJH: I can't find the correct React place for this / way to do this + // so it shows a warning for the user, and doesn't continue to try to process + if (bookID!=='OBS' && !books.isValidBookID(bookID)) { + console.log(`Invalid '${bookID}' bookID given!`) + setResultValue(

    Please enter a valid USFM book identifier or 'OBS'. ('{bookID}' is not valid.)

    ); + return; + } + + // Preload the reference repos + setResultValue(

    Preloading TA/TQ/TW repos for {username} {languageCode}…

    ); + for (const repoCode of ['TA', 'TQ', 'TW']) { + const repoName = getRepoName(languageCode, repoCode); + console.log(`Preloading zip file for ${repoName}…`); + const zipFetchSucceeded = await fetchRepositoryZipFile({ username, repository: repoName, branch }); + if (!zipFetchSucceeded) + console.log(`checkRepo: misfetched zip file for repo with ${zipFetchSucceeded}`); + } // Display our "waiting" message - setResultValue(

    Waiting for check results for {username} {language_code} {bookID} book package…

    ); + setResultValue(

    Waiting for check results for {username} {languageCode} {bookID} book package…

    ); - const rawCBPResults = await checkBookPackage(username, language_code, bookID, setResultValue, checkingOptions); + const rawCBPResults = await checkBookPackage(username, languageCode, bookID, setResultValue, checkingOptions); // console.log("checkBookPackage() returned", typeof rawCBPResults); //, JSON.stringify(rawCBPResults)); // Add some extra fields to our rawCBPResults object in case we need this information again later rawCBPResults.checkType = 'BookPackage'; rawCBPResults.username = username; - rawCBPResults.language_code = language_code; + rawCBPResults.languageCode = languageCode; rawCBPResults.bookID = bookID; rawCBPResults.checkedOptions = checkingOptions; @@ -80,7 +97,7 @@ function BookPackageCheck(/*username, language_code, bookID,*/ props) { function renderSummary(processedResults) { return (<> -

    Checked {username} {language_code} {bookID} (from {branch === undefined ? 'DEFAULT' : branch} branches)

    +

    Checked {username} {languageCode} {bookID} (from {branch === undefined ? 'DEFAULT' : branch} branches)

        Successfully checked {processedResults.checkedFileCount.toLocaleString()} file{processedResults.checkedFileCount===1?'':'s'} from {processedResults.checkedRepoNames.length} repo{processedResults.checkedRepoNames.length===1?'':'s'}: {processedResults.checkedRepoNames.join(', ')}
            including {processedResults.checkedFilenameExtensions.length} file type{processedResults.checkedFilenameExtensions.size === 1 ? '' : 's'}: {processedResults.checkedFilenameExtensions.join(', ')}.

        Finished in .

    @@ -146,10 +163,7 @@ function BookPackageCheck(/*username, language_code, bookID,*/ props) { // console.log("Finished rendering bit."); })(); // end of async part in unnamedFunction // eslint-disable-next-line react-hooks/exhaustive-deps - }, [bookID, branch, JSON.stringify(checkingOptions), language_code, JSON.stringify(props), username]); // end of useEffect part - - if (bookID!=='OBS' && !books.isValidBookID(bookID)) - return (

    Please enter a valid USFM book identifier. ('{bookID}' is not valid.)

    ); + }, [bookID, branch, JSON.stringify(checkingOptions), languageCode, JSON.stringify(props), username]); // end of useEffect part // {/*
    */} return ( @@ -163,7 +177,7 @@ function BookPackageCheck(/*username, language_code, bookID,*/ props) { // /** @ignore */ // username: PropTypes.object.isRequired, // /** @ignore */ -// language_code: PropTypes.object.isRequired, +// languageCode: PropTypes.object.isRequired, // bookID: PropTypes.object.isRequired, // props: PropTypes.object, // }; diff --git a/src/demos/book-package-check/README.md b/src/demos/book-package-check/README.md index 5dd8d9dc..8971160d 100644 --- a/src/demos/book-package-check/README.md +++ b/src/demos/book-package-check/README.md @@ -6,7 +6,7 @@ See a list of valid book identifiers [here](http://ubsicap.github.io/usfm/identi Note that `OBS` can also be entered here as a *pseudo book identifier* in order to check an **Open Bible Stories** repo. -`Book Package Check` calls `checkBookPackage()` which then calls `checkFile()` for the book file in each repo (or calls `checkRepo()` for **OBS**). +`Book Package Check` calls `checkBookPackage()` which then calls `checkFileContents()` for the book file in each repo (or calls `checkRepo()` for **OBS**). **Warning**: Some book packages contain many files and/or very large files, and downloading them all and then checking them might slow down your browser -- maybe even causing pop-up messages asking to confirm that you want to keep waiting. @@ -17,7 +17,7 @@ import BookPackageCheck from './BookPackageCheck'; Waiting for check results for {username} {language_code} {bookID} book package: checked {checkedRepoNames.length.toLocaleString()}/5 repos…

    ); +// setResultValue(

    Waiting for check results for {username} {languageCode} {bookID} book package: checked {checkedRepoNames.length.toLocaleString()}/5 repos…

    ); // } // // Add some extra fields to our checkFileResult object diff --git a/src/demos/book-packages-check/BookPackagesCheck.js b/src/demos/book-packages-check/BookPackagesCheck.js index f60986d0..00d5d8f0 100644 --- a/src/demos/book-packages-check/BookPackagesCheck.js +++ b/src/demos/book-packages-check/BookPackagesCheck.js @@ -1,69 +1,81 @@ import React, { useState, useEffect } from 'react'; // import { withStyles } from '@material-ui/core/styles'; import * as books from '../../core/books/books'; +import { getRepoName, ourParseInt, fetchRepositoryZipFile } from '../../core'; import checkBookPackages from './checkBookPackages'; import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; -import { ourParseInt } from '../../core/utilities'; // import { consoleLogObject } from '../../core/utilities'; -//const VALIDATOR_VERSION_STRING = '0.0.3'; +// const BPS_VALIDATOR_VERSION_STRING = '0.1.1'; -function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { - // Check a single Bible book across many repositories - const [result, setResultValue] = useState("Waiting-CheckBookPackages"); +function BookPackagesCheck(/*username, languageCode, bookIDs,*/ props) { + // Check a single Bible book across many repositories + const [result, setResultValue] = useState("Waiting-CheckBookPackages"); - // console.log(`I'm here in BookPackagesCheck v${VALIDATOR_VERSION_STRING}`); - // consoleLogObject("props", props); - // consoleLogObject("props.classes", props.classes); + // console.log(`I'm here in BookPackagesCheck v${BPS_VALIDATOR_VERSION_STRING}`); + // consoleLogObject("props", props); + // consoleLogObject("props.classes", props.classes); - let username = props.username; - // console.log(`username='${username}'`); - let language_code = props.language_code; - // console.log(`language_code='${language_code}'`); - let bookIDs = props.bookIDs; - // console.log(`bookIDs='${bookIDs}'`); - let branch = props.branch; - // console.log(`branch='${branch}'`); + let username = props.username; + // console.log(`username='${username}'`); + let languageCode = props.languageCode; + // console.log(`languageCode='${languageCode}'`); + let bookIDs = props.bookIDs; + // console.log(`bookIDs='${bookIDs}'`); + let branch = props.branch; + // console.log(`branch='${branch}'`); - // Clear cached files if we've changed repo - // autoClearCache(bookIDs); // This technique avoids the complications of needing a button + // Clear cached files if we've changed repo + // autoClearCache(bookIDs); // This technique avoids the complications of needing a button - let bookIDList = []; - let bookIDInvalid; - for (let bookID of bookIDs.split(',')) { - bookID = bookID.trim(); - if (!books.isValidBookID(bookID) && bookID!=='OBS') { - bookIDInvalid = bookID; + let bookIDList = []; + let bookIDInvalid; + for (let bookID of bookIDs.split(',')) { + bookID = bookID.trim(); + if (!books.isValidBookID(bookID) && bookID!=='OBS') { + bookIDInvalid = bookID; + } + bookIDList.push(bookID); } - bookIDList.push(bookID); - } - // console.log(`bookIDList (${bookIDList.length}) = ${bookIDList.join(', ')}`); - - let checkingOptions = { // Uncomment any of these to test them - // 'extractLength': 25, - }; - // Or this allows the parameters to be specified as a BookPackagesCheck property - if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); - - useEffect(() => { - // Use an IIFE (Immediately Invoked Function Expression) - // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 - (async () => { - // console.log("Started unnamedFunction()"); + // console.log(`bookIDList (${bookIDList.length}) = ${bookIDList.join(', ')}`); + + let checkingOptions = { // Uncomment any of these to test them + // 'extractLength': 25, + }; + // Or this allows the parameters to be specified as a BookPackagesCheck property + if (props.extractLength) checkingOptions.extractLength = ourParseInt(props.extractLength); + + useEffect(() => { + // console.log("BookPackagesCheck.useEffect() called with ", JSON.stringify(props)); + + // Use an IIFE (Immediately Invoked Function Expression) + // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 + (async () => { + // console.log("Started BookPackagesCheck.unnamedFunction()"); + + // Preload the reference repos + setResultValue(

    Preloading UHB/UGNT, and TA/TQ/TW repos for {username} {languageCode}…

    ); + for (const repoCode of ['UHB','UGNT', 'TA','TQ','TW']) { + const repoName = getRepoName(languageCode, repoCode); + console.log(`Preloading zip file for ${repoName}…`); + const zipFetchSucceeded = await fetchRepositoryZipFile({ username, repository: repoName, branch }); + if (!zipFetchSucceeded) + console.log(`checkRepo: misfetched zip file for repo with ${zipFetchSucceeded}`); + } // Display our "waiting" message - setResultValue(

    Waiting for check results for {username} {language_code} {bookIDList.join(', ')} book packages…

    ); + setResultValue(

    Waiting for check results for {username} {languageCode} {bookIDList.join(', ')} book packages…

    ); - const rawCBPsResults = await checkBookPackages(username, language_code, bookIDList, setResultValue, checkingOptions); + const rawCBPsResults = await checkBookPackages(username, languageCode, bookIDList, setResultValue, checkingOptions); // console.log("checkBookPackage() returned", typeof rawCBPsResults); //, JSON.stringify(rawCBPsResults)); // Add some extra fields to our rawCBPsResults object in case we need this information again later rawCBPsResults.checkType = 'BookPackages'; rawCBPsResults.username = username; - rawCBPsResults.language_code = language_code; + rawCBPsResults.languageCode = languageCode; rawCBPsResults.bookIDs = bookIDs; rawCBPsResults.bookIDList = bookIDList; rawCBPsResults.checkedOptions = checkingOptions; @@ -96,7 +108,7 @@ function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { function renderSummary() { return (<> -

    Checked {username} {language_code} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches)

    +

    Checked {username} {languageCode} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches)

        Successfully checked {processedResults.checkedFileCount.toLocaleString()} file{processedResults.checkedFileCount===1?'':'s'} from {username} {processedResults.checkedRepoNames.join(', ')}
            including {processedResults.checkedFilenameExtensions.length} file type{processedResults.checkedFilenameExtensions.size === 1 ? '' : 's'}: {processedResults.checkedFilenameExtensions.join(', ')}.

        Finished in .

    @@ -123,13 +135,13 @@ function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { if (processedResults.severeList.length || processedResults.mediumList.length || processedResults.lowList.length) setResultValue(<> -

    Checked {username} {language_code} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) +

    Checked {username} {languageCode} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) {processedResults.numIgnoredNotices ? ` (but ${processedResults.numIgnoredNotices.toLocaleString()} ignored errors/warnings)` : ""}

    ); else // no severe, medium, or low notices setResultValue(<> -

    Checked {username} {language_code} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) +

    Checked {username} {languageCode} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) {processedResults.numIgnoredNotices ? ` (with a total of ${processedResults.numIgnoredNotices.toLocaleString()} notices ignored)` : ""}

    ); @@ -140,13 +152,13 @@ function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { if (processedResults.warningList.length) setResultValue(<> -

    Checked {username} {language_code} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) +

    Checked {username} {languageCode} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) {processedResults.numIgnoredNotices ? ` (but ${processedResults.numIgnoredNotices.toLocaleString()} ignored errors/warnings)` : ""}

    ); else // no warnings setResultValue(<> -

    Checked {username} {language_code} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) +

    Checked {username} {languageCode} {bookIDList.join(', ')} (from {branch === undefined ? 'DEFAULT' : branch} branches) {processedResults.numIgnoredNotices ? ` (with a total of ${processedResults.numIgnoredNotices.toLocaleString()} notices ignored)` : ""}

    ); @@ -154,9 +166,9 @@ function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { // console.log("Finished rendering bit."); })(); // end of async part in unnamedFunction - // Doesn't work if we add this to next line: bookIDList,bookIDs,username,branch,checkingOptions,language_code,props + // Doesn't work if we add this to next line: bookIDList,bookIDs,username,branch,checkingOptions,languageCode,props // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(bookIDList), bookIDs, branch, JSON.stringify(checkingOptions), language_code, JSON.stringify(props), username]); // end of useEffect part + }, [JSON.stringify(bookIDList), bookIDs, branch, JSON.stringify(checkingOptions), languageCode, JSON.stringify(props), username]); // end of useEffect part if (bookIDInvalid) { return (

    Please enter only valid USFM book identifiers separated by commas. ('{bookIDInvalid}' is not valid.)

    ); @@ -174,7 +186,7 @@ function BookPackagesCheck(/*username, language_code, bookIDs,*/ props) { // /** @ignore */ // username: PropTypes.object.isRequired, // /** @ignore */ -// language_code: PropTypes.object.isRequired, +// languageCode: PropTypes.object.isRequired, // bookIDs: PropTypes.object.isRequired, // props: PropTypes.object, // }; diff --git a/src/demos/book-packages-check/README.md b/src/demos/book-packages-check/README.md index 6e915d6b..b3e3c38e 100644 --- a/src/demos/book-packages-check/README.md +++ b/src/demos/book-packages-check/README.md @@ -6,7 +6,7 @@ See a list of valid book identifiers [here](http://ubsicap.github.io/usfm/identi Note that `OBS` can also be entered here as a *pseudo book identifier* in order to check an **Open Bible Stories** repo. -`Book Packages Check` calls `checkBookPackages()` which then calls `checkBookPackage()` for each given book identifier, which in turn calls `checkFile()` for the book file in each repo (or calls `checkRepo()` for **OBS**). +`Book Packages Check` calls `checkBookPackages()` which then calls `checkBookPackage()` for each given book identifier, which in turn calls `checkFileContents()` for the book file in each repo (or calls `checkRepo()` for **OBS**). **Warning**: Some book packages contain many files and/or very large files, and downloading them all and then checking them might slow down your browser -- maybe even causing pop-up messages asking to confirm that you want to keep waiting. @@ -17,10 +17,10 @@ import BookPackagesCheck from './BookPackagesCheck'; 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); + console.log(`cBPs addNotice10: (priority=${priority}) ${extra} ${message}${characterIndex > 0 ? ` (at character ${characterIndex}${1})` : ""}${extract ? ` ${extract}` : ""}${location}`); console.assert(priority !== undefined, "cBPs addNotice10: 'priority' parameter should be defined"); console.assert(typeof priority === 'number', `cBPs addNotice10: 'priority' parameter should be a number not a '${typeof priority}'`); console.assert(message !== undefined, "cBPs addNotice10: 'message' parameter should be defined"); @@ -44,7 +44,7 @@ async function checkBookPackages(username, language_code, bookIDList, setResultV console.assert(typeof location === 'string', `cBPs addNotice10: 'location' parameter should be a string not a '${typeof location}'`); console.assert(extra !== undefined, "cBPs addNotice10: 'extra' parameter should be defined"); console.assert(typeof extra === 'string', `cBPs addNotice10: 'extra' parameter should be a string not a '${typeof extra}'`); - checkBookPackagesResult.noticeList.push({priority,message, bookID,C,V, lineNumber, characterIndex, extract, location, extra}); + checkBookPackagesResult.noticeList.push({priority,message, bookID,C,V, repoName,filename,rowID,lineNumber, fieldName, characterIndex, extract, location, extra}); } @@ -53,7 +53,7 @@ async function checkBookPackages(username, language_code, bookIDList, setResultV for (const bookID of bookIDList) { // console.log(`checkBookPackages bookID: ${bookID}`); - // const generalLocation = ` ${language_code} ${bookID} book packages from ${username}`; + // const generalLocation = ` ${languageCode} ${bookID} book packages from ${username}`; if (bookID !== 'OBS') { // eslint-disable-next-line no-unused-vars let bookNumberAndName; //, whichTestament; @@ -70,7 +70,7 @@ async function checkBookPackages(username, language_code, bookIDList, setResultV // We use the generalLocation here (does not include repo name) // so that we can adjust the returned strings ourselves - const cbpResultObject = await checkBookPackage(username, language_code, bookID, setResultValue, checkingOptions); + const cbpResultObject = await checkBookPackage(username, languageCode, bookID, setResultValue, checkingOptions); // console.log(`checkBookPackage() returned ${cbpResultObject.successList.length} success message(s) and ${cbpResultObject.noticeList.length} notice(s)`); // Concat is faster if we don't need to process each success message individually @@ -97,7 +97,7 @@ async function checkBookPackages(username, language_code, bookIDList, setResultV // addSuccessMessage(`${checkedFileCount.toLocaleString()}/ Checked ${bookID} book package`); // Update our "waiting" message {checkedFileCount==1?'':'s'} - // setResultValue(

    Waiting for check results for {username} {language_code} {bookIDList} book package: checked {checkedFileCount.toLocaleString()}/5 repos…

    ); + // setResultValue(

    Waiting for check results for {username} {languageCode} {bookIDList} book package: checked {checkedFileCount.toLocaleString()}/5 repos…

    ); } // Add some extra fields to our checkFileResult object @@ -107,7 +107,7 @@ async function checkBookPackages(username, language_code, bookIDList, setResultV checkBookPackagesResult.checkedFilenameExtensions = [...checkedFilenameExtensions]; // convert Set to Array checkBookPackagesResult.checkedFilesizes = totalCheckedSize; checkedRepoNames = [...checkedRepoNames]; // Convert set to Array - const index = checkedRepoNames.indexOf(`${username}/${language_code}_obs`); + const index = checkedRepoNames.indexOf(`${username}/${languageCode}_obs`); if (index !== -1) checkedRepoNames[index] = 'OBS'; // Looks tidier here checkBookPackagesResult.checkedRepoNames = checkedRepoNames; // checkBookPackagesResult.checkedOptions = checkingOptions; // This is done at the caller level diff --git a/src/demos/clear-cache/ClearCache.js b/src/demos/clear-cache/ClearCache.js index 26288e39..7903a6b0 100644 --- a/src/demos/clear-cache/ClearCache.js +++ b/src/demos/clear-cache/ClearCache.js @@ -25,7 +25,7 @@ function ClearCache({areYouSure}) { // /** @ignore */ // username: PropTypes.object.isRequired, // /** @ignore */ -// language_code: PropTypes.object.isRequired, +// languageCode: PropTypes.object.isRequired, // bookIDs: PropTypes.object.isRequired, // props: PropTypes.object, // }; diff --git a/src/demos/file-check/FileCheck.js b/src/demos/file-check/FileCheck.js index 12fa1dbc..0605128e 100644 --- a/src/demos/file-check/FileCheck.js +++ b/src/demos/file-check/FileCheck.js @@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react'; // import { Paper, Button } from '@material-ui/core'; // import { RepositoryContext, FileContext } from 'gitea-react-toolkit'; import { withStyles } from '@material-ui/core/styles'; -import { getFile, checkFile } from '../../core'; +import { getFile, checkFileContents } from '../../core'; import { processNoticesToErrorsWarnings, processNoticesToSevereMediumLow, processNoticesToSingleList } from '../notice-processing-functions'; import { RenderSuccessesErrorsWarnings, RenderSuccessesSevereMediumLow, RenderSuccessesWarningsGradient, RenderElapsedTime } from '../RenderProcessedResults'; import { ourParseInt } from '../../core/utilities'; @@ -20,6 +20,8 @@ function FileCheck(props) { const [result, setResultValue] = useState("Waiting-FileCheck"); useEffect(() => { + // console.log("FileCheck.useEffect() called with ", JSON.stringify(props)); + // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 (async () => { @@ -31,7 +33,7 @@ function FileCheck(props) { const fileContent = await getFile({ username: username, repository: repoName, path: filename, branch: branch }); let rawCFResults = { noticeList:[{priority:990, message:"Unable to load file", filename}], elapsedSeconds:0 }; if (fileContent) - rawCFResults = await checkFile(filename, fileContent, givenLocation, checkingOptions); + rawCFResults = await checkFileContents(filename, fileContent, givenLocation, checkingOptions); // console.log(`FileCheck got initial results with ${rawCFResults.successList.length} success message(s) and ${rawCFResults.noticeList.length} notice(s)`); // Since we know the repoName here, add it to our notices @@ -126,7 +128,8 @@ function FileCheck(props) { } else setResultValue(Invalid displayType='{displayType}') })(); // end of async part in unnamedFunction // Doesn't work if we add this to next line: username,repoName,branch,checkingOptions,filename,givenLocation,props - }); // end of useEffect part + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // end of useEffect part const username = props.username; // console.log(`FileCheck username='${username}'`); diff --git a/src/demos/file-check/checkFile.js b/src/demos/file-check/checkFile.js index e29a48fd..74a4515f 100644 --- a/src/demos/file-check/checkFile.js +++ b/src/demos/file-check/checkFile.js @@ -14,7 +14,7 @@ // async function checkFileDemo(filename, fileContent, givenLocation, checkingOptions) { // // Determine the file type from the filename extension // // and return the results of checking that kind of file -// // console.log(`I'm here in checkFile v${CHECK_FILE_VERSION_STRING} +// // console.log(`I'm here in checkFileContents v${CHECK_FILE_VERSION_STRING} // // with ${filename}, ${fileContent.length} chars, ${givenLocation}, ${JSON.stringify(checkingOptions)}`); // const startTime = new Date(); @@ -27,7 +27,7 @@ // // console.log(`Have TSV filenameMain=${filenameMain}`); // const bookID = filenameMain.substring(filenameMain.length - 3); // // console.log(`Have TSV bookcode=${bookID}`); -// console.assert(books.isValidBookID(bookID), `checkFile: '${bookID}' is not a valid USFM book identifier`); +// console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); // checkFileResult = await checkTN_TSVText(bookID, fileContent, ourCFLocation, checkingOptions); // } // else if (filename.toLowerCase().endsWith('.usfm')) { @@ -35,14 +35,14 @@ // // console.log(`Have USFM filenameMain=${filenameMain}`); // const bookID = filenameMain.substring(filenameMain.length - 3); // // console.log(`Have USFM bookcode=${bookID}`); -// console.assert(books.isValidBookID(bookID), `checkFile: '${bookID}' is not a valid USFM book identifier`); +// console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); // checkFileResult = checkUSFMText(bookID, filename, fileContent, ourCFLocation, checkingOptions); // } else if (filename.toLowerCase().endsWith('.sfm')) { // const filenameMain = filename.substring(0, filename.length - 4); // drop .sfm // console.log(`Have SFM filenameMain=${filenameMain}`); // const bookID = filenameMain.substring(2, 5); // console.log(`Have SFM bookcode=${bookID}`); -// console.assert(books.isValidBookID(bookID), `checkFile: '${bookID}' is not a valid USFM book identifier`); +// console.assert(books.isValidBookID(bookID), `checkFileContents: '${bookID}' is not a valid USFM book identifier`); // checkFileResult = checkUSFMText(bookID, filename, fileContent, ourCFLocation, checkingOptions); // } else if (filename.toLowerCase().endsWith('.md')) // checkFileResult = checkMarkdownText(filename, fileContent, ourCFLocation, checkingOptions); @@ -56,7 +56,7 @@ // checkFileResult = checkPlainText(filename, fileContent, ourCFLocation, checkingOptions); // checkFileResult.noticeList.unshift({priority:995, message:"File extension is not recognized, so treated as plain text.", location:filename}); // } -// // console.log(`checkFile got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); +// // console.log(`checkFileContents got initial results with ${checkFileResult.successList.length} success message(s) and ${checkFileResult.noticeList.length} notice(s)`); // // Add some extra fields to our checkFileResult object // // in case we need this information again later @@ -68,6 +68,6 @@ // checkFileResult.elapsedSeconds = (new Date() - startTime) / 1000; // seconds // return checkFileResult; // }; -// // end of checkFile() +// // end of checkFileContents() // export default checkFileDemo; diff --git a/src/demos/notice-processing-functions.js b/src/demos/notice-processing-functions.js index 3bfafd5c..0370bd7b 100644 --- a/src/demos/notice-processing-functions.js +++ b/src/demos/notice-processing-functions.js @@ -1,7 +1,7 @@ // import { displayPropertyNames, consoleLogObject } from './utilities'; -// const NOTICE_PROCESSOR_VERSION_STRING = '0.6.1'; +// const NOTICE_PROCESSOR_VERSION_STRING = '0.6.2'; // All of the following can be overriden with optionalProcessingOptions const DEFAULT_MAXIMUM_SIMILAR_MESSAGES = 3; // Zero means no suppression of similar messages @@ -43,7 +43,9 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { V: Verse number string (can also be a bridge, e.g., '22-23') repoName: repository name (if relevant) filename: string (if relevant) + rowID: 4-character string (if relevant) lineNumber: A one-based integer indicating the line number in the file + fieldName: string (if relevant) characterIndex: A zero-based integer index which indicates the position of the error on the line or in the text field as appropriate. extract: An extract of the checked text which indicates the area @@ -114,7 +116,8 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { duplicatePriorityList.push(thisPriority); // so that we only give the error once } // Check fields for bad values, and also across fields for unexpected combinations - const thisRepoName = thisGivenNotice.repoName, thisFilename = thisGivenNotice.filename, thisLineNumber = thisGivenNotice.lineNumber, thisLocation = thisGivenNotice.location; + const thisRepoName = thisGivenNotice.repoName, thisFilename = thisGivenNotice.filename, thisLineNumber = thisGivenNotice.lineNumber, + thisRowID = thisGivenNotice.rowID, thisFieldName = thisGivenNotice.fieldName, thisLocation = thisGivenNotice.location if (thisRepoName) { console.assert(thisRepoName.indexOf(' ') < 0 && thisRepoName.indexOf('/') < 0 && thisRepoName.indexOf('\\') < 0, `repoName '${thisRepoName}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); if (thisLocation) @@ -125,11 +128,22 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { if (thisLocation) console.assert(thisLocation.indexOf(thisFilename) < 0, `filename is repeated in location in ${JSON.stringify(thisGivenNotice)}`); } + if (thisRowID) { + console.assert(thisRowID.indexOf(' ') < 0 && thisRowID.indexOf('/') < 0 && thisRowID.indexOf('\\') < 0, `rowID '${thisRowID}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); + if (thisLocation) + console.assert(thisLocation.indexOf(thisRowID) < 0, `rowID is repeated in location in ${JSON.stringify(thisGivenNotice)}`); + } + if (thisFieldName) { + console.assert(thisFieldName.indexOf(' ') < 0 && thisFieldName.indexOf('/') < 0 && thisFieldName.indexOf('\\') < 0, `fieldName '${thisFieldName}' contains unexpected characters in ${JSON.stringify(thisGivenNotice)}`); + if (thisLocation) + console.assert(thisLocation.indexOf(thisFieldName) < 0, `fieldName is repeated in location in ${JSON.stringify(thisGivenNotice)}`); + } if (thisLineNumber) { // console.log("thisLineNumber", thisLineNumber); + // Note: lineNumber can occur in location, e.g., in 3 in '3JN' so have to take extra care not to give false alarms console.assert(typeof thisLineNumber === 'number' && thisLineNumber > 0, `lineNumber '${thisLineNumber}' contains unexpected value in ${JSON.stringify(thisGivenNotice)}`); - if (thisLocation) - console.assert(thisLocation.indexOf(thisLineNumber + '') < 0 && thisLocation.indexOf(thisLineNumber.toLocaleString()) < 0, `lineNumber is repeated in location in ${JSON.stringify(thisGivenNotice)}`); + if (thisLocation && (!thisGivenNotice.bookID || thisGivenNotice.bookID.indexOf(thisLineNumber+'')<0)) + console.assert(thisLocation.indexOf(thisLineNumber + '') < 0 && thisLocation.indexOf(thisLineNumber.toLocaleString()) < 0, `lineNumber might be repeated in location in ${JSON.stringify(thisGivenNotice)}`); } numberStore[thisPriority] = thisMsg; } @@ -276,6 +290,25 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { else if (sortBy !== 'AsFound') console.log(`ERROR: Sorting '${sortBy}' is not implemented yet!!!`); + /* + // Add additional information fields to the location + const newNoticeList = []; + for (const thisNotice of remainingNoticeList) { + const newNotice = thisNotice; + if (newNotice.location) newNotice.location = newNotice.location.trim(); // Remove any leading spaces + else newNotice.location = ''; + if (newNotice.repoName) newNotice.location = `in ${newNotice.filename} repoName ${newNotice.location}` + if (newNotice.filename) newNotice.location = `in file ${newNotice.filename} ${newNotice.location}`; + if (newNotice.rowID) newNotice.location = `with ID ${newNotice.rowID} ${newNotice.location}`; + if (newNotice.lineNumber) newNotice.location = `in line ${newNotice.lineNumber} ${newNotice.location}`; + if (newNotice.fieldName) newNotice.location = `in ${newNotice.fieldName} field ${newNotice.location}`; + // Default is to prepend extra to the message + // This prevents errors/warnings from different repos or books from being combined + if (newNotice.extra) newNotice.message = `${newNotice.extra} ${newNotice.message}`; + newNoticeList.push(newNotice); + } + */ + // Add in extra location info if it's there // Default is to prepend it to the msg // This prevents errors/warnings from different repos or books from being combined @@ -284,274 +317,268 @@ function processNoticesCommon(givenNoticeObject, optionalProcessingOptions) { // console.log(`We need to add the extra location, e.g. '${remainingNoticeList[0][5]}': will prepend it to the messages`); const newNoticeList = []; for (const thisNotice of remainingNoticeList) { - console.assert(thisNotice.extra && thisNotice.extra.length, `Expect thisNotice to have an "extra" field: ${JSON.stringify(thisNotice)}`) - // const newNotice = { - // priority: thisNotice.priority, - // message: `${thisNotice.extra} ${thisNotice.message}`, - // characterIndex: thisNotice.characterIndex, - // extract: thisNotice.extract, - // location: thisNotice.location - // }; - // if (thisNotice.bookID) newNotice.bookID = thisNotice.bookID; - // if (thisNotice.C) newNotice.C = thisNotice.C; - // if (thisNotice.V) newNotice.V = thisNotice.V; - const newNotice = { ...thisNotice, message: `${thisNotice.extra} ${thisNotice.message}` }; + const thisExtra = thisNotice.extra; + console.assert(thisExtra && thisExtra.length, `Expect thisNotice to have an "extra" field: ${JSON.stringify(thisNotice)}`) + const newNotice = { ...thisNotice }; + // We don't need the extra field if we've already got this info + if (thisExtra !== thisNotice.repoName && thisExtra !== thisNotice.bookID) + newNotice.message = `${thisNotice.extra} ${thisNotice.message}`; delete newNotice.extra; // since we've used it (if it existed) newNoticeList.push(newNotice); } remainingNoticeList = newNoticeList; } - // Count the number of occurrences of each message - // ready for further processing - const allTotals = {}; - for (const thisNotice of remainingNoticeList) - if (isNaN(allTotals[thisNotice.priority])) allTotals[thisNotice.priority] = 1; - else allTotals[thisNotice.priority]++; - - return [remainingNoticeList, allTotals, resultObject]; -} -// end of processNoticesCommon function - - -export function processNoticesToErrorsWarnings(givenNoticeObject, optionalProcessingOptions) { - /* - Available options are: - errorPriorityLevel (integer; default is DEFAULT_ERROR_PRIORITY_LEVEL above) - maximumSimilarMessages (integer; default is DEFAULT_MAXIMUM_SIMILAR_MESSAGES above) - - Returns an object with: - successList: a list of strings describing what has been checked - errorList - warningList - numIgnoredNotices, numSuppressedErrors, numSuppressedWarnings - processingOptions: just helpfully passes on what we were given (may be undefined) - Also, any other parameters are just passed through, - although filenameList might be abbreviated, e.g. for 100s of .md files. - */ - // console.log(`processNoticesToErrorsWarnings v${NOTICE_PROCESSOR_VERSION_STRING} with options=${JSON.stringify(optionalProcessingOptions)} - // Given ${givenNoticeObject.successList.length.toLocaleString()} success string(s) plus ${givenNoticeObject.noticeList.length.toLocaleString()} notice(s)`); - - const [remainingNoticeList, allTotals, resultObject] = processNoticesCommon(givenNoticeObject, optionalProcessingOptions); - - // Add the fields that we need here to the existing resultObject - resultObject.errorList = []; resultObject.warningList = []; - resultObject.numSuppressedErrors = 0; resultObject.numSuppressedWarnings = 0; + // Count the number of occurrences of each message + // ready for further processing + const allTotals = {}; + for (const thisNotice of remainingNoticeList) + if (isNaN(allTotals[thisNotice.priority])) allTotals[thisNotice.priority] = 1; + else allTotals[thisNotice.priority]++; - let maximumSimilarMessages; - try { - maximumSimilarMessages = optionalProcessingOptions.maximumSimilarMessages; - } catch (npfMSMerror) { } - if (typeof maximumSimilarMessages !== 'number' || isNaN(maximumSimilarMessages)) { - maximumSimilarMessages = DEFAULT_MAXIMUM_SIMILAR_MESSAGES; - // console.log(`Using default maximumSimilarMessages=${maximumSimilarMessages}`); + return [remainingNoticeList, allTotals, resultObject]; } - // else console.log(`Using supplied maximumSimilarMessages=${maximumSimilarMessages} cf. default=${DEFAULT_MAXIMUM_SIMILAR_MESSAGES}`); - let errorPriorityLevel; - try { - errorPriorityLevel = optionalProcessingOptions.errorPriorityLevel; - } catch (npfEPLerror) { } - if (errorPriorityLevel === undefined) { - errorPriorityLevel = DEFAULT_ERROR_PRIORITY_LEVEL; - // console.log(`Using default errorPriorityLevel=${errorPriorityLevel}`); - } - else console.log(`Using supplied errorPriorityLevel=${errorPriorityLevel} cf. default=${DEFAULT_ERROR_PRIORITY_LEVEL}`); + // end of processNoticesCommon function + + + export function processNoticesToErrorsWarnings(givenNoticeObject, optionalProcessingOptions) { + /* + Available options are: + errorPriorityLevel (integer; default is DEFAULT_ERROR_PRIORITY_LEVEL above) + maximumSimilarMessages (integer; default is DEFAULT_MAXIMUM_SIMILAR_MESSAGES above) + + Returns an object with: + successList: a list of strings describing what has been checked + errorList + warningList + numIgnoredNotices, numSuppressedErrors, numSuppressedWarnings + processingOptions: just helpfully passes on what we were given (may be undefined) + Also, any other parameters are just passed through, + although filenameList might be abbreviated, e.g. for 100s of .md files. + */ + // console.log(`processNoticesToErrorsWarnings v${NOTICE_PROCESSOR_VERSION_STRING} with options=${JSON.stringify(optionalProcessingOptions)} + // Given ${givenNoticeObject.successList.length.toLocaleString()} success string(s) plus ${givenNoticeObject.noticeList.length.toLocaleString()} notice(s)`); + + const [remainingNoticeList, allTotals, resultObject] = processNoticesCommon(givenNoticeObject, optionalProcessingOptions); + + // Add the fields that we need here to the existing resultObject + resultObject.errorList = []; resultObject.warningList = []; + resultObject.numSuppressedErrors = 0; resultObject.numSuppressedWarnings = 0; + + let maximumSimilarMessages; + try { + maximumSimilarMessages = optionalProcessingOptions.maximumSimilarMessages; + } catch (npfMSMerror) { } + if (typeof maximumSimilarMessages !== 'number' || isNaN(maximumSimilarMessages)) { + maximumSimilarMessages = DEFAULT_MAXIMUM_SIMILAR_MESSAGES; + // console.log(`Using default maximumSimilarMessages=${maximumSimilarMessages}`); + } + // else console.log(`Using supplied maximumSimilarMessages=${maximumSimilarMessages} cf. default=${DEFAULT_MAXIMUM_SIMILAR_MESSAGES}`); + let errorPriorityLevel; + try { + errorPriorityLevel = optionalProcessingOptions.errorPriorityLevel; + } catch (npfEPLerror) { } + if (errorPriorityLevel === undefined) { + errorPriorityLevel = DEFAULT_ERROR_PRIORITY_LEVEL; + // console.log(`Using default errorPriorityLevel=${errorPriorityLevel}`); + } + else console.log(`Using supplied errorPriorityLevel=${errorPriorityLevel} cf. default=${DEFAULT_ERROR_PRIORITY_LEVEL}`); - // Check for repeated notices that should be compressed - // while simultaneously separating into error and warning lists - let counter = {}; - for (const thisNotice of remainingNoticeList) { - const thisPriority = thisNotice.priority, thisMsg = thisNotice.message; - const thisID = thisPriority + thisMsg; // Could have identical worded messages but with different priorities - if (isNaN(counter[thisID])) counter[thisID] = 1; - else counter[thisID]++; - if (maximumSimilarMessages > 0 && counter[thisID] === maximumSimilarMessages + 1) { - if (thisPriority >= errorPriorityLevel) { - const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; - resultObject.errorList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR ERROR${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); - resultObject.numSuppressedErrors++; - } else { - const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; - resultObject.warningList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR WARNING${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); - resultObject.numSuppressedWarnings++; - } - } else if (maximumSimilarMessages > 0 && counter[thisID] > maximumSimilarMessages + 1) { - if (thisPriority >= errorPriorityLevel) - resultObject.numSuppressedErrors++; + // Check for repeated notices that should be compressed + // while simultaneously separating into error and warning lists + let counter = {}; + for (const thisNotice of remainingNoticeList) { + const thisPriority = thisNotice.priority, thisMsg = thisNotice.message; + const thisID = thisPriority + thisMsg; // Could have identical worded messages but with different priorities + if (isNaN(counter[thisID])) counter[thisID] = 1; + else counter[thisID]++; + if (maximumSimilarMessages > 0 && counter[thisID] === maximumSimilarMessages + 1) { + if (thisPriority >= errorPriorityLevel) { + const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; + resultObject.errorList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR ERROR${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); + resultObject.numSuppressedErrors++; + } else { + const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; + resultObject.warningList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR WARNING${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); + resultObject.numSuppressedWarnings++; + } + } else if (maximumSimilarMessages > 0 && counter[thisID] > maximumSimilarMessages + 1) { + if (thisPriority >= errorPriorityLevel) + resultObject.numSuppressedErrors++; + else + resultObject.numSuppressedWarnings++; + } else if (thisPriority >= errorPriorityLevel) + resultObject.errorList.push(thisNotice); else - resultObject.numSuppressedWarnings++; - } else if (thisPriority >= errorPriorityLevel) - resultObject.errorList.push(thisNotice); - else - resultObject.warningList.push(thisNotice); - } - - // console.log(`processNoticesToErrorsWarnings is returning ${resultObject.successList.length} successes, ${resultObject.errorList.length} errors, and ${resultObject.warningList.length} warnings - // numIgnoredNotices=${resultObject.numIgnoredNotices} numSuppressedErrors=${resultObject.numSuppressedErrors} numSuppressedWarnings=${resultObject.numSuppressedWarnings}`); - return resultObject; -} -// end of processNoticesToErrorsWarnings function - - -export function processNoticesToSevereMediumLow(givenNoticeObject, optionalProcessingOptions) { - /* - Available options are: - severePriorityLevel (integer; default is DEFAULT_SEVERE_PRIORITY_LEVEL above) - mediumPriorityLevel (integer; default is DEFAULT_MEDIUM_PRIORITY_LEVEL above) - maximumSimilarMessages (integer; default is DEFAULT_MAXIMUM_SIMILAR_MESSAGES above) - - Returns an object with: - successList: a list of strings describing what has been checked - severeList - mediumList - lowList - numIgnoredNotices, numSevereSuppressed, numMediumSuppressed, numLowSuppressed - processingOptions: just helpfully passes on what we were given (may be undefined) - Also, any other parameters are just passed through, - although filenameList might be abbreviated, e.g. for 100s of .md files. - */ - // console.log(`processNoticesToSevereMediumLow v${NOTICE_PROCESSOR_VERSION_STRING} with options=${JSON.stringify(optionalProcessingOptions)} - // Given ${givenNoticeObject.successList.length.toLocaleString()} success string(s) plus ${givenNoticeObject.noticeList.length.toLocaleString()} notice(s)`); - - const [remainingNoticeList, allTotals, resultObject] = processNoticesCommon(givenNoticeObject, optionalProcessingOptions); - - // Add the fields that we need here to the existing resultObject - resultObject.severeList = []; resultObject.mediumList = []; resultObject.lowList = []; - resultObject.numSevereSuppressed = 0; resultObject.numMediumSuppressed = 0; resultObject.numLowSuppressed = 0; + resultObject.warningList.push(thisNotice); + } - let maximumSimilarMessages; - try { - maximumSimilarMessages = optionalProcessingOptions.maximumSimilarMessages; - } catch (npfMSMerror) { } - if (typeof maximumSimilarMessages !== 'number' || isNaN(maximumSimilarMessages)) { - maximumSimilarMessages = DEFAULT_MAXIMUM_SIMILAR_MESSAGES; - // console.log(`Using default maximumSimilarMessages=${maximumSimilarMessages}`); + // console.log(`processNoticesToErrorsWarnings is returning ${resultObject.successList.length} successes, ${resultObject.errorList.length} errors, and ${resultObject.warningList.length} warnings + // numIgnoredNotices=${resultObject.numIgnoredNotices} numSuppressedErrors=${resultObject.numSuppressedErrors} numSuppressedWarnings=${resultObject.numSuppressedWarnings}`); + return resultObject; } - // else console.log(`Using supplied maximumSimilarMessages=${maximumSimilarMessages} cf. default=${DEFAULT_MAXIMUM_SIMILAR_MESSAGES}`); - let severePriorityLevel; - try { - severePriorityLevel = optionalProcessingOptions.severePriorityLevel; - } catch (npfSPLerror) { } - if (severePriorityLevel === undefined) { - severePriorityLevel = DEFAULT_SEVERE_PRIORITY_LEVEL; - // console.log(`Using default severePriorityLevel=${severePriorityLevel}`); - } - else console.log(`Using supplied severePriorityLevel=${severePriorityLevel} cf. default=${DEFAULT_SEVERE_PRIORITY_LEVEL}`); - let mediumPriorityLevel; - try { - mediumPriorityLevel = optionalProcessingOptions.mediumPriorityLevel; - } catch (nfpMPLerror) { } - if (mediumPriorityLevel === undefined) { - mediumPriorityLevel = DEFAULT_MEDIUM_PRIORITY_LEVEL; - // console.log(`Using default mediumPriorityLevel=${mediumPriorityLevel}`); - } - else console.log(`Using supplied mediumPriorityLevel=${mediumPriorityLevel} cf. default=${DEFAULT_MEDIUM_PRIORITY_LEVEL}`); + // end of processNoticesToErrorsWarnings function + + + export function processNoticesToSevereMediumLow(givenNoticeObject, optionalProcessingOptions) { + /* + Available options are: + severePriorityLevel (integer; default is DEFAULT_SEVERE_PRIORITY_LEVEL above) + mediumPriorityLevel (integer; default is DEFAULT_MEDIUM_PRIORITY_LEVEL above) + maximumSimilarMessages (integer; default is DEFAULT_MAXIMUM_SIMILAR_MESSAGES above) + + Returns an object with: + successList: a list of strings describing what has been checked + severeList + mediumList + lowList + numIgnoredNotices, numSevereSuppressed, numMediumSuppressed, numLowSuppressed + processingOptions: just helpfully passes on what we were given (may be undefined) + Also, any other parameters are just passed through, + although filenameList might be abbreviated, e.g. for 100s of .md files. + */ + // console.log(`processNoticesToSevereMediumLow v${NOTICE_PROCESSOR_VERSION_STRING} with options=${JSON.stringify(optionalProcessingOptions)} + // Given ${givenNoticeObject.successList.length.toLocaleString()} success string(s) plus ${givenNoticeObject.noticeList.length.toLocaleString()} notice(s)`); + + const [remainingNoticeList, allTotals, resultObject] = processNoticesCommon(givenNoticeObject, optionalProcessingOptions); + + // Add the fields that we need here to the existing resultObject + resultObject.severeList = []; resultObject.mediumList = []; resultObject.lowList = []; + resultObject.numSevereSuppressed = 0; resultObject.numMediumSuppressed = 0; resultObject.numLowSuppressed = 0; + + let maximumSimilarMessages; + try { + maximumSimilarMessages = optionalProcessingOptions.maximumSimilarMessages; + } catch (npfMSMerror) { } + if (typeof maximumSimilarMessages !== 'number' || isNaN(maximumSimilarMessages)) { + maximumSimilarMessages = DEFAULT_MAXIMUM_SIMILAR_MESSAGES; + // console.log(`Using default maximumSimilarMessages=${maximumSimilarMessages}`); + } + // else console.log(`Using supplied maximumSimilarMessages=${maximumSimilarMessages} cf. default=${DEFAULT_MAXIMUM_SIMILAR_MESSAGES}`); + let severePriorityLevel; + try { + severePriorityLevel = optionalProcessingOptions.severePriorityLevel; + } catch (npfSPLerror) { } + if (severePriorityLevel === undefined) { + severePriorityLevel = DEFAULT_SEVERE_PRIORITY_LEVEL; + // console.log(`Using default severePriorityLevel=${severePriorityLevel}`); + } + else console.log(`Using supplied severePriorityLevel=${severePriorityLevel} cf. default=${DEFAULT_SEVERE_PRIORITY_LEVEL}`); + let mediumPriorityLevel; + try { + mediumPriorityLevel = optionalProcessingOptions.mediumPriorityLevel; + } catch (nfpMPLerror) { } + if (mediumPriorityLevel === undefined) { + mediumPriorityLevel = DEFAULT_MEDIUM_PRIORITY_LEVEL; + // console.log(`Using default mediumPriorityLevel=${mediumPriorityLevel}`); + } + else console.log(`Using supplied mediumPriorityLevel=${mediumPriorityLevel} cf. default=${DEFAULT_MEDIUM_PRIORITY_LEVEL}`); - // Check for repeated notices that should be compressed - // while simultaneously separating into error and warning lists - let counter = {}; - for (const thisNotice of remainingNoticeList) { - const thisPriority = thisNotice.priority, thisMsg = thisNotice.message; - const thisID = thisPriority + thisMsg; // Could have identical worded messages but with different priorities - if (isNaN(counter[thisID])) counter[thisID] = 1; - else counter[thisID]++; - if (maximumSimilarMessages > 0 && counter[thisID] === maximumSimilarMessages + 1) { - if (thisPriority >= severePriorityLevel) { - const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; - resultObject.severeList.push({ prioriyy: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR ERROR${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); - resultObject.numSevereSuppressed++; - } else if (thisPriority >= mediumPriorityLevel) { - const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; - resultObject.mediumList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR ERROR${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); - resultObject.numMediumSuppressed++; - } else { - const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; - resultObject.lowList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR WARNING${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); - resultObject.numLowSuppressed++; - } - } else if (maximumSimilarMessages > 0 && counter[thisID] > maximumSimilarMessages + 1) { - if (thisPriority >= severePriorityLevel) - resultObject.numSevereSuppressed++; + // Check for repeated notices that should be compressed + // while simultaneously separating into error and warning lists + let counter = {}; + for (const thisNotice of remainingNoticeList) { + const thisPriority = thisNotice.priority, thisMsg = thisNotice.message; + const thisID = thisPriority + thisMsg; // Could have identical worded messages but with different priorities + if (isNaN(counter[thisID])) counter[thisID] = 1; + else counter[thisID]++; + if (maximumSimilarMessages > 0 && counter[thisID] === maximumSimilarMessages + 1) { + if (thisPriority >= severePriorityLevel) { + const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; + resultObject.severeList.push({ prioriyy: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR ERROR${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); + resultObject.numSevereSuppressed++; + } else if (thisPriority >= mediumPriorityLevel) { + const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; + resultObject.mediumList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR ERROR${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); + resultObject.numMediumSuppressed++; + } else { + const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; + resultObject.lowList.push({ priority: -1, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR WARNING${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); + resultObject.numLowSuppressed++; + } + } else if (maximumSimilarMessages > 0 && counter[thisID] > maximumSimilarMessages + 1) { + if (thisPriority >= severePriorityLevel) + resultObject.numSevereSuppressed++; + else if (thisPriority >= mediumPriorityLevel) + resultObject.numMediumSuppressed++; + else + resultObject.numLowSuppressed++; + } else if (thisPriority >= severePriorityLevel) + resultObject.severeList.push(thisNotice); else if (thisPriority >= mediumPriorityLevel) - resultObject.numMediumSuppressed++; + resultObject.mediumList.push(thisNotice); else - resultObject.numLowSuppressed++; - } else if (thisPriority >= severePriorityLevel) - resultObject.severeList.push(thisNotice); - else if (thisPriority >= mediumPriorityLevel) - resultObject.mediumList.push(thisNotice); - else - resultObject.lowList.push(thisNotice); - } - - // console.log(`processNoticesToSevereMediumLow is returning ${resultObject.successList.length} successes, ${resultObject.severeList.length} severe, ${resultObject.mediumList.length} medium, and ${resultObject.lowList.length} low - // numIgnoredNotices=${resultObject.numIgnoredNotices} numSevereSuppressed=${resultObject.numSevereSuppressed} numMediumSuppressed=${resultObject.numMediumSuppressed} numLowSuppressed=${resultObject.numLowSuppressed}`); - return resultObject; -} -// end of processNoticesToSevereMediumLow function - - -export function processNoticesToSingleList(givenNoticeObject, optionalProcessingOptions) { - /* - Available options are: - severePriorityLevel (integer; default is DEFAULT_SEVERE_PRIORITY_LEVEL above) - mediumPriorityLevel (integer; default is DEFAULT_MEDIUM_PRIORITY_LEVEL above) - maximumSimilarMessages (integer; default is DEFAULT_MAXIMUM_SIMILAR_MESSAGES above) - - Returns an object with: - successList: a list of strings describing what has been checked - warningList - numIgnoredNotices, numSevereSuppressed, numMediumSuppressed, numLowSuppressed - processingOptions: just helpfully passes on what we were given (may be undefined) - Also, any other parameters are just passed through, - although filenameList might be abbreviated, e.g. for 100s of .md files. - */ - // console.log(`processNoticesToSingleList v${NOTICE_PROCESSOR_VERSION_STRING} with options=${JSON.stringify(optionalProcessingOptions)} - // Given ${givenNoticeObject.successList.length.toLocaleString()} success string(s) plus ${givenNoticeObject.noticeList.length.toLocaleString()} notice(s)`); - - // We default to sorting ByPriority unless something else was specified - let sortBy; - try { - sortBy = optionalProcessingOptions.sortBy; - } catch (npfSBerror) { } - if (sortBy === undefined) - optionalProcessingOptions.sortBy = 'ByPriority'; - - const [remainingNoticeList, allTotals, resultObject] = processNoticesCommon(givenNoticeObject, optionalProcessingOptions); - - // Add the fields that we need here to the existing resultObject - resultObject.warningList = []; resultObject.numSuppressedWarnings = 0; + resultObject.lowList.push(thisNotice); + } - let maximumSimilarMessages; - try { - maximumSimilarMessages = optionalProcessingOptions.maximumSimilarMessages; - } catch (npfMSMerror) { } - if (typeof maximumSimilarMessages !== 'number' || isNaN(maximumSimilarMessages)) { - maximumSimilarMessages = DEFAULT_MAXIMUM_SIMILAR_MESSAGES; - // console.log(`Using default maximumSimilarMessages=${maximumSimilarMessages}`); + // console.log(`processNoticesToSevereMediumLow is returning ${resultObject.successList.length} successes, ${resultObject.severeList.length} severe, ${resultObject.mediumList.length} medium, and ${resultObject.lowList.length} low + // numIgnoredNotices=${resultObject.numIgnoredNotices} numSevereSuppressed=${resultObject.numSevereSuppressed} numMediumSuppressed=${resultObject.numMediumSuppressed} numLowSuppressed=${resultObject.numLowSuppressed}`); + return resultObject; } - // else console.log(`Using supplied maximumSimilarMessages=${maximumSimilarMessages} cf. default=${DEFAULT_MAXIMUM_SIMILAR_MESSAGES}`); + // end of processNoticesToSevereMediumLow function + + + export function processNoticesToSingleList(givenNoticeObject, optionalProcessingOptions) { + /* + Available options are: + severePriorityLevel (integer; default is DEFAULT_SEVERE_PRIORITY_LEVEL above) + mediumPriorityLevel (integer; default is DEFAULT_MEDIUM_PRIORITY_LEVEL above) + maximumSimilarMessages (integer; default is DEFAULT_MAXIMUM_SIMILAR_MESSAGES above) + + Returns an object with: + successList: a list of strings describing what has been checked + warningList + numIgnoredNotices, numSevereSuppressed, numMediumSuppressed, numLowSuppressed + processingOptions: just helpfully passes on what we were given (may be undefined) + Also, any other parameters are just passed through, + although filenameList might be abbreviated, e.g. for 100s of .md files. + */ + // console.log(`processNoticesToSingleList v${NOTICE_PROCESSOR_VERSION_STRING} with options=${JSON.stringify(optionalProcessingOptions)} + // Given ${givenNoticeObject.successList.length.toLocaleString()} success string(s) plus ${givenNoticeObject.noticeList.length.toLocaleString()} notice(s)`); + + // We default to sorting ByPriority unless something else was specified + let sortBy; + try { + sortBy = optionalProcessingOptions.sortBy; + } catch (npfSBerror) { } + if (sortBy === undefined) + optionalProcessingOptions.sortBy = 'ByPriority'; + + const [remainingNoticeList, allTotals, resultObject] = processNoticesCommon(givenNoticeObject, optionalProcessingOptions); + + // Add the fields that we need here to the existing resultObject + resultObject.warningList = []; resultObject.numSuppressedWarnings = 0; + + let maximumSimilarMessages; + try { + maximumSimilarMessages = optionalProcessingOptions.maximumSimilarMessages; + } catch (npfMSMerror) { } + if (typeof maximumSimilarMessages !== 'number' || isNaN(maximumSimilarMessages)) { + maximumSimilarMessages = DEFAULT_MAXIMUM_SIMILAR_MESSAGES; + // console.log(`Using default maximumSimilarMessages=${maximumSimilarMessages}`); + } + // else console.log(`Using supplied maximumSimilarMessages=${maximumSimilarMessages} cf. default=${DEFAULT_MAXIMUM_SIMILAR_MESSAGES}`); - // Check for repeated notices that should be compressed - // while simultaneously creating warning list - let counter = {}; - for (const thisNotice of remainingNoticeList) { - const thisPriority = thisNotice.priority, thisMsg = thisNotice.message; - const thisID = thisPriority + thisMsg; // Could have identical worded messages but with different priorities - if (isNaN(counter[thisID])) counter[thisID] = 1; - else counter[thisID]++; - if (maximumSimilarMessages > 0 && counter[thisID] === maximumSimilarMessages + 1) { - const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; - resultObject.warningList.push({ priority: thisPriority, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR WARNING${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); - resultObject.numSuppressedWarnings++; - } else if (maximumSimilarMessages > 0 && counter[thisID] > maximumSimilarMessages + 1) { - resultObject.numSuppressedWarnings++; - } else - resultObject.warningList.push(thisNotice); - } + // Check for repeated notices that should be compressed + // while simultaneously creating warning list + let counter = {}; + for (const thisNotice of remainingNoticeList) { + const thisPriority = thisNotice.priority, thisMsg = thisNotice.message; + const thisID = thisPriority + thisMsg; // Could have identical worded messages but with different priorities + if (isNaN(counter[thisID])) counter[thisID] = 1; + else counter[thisID]++; + if (maximumSimilarMessages > 0 && counter[thisID] === maximumSimilarMessages + 1) { + const numSuppressed = allTotals[thisPriority] - maximumSimilarMessages; + resultObject.warningList.push({ priority: thisPriority, message: thisMsg, location: ` ◄ ${numSuppressed.toLocaleString()} MORE SIMILAR WARNING${numSuppressed === 1 ? '' : 'S'} SUPPRESSED` }); + resultObject.numSuppressedWarnings++; + } else if (maximumSimilarMessages > 0 && counter[thisID] > maximumSimilarMessages + 1) { + resultObject.numSuppressedWarnings++; + } else + resultObject.warningList.push(thisNotice); + } - // console.log(`processNoticesToSingleList is returning ${resultObject.successList.length} successes, ${resultObject.warningList.length} warnings - // numIgnoredNotices=${resultObject.numIgnoredNotices} numSuppressedWarnings=${resultObject.numSuppressedWarnings}`); - return resultObject; -} + // console.log(`processNoticesToSingleList is returning ${resultObject.successList.length} successes, ${resultObject.warningList.length} warnings + // numIgnoredNotices=${resultObject.numIgnoredNotices} numSuppressedWarnings=${resultObject.numSuppressedWarnings}`); + return resultObject; + } // end of processNoticesToSingleList function diff --git a/src/demos/repo-check/RepoCheck.js b/src/demos/repo-check/RepoCheck.js index 787ea9a8..8e9e542d 100644 --- a/src/demos/repo-check/RepoCheck.js +++ b/src/demos/repo-check/RepoCheck.js @@ -41,10 +41,12 @@ function RepoCheck(/*username, languageCode,*/ props) { const [result, setResultValue] = useState("Waiting-checkRepo"); useEffect(() => { + // console.log("RepoCheck.useEffect() called with ", JSON.stringify(props)); + // Use an IIFE (Immediately Invoked Function Expression) // e.g., see https://medium.com/javascript-in-plain-english/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174 (async () => { - // console.log("Started unnamedFunction()"); + // console.log("Started RepoCheck.unnamedFunction()"); // Display our "waiting" message setResultValue(

    Waiting for check results for {repoName} repo…

    ); @@ -160,7 +162,8 @@ function RepoCheck(/*username, languageCode,*/ props) { } })(); // end of async part in unnamedFunction // Doesn't work if we add this to next line: languageCode,username,repoName,branch,checkingOptions,props - }); // end of useEffect part + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // end of useEffect part // {/*
    */} return ( diff --git a/src/demos/repo-check/checkRepo.js b/src/demos/repo-check/checkRepo.js index a044293a..cac23d27 100644 --- a/src/demos/repo-check/checkRepo.js +++ b/src/demos/repo-check/checkRepo.js @@ -1,6 +1,6 @@ // import React from 'react'; // // import * as books from '../../core/books/books'; -// import { books, checkFile } from '../../core'; +// import { books, checkFileContents } from '../../core'; // // import { getFilelistFromFetchedTreemaps, getFilelistFromFetchedZip } from '../helpers'; // // import { fetchRepo, getBlobContent } from './helpers' // import { fetchRepositoryZipFile, getFilelistFromZip, getFile } from '../../core/getApi'; @@ -66,24 +66,24 @@ // } -// async function ourCheckFile(bookOrFileCode, cfBookID, filename, file_content, fileLocation, optionalCheckingOptions) { +// async function ourCheckFileContents(bookOrFileCode, cfBookID, filename, file_content, fileLocation, optionalCheckingOptions) { // // We assume that checking for compulsory fields is done elsewhere -// // console.log(`checkRepo ourCheckFile(${filename})…`); +// // console.log(`checkRepo ourCheckFileContents(${filename})…`); // // Updates the global list of notices -// console.assert(bookOrFileCode !== undefined, "ourCheckFile: 'bookOrFileCode' parameter should be defined"); -// console.assert(typeof bookOrFileCode === 'string', `ourCheckFile: 'bookOrFileCode' parameter should be a string not a '${typeof bookOrFileCode}'`); -// console.assert(cfBookID !== undefined, "ourCheckFile: 'cfBookID' parameter should be defined"); -// console.assert(typeof cfBookID === 'string', `ourCheckFile: 'cfBookID' parameter should be a string not a '${typeof cfBookID}'`); -// console.assert(filename !== undefined, "ourCheckFile: 'filename' parameter should be defined"); -// console.assert(typeof filename === 'string', `ourCheckFile: 'filename' parameter should be a string not a '${typeof filename}'`); -// console.assert(file_content !== undefined, "ourCheckFile: 'file_content' parameter should be defined"); -// console.assert(typeof file_content === 'string', `ourCheckFile: 'file_content' parameter should be a string not a '${typeof file_content}'`); -// console.assert(fileLocation !== undefined, "ourCheckFile: 'fileLocation' parameter should be defined"); -// console.assert(typeof fileLocation === 'string', `ourCheckFile: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); - -// const resultObject = await checkFile(filename, file_content, fileLocation, optionalCheckingOptions); -// // console.log("checkFile() returned", resultObject.successList.length, "success message(s) and", resultObject.noticeList.length, "notice(s)"); +// console.assert(bookOrFileCode !== undefined, "ourCheckFileContents: 'bookOrFileCode' parameter should be defined"); +// console.assert(typeof bookOrFileCode === 'string', `ourCheckFileContents: 'bookOrFileCode' parameter should be a string not a '${typeof bookOrFileCode}'`); +// console.assert(cfBookID !== undefined, "ourCheckFileContents: 'cfBookID' parameter should be defined"); +// console.assert(typeof cfBookID === 'string', `ourCheckFileContents: 'cfBookID' parameter should be a string not a '${typeof cfBookID}'`); +// console.assert(filename !== undefined, "ourCheckFileContents: 'filename' parameter should be defined"); +// console.assert(typeof filename === 'string', `ourCheckFileContents: 'filename' parameter should be a string not a '${typeof filename}'`); +// console.assert(file_content !== undefined, "ourCheckFileContents: 'file_content' parameter should be defined"); +// console.assert(typeof file_content === 'string', `ourCheckFileContents: 'file_content' parameter should be a string not a '${typeof file_content}'`); +// console.assert(fileLocation !== undefined, "ourCheckFileContents: 'fileLocation' parameter should be defined"); +// console.assert(typeof fileLocation === 'string', `ourCheckFileContents: 'fileLocation' parameter should be a string not a '${typeof fileLocation}'`); + +// const resultObject = await checkFileContents(filename, file_content, 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); @@ -96,7 +96,7 @@ // characterIndex:noticeEntry.characterIndex, extract:noticeEntry.extract, // location:noticeEntry.location, extra:bookOrFileCode}); // } -// // end of ourCheckFile function +// // end of ourCheckFileContents function // // Main code for checkRepo() @@ -173,7 +173,7 @@ // } // if (repoFileContent) { // // console.log(`checkRepo checking ${thisFilename}`); -// await ourCheckFile(bookOrFileCode, ourBookID, thisFilename, repoFileContent, ourLocation, checkingOptions); +// await ourCheckFileContents(bookOrFileCode, ourBookID, thisFilename, repoFileContent, ourLocation, checkingOptions); // checkedFileCount += 1; // checkedFilenames.push(thisFilename); // checkedFilenameExtensions.add(thisFilenameExtension); diff --git a/styleguide.config.js b/styleguide.config.js index 05747922..0daad7a4 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -73,7 +73,7 @@ let sections = [ // The difficulty with displaying the various functions this way // is that they all appear and run on a SINGLE web-page. name: 'Sample Notice Processing Functions', - content: 'src/core/README.md', + // content: 'src/core/README.md', sections: [ { name: 'Process notices -> Errors/Warnings',