core/converters/identifier.converter.ts

core/converters/identifier.converter.ts is a file in GovLab Context. 46 lines of code and 10 definitions.

import {
    DIGIT_END,
    DIGIT_START,
    LOWER_END,
    LOWER_START,
    SLUG_SEPARATOR,
} from "#configuration/constants/identifier.constants";
import { identifierParts, normalizeWord } from "@govlab/constants";

const SPACE = " ";

const inRange = function inRange(code: number, start: number, end: number): boolean {
    return code >= start && code <= end;
};

const isAlnum = function isAlnum(code: number | undefined): boolean {
    if (typeof code !== "number") {
        return false;
    }
    return inRange(code, DIGIT_START, DIGIT_END) || inRange(code, LOWER_START, LOWER_END);
};

interface SlugState {
    out: string;
    prevHyphen: boolean;
}

const appended = function appended(state: SlugState, ch: string): SlugState {
    if (isAlnum(ch.codePointAt(0))) {
        return { out: state.out + ch, prevHyphen: false };
    }
    if (state.prevHyphen || state.out.length === 0) {
        return state;
    }
    return { out: `${state.out}${SLUG_SEPARATOR}`, prevHyphen: true };
};

export const slugify = function slugify(name: string): string {
    const lowered = name.toLowerCase();
    let state: SlugState = { out: "", prevHyphen: false };
    for (let at = 0; at < lowered.length; at += 1) {
        state = appended(state, lowered.charAt(at));
    }
    return state.out.endsWith(SLUG_SEPARATOR) ? state.out.slice(0, -1) : state.out;
};

export const nameKeyOf = function nameKeyOf(phrase: string): string {
    return slugify(identifierParts(phrase).join(SPACE))
        .split(SLUG_SEPARATOR)
        .filter((word) => word.length > 0)
        .map((word) => normalizeWord(word))
        .join(SLUG_SEPARATOR);
};