domain/converters/search.fragment.converter.ts

domain/converters/search.fragment.converter.ts is a file in Bane's Lab Site. 68 lines of code and 12 definitions.

import type { Section, Subsection } from "#types/document.types";
import { isGlossary, textsOf } from "#core/analyzers/search.analyzer";
import { markupWords, matchesAll } from "#core/matchers/search.matcher";
import type { Block } from "#types/block.types";

const heldWords = new WeakMap<object, readonly string[]>();

const wordsIn = function wordsIn(value: object): readonly string[] {
    const held = heldWords.get(value);
    if (held !== undefined) {
        return held;
    }
    const words = textsOf(value).flatMap(markupWords);
    heldWords.set(value, words);
    return words;
};

const proseWords = function proseWords(
    parts: readonly (string | undefined)[],
    blocks: readonly Block[],
): readonly string[] {
    return [
        ...parts.flatMap((part) => (part === undefined ? [] : markupWords(part))),
        ...blocks.filter((block) => !isGlossary(block)).flatMap(wordsIn),
    ];
};

const narrowGlossaries = function narrowGlossaries(terms: readonly string[], blocks: readonly Block[]): Block[] {
    return blocks.filter(isGlossary).flatMap((block) => {
        const entries = block.entries.filter((entry) => matchesAll(terms, wordsIn(entry)));
        return entries.length === 0 ? [] : [{ ...block, entries }];
    });
};

export const narrowSubsection = function narrowSubsection(
    terms: readonly string[],
    sub: Subsection,
): Subsection | null {
    if (matchesAll(terms, proseWords([sub.title, sub.content], sub.blocks ?? []))) {
        return sub;
    }
    const blocks = narrowGlossaries(terms, sub.blocks ?? []);
    if (blocks.length === 0) {
        return null;
    }
    return {
        blocks,
        title: sub.title,
        ...(sub.id === undefined ? {} : { id: sub.id }),
        ...(sub.layout === undefined ? {} : { layout: sub.layout }),
    };
};

export const narrowSection = function narrowSection(terms: readonly string[], section: Section): Section | null {
    if (matchesAll(terms, proseWords([section.title, section.intro], section.blocks ?? []))) {
        return section;
    }
    const subsections = section.subsections.flatMap((sub) => {
        const narrowed = narrowSubsection(terms, sub);
        return narrowed === null ? [] : [narrowed];
    });
    const blocks = narrowGlossaries(terms, section.blocks ?? []);
    if (subsections.length === 0 && blocks.length === 0) {
        return null;
    }
    return {
        icon: section.icon,
        id: section.id,
        subsections,
        title: section.title,
        ...(blocks.length === 0 ? {} : { blocks }),
        ...(section.layout === undefined ? {} : { layout: section.layout }),
    };
};