core/resolvers/template.resolver.ts
core/resolvers/template.resolver.ts is a file in GovLab Context. 36 lines of code and 10 definitions.
import type { TemplateRecord, TemplateSlot } from "#types/grammar.types";
import { enumViolation, missingRequiredSlot } from "#configuration/strings/grammar.strings";
import type { TemplateResolveResult } from "#types/grammar.document.types";
const slotMarkOf = function slotMarkOf(name: string): string {
return `{${name}}`;
};
const suppliedValue = function suppliedValue(slots: Record<string, string>, name: string): string {
return Object.hasOwn(slots, name) ? (slots[name] ?? "") : "";
};
const outOfEnum = function outOfEnum(slot: TemplateSlot, value: string): boolean {
if (value === "" || !Array.isArray(slot.enum) || slot.enum.length === 0) {
return false;
}
return !slot.enum.includes(value);
};
const slotViolation = function slotViolation(slot: TemplateSlot, value: string): string | null {
if (slot.required && value === "") {
return missingRequiredSlot(slot.name);
}
return outOfEnum(slot, value) ? enumViolation(slot.name) : null;
};
const substitute = function substitute(body: string, slots: Record<string, string>): string {
return Object.entries(slots).reduce((text, [name, value]) => text.replaceAll(slotMarkOf(name), value), body);
};
export const resolvePagTemplate = function resolvePagTemplate(
template: TemplateRecord,
slots: Record<string, string>,
): TemplateResolveResult {
const violations = template.slots.flatMap((slot) => slotViolation(slot, suppliedValue(slots, slot.name)) ?? []);
const text = substitute(template.body, slots);
const unresolved = template.slots.filter((slot) => text.includes(slotMarkOf(slot.name))).map((slot) => slot.name);
return { text, unresolved, violations };
};
export const slotIsDangling = function slotIsDangling(template: TemplateRecord, slot: TemplateSlot): boolean {
return !template.body.includes(slotMarkOf(slot.name));
};