From 87988954ad7314bee59932b0e5ef3474936ed33e Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 20 Nov 2023 13:59:13 -0400 Subject: data: update and revamp isCommentary validator --- src/data/things/validators.js | 59 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) (limited to 'src/data') diff --git a/src/data/things/validators.js b/src/data/things/validators.js index 2893e7fd..569a7b34 100644 --- a/src/data/things/validators.js +++ b/src/data/things/validators.js @@ -5,7 +5,8 @@ import printable_characters from 'printable-characters'; const {strlen} = printable_characters; import {colors, ENABLE_COLOR} from '#cli'; -import {empty, typeAppearance, withAggregate} from '#sugar'; +import {cut, empty, typeAppearance, withAggregate} from '#sugar'; +import {commentaryRegex} from '#wiki-data'; function inspect(value) { return nodeInspect(value, {colors: ENABLE_COLOR}); @@ -248,18 +249,56 @@ export function isColor(color) { throw new TypeError(`Unknown color format`); } -export function isCommentary(commentary) { - isString(commentary); +export function isCommentary(commentaryText) { + isString(commentaryText); - const [firstLine] = commentary.match(/.*/); - if (!firstLine.replace(/<\/b>/g, '').includes(':')) { - throw new TypeError(`Missing commentary citation: "${ - firstLine.length > 40 - ? firstLine.slice(0, 40) + '...' - : firstLine - }"`); + const rawMatches = + Array.from(commentaryText.matchAll(commentaryRegex)); + + if (empty(rawMatches)) { + throw new TypeError(`Expected at least one commentary heading`); } + const niceMatches = + rawMatches.map(match => ({ + position: match.index, + length: match[0].length, + })); + + validateArrayItems(({position, length}, index) => { + if (index === 0 && position > 0) { + throw new TypeError(`Expected first commentary heading to be at top`); + } + + const ownInput = commentaryText.slice(position, position + length); + const restOfInput = commentaryText.slice(position + length); + const nextLineBreak = restOfInput.indexOf('\n'); + const upToNextLineBreak = restOfInput.slice(0, nextLineBreak); + + if (/\S/.test(upToNextLineBreak)) { + throw new TypeError( + `Expected commentary heading to occupy entire line, got extra text:\n` + + `${colors.green(`"${cut(ownInput, 40)}"`)} (<- heading)\n` + + `(extra on same line ->) ${colors.red(`"${cut(upToNextLineBreak, 30)}"`)}\n` + + `(Check for missing "|-" in YAML, or a misshapen annotation)`); + } + + const nextHeading = + (index === niceMatches.length - 1 + ? commentaryText.length + : niceMatches[index + 1].position); + + const upToNextHeading = + commentaryText.slice(position + length, nextHeading); + + if (!/\S/.test(upToNextHeading)) { + throw new TypeError( + `Expected commentary entry to have body text, only got a heading`); + } + + return true; + })(niceMatches); + return true; } -- cgit 1.3.0-6-gf8a5