/* * Copyright (c) 2023, networkException * * SPDX-License-Identifier: BSD-2-Clause */ import { Color } from './html/highlighter/properties/color.js'; import { Property } from './html/highlighter/property.js'; import { Span } from './html/highlighter/span.js'; import { Inspector } from './html/inspector.js'; const sameProperties = (a: Array | undefined, b: Array | undefined): boolean => { if (a === undefined || b === undefined) return false; if (a.length !== b.length) return false; for (const property of a) { let found = false; for (const otherProperty of b) if (property.equals(otherProperty)) found = true; if (!found) return false; } return true; }; const applyProperties = (element: HTMLSpanElement, properties: Array): void => { for (const property of properties) property.apply(element); }; export function render(text: string, spans: Array, inspector: Inspector): void { console.time('render'); const container = document.createElement('pre'); container.ariaHidden = 'true'; for (const child of document.body.children) { (child as HTMLElement).style.display = 'none'; child.ariaHidden = 'false'; } document.body.appendChild(container); const defaultProperties: Array = [ Color.Plain ]; const defaultTagName: keyof HTMLElementTagNameMap = 'span'; let lastProperties: Array = defaultProperties; let lastTagName: keyof HTMLElementTagNameMap = defaultTagName; let lastElement: HTMLSpanElement = document.createElement(lastTagName); applyProperties(lastElement, lastProperties); container.appendChild(lastElement); for (let characterIndex = 0; characterIndex < text.length; characterIndex++) { const character = text[characterIndex]; let topMostProperties: Array = defaultProperties; let topMostTagName: keyof HTMLElementTagNameMap = defaultTagName; const matchingSpans = new Array(); for (const span of spans) { if (span.contains(characterIndex)) { matchingSpans.push(span); topMostProperties = span.properties; topMostTagName = span.tagName; } } if (sameProperties(lastProperties, topMostProperties) && topMostTagName === lastTagName) { lastElement.textContent += character; inspector.instrument(lastElement, matchingSpans); } else { lastElement = document.createElement(topMostTagName); lastElement.textContent = character; inspector.instrument(lastElement, matchingSpans); applyProperties(lastElement, topMostProperties); lastProperties = topMostProperties; lastTagName = topMostTagName; container.appendChild(lastElement); } } console.timeEnd('render'); }