core/validators/document.validator.ts
core/validators/document.validator.ts is a file in GovLab Docs. 48 lines of code and 14 definitions.
import { SPINE_DETAILS, missingFrontmatterField } from "#configuration/strings/document.strings";
import type { SpineDefect, SpineOptions } from "#types/document.types";
import { parseFrontmatter } from "#core/parsers/metadata.parser";
import { splitLines } from "#core/parsers/markdown.parser";
const TITLE_PREFIX = "# ";
const SETEXT_CHAR = "=";
const isSetextUnderline = function isSetextUnderline(line: string): boolean {
for (const char of line) {
if (char !== SETEXT_CHAR) {
return false;
}
}
return line.length > 0;
};
const titleDefect = function titleDefect(source: string, bodyStart: number): SpineDefect | null {
const lines = splitLines(source);
let at = bodyStart;
while (at < lines.length && (lines[at] ?? "").trim() === "") {
at += 1;
}
const first = lines[at] ?? "";
const setext = first.trim().length > 0 && isSetextUnderline((lines[at + 1] ?? "").trim());
return first.startsWith(TITLE_PREFIX) || setext
? null
: { code: "no-title", detail: SPINE_DETAILS.noTitle, line: at + 1 };
};
const missingFields = function missingFields(
fields: Record<string, string>,
requiredKeys: readonly string[],
): SpineDefect[] {
return requiredKeys
.filter((key) => (fields[key] ?? "") === "")
.map((key): SpineDefect => ({ code: "missing-field", detail: missingFrontmatterField(key), line: 1 }));
};
export const validateSpine = function validateSpine(
source: string,
requiredKeys: readonly string[],
options: SpineOptions = {},
): SpineDefect[] {
const { requireFrontmatter = true, requireTitle = true } = options;
const frontmatter = parseFrontmatter(source);
if (!frontmatter.present && requireFrontmatter) {
return [{ code: "no-frontmatter", detail: SPINE_DETAILS.noFrontmatter, line: 1 }];
}
const fieldDefects = frontmatter.present ? missingFields(frontmatter.fields, requiredKeys) : [];
const title = requireTitle ? titleDefect(source, frontmatter.bodyStart) : null;
return title === null ? fieldDefects : [...fieldDefects, title];
};