# core/validators/link.validator.ts

> 30 lines of code and 9 definitions.

Tree: Bane's Lab Content
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/content#file-content-core-validators-link-validator-ts
Source text: https://banes-lab.com/source/content/core/validators/link.validator.ts.txt

Listed in [core/validators](https://banes-lab.com/api/source/content/core/validators.md), after [core/validators/leak.validator.ts](https://banes-lab.com/source/content/core/validators/leak.validator.ts.md) and before [core/validators/panel.validator.ts](https://banes-lab.com/source/content/core/validators/panel.validator.ts.md).

## 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)

## Contained in

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

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