|
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}`)), |
|
) |
|
} |
|
|