# shared/formatters/writing.formatter.ts

> 70 lines of code and 22 definitions.

Tree: Governance tree
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/governance#file-governance-shared-formatters-writing-formatter-ts
Source text: https://banes-lab.com/source/governance/shared/formatters/writing.formatter.ts.txt

Listed in [shared/formatters](https://banes-lab.com/api/source/governance/shared/formatters.md).

## Definitions

- `stateOf` (lexical_declaration, line 14)
- `checkLabel` (lexical_declaration, line 25)
- `LINE` (lexical_declaration, line 3)
- `BLANK` (lexical_declaration, line 4)
- `ITEM` (lexical_declaration, line 5)
- `NESTED` (lexical_declaration, line 6)
- `LIST` (lexical_declaration, line 8)
- `AND` (lexical_declaration, line 9)
- `REVIEW` (lexical_declaration, line 10)
- `ENFORCED` (lexical_declaration, line 11)
- `OFF` (lexical_declaration, line 12)
- `itemsOf` (lexical_declaration, line 21)
- `exampleLines` (lexical_declaration, line 29)
- `repaired` (lexical_declaration, line 30)
- `ruleBlock` (lexical_declaration, line 34)
- `lines` (lexical_declaration, line 35)
- `layerBlock` (lexical_declaration, line 50)
- `covers` (lexical_declaration, line 51)
- `defers` (lexical_declaration, line 52)
- `canonMarkdown` (lexical_declaration, line 67, exported)
- `index` (lexical_declaration, line 72, exported)
- `closing` (lexical_declaration, line 77, exported)

## Source

```typescript
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;
};
```
