/** * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop * SPDX-License-Identifier: GPL-3.0-or-later * @author Author: Sascha Nitsch (grumpydeveloper) * @internal **/ import { RenderTree } from './rendertree'; import Formula from 'fparser'; /** * base class for all RenderTree nodes */ export abstract class RTNode { /** root render tree */ protected root: RenderTree; /** * calculate given expression * @param exp expression string * @returns result as number or 0 in case of error */ calc(exp: string): number { if (exp === '') { return 0; } try { const fObj = new Formula(exp); return fObj.evaluate({}); } catch(e) { } return 0; } /** * abstract function to clone the node * must be implemented by every sub class */ abstract clone(): RTNode; /** * constructor * @param root parent RenderTree */ constructor(root: RenderTree) { this.root = root; } /** * helper function to get value from attribute or from named child node * @param node current HTML element * @param name name of element to fetch * @return value or '' in case of error */ static getField(node: HTMLElement, name: string): string { // try attribute let field = node.getAttribute(name); // try child nodes node.childNodes.forEach((child) => { if (child.nodeType === 1) { const childElem = child; if (childElem.localName === name) { field = childElem.innerHTML; } } }); return field; } /** * abstract function to render the node * must be implemented by every sub class * @param target target to render into */ abstract render(target: HTMLElement): void; /** * resolve a string using variable replacements * @param input input string * @returns input strings with replaced variables */ resolveString(input: string): string { if (!input || input.indexOf('$') < 0) { return input; } let str = input; let dollar; let lastDollar = 0; while ((dollar = str.indexOf('${', lastDollar)) >= 0) { if (str.at(dollar - 1) == '\\') { str = str.substring(0, dollar - 1) + str.substring(dollar); lastDollar = dollar + 1; continue; } const end = str.indexOf('}', dollar); if (end < 0) break; const search = str.substring(dollar + 2, end); const replace = this.root.getDefinition(search); str = str.replace(str.substring(dollar, end + 1), replace); } return (str); } }