import { CITE_ATTRIBUTE, CITE_CLASS } from "#configuration/constants/chapter.constants"; import type { ElementTag } from "#types/element.types"; import type { Run } from "#types/markup.types"; import { convertMarkup } from "#core/converters/markup.converter"; import { createElement } from "#core/factories/element.factory"; import { createLink } from "#presentation/components/link.component"; const NO_CLASS = ""; const TAG_BY_KIND: ReadonlyMap = new Map([ ["strong", "strong"], ["emphasis", "em"], ["code", "code"], ["link", "a"], ["break", "br"], ["cite", "span"], ]); const renderRun = function renderRun(run: Run): Node { const tag = TAG_BY_KIND.get(run.kind); if (tag === undefined) { return document.createTextNode(run.text); } if (run.kind === "link" && run.href !== undefined) { return createLink(run.href, NO_CLASS, [run.text]); } if (run.kind === "cite") { return createElement("span", { attributes: { [CITE_ATTRIBUTE]: run.text }, className: CITE_CLASS, text: run.text, }); } return createElement(tag, run.kind === "break" ? {} : { text: run.text }); }; const renderMarkup = function renderMarkup(markup: string): readonly Node[] { return convertMarkup(markup).map(renderRun); }; export const plainText = function plainText(markup: string): string { return convertMarkup(markup) .map((run) => run.text) .join(NO_CLASS); }; export const fillMarkup = function fillMarkup(element: T, markup: string): T { element.replaceChildren(...renderMarkup(markup)); return element; };