From 8d965156e75493df48ccb9696a26c513b22c790d Mon Sep 17 00:00:00 2001 From: ke4tch Date: Thu, 18 Jun 2026 10:36:48 -0400 Subject: [PATCH 1/2] Changed recommended tags; correct Notability placement test; add appId to TemplateManager; enhanced source checking; correct doc typo --- lib/biocheck-api/README.md | 304 +++++++++--------- lib/biocheck-api/readme-base.md | 2 +- lib/biocheck-api/src/BioCheckPerson.js | 3 +- .../src/BioCheckTemplateManager.js | 29 +- lib/biocheck-api/src/Biography.js | 11 +- lib/biocheck-api/src/SourceRules.js | 15 +- 6 files changed, 198 insertions(+), 166 deletions(-) diff --git a/lib/biocheck-api/README.md b/lib/biocheck-api/README.md index cb677682..6e3ae4b8 100644 --- a/lib/biocheck-api/README.md +++ b/lib/biocheck-api/README.md @@ -21,7 +21,7 @@ import { BioCheckPerson } from "./BioCheckPerson.js"; import { Biography } from "./Biography.js"; // initialization - just once - let bioCheckTemplateManager = new BioCheckTemplateManager(); + let bioCheckTemplateManager = new BioCheckTemplateManager(appId); bioCheckTemplateManager.load(); // For each person. Get the bio text and dates to test @@ -53,8 +53,7 @@ import { Biography } from "./Biography.js"; * [BioCheckPerson][1] * [BioCheckTemplateManager][2] * [Biography][3] -* [dnaInvaldSourceCount][4] -* [SourceRules][5] +* [SourceRules][4] ## BioCheckPerson @@ -77,25 +76,25 @@ When requesting the profile using the WikiTree API, resolveRedirect should be us #### Parameters -* `profileObj` **[Object][6]** containing the profile as returned from WikiTree APIs -* `mustBeOpen` **[Boolean][7]** true if profile must be open privacy -* `mustBeOrphan` **[Boolean][7]** true if profile must not have a manager -* `ignorePre1500` **[Boolean][7]** true to ignore Pre1500 profiles -* `userId` **[String][8]** ID number of the person running the app (not the WikiTree-Id) +* `profileObj` **[Object][5]** containing the profile as returned from WikiTree APIs +* `mustBeOpen` **[Boolean][6]** true if profile must be open privacy +* `mustBeOrphan` **[Boolean][6]** true if profile must not have a manager +* `ignorePre1500` **[Boolean][6]** true to ignore Pre1500 profiles +* `userId` **[String][7]** ID number of the person running the app (not the WikiTree-Id) -Returns **[Boolean][7]** true if this person can be checked else false +Returns **[Boolean][6]** true if this person can be checked else false ### hasBio Does this person have a bio -Returns **[Boolean][7]** true if person has bio +Returns **[Boolean][6]** true if person has bio ### getBio Get bio string for this person -Returns **[String][8]** bio string +Returns **[String][7]** bio string ### clearBio @@ -106,98 +105,98 @@ to allow for garbage collection Get wikiTreeId for the person -Returns **[String][8]** wikiTreeId (e.g., Doe-100) +Returns **[String][7]** wikiTreeId (e.g., Doe-100) ### getProfileId Get profileId for the person -Returns **[String][8]** profileId (e.g., 12345678) +Returns **[String][7]** profileId (e.g., 12345678) ### getReportName Get name to report -Returns **[String][8]** string with first and last name +Returns **[String][7]** string with first and last name ### getManagerId Get manager Id for the person -Returns **[String][8]** manager Id +Returns **[String][7]** manager Id ### isMember Is profile for a member -Returns **[Boolean][7]** true if profile for a member +Returns **[Boolean][6]** true if profile for a member ### isOrphan Is profile an orphan -Returns **[Boolean][7]** true if profile is an orphan +Returns **[Boolean][6]** true if profile is an orphan ### getManagers Get managers for this profile as a String -Returns **[String][8]** list of managers +Returns **[String][7]** list of managers ### hasLocation Does profile have either birth or death location -Returns **[Boolean][7]** true if either location present +Returns **[Boolean][6]** true if either location present or the privacy does not let us determine location ### hasBirthLocation Does profile have birth location -Returns **[Boolean][7]** true if birth location +Returns **[Boolean][6]** true if birth location ### hasDeathLocation Does profile have death location -Returns **[Boolean][7]** true if death location +Returns **[Boolean][6]** true if death location ### getPrivacy Get the privacy -Returns **[Number][9]** numeric privacy level +Returns **[Number][8]** numeric privacy level ### getPrivacyString Get the privacy as a string to be displayed to the user -Returns **[String][8]** privacy string (i.e., the color) +Returns **[String][7]** privacy string (i.e., the color) ### getResearchStatus Get the research status -Returns **[Number][9]** numeric research status +Returns **[Number][8]** numeric research status ### getResearchStatusString Get the research status as a string to be displayed to the user -Returns **[String][8]** research status string +Returns **[String][7]** research status string ### isUncheckedDueToPrivacy Was profile not checked due to privacy -Returns **[Boolean][7]** true if profile could not be checked due to privacy +Returns **[Boolean][6]** true if profile could not be checked due to privacy ### isUncheckedDueToDate Was profile not checked due to date -Returns **[Boolean][7]** true if profile could not be checked due to date +Returns **[Boolean][6]** true if profile could not be checked due to date ### build @@ -210,19 +209,19 @@ mStatusFather, mStatusMother Is the person before 1500 -Returns **[Boolean][7]** true if either birth or death date before 1500 +Returns **[Boolean][6]** true if either birth or death date before 1500 ### isPre1700 Is the person before 1700 -Returns **[Boolean][7]** true if either birth or death date before 1700 +Returns **[Boolean][6]** true if either birth or death date before 1700 ### isTooOldToRemember Is the person born > 150 years ago or died > 100 years ago -Returns **[Boolean][7]** true if born > 150 years ago or died > 100 years ago +Returns **[Boolean][6]** true if born > 150 years ago or died > 100 years ago ### hasBirthDate @@ -237,19 +236,19 @@ Does the profile have a death date Does the profile lack dates Only looks at open and private profiles -Returns **[Boolean][7]** true if profile has neither birth nor death date +Returns **[Boolean][6]** true if profile has neither birth nor death date ### getBirthDate Get birth date -Returns **[Date][10]** birth date +Returns **[Date][9]** birth date ### getDeathDate Get death date -Returns **[Date][10]** death date +Returns **[Date][9]** death date ### getReportDate @@ -258,9 +257,9 @@ Convert date to a display format #### Parameters * `isBirth` -* `true` **[Boolean][7]** to get birth date, else death date +* `true` **[Boolean][6]** to get birth date, else death date -Returns **[String][8]** string in the form yyyy mon dd +Returns **[String][7]** string in the form yyyy mon dd ## BioCheckTemplateManager @@ -277,12 +276,24 @@ This can take some time. You can instead use loadPrep to get a promise and then await loadTemplates using that promise if there is other initialization to be performed. +#### Parameters + +* `appId` appId to use for WT+ request + + + * Throws **any** error getting response ### loadPrep Send request to load templates from WT+ +#### Parameters + +* `appId` appId to use for WT+ request + + + * Throws **any** error getting response Returns **any** promise for use with loadTemplates @@ -321,17 +332,17 @@ Information about the biography style can be accessed via get methods. #### Parameters -* `inStr` **[String][8]** the bio string. This contains the bio as returned +* `inStr` **[String][7]** the bio string. This contains the bio as returned by the WikiTree API in Wiki format for the profile. Alternately, it can be contents obtained from the Edit or Add person pages. * `thePerson` **[BioCheckPerson][1]** person to check -* `bioSearchString` **[String][8]** search string to search for in bio +* `bioSearchString` **[String][7]** search string to search for in bio ### validate Validate contents of bio -Returns **[Boolean][7]** true if profile looks good, else false. +Returns **[Boolean][6]** true if profile looks good, else false. Returns false a profile that appears unsourced (is ?), a profile with an empty bio, a profile with no dates, or a profile that has an Unsourced Research Notes Box or is in an Unsourced category. @@ -349,7 +360,7 @@ the start of the next heading or end of the biography. The \n character terminates a line, which are returned in an array. Blank lines are included. -Returns **[Array][11]** of bio string lines +Returns **[Array][10]** of bio string lines ### validateSourcesStr @@ -358,10 +369,10 @@ used when adding a new person in basic mode. #### Parameters -* `sourcesStr` **[String][8]** string containing sources +* `sourcesStr` **[String][7]** string containing sources * `thePerson` {BioCheckPerson} person to check -Returns **[Boolean][7]** true if sources found. +Returns **[Boolean][6]** true if sources found. ### hasProblems @@ -369,176 +380,175 @@ Does biography have problems. problems include: no valid sources, no sources, empty, marked unsourced, undated, has style issues -Returns **[Boolean][7]** true if bio has problems +Returns **[Boolean][6]** true if bio has problems ### isEmpty is bio empty -Returns **[Boolean][7]** true if bio empty +Returns **[Boolean][6]** true if bio empty ### hasCategories does bio have categories -Returns **[Boolean][7]** true if bio has categories +Returns **[Boolean][6]** true if bio has categories ### isMarkedUnsourced does bio have Unsourced template or category -Returns **[Boolean][7]** true if bio has Unsourced template or category +Returns **[Boolean][6]** true if bio has Unsourced template or category ### isUndated is bio undated -Returns **[Boolean][7]** true if bio has neither birth nor death date +Returns **[Boolean][6]** true if bio has neither birth nor death date ### getTotalBioLines get total number of lines in bio -Returns **[Number][9]** total number of bio lines +Returns **[Number][8]** total number of bio lines ### getInlineRefCount get number of inline ref -Returns **[Number][9]** number of inline ref +Returns **[Number][8]** number of inline ref ### getPossibleSourcesLineCount get number of lines that might contain sources -Returns **[Number][9]** number of lines that might contain sources +Returns **[Number][8]** number of lines that might contain sources ### hasNonCategoryTextBeforeBiographyHeading does bio have non category text before biography heading -Returns **[Boolean][7]** true if bio has non category text before bio heading +Returns **[Boolean][6]** true if bio has non category text before bio heading ### hasStyleIssues does bio have style issues -Returns **[Boolean][7]** true if bio has style issues +Returns **[Boolean][6]** true if bio has style issues ### hasEndlessComment does bio have endless comment -Returns **[Boolean][7]** true if bio has endless comment +Returns **[Boolean][6]** true if bio has endless comment ### isMissingBiographyHeading is bio missing biography heading -Returns **[Boolean][7]** true if bio is missing biography heading +Returns **[Boolean][6]** true if bio is missing biography heading ### hasHeadingWithNoLinesFollowing does bio have biography heading with no lines following -Returns **[Boolean][7]** true if bio has biography heading with no lines following +Returns **[Boolean][6]** true if bio has biography heading with no lines following ### hasMultipleBioHeadings does bio have multiple biography headings -Returns **[Boolean][7]** true if bio has multiple biography headings +Returns **[Boolean][6]** true if bio has multiple biography headings ### hasRefWithoutEnd does bio have ref with ending ref -Returns **[Boolean][7]** true if bio haref with ending refs +Returns **[Boolean][6]** true if bio haref with ending refs ### hasSpanWithoutEndingSpan does bio have span without ending span -Returns **[Boolean][7]** true if bio has span without ending span +Returns **[Boolean][6]** true if bio has span without ending span ### isMissingSourcesHeading is bio missing sources heading -Returns **[Boolean][7]** true if bio is missing sources heading +Returns **[Boolean][6]** true if bio is missing sources heading ### hasMultipleSourceHeadings does bio have multiple sources headings -Returns **[Boolean][7]** true if bio has multiple sources headings +Returns **[Boolean][6]** true if bio has multiple sources headings ### getMisplacedLineCount how many lines are between Sources and references -Returns **[Number][9]** number of lines between sources and references +Returns **[Number][8]** number of lines between sources and references ### isMissingReferencesTag is bio missing the references tag -Returns **[Boolean][7]** true if is missing the references tag +Returns **[Boolean][6]** true if is missing the references tag ### hasMultipleReferencesTags does bio have multiple references tags -Returns **[Boolean][7]** true if bio has multiple references tags +Returns **[Boolean][6]** true if bio has multiple references tags ### hasRefAfterReferences does bio have ref after references -Returns **[Boolean][7]** true if bio has ref after references +Returns **[Boolean][6]** true if bio has ref after references ### hasAcknowledgementsBeforeSources does bio have acknowledgements before sources -Returns **[Boolean][7]** true if bio has acknowledgements before sources +Returns **[Boolean][6]** true if bio has acknowledgements before sources ### hasSectionAfterAdvanceDirective does bio have section after advance directive -Returns **[Boolean][7]** true if bio has section heading after advance directive +Returns **[Boolean][6]** true if bio has section heading after advance directive ### hasUnknownSection does bio have unknown section headings -Returns **[Boolean][7]** true if bio has unknown section headings +Returns **[Boolean][6]** true if bio has unknown section headings ### hasPaternalDnaConf does bio have paternal Dna confirmation -Returns **[Boolean][7]** true if bio has paternal Dna confirmation +Returns **[Boolean][6]** true if bio has paternal Dna confirmation ### hasMaternalDnaConf does bio have maternal Dna confirmation -Returns **[Boolean][7]** true if bio has maternal Dna confirmation +Returns **[Boolean][6]** true if bio has maternal Dna confirmation ### getSectionMessages -/\*\* Return messages for reporting -Returns **[Array][11]** sectionMessages\[] +Returns **[Array][10]** sectionMessages\[] ### getStyleMessages Return messages for reporting -Returns **[Array][11]** styleMessages\[] +Returns **[Array][10]** styleMessages\[] ### getDnaSourceList @@ -552,37 +562,33 @@ dnaSourceText: "", does bio have search string -Returns **[Boolean][7]** true if bio has the searchString +Returns **[Boolean][6]** true if bio has the searchString that was supplied to the parse() method ### hasSources does bio appear to have sources -Returns **[Boolean][7]** true if bio appears to have sources +Returns **[Boolean][6]** true if bio appears to have sources ### getInvalidSources get invalid sources found for profile -Returns **[Array][11]** array of String of invalid source lines +Returns **[Array][10]** array of String of invalid source lines ### getInvalidDnaSources get invalid DNA sources found for profile -Returns **[Array][11]** array of String of invalid source lines +Returns **[Array][10]** array of String of invalid source lines for reporting ### getValidSources get valid sources found for profile -Returns **[Array][11]** array of String of valid source lines - -## dnaInvaldSourceCount - -Return invalid DNA Source list (for reporting) +Returns **[Array][10]** array of String of valid source lines ## SourceRules @@ -600,9 +606,9 @@ Determine if a line is a valid biography heading #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if bio heading else false +Returns **[Boolean][6]** true if bio heading else false ### isResearchNotesHeading @@ -610,9 +616,9 @@ Determine if a line is a valid research notes heading #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if research notes heading else false +Returns **[Boolean][6]** true if research notes heading else false ### isSourcesHeading @@ -620,9 +626,9 @@ Determine if a line is a valid sources heading #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if sources heading else false +Returns **[Boolean][6]** true if sources heading else false ### isAckHeading @@ -630,9 +636,9 @@ Determine if a line is a valid acknowledgements heading #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if acknowledgements heading else false +Returns **[Boolean][6]** true if acknowledgements heading else false ### isAdvanceDirective @@ -640,9 +646,9 @@ Determine if a line is a valid advance directive heading #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if advance directive heading else false +Returns **[Boolean][6]** true if advance directive heading else false ### hasDnaTestCompany @@ -650,9 +656,9 @@ Determine if a line contains a DNA testing company #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if a DNA testing company +Returns **[Boolean][6]** true if a DNA testing company ### hasCommonDnaTestCompany @@ -660,9 +666,9 @@ Determine if a line has a common DNA testing company #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if a common DNA testing company +Returns **[Boolean][6]** true if a common DNA testing company ### isDnaSourceIdentifier @@ -670,9 +676,9 @@ Determine if a line is something specifying DNA source #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if something specifying a DNA source +Returns **[Boolean][6]** true if something specifying a DNA source ### isResearchNoteBox @@ -681,9 +687,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if research notes box else false +Returns **[Boolean][6]** true if research notes box else false ### getResearchNoteBoxStatus @@ -692,9 +698,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[String][8]** status value or blank if not a research notes box +Returns **[String][7]** status value or blank if not a research notes box ### getNavBoxStatus @@ -703,9 +709,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[String][8]** status value or blank if not a nav box +Returns **[String][7]** status value or blank if not a nav box ### getProjectBoxStatus @@ -714,9 +720,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[String][8]** status value or blank if not a Project box +Returns **[String][7]** status value or blank if not a Project box ### getStickerStatus @@ -725,9 +731,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[String][8]** status value or blank if not a Project box +Returns **[String][7]** status value or blank if not a Project box ### isProjectBox @@ -736,9 +742,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if research notes box else false +Returns **[Boolean][6]** true if research notes box else false ### isNavBox @@ -747,9 +753,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if nav box else false +Returns **[Boolean][6]** true if nav box else false ### isNotabilityTemplate @@ -759,9 +765,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if notability else false +Returns **[Boolean][6]** true if notability else false ### isSticker @@ -770,9 +776,9 @@ assumes the leading {{ removed and line is lower case #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if sticker else false +Returns **[Boolean][6]** true if sticker else false ### isRecommendedTag @@ -782,9 +788,9 @@ Typically used for a line that starts with < #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if recommended else false +Returns **[Boolean][6]** true if recommended else false ### isCensus @@ -792,9 +798,9 @@ Determine if a line is a census line #### Parameters -* `line` **[String][8]** to test +* `line` **[String][7]** to test -Returns **[Boolean][7]** true if census line else false +Returns **[Boolean][6]** true if census line else false ### hasCensusString @@ -802,7 +808,7 @@ Determine if a line contains a census string #### Parameters -* `line` **[String][8]** the line +* `line` **[String][7]** the line Returns **any** census string if line contains census string @@ -812,9 +818,9 @@ Determine if line by itself is an invalid source #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if invalid source else false +Returns **[Boolean][6]** true if invalid source else false ### removeInvalidSourcePart @@ -822,9 +828,9 @@ Remove a string that by itself on a line is not a valid source #### Parameters -* `line` **[String][8]** the line to check +* `line` **[String][7]** the line to check -Returns **[String][8]** line with any invalid sources removed +Returns **[String][7]** line with any invalid sources removed ### removeInvalidSourcePartTooOld @@ -833,9 +839,9 @@ for too old to remember #### Parameters -* `line` **[String][8]** the line to check +* `line` **[String][7]** the line to check -Returns **[String][8]** line with any invalid sources removed +Returns **[String][7]** line with any invalid sources removed ### removeInvalidSourcePartPre1700 @@ -843,9 +849,9 @@ Remove a string that by itself on a line is not a valid source Pre1700 #### Parameters -* `line` **[String][8]** the line to check +* `line` **[String][7]** the line to check -Returns **[String][8]** line with any invalid sources removed +Returns **[String][7]** line with any invalid sources removed ### isInvalidPartialSource @@ -853,9 +859,9 @@ Determine if line is an invalid source when found anywhere on a line #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if found on invalid partial source list, else false +Returns **[Boolean][6]** true if found on invalid partial source list, else false ### isInvalidPartialSourceTooOld @@ -864,9 +870,9 @@ when the person is too old to remember #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if found on too old partial source list, else false +Returns **[Boolean][6]** true if found on too old partial source list, else false ### isInvalidPartialSourcePre1700 @@ -875,9 +881,9 @@ and the person is Pre1700 #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if found on pre1700 partial source list, else false +Returns **[Boolean][6]** true if found on pre1700 partial source list, else false ### isValidPartialSourcePre1700 @@ -886,9 +892,9 @@ and the person is Pre1700 #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if found on pre1700 valid partial source list, else false +Returns **[Boolean][6]** true if found on pre1700 valid partial source list, else false ### isInvalidStartPartialSource @@ -896,9 +902,9 @@ Determine if line starts with something on the invalid partial source list #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if starts with invalid source, else false +Returns **[Boolean][6]** true if starts with invalid source, else false ### isInvalidSourceTooOld @@ -907,9 +913,9 @@ remember #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if invalid source else false +Returns **[Boolean][6]** true if invalid source else false ### isInvalidSourcePre1700 @@ -917,9 +923,9 @@ Determine if line by itself is an invalid source for Pre1700 #### Parameters -* `line` **[String][8]** input source string +* `line` **[String][7]** input source string -Returns **[Boolean][7]** true if invalid source else false +Returns **[Boolean][6]** true if invalid source else false [1]: #biocheckperson @@ -927,18 +933,16 @@ Returns **[Boolean][7]** true if invalid source else false [3]: #biography -[4]: #dnainvaldsourcecount - -[5]: #sourcerules +[4]: #sourcerules -[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number +[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date -[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array diff --git a/lib/biocheck-api/readme-base.md b/lib/biocheck-api/readme-base.md index 808627e3..a0a6790b 100644 --- a/lib/biocheck-api/readme-base.md +++ b/lib/biocheck-api/readme-base.md @@ -21,7 +21,7 @@ import { BioCheckPerson } from "./BioCheckPerson.js"; import { Biography } from "./Biography.js"; // initialization - just once - let bioCheckTemplateManager = new BioCheckTemplateManager(); + let bioCheckTemplateManager = new BioCheckTemplateManager(appId); bioCheckTemplateManager.load(); // For each person. Get the bio text and dates to test diff --git a/lib/biocheck-api/src/BioCheckPerson.js b/lib/biocheck-api/src/BioCheckPerson.js index e1cd0795..9e5f4ae5 100644 --- a/lib/biocheck-api/src/BioCheckPerson.js +++ b/lib/biocheck-api/src/BioCheckPerson.js @@ -349,7 +349,7 @@ export class BioCheckPerson { * or the privacy does not let us determine location */ hasLocation() { - if (this.person.privacyLevel >= BioCheckPerson.MIN_PRIVACY) { + if (this.person.privacyLevel < BioCheckPerson.MIN_PRIVACY) { return true; } else { return this.person.hasLocation; @@ -471,6 +471,7 @@ export class BioCheckPerson { * mStatusFather, mStatusMother */ build() { + this.person.privacyLevel = this.OPEN_PRIVACY; let bDay = document.getElementById("mBirthDate").value; let dDay = document.getElementById("mDeathDate").value; this.#birthDate = null; diff --git a/lib/biocheck-api/src/BioCheckTemplateManager.js b/lib/biocheck-api/src/BioCheckTemplateManager.js index 0f6b547e..f7d9b03a 100644 --- a/lib/biocheck-api/src/BioCheckTemplateManager.js +++ b/lib/biocheck-api/src/BioCheckTemplateManager.js @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2025 Kathryn J Knight +Copyright (c) 2026 Kathryn J Knight Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -54,11 +54,12 @@ export class BioCheckTemplateManager { * a promise and then await loadTemplates using that promise if * there is other initialization to be performed. * + * @param appId appId to use for WT+ request * @throws error getting response */ - async load() { + async load(appId) { try { - await this.#loadTemplates(); + await this.#loadTemplates(appId); } catch (e) { console.log('Error loading templates ' + e); throw('Error loading templates'); @@ -68,10 +69,11 @@ export class BioCheckTemplateManager { * Do the actual load separately so we can wait for this synchronously * The problem with this is that it can take a long time. Can we instead * be asynchronous in WBE and TreeApps and wait before user clicks in the App? + * @param appId appId to use for WT+ request */ - async #loadTemplates() { + async #loadTemplates(appId) { try { - let url = "https://plus.wikitree.com/chrome/templatesExp.json?appid=bioCheck"; + let url = this.#buildUrl(appId); let fetchResponse = await fetch(url, { cache: 'no-store' }); if (!fetchResponse.ok) { console.log("Error " + fetchResponse.status); @@ -90,12 +92,13 @@ export class BioCheckTemplateManager { /** * Send request to load templates from WT+ + * @param appId appId to use for WT+ request * @return promise for use with loadTemplates * @throws error getting response */ - loadPrep() { + loadPrep(appId) { try { - let url = "https://plus.wikitree.com/chrome/templatesExp.json?appid=bioCheck"; + let url = this.#buildUrl(appId); let p = fetch(url, { cache: 'no-store' }); return p; } catch (e) { @@ -125,4 +128,16 @@ export class BioCheckTemplateManager { throw('Error loading templates'); } } + + /* + * request url with input appId, default to bioCheck if none + * + */ + #buildUrl(appId) { + if ((appId == null) || (appId.length == 0)) { + appId = 'bioCheckTreeApp'; + } + let url = 'https://plus.wikitree.com/chrome/templatesExp.json?appid=' + appId; + return url; + } } diff --git a/lib/biocheck-api/src/Biography.js b/lib/biocheck-api/src/Biography.js index e8bcf97f..9a57c3ed 100644 --- a/lib/biocheck-api/src/Biography.js +++ b/lib/biocheck-api/src/Biography.js @@ -1037,7 +1037,6 @@ validateSourcesStr(sourcesStr, thePerson) { hasMaternalDnaConf() { return this.#style.bioHasMaternalDnaConf; } - /** /** * Return messages for reporting * @returns {Array} sectionMessages[] @@ -1062,11 +1061,6 @@ validateSourcesStr(sourcesStr, thePerson) { getDnaSourceList() { return this.#dnaSourceList; } - /** - * Return invalid DNA Source list (for reporting) - */ - - #dnaInvaldSourceCount = 0; /** * does bio have search string * @returns {Boolean} true if bio has the searchString @@ -1710,6 +1704,7 @@ validateSourcesStr(sourcesStr, thePerson) { this.#messages.styleMessages.push("Mother not marked as Confirmed with DNA"); this.#bioScore--; } + } /* @@ -1906,6 +1901,9 @@ validateSourcesStr(sourcesStr, thePerson) { this.#bioScore--; } } else { + // changes in help now no lines before Biography heading + this.#unexpectedLines.push(line); + /* if ((line.startsWith('[[')) && (line.endsWith(']]'))) { this.#unexpectedLines.push(line); } @@ -1913,6 +1911,7 @@ validateSourcesStr(sourcesStr, thePerson) { (line.includes('collaborative work-in-progress'))) { this.#unexpectedLines.push(line); } + */ } } } diff --git a/lib/biocheck-api/src/SourceRules.js b/lib/biocheck-api/src/SourceRules.js index 3212b4f3..255d15c0 100644 --- a/lib/biocheck-api/src/SourceRules.js +++ b/lib/biocheck-api/src/SourceRules.js @@ -192,10 +192,14 @@ class SourceRules { "", + "", "", + "", "<0", "<1", "<2", @@ -282,6 +286,7 @@ class SourceRules { "title: marriage", "'''see also:'''", "well documented", + "www.ancestry.au", "www.ancestry.ca", "www.bms2000.org", "confirmed by dna", @@ -300,6 +305,7 @@ class SourceRules { "research records", "various archives", "www.ancestry.com", + "www.wikitree.com", "acknowledgements:", "ash.howison.co.nz", "familysearch.com", @@ -772,6 +778,8 @@ class SourceRules { "thepeerage.com", "trees.ancestry.com", "unsourced family tree handed down", + "wc.rootsweb", + "worldconnect.rootsweb", "world family tree", "www.geni.com/people", // compilations (typically from family trees) @@ -1001,7 +1009,7 @@ class SourceRules { projectBox.status = templates[i].status.toLowerCase().trim(); this.#projectBox.push(projectBox); } - if (templates[i].type.toLowerCase().trim() === 'formattingtemplate') { + if (templates[i].type.toLowerCase().trim() === 'formatting template') { let formattingTemplate = { name: "", status: "", @@ -1121,6 +1129,11 @@ class SourceRules { }); return stat; } + +// TODO testing +getNavBox() { + return this.#navBox; +} /** * Return status value for Nav Box * assumes the leading {{ removed and line is lower case From 73019a2cfd9da0fdb333b9ab8d0ef7e27b153e49 Mon Sep 17 00:00:00 2001 From: ke4tch Date: Sun, 28 Jun 2026 12:26:31 -0400 Subject: [PATCH 2/2] Correct and improve source checking --- lib/biocheck-api/src/BioCheckPerson.js | 7 +- lib/biocheck-api/src/Biography.js | 190 +++++++++++++++++-------- lib/biocheck-api/src/SourceRules.js | 11 +- 3 files changed, 142 insertions(+), 66 deletions(-) diff --git a/lib/biocheck-api/src/BioCheckPerson.js b/lib/biocheck-api/src/BioCheckPerson.js index 9e5f4ae5..69354e51 100644 --- a/lib/biocheck-api/src/BioCheckPerson.js +++ b/lib/biocheck-api/src/BioCheckPerson.js @@ -346,14 +346,9 @@ export class BioCheckPerson { /** * Does profile have either birth or death location * @returns {Boolean} true if either location present - * or the privacy does not let us determine location */ hasLocation() { - if (this.person.privacyLevel < BioCheckPerson.MIN_PRIVACY) { - return true; - } else { - return this.person.hasLocation; - } + return this.person.hasLocation; } /** * Does profile have birth location diff --git a/lib/biocheck-api/src/Biography.js b/lib/biocheck-api/src/Biography.js index 9a57c3ed..93bc3788 100644 --- a/lib/biocheck-api/src/Biography.js +++ b/lib/biocheck-api/src/Biography.js @@ -81,6 +81,8 @@ export class Biography { #bioScore = 0; // ranking based on bioCheck #bioLineArray = []; // after == Biography == before Sources + #checkAllDates = false; // true to check all dates + // Hold results of parsing and validating a WikiTree biography #stats = { bioIsEmpty: false, @@ -135,14 +137,19 @@ export class Biography { invalidSource: [], // Invalid sources that were found validSource: [], invalidDnaSourceList: [], // Invalid source list for reporting + hasModernSources: false, + hasTooOldSources: false, + hasPre1700Sources: false, }; #messages = { sectionMessages: [], styleMessages: [], }; - #dnaReason = "" // Why is DNA confirmation incomplete + #dnaReason = ""; // Why is DNA confirmation incomplete #dnaSourceList = []; // DNA confirmation source -- collection of source and reason + #isDnaLine = false; // from testing one line + #isRepository = false; static #START_OF_COMMENT = ""; @@ -595,7 +602,8 @@ export class Biography { } // Check for absense of either birth or death location - if (!thePerson.hasLocation()) { + // when returned by the API + if (((thePerson.getPrivacy()) > 40) && (!thePerson.hasLocation())) { this.#style.bioMissingLocations = true; this.#style.bioHasStyleIssues = true; } @@ -622,6 +630,16 @@ export class Biography { return; } + /** + * Validate contents of bio + * Check for valid sources for all dates + * @returns {Boolean} true if profile looks good, else false. + */ + validateAllDates() { + this.#checkAllDates = true; + return this.validate(); + } + /** * Validate contents of bio * @returns {Boolean} true if profile looks good, else false. @@ -786,15 +804,15 @@ export class Biography { * @param thePerson {BioCheckPerson} person to check * @returns {Boolean} true if sources found. */ -validateSourcesStr(sourcesStr, thePerson) { - // build bioLines from the input sources string then validate - this.#getLines(sourcesStr); - this.#isPre1500 = thePerson.isPre1500(); - this.#isPre1700 = thePerson.isPre1700(); - this.#tooOldToRemember = thePerson.isTooOldToRemember(); - this.#fatherDnaMarked = thePerson.person.fatherDnaConfirmed; - this.#motherDnaMarked = thePerson.person.motherDnaConfirmed; - this.#scorePerson(thePerson); + validateSourcesStr(sourcesStr, thePerson) { + // build bioLines from the input sources string then validate + this.#getLines(sourcesStr); + this.#isPre1500 = thePerson.isPre1500(); + this.#isPre1700 = thePerson.isPre1700(); + this.#tooOldToRemember = thePerson.isTooOldToRemember(); + this.#fatherDnaMarked = thePerson.person.fatherDnaConfirmed; + this.#motherDnaMarked = thePerson.person.motherDnaConfirmed; + this.#scorePerson(thePerson); let isValid = this.#validateReferenceStrings(false); if (isValid) { this.#sources.sourcesFound = true; @@ -1078,6 +1096,27 @@ validateSourcesStr(sourcesStr, thePerson) { hasSources() { return this.#sources.sourcesFound; } + /** + * does bio have modern sources + * @returns {Boolean} true if bio appears to have modern sources + */ + hasModernSources() { + return this.#sources.hasModernSources; + } + /** + * does bio have too old to remember sources + * @returns {Boolean} true if bio appears to have too old to remember sources + */ + hasTooOldSources() { + return this.#sources.hasTooOldSources; + } + /** + * does bio have Pre1700 sources + * @returns {Boolean} true if bio appears to have Pre1700 sources + */ + hasPre1700Sources() { + return this.#sources.hasPre1700Sources; + } /** * get invalid sources found for profile * @returns {Array} array of String of invalid source lines @@ -1996,8 +2035,8 @@ validateSourcesStr(sourcesStr, thePerson) { */ #isValidSource(mixedCaseLine) { let isValid = false; // assume guilty - let isRepository = false; - let isDnaLine = false; + this.#isRepository = false; + this.#isDnaLine = false; // just ignore starting * if (mixedCaseLine.startsWith("*")) { mixedCaseLine = mixedCaseLine.substring(1); @@ -2006,6 +2045,58 @@ validateSourcesStr(sourcesStr, thePerson) { // perform tests on lower case line let line = mixedCaseLine.toLowerCase().trim(); + // It takes a minimum number of characters to be valid + //if (line.length >= Biography.#MIN_SOURCE_LEN) { + isValid = this.#isValidSourceLine(line, mixedCaseLine); + //} // endif too short when stripped of whitespace + + // Save line for reporting + if (isValid) { + this.#sources.validSource.push(mixedCaseLine); + } else { + if ((!this.#isRepository) && (!this.#isDnaLine)) { + if (!this.#ignoreDnaStart(line)) { + this.#sources.invalidSource.push(mixedCaseLine); + } + } + } + if (isValid) { + this.#sources.hasModernSources = true; + } + if (this.#checkAllDates && (!this.#sources.hasPre1700Sources)) { + // Check when you have no profile dates + // have already checked what essentially would be modern + // and if you have found Pre1700 then TooOld is covered + // and in this case only need to know if you find one good one + let savedTooOld = this.#tooOldToRemember; + let savedPre1700 = this.#treatAsPre1700; + this.#treatAsPre1700 = true; + this.#tooOldToRemember = true; + if (this.#isValidSourceLine(line, mixedCaseLine)) { + this.#sources.hasPre1700Sources = true; + this.#sources.hasTooOldSources = true; + } else { + this.#treatAsPre1700 = savedPre1700; + if (!this.#sources.hasTooOldSources) { + if (this.#isValidSourceLine(line, mixedCaseLine)) { + this.#sources.hasTooOldSources = true; + } + } + } + this.#treatAsPre1700 = savedPre1700; + this.#tooOldToRemember = savedTooOld; + } + + return isValid; + } + + /* + * Determine if valid source line + * @param {String} input source line + * @returns {Boolean} true if valid source, else false + */ + #isValidSourceLine(line, mixedCaseLine) { + let isValid = false; // ignore starting source: if (line.length > 0 && line.startsWith(Biography.#SOURCE_START)) { line = line.substring(7); @@ -2016,7 +2107,6 @@ validateSourcesStr(sourcesStr, thePerson) { line = line.slice(0, -1); line = line.trim(); } - // It takes a minimum number of characters to be valid if (line.length >= Biography.#MIN_SOURCE_LEN) { if (!this.#isInvalidStandAloneSource(line)) { line = line.trim(); @@ -2035,24 +2125,21 @@ validateSourcesStr(sourcesStr, thePerson) { line = line.replace(/\u0027/g, ''); // lines with ' will not match line = line.replace(/\u0026/g, 'and'); // and convert & to and let str = line.replace('family tree dna', ''); // valid in DNA confirmation - if (this.#onAnyPartialSourceList(str)) { - isValid = false; - } else { + if (!this.#onAnyPartialSourceList(str)) { // Check for line that starts with something on the invalid start partial list - if (this.#sourceRules.isInvalidStartPartialSource(line)) { - isValid = false; - } else { + if (!this.#sourceRules.isInvalidStartPartialSource(line)) { + // TODO can you refactor so this uses a plugin architecture? // Some other things to check if (!this.#isJustCensus(line)) { if (!this.#invalidFamilyTree(line)) { - isRepository = this.#isJustRepository(line) - if (!isRepository) { + this.#isRepository = this.#isJustRepository(line) + if (!this.#isRepository) { if (!this.#isJustGedcomCrud(line)) { if (!this.#isJustThePeerage(line)) { - isDnaLine = this.#isDnaSourceLine(line); - if (isDnaLine) { + this.#isDnaLine = this.#isDnaSourceLine(line); + if (this.#isDnaLine) { // if it says confident or suggested instead of confirmed // it should be neither a DNA nor traditional source this.#isValidDnaConfirmation(line, mixedCaseLine); @@ -2076,19 +2163,8 @@ validateSourcesStr(sourcesStr, thePerson) { } // endif on any valid partial list } // endif a findagrave citation } // endif on the list of invalid sources - } // endif too short when stripped of whitespace - - // Save line for reporting - if (isValid) { - this.#sources.validSource.push(mixedCaseLine); - } else { - if ((!isRepository) && (!isDnaLine)) { - if (!this.#ignoreDnaStart(line)) { - this.#sources.invalidSource.push(mixedCaseLine); - } - } } - return isValid; + return isValid } /* @@ -2100,13 +2176,12 @@ validateSourcesStr(sourcesStr, thePerson) { let isInvalidStandAlone = this.#sourceRules.isInvalidSource(line); if (!isInvalidStandAlone && this.#tooOldToRemember) { isInvalidStandAlone = this.#sourceRules.isInvalidSourceTooOld(line); - - if ((this.#isPre1700 || this.#treatAsPre1700) && !isInvalidStandAlone) { - isInvalidStandAlone = this.#sourceRules.isInvalidSourcePre1700(line); - } - if (this.#isPre1500 && !isInvalidStandAlone) { - // TODO add more pre1500 validation - } + } + if ((this.#isPre1700 || this.#treatAsPre1700) && !isInvalidStandAlone) { + isInvalidStandAlone = this.#sourceRules.isInvalidSourcePre1700(line); + } + if (this.#isPre1500 && !isInvalidStandAlone) { + ; // TODO add more pre1500 validation } return isInvalidStandAlone; } @@ -2118,13 +2193,12 @@ validateSourcesStr(sourcesStr, thePerson) { */ #onAnyPartialSourceList(line) { let foundInvalidPartialSource = this.#sourceRules.isInvalidPartialSource(line); - if (this.#tooOldToRemember && !foundInvalidPartialSource) { - foundInvalidPartialSource = this.#sourceRules.isInvalidPartialSourceTooOld(line); - } if ((this.#isPre1700 || this.#treatAsPre1700) && !foundInvalidPartialSource) { foundInvalidPartialSource = this.#sourceRules.isInvalidPartialSourcePre1700(line); } - // TODO add more pre1500 validation + if ((this.#tooOldToRemember || this.#treatAsPre1700) && !foundInvalidPartialSource) { + foundInvalidPartialSource = this.#sourceRules.isInvalidPartialSourceTooOld(line); + } return foundInvalidPartialSource; } /* @@ -2219,14 +2293,12 @@ validateSourcesStr(sourcesStr, thePerson) { nextIndex = index + 1; // Skip the 0 - ) { + if (!line.startsWith(Biography.#REFERENCES_TAG) && + !line.startsWith(Biography.#HEADING_START) && + !line.includes(Biography.#SEE_ALSO) && + !line.includes(Biography.#SEE_ALSO2) && + !line.includes(Biography.#SEE_ALSO3) && + line.length > 0) { // Now gather all lines from this line until an empty line // or a line that starts with * to test as the source // TODO consider in the future combining when nextLine @@ -2439,7 +2511,7 @@ validateSourcesStr(sourcesStr, thePerson) { * @returns {Boolean} true if this is just a repository line */ #isJustRepository(line) { - let isRepository = false; + let isRepos = false; if (line.includes("repository")) { let repositoryStrings = [ "ancestry.com.au", @@ -2488,11 +2560,11 @@ validateSourcesStr(sourcesStr, thePerson) { line = line.trim(); if (line.length > 0) { if (line === "repository") { - isRepository = true; + isRepos = true; } } } - return isRepository; + return isRepos; } /* @@ -3131,7 +3203,7 @@ validateSourcesStr(sourcesStr, thePerson) { * @param thePerson {BioCheckPerson} person */ #scorePerson(thePerson) { - if (thePerson.isUndated()) { + if (!this.#checkAllDates && (thePerson.isUndated())) { this.#bioScore = this.#bioScore - 10; } } diff --git a/lib/biocheck-api/src/SourceRules.js b/lib/biocheck-api/src/SourceRules.js index 255d15c0..9d8d62d4 100644 --- a/lib/biocheck-api/src/SourceRules.js +++ b/lib/biocheck-api/src/SourceRules.js @@ -367,6 +367,7 @@ class SourceRules { "family search website", "freereg baptism entry", "maternal dna matches:", + "military grave marker", "mormon church records", "paternal dna matches:", "replace this citation", @@ -548,6 +549,7 @@ class SourceRules { // anywhere in a line not a valid source #invalidPartialSourceList = [ "through the import of", + ".ged", "add sources here", "add [[sources]] here", "family tree maker", @@ -556,6 +558,7 @@ class SourceRules { "replace this citation", "family member and primary source", "i am a primary source", + "olmste(a)d files of", ]; // anywhere on a line is a valid source @@ -571,6 +574,7 @@ class SourceRules { "entered by", "no sources.", "uploaded by", + "repository:", "no repo record found", "source will be added by", "no sour record found", @@ -627,6 +631,7 @@ class SourceRules { "firsthand knowledge", "immediate family member", "as remembered by", + "personal recollection", "selon la mémoire de", "zoals herinnerd door", "eigen kennis", @@ -744,6 +749,7 @@ class SourceRules { "ancestry.com-oneworld tree", "árbol de familia", "arbre généalogique", + "as remembered by", "družinsko drevo", "drzewo rodzinne", "familie træ", @@ -785,6 +791,7 @@ class SourceRules { // compilations (typically from family trees) "ancestral file", "derbund wft", + "derbund software", "family data collection", "family group sheet", "international genealogical index", @@ -834,9 +841,11 @@ class SourceRules { // List of short strings that are not by themselves a valid source // to use for pulling apart a "source" that is a combination of these - // list of sources not valid by themselves that are < 15 characterse + // list of sources not valid by themselves that are < 15 characters // but you want to find these in reverse order to remove from the source #invalidSourceListShort = [ + //123456789012345 + "personal knowledge", "ancestry.co.uk", "ancestrydotcom", "billion graves",