105 lines
2.6 KiB
TypeScript
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);
|
|
}
|
|
|
|
|
|
}
|