import React from 'react' export type AbstractNode = { name: string attributes: { [key: string]: string } children?: AbstractNode[] } export type Attrs = { [key: string]: string } export function normalizeAttrs(attrs: Attrs = {}): Attrs { return Object.keys(attrs).reduce((acc: Attrs, key) => { const val = attrs[key] key = key.replace(/([-]\w)/g, (g: string) => g[1].toUpperCase()) key = key.replace(/([:]\w)/g, (g: string) => g[1].toUpperCase()) switch (key) { case 'class': acc.className = val delete acc.class break case 'style': (acc.style as any) = val.split(';').reduce((prev, next) => { const pairs = next?.split(':') if (pairs[0] && pairs[1]) { const k = pairs[0].replace(/([-]\w)/g, (g: string) => g[1].toUpperCase()) prev[k] = pairs[1] } return prev }, {} as Attrs) break default: acc[key] = val } return acc }, {}) } export function generate( node: AbstractNode, key: string, rootProps?: { [key: string]: any } | false, ): any { if (!rootProps) { return React.createElement( node.name, { key, ...normalizeAttrs(node.attributes) }, (node.children || []).map((child, index) => generate(child, `${key}-${node.name}-${index}`)), ) } return React.createElement( node.name, { key, ...normalizeAttrs(node.attributes), ...rootProps, }, (node.children || []).map((child, index) => generate(child, `${key}-${node.name}-${index}`)), ) }