presentationmaker_js/src/rendertree/rtnode.ts
2024-07-05 20:13:58 +02:00

105 lines
2.6 KiB
TypeScript

/**
* 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 <number>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 = <HTMLElement>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);
}
}