core/matchers/target.matcher.ts

core/matchers/target.matcher.ts is a file in GovLab Quality. 56 lines of code and 13 definitions.

import {
    ES_LEGACY_BASE,
    ES_LEGACY_MAX,
    ES_MODERN_BASE,
    ES_NEXT,
    ES_PREFIX_LEN,
    MIN_TOKEN_LEN,
    YEAR_THRESHOLD,
} from "#configuration/constants/target.constants";
import { everyChar, isDigit } from "@govlab/constants";
import type { EsTokenSpan } from "#types/target.types";

const isEsPrefix = function isEsPrefix(token: string): boolean {
    return token.slice(0, ES_PREFIX_LEN).toUpperCase() === "ES";
};

const yearOfVersion = function yearOfVersion(n: number): number {
    if (n >= YEAR_THRESHOLD) {
        return n;
    }
    return n <= ES_LEGACY_MAX ? ES_LEGACY_BASE + n : ES_MODERN_BASE + n;
};

export const esTokenYear = function esTokenYear(token: string): number | null {
    if (token.length < MIN_TOKEN_LEN || !isEsPrefix(token)) {
        return null;
    }
    const rest = token.slice(ES_PREFIX_LEN);
    if (rest.toLowerCase() === ES_NEXT) {
        return Number.POSITIVE_INFINITY;
    }
    return rest.length > 0 && everyChar(rest, isDigit) ? yearOfVersion(Number(rest)) : null;
};

const spanAt = function spanAt(text: string, open: number): { end: number; span: EsTokenSpan | null } {
    const close = text.indexOf('"', open + 1);
    if (close === -1) {
        return { end: text.length, span: null };
    }
    const token = text.slice(open + 1, close);
    return { end: close, span: esTokenYear(token) === null ? null : { close, open, token } };
};

const findEsTokenSpans = function findEsTokenSpans(text: string): EsTokenSpan[] {
    const spans: EsTokenSpan[] = [];
    let at = text.indexOf('"');
    while (at !== -1) {
        const { end, span } = spanAt(text, at);
        if (span !== null) {
            spans.push(span);
        }
        at = text.indexOf('"', end + 1);
    }
    return spans;
};

export const findStaleEsTokens = function findStaleEsTokens(text: string, minYear: number): EsTokenSpan[] {
    return findEsTokenSpans(text).filter((span) => {
        const year = esTokenYear(span.token);
        return year !== null && year < minYear;
    });
};