<script lang="ts">
  import { VNodeData } from 'vue'
  import { defineComponent } from '@vue/composition-api'

  /**
   * Use this component to render raw SVG content
   * without the need to use the `v-html` directive
   * which requires a parent node in Vue 2.x (ex: `<div v-html="..."></div>`).
   * `<NSvgFragment :src="..." />` will directly render the svg tag with its content.
   * */
  export default defineComponent({
    functional: true,
    props: {
      src: { type: String, default: '' },
    },
    render(h, context) {
      try {
        const UniversalDOMParser = typeof window === 'undefined' ? require('universal-dom-parser') : DOMParser
        const svgRoot = new UniversalDOMParser().parseFromString(context.props.src, 'image/svg+xml').firstChild as Element

        const svgAttributes = {} as { [key: string]: unknown }
        for (const attribute of Array.from(svgRoot?.attributes ?? [])) {
          svgAttributes[attribute.name] = attribute.value
        }

        const combinedAttributes: VNodeData['attrs'] & { class?: VNodeData['class']; style?: VNodeData['style'] } = {
          ...(context.data.attrs ?? {}),
          ...svgAttributes,
          ...{
            class: [context.data.class, (svgAttributes.class as string) || ''],
            style: [context.data.style, (svgAttributes.style as string) || ''],
          },
        }

        const { class: classNames, style: styles, ...attributes } = combinedAttributes

        return h('svg', {
          ...context.data,
          attrs: attributes,
          style: styles,
          class: classNames,
          domProps: {
            innerHTML: `${svgRoot?.innerHTML}`,
          },
        })
      } catch (error) {
        console.error(error)
        return h('svg', context.data, [])
      }
    },
  })
</script>