nwex.de/src/view.ts

89 lines
2.8 KiB
TypeScript

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<Property> | undefined, b: Array<Property> | 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<Property>): void => {
for (const property of properties)
property.apply(element);
};
export function render(text: string, spans: Array<Span>, 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<Property> = [ Color.Plain ];
const defaultTagName: keyof HTMLElementTagNameMap = 'span';
let lastProperties: Array<Property> = 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<Property> = defaultProperties;
let topMostTagName: keyof HTMLElementTagNameMap = defaultTagName;
const matchingSpans = new Array<Span>();
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');
}