# core/plugins/manifest.readme.plugin.ts

> 84 lines of code and 14 definitions.

Tree: GovLab Docs
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/docs#file-docs-core-plugins-manifest-readme-plugin-ts
Source text: https://banes-lab.com/source/docs/core/plugins/manifest.readme.plugin.ts.txt

Listed in [core/plugins](https://banes-lab.com/api/source/docs/core/plugins.md), after [core/plugins/manifest.quality.plugin.ts](https://banes-lab.com/source/docs/core/plugins/manifest.quality.plugin.ts.md) and before [core/plugins/manifest.scope.plugin.ts](https://banes-lab.com/source/docs/core/plugins/manifest.scope.plugin.ts.md).

## Definitions

- `extraError` (lexical_declaration, line 66)
- `coreErrors` (lexical_declaration, line 57)
- `isKnownField` (lexical_declaration, line 50)
- `isApiNotes` (lexical_declaration, line 16)
- `validate` (method_definition, line 82, exported)
- `isInstall` (lexical_declaration, line 24)
- `contribute` (method_definition, line 74, exported)
- `FieldCheck` (type_alias_declaration, line 12)
- `SECTION` (lexical_declaration, line 14)
- `CORE` (lexical_declaration, line 28)
- `OPTIONAL` (lexical_declaration, line 41)
- `plugin` (lexical_declaration, line 73, exported)
- `docs` (lexical_declaration, line 83, exported)
- `extras` (lexical_declaration, line 90, exported)

## Contained in

- [core/plugins](https://banes-lab.com/anatomy/docs/folder-docs-core-plugins.md)

## Uses

- [configuration/strings/manifest.strings.ts](https://banes-lab.com/source/docs/configuration/strings/manifest.strings.ts.md)
- [core/predicates/readme.predicate.ts](https://banes-lab.com/source/docs/core/predicates/readme.predicate.ts.md)
- [core/predicates/record.predicate.ts](https://banes-lab.com/source/docs/core/predicates/record.predicate.ts.md)
- [core/validators/diagram.validator.ts](https://banes-lab.com/source/docs/core/validators/diagram.validator.ts.md)

## Grounds

- [Manifest-Based Design](https://banes-lab.com/records/architecture/manifest-based-design.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/docs/folder-docs-configuration-strings.md)
- [core/plugins](https://banes-lab.com/anatomy/docs/folder-docs-core-plugins.md)
- [core/predicates](https://banes-lab.com/anatomy/docs/folder-docs-core-predicates.md)
- [core/validators](https://banes-lab.com/anatomy/docs/folder-docs-core-validators.md)

## Source

```typescript
import {
    DOCS_FIELD_ERRORS,
    MANIFEST_ERRORS,
    customDocsField,
    missingDocsField,
} from "#configuration/strings/manifest.strings";
import { isNonEmptyString, isRenderable, isStringArray } from "#core/predicates/readme.predicate";
import type { Manifest } from "#types/readme.types";
import type { ManifestPlugin } from "#types/manifest.types";
import { isPlainRecord } from "#core/predicates/record.predicate";

type FieldCheck = (value: unknown) => boolean;

const SECTION = "docs";

const isApiNotes = function isApiNotes(value: unknown): boolean {
    return (
        Array.isArray(value) &&
        value.length > 0 &&
        value.every((note) => isPlainRecord(note) && isNonEmptyString(note["name"]) && isNonEmptyString(note["note"]))
    );
};

const isInstall = function isInstall(value: unknown): boolean {
    return typeof value === "string" || isRenderable(value);
};

const CORE: ReadonlyMap<keyof typeof DOCS_FIELD_ERRORS, FieldCheck> = new Map<
    keyof typeof DOCS_FIELD_ERRORS,
    FieldCheck
>([
    ["aiContext", isRenderable],
    ["configuration", isRenderable],
    ["disposal", isStringArray],
    ["overview", isNonEmptyString],
    ["quickStart", isRenderable],
    ["whenNotToUse", isStringArray],
    ["whenToUse", isStringArray],
]);

const OPTIONAL: ReadonlyMap<keyof typeof DOCS_FIELD_ERRORS, FieldCheck> = new Map<
    keyof typeof DOCS_FIELD_ERRORS,
    FieldCheck
>([
    ["api", isRenderable],
    ["apiNotes", isApiNotes],
    ["install", isInstall],
]);

const isKnownField = function isKnownField(
    fields: ReadonlyMap<keyof typeof DOCS_FIELD_ERRORS, FieldCheck>,
    key: string,
): key is keyof typeof DOCS_FIELD_ERRORS {
    return [...fields.keys()].some((field) => field === key);
};

const coreErrors = function coreErrors(docs: Manifest): string[] {
    return [...CORE].flatMap(([key, check]) => {
        if (docs[key] === undefined) {
            return [missingDocsField(key)];
        }
        return check(docs[key]) ? [] : [DOCS_FIELD_ERRORS[key]];
    });
};

const extraError = function extraError(docs: Manifest, key: string): string[] {
    if (isKnownField(OPTIONAL, key)) {
        return (OPTIONAL.get(key) ?? isRenderable)(docs[key]) ? [] : [DOCS_FIELD_ERRORS[key]];
    }
    return isRenderable(docs[key]) ? [] : [customDocsField(key)];
};

export const plugin: ManifestPlugin = {
    contribute(manifest, entry) {
        if (isPlainRecord(manifest[SECTION])) {
            entry["documented"] = true;
        }
    },
    name: "docs",
    section: {
        keys: [SECTION],
        validate(manifest) {
            const docs = manifest[SECTION];
            if (docs === undefined) {
                return [];
            }
            if (!isPlainRecord(docs)) {
                return [MANIFEST_ERRORS.docsShape];
            }
            const extras = Object.keys(docs).filter((key) => !isKnownField(CORE, key));
            return [...coreErrors(docs), ...extras.flatMap((key) => extraError(docs, key))];
        },
    },
};
```
