You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.ts 2.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import React from 'react'
  2. export type AbstractNode = {
  3. name: string
  4. attributes: {
  5. [key: string]: string
  6. }
  7. children?: AbstractNode[]
  8. }
  9. export type Attrs = {
  10. [key: string]: string
  11. }
  12. export function normalizeAttrs(attrs: Attrs = {}): Attrs {
  13. return Object.keys(attrs).reduce((acc: Attrs, key) => {
  14. // Filter out editor metadata attributes before processing
  15. if (key.startsWith('inkscape:')
  16. || key.startsWith('sodipodi:')
  17. || key.startsWith('xmlns:inkscape')
  18. || key.startsWith('xmlns:sodipodi')
  19. || key.startsWith('xmlns:svg')
  20. || key === 'data-name')
  21. return acc
  22. const val = attrs[key]
  23. key = key.replace(/([-]\w)/g, (g: string) => g[1].toUpperCase())
  24. key = key.replace(/([:]\w)/g, (g: string) => g[1].toUpperCase())
  25. // Additional filter after camelCase conversion
  26. if (key === 'xmlnsInkscape'
  27. || key === 'xmlnsSodipodi'
  28. || key === 'xmlnsSvg'
  29. || key === 'dataName')
  30. return acc
  31. switch (key) {
  32. case 'class':
  33. acc.className = val
  34. delete acc.class
  35. break
  36. case 'style':
  37. (acc.style as any) = val.split(';').reduce((prev, next) => {
  38. const pairs = next?.split(':')
  39. if (pairs[0] && pairs[1]) {
  40. const k = pairs[0].replace(/([-]\w)/g, (g: string) => g[1].toUpperCase())
  41. prev[k] = pairs[1]
  42. }
  43. return prev
  44. }, {} as Attrs)
  45. break
  46. default:
  47. acc[key] = val
  48. }
  49. return acc
  50. }, {})
  51. }
  52. export function generate(
  53. node: AbstractNode,
  54. key: string,
  55. rootProps?: { [key: string]: any } | false,
  56. ): any {
  57. if (!rootProps) {
  58. return React.createElement(
  59. node.name,
  60. { key, ...normalizeAttrs(node.attributes) },
  61. (node.children || []).map((child, index) => generate(child, `${key}-${node.name}-${index}`)),
  62. )
  63. }
  64. return React.createElement(
  65. node.name,
  66. {
  67. key,
  68. ...normalizeAttrs(node.attributes),
  69. ...rootProps,
  70. },
  71. (node.children || []).map((child, index) => generate(child, `${key}-${node.name}-${index}`)),
  72. )
  73. }