shared/formatters/writing.formatter.ts
shared/formatters/writing.formatter.ts is a file in GovLab Extension Host. 70 lines of code and 22 definitions.
import type { CanonCheck, CanonExample, CanonLayer, CanonRule } from "../../types/writing.types.ts";
const LINE = "\n";
const BLANK = "\n\n";
const ITEM = "- ";
const NESTED = " - ";
const LIST = ", ";
const AND = " and ";
const REVIEW = "review";
const ENFORCED = "enforced in ";
const OFF = "off";
const stateOf = function stateOf(check: CanonCheck): string {
if (check.detection === REVIEW) {
return REVIEW;
}
return check.enforcedIn.length === 0 ? OFF : ENFORCED + check.enforcedIn.map((id) => `\`${id}\``).join(AND);
};
const itemsOf = function itemsOf(label: string, values: readonly string[]): readonly string[] {
return values.length === 0 ? [] : [`${ITEM}**${label}:**`, ...values.map((value) => NESTED + value)];
};
const checkLabel = function checkLabel(check: CanonCheck): string {
return `${check.id} (${stateOf(check)})`;
};
const exampleLines = function exampleLines(example: CanonExample): readonly string[] {
const repaired = example.repaired === null ? [] : [`${NESTED}Repaired: "${example.repaired}"`];
return [`${NESTED}Rejected: "${example.rejected}" ${example.why}`, ...repaired];
};
const ruleBlock = function ruleBlock(rule: CanonRule): string {
const lines = [
`### ${rule.id}`,
"",
rule.rule,
"",
`${ITEM}**Why:** ${rule.why}`,
...itemsOf("Conditions", rule.conditions),
...itemsOf("Banned", rule.bans),
...(rule.examples.length === 0 ? [] : [`${ITEM}**Examples:**`, ...rule.examples.flatMap(exampleLines)]),
`${ITEM}**Held by:** ${rule.gate ?? REVIEW}`,
...(rule.checks.length === 0 ? [] : [`${ITEM}**Checks:** ${rule.checks.map(checkLabel).join(LIST)}`]),
];
return lines.join(LINE);
};
const layerBlock = function layerBlock(layer: CanonLayer): string {
const covers = [`**Covers:**`, "", ...layer.covers.map((entry) => ITEM + entry)].join(LINE);
const defers =
layer.defersTo.length === 0
? []
: [
[
"**Defers to:**",
"",
...layer.defersTo.map((home) => `${ITEM}\`${home.path}\`: ${home.covers}`),
].join(LINE),
];
return [`## ${layer.title} (\`${layer.id}\`)`, layer.intro, covers, ...defers, ...layer.rules.map(ruleBlock)].join(
BLANK,
);
};
export const canonMarkdown = function canonMarkdown(
layers: readonly CanonLayer[],
header: readonly string[],
precedence: string,
): string {
const index = [
"## Layers",
"",
...layers.map((layer) => `${ITEM}\`${layer.id}\`: ${layer.title}, ${String(layer.rules.length)} rule(s)`),
].join(LINE);
const closing = `## Precedence${BLANK}${precedence}`;
return [...header, index, ...layers.map(layerBlock), closing].join(BLANK) + LINE;
};