module.exports = { objectTree: function(obj) { function traverse(o) { if (o === null || typeof o !== 'object') return o; if (Array.isArray(o)) { // RGB oder RGBA-Erkennung: Array aus 3 oder 4 Zahlen if ((o.length === 3 || o.length === 4) && o.every(v => typeof v === 'number')) { // const rgbString = o.length === 3 // ? `rgb(${o.join(',')})` // : `rgba(${o.join(',')})`; const rgbString = o.join(','); return { key: null, value: rgbString, children: null, isRGB: true }; } // normales Array return o.map((v, i) => ({ key: i, value: typeof v !== 'object' ? v : null, children: typeof v === 'object' ? traverse(v) : null })); } const result = []; for (const key in o) { if (o.hasOwnProperty(key)) { const val = o[key]; const children = (val !== null && typeof val === 'object') ? traverse(val) : null; result.push({ key, value: children ? null : val, children }); } } return result; } return traverse(obj); }, jsonEntriesRecursive: function(obj, options) { const entries = []; function traverse(prefix, data) { if (Array.isArray(data)) { data.forEach((item, index) => { const arrayKey = `${prefix}[${index}]`; if (typeof item === "object" && item !== null) { traverse(arrayKey, item); // Rekursion für Array-Objekte } else { entries.push({ key: arrayKey, value: item }); } }); } else if (typeof data === "object" && data !== null) { for (const key in data) { if (!Object.prototype.hasOwnProperty.call(data, key)) continue; const value = data[key]; const fullKey = prefix ? `${prefix}.${key}` : key; if (typeof value === "object" && value !== null) { traverse(fullKey, value); // Rekursion für verschachtelte Objekte } else { entries.push({ key: fullKey, value }); } } } else { // Primitive Werte am obersten Level entries.push({ key: prefix, value: data }); } console.log({ key: prefix, value: data }) } traverse("", obj); // Handlebars-Block Helper if (options.fn) { return options.fn(entries); } return entries; }, groupBy: function(items, keys, options) { // keys kann String oder Array sein if (!Array.isArray(keys)) keys = [keys]; if (!keys.length) return ''; const key = keys[0]; // aktueller Gruppierungsschlüssel const remainingKeys = keys.slice(1); // restliche Schlüssel // Gruppieren nach aktuellem Schlüssel const groups = {}; items.forEach(item => { let groupKeys = item[key]; if (!Array.isArray(groupKeys)) groupKeys = [groupKeys]; groupKeys.forEach(groupKey => { if (!groups[groupKey]) groups[groupKey] = []; groups[groupKey].push(item); }); }); // Ergebnis zusammensetzen let result = ''; for (const group in groups) { const groupItems = groups[group]; if (remainingKeys.length > 0) { // Rekursive Verschachtelung // Wir rufen die gleiche Helper-Funktion intern auf const nestedResult = Handlebars.helpers.groupBy(groupItems, remainingKeys, options); result += options.fn({ key: group, items: nestedResult }); } else { // Basisfall: keine weiteren Keys, items direkt weitergeben result += options.fn({ key: group, items: groupItems }); } } return result; }, parseArray: function(str){ try { return JSON.parse(str); } catch (e) { return []; } }, ifSingle: function(array, options) { if (Array.isArray(array) && array.length === 1) { return options.fn(array[0]); // Item direkt übergeben } return options.inverse(this); // else-Block }, findValue: function(array, searchKey, searchValue, returnKey) { if (!Array.isArray(array)) return ""; for (let i = 0; i < array.length; i++) { const item = array[i]; if (item && item[searchKey] === searchValue) { return item[returnKey] ?? ""; } } return ""; } };