# core/validators/link.validator.ts

> 30 lines of code and 9 definitions.

Tree: Build tree
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/build#file-build-core-validators-link-validator-ts
Source text: https://banes-lab.com/assets/sources/source.673798623c9fd131e469b3402049f4deb250eb263f2330f103f7666f7056117d.generated.txt

## Definitions

- `pageLinks` (lexical_declaration, line 3)
- `linkChanges` (lexical_declaration, line 15, exported)
- `bySection` (lexical_declaration, line 16, exported)
- `pageOf` (lexical_declaration, line 17, exported)
- `byPage` (lexical_declaration, line 18, exported)
- `lost` (lexical_declaration, line 19, exported)
- `moved` (lexical_declaration, line 20, exported)
- `held` (lexical_declaration, line 22, exported)
- `onPage` (lexical_declaration, line 23, exported)

## Source

```typescript
import type { LinkChange, LinkChanges, LinkSet, PageSection } from "#types/writing.types";

const pageLinks = function pageLinks(sections: readonly PageSection[]): ReadonlyMap<string, ReadonlySet<string>> {
    const byPage = new Map<string, Set<string>>();
    for (const section of sections) {
        const held = byPage.get(section.page) ?? new Set<string>();
        for (const link of section.links) {
            held.add(link);
        }
        byPage.set(section.page, held);
    }
    return byPage;
};

export const linkChanges = function linkChanges(baseline: LinkSet, sections: readonly PageSection[]): LinkChanges {
    const bySection = new Map(sections.map((section) => [section.key, new Set(section.links)]));
    const pageOf = new Map(sections.map((section) => [section.key, section.page]));
    const byPage = pageLinks(sections);
    const lost: LinkChange[] = [];
    const moved: LinkChange[] = [];
    for (const [key, links] of Object.entries(baseline)) {
        const held = bySection.get(key);
        const onPage = byPage.get(pageOf.get(key) ?? key);
        for (const target of links ?? []) {
            if (held?.has(target) === true) {
                continue;
            }
            (onPage?.has(target) === true ? moved : lost).push({ key, target });
        }
    }
    return { lost, moved };
};
```
