# tools/core/matchers/reference.matcher.ts

> 118 lines of code and 29 definitions.

Tree: Coordination tree
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-matchers-reference-matcher-ts
Source text: https://banes-lab.com/assets/sources/source.35207c9f205555b9d47c20492a842c621d1aaed38c8487db9a828c134c16eef6.generated.txt

## Definitions

- `hasPrefix` (lexical_declaration, line 18)
- `consider` (lexical_declaration, line 95, exported)
- `isExternal` (lexical_declaration, line 80)
- `isPattern` (lexical_declaration, line 71)
- `referencesIn` (lexical_declaration, line 92, exported)
- `REFERENCE_FIELDS` (lexical_declaration, line 3, exported)
- `REFERENCE_INLINE_KINDS` (lexical_declaration, line 5)
- `EXTERNAL_PREFIXES` (lexical_declaration, line 7)
- `LOCAL_SCHEME` (lexical_declaration, line 9)
- `Reference` (interface_declaration, line 11, exported)
- `i` (lexical_declaration, line 22)
- `stripAnchor` (lexical_declaration, line 30)
- `hash` (lexical_declaration, line 31)
- `stripLocator` (lexical_declaration, line 35)
- `index` (lexical_declaration, line 41)
- `char` (lexical_declaration, line 42)
- `digit` (lexical_declaration, line 43)
- `unquote` (lexical_declaration, line 52)
- `start` (lexical_declaration, line 53)
- `end` (lexical_declaration, line 54)
- `firstToken` (lexical_declaration, line 64)
- `space` (lexical_declaration, line 65)
- `PLACEHOLDERS` (lexical_declaration, line 69)
- `colon` (lexical_declaration, line 87)
- `out` (lexical_declaration, line 93, exported)
- `value` (lexical_declaration, line 96, exported)
- `target` (lexical_declaration, line 107, exported)
- `slash` (lexical_declaration, line 112, exported)
- `isField` (lexical_declaration, line 126, exported)

## Source

```typescript
import { INLINE_KINDS, type Segment } from "../types/segment.types.ts";

export const REFERENCE_FIELDS = ["see", "source", "detect"] as const;

const REFERENCE_INLINE_KINDS: ReadonlySet<string> = new Set(INLINE_KINDS);

const EXTERNAL_PREFIXES = ["http://", "https://", "mailto:", "#"];

const LOCAL_SCHEME = "local:";

export interface Reference {
    readonly raw: string;
    readonly target: string;
    readonly locus: string;
    readonly line: number;
}

const hasPrefix = function hasPrefix(text: string, prefix: string): boolean {
    if (prefix.length > text.length) {
        return false;
    }
    for (let i = 0; i < prefix.length; i += 1) {
        if (text[i] !== prefix[i]) {
            return false;
        }
    }
    return true;
};

const stripAnchor = function stripAnchor(value: string): string {
    const hash = value.indexOf("#");
    return hash === -1 ? value : value.slice(0, hash);
};

const stripLocator = function stripLocator(value: string): string {
    const colon = value.lastIndexOf(":");
    if (colon <= 0 || colon === value.length - 1) {
        return value;
    }

    for (let index = colon + 1; index < value.length; index += 1) {
        const char = value.charAt(index);
        const digit = char >= "0" && char <= "9";
        if (!digit && char !== "-") {
            return value;
        }
    }

    return value.slice(0, colon);
};

const unquote = function unquote(value: string): string {
    let start = 0;
    let end = value.length;
    while (start < end && value[start] === "`") {
        start += 1;
    }
    while (end > start && value[end - 1] === "`") {
        end -= 1;
    }
    return value.slice(start, end);
};

const firstToken = function firstToken(value: string): string {
    const space = value.indexOf(" ");
    return space === -1 ? value : value.slice(0, space);
};

const PLACEHOLDERS = ["<", ">", "*", "?"];

const isPattern = function isPattern(value: string): boolean {
    for (const character of PLACEHOLDERS) {
        if (value.includes(character)) {
            return true;
        }
    }
    return false;
};

const isExternal = function isExternal(value: string): boolean {
    for (const prefix of EXTERNAL_PREFIXES) {
        if (hasPrefix(value, prefix)) {
            return true;
        }
    }

    const colon = value.indexOf(":");
    const slash = value.indexOf("/");
    return colon !== -1 && (slash === -1 || colon < slash);
};

export const referencesIn = function referencesIn(segment: Segment): Reference[] {
    const out: Reference[] = [];

    const consider = (raw: string, locus: string): void => {
        let value = unquote(firstToken(raw));
        if (hasPrefix(value, LOCAL_SCHEME)) {
            value = value.slice(LOCAL_SCHEME.length);
        }
        if (value.length === 0 || isExternal(value)) {
            return;
        }
        if (hasPrefix(value, "@")) {
            value = value.slice(1);
        }

        const target = stripLocator(stripAnchor(value));
        if (target.length === 0) {
            return;
        }

        const slash = target.lastIndexOf("/");
        if (slash === -1) {
            return;
        }
        if (!target.slice(slash + 1).includes(".")) {
            return;
        }
        if (isPattern(target)) {
            return;
        }

        out.push({ line: segment.line, locus, raw, target });
    };

    const isField = segment.kind === "field" || segment.kind === "frontmatter-field";
    if (isField && segment.key !== undefined && segment.value !== undefined) {
        for (const key of REFERENCE_FIELDS) {
            if (segment.key === key) {
                consider(segment.value, `${key}:`);
            }
        }
    }

    for (const inline of segment.inlines) {
        if (REFERENCE_INLINE_KINDS.has(inline.kind)) {
            consider(inline.value, inline.kind);
        }
    }

    return out;
};
```
