# shared/analyzers/document.analyzer.ts

> 36 lines of code and 8 definitions.

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

Listed in [shared/analyzers](https://banes-lab.com/api/source/governance/shared/analyzers.md), after [shared/analyzers/diagram.analyzer.ts](https://banes-lab.com/source/governance/shared/analyzers/diagram.analyzer.ts.md) and before [shared/analyzers/generator.analyzer.ts](https://banes-lab.com/source/governance/shared/analyzers/generator.analyzer.ts.md).

## Definitions

- `found` (lexical_declaration, line 17)
- `sentenceFindings` (lexical_declaration, line 21)
- `documentFindingsOf` (lexical_declaration, line 37, exported)
- `isEnforced` (lexical_declaration, line 13)
- `composedFinding` (lexical_declaration, line 32)
- `KNOWN_TERMS` (lexical_declaration, line 11)
- `{ words }` (lexical_declaration, line 22)
- `check` (lexical_declaration, line 33)

## Uses

- [shared/analyzers/composition.analyzer.ts](https://banes-lab.com/source/governance/shared/analyzers/composition.analyzer.ts.md)
- [shared/analyzers/sentence.analyzer.ts](https://banes-lab.com/source/governance/shared/analyzers/sentence.analyzer.ts.md)
- [shared/manifests/writing.canon.manifest.ts](https://banes-lab.com/source/governance/shared/manifests/writing.canon.manifest.ts.md)
- [shared/matchers/vocabulary.matcher.ts](https://banes-lab.com/source/governance/shared/matchers/vocabulary.matcher.ts.md)

## Source

```typescript
import { BANNED_TERMS, KNOWN_VIOLATIONS, PROPER_NAMES } from "../manifests/vocabulary.manifest.ts";
import type { CanonCheckId, CompositionFinding, DocumentFinding } from "../../types/writing.types.ts";
import { DOCUMENT_CHANNEL, isCheckEnforced } from "../manifests/writing.canon.manifest.ts";
import { LONG_DASH, SEMICOLON } from "../manifests/punctuation.manifest.ts";
import { firstKnownIn, firstTermIn } from "../matchers/vocabulary.matcher.ts";
import { sentencesOf, shapeOf } from "./sentence.analyzer.ts";
import { CHECK_BY_KIND } from "../manifests/composition.manifest.ts";
import { SENTENCE_CAP } from "../manifests/sentence.manifest.ts";
import { compositionFindingsOf } from "./composition.analyzer.ts";

const KNOWN_TERMS: readonly string[] = [...KNOWN_VIOLATIONS.keys()];

const isEnforced = function isEnforced(finding: DocumentFinding): boolean {
    return isCheckEnforced(finding.check, DOCUMENT_CHANNEL);
};

const found = function found(check: CanonCheckId, evidence: string | null, sentence: string): DocumentFinding[] {
    return evidence === null ? [] : [{ check, evidence, sentence }];
};

const sentenceFindings = function sentenceFindings(sentence: string): DocumentFinding[] {
    const { words } = shapeOf(sentence);
    return [
        ...found("no-semicolon", sentence.includes(SEMICOLON) ? SEMICOLON : null, sentence),
        ...found("no-long-dash", sentence.includes(LONG_DASH) ? LONG_DASH : null, sentence),
        ...found("named-party", firstKnownIn(sentence, KNOWN_TERMS, PROPER_NAMES), sentence),
        ...found("no-praise-vocabulary", firstTermIn(sentence, BANNED_TERMS), sentence),
        ...found("sentence-cap", words > SENTENCE_CAP ? `${String(words)} words` : null, sentence),
    ];
};

const composedFinding = function composedFinding(finding: CompositionFinding): DocumentFinding[] {
    const check = CHECK_BY_KIND.get(finding.kind);
    return check === undefined ? [] : found(check, finding.evidence, finding.sentence);
};

export const documentFindingsOf = function documentFindingsOf(text: string): DocumentFinding[] {
    return [
        ...compositionFindingsOf(text).flatMap(composedFinding),
        ...sentencesOf(text).flatMap(sentenceFindings),
    ].filter(isEnforced);
};
```
