import { Vue, mergeData } from '../../vue'
import { omit } from '../../utils/object'
import { kebabCase, pascalCase, trim } from '../../utils/string'
import { BVIconBase, props as BVIconBaseProps } from './icon-base'

/**
 * Icon component generator function
 *
 * @param {string} icon name (minus the leading `BIcon`)
 * @param {string} raw `innerHTML` for SVG
 * @return {VueComponent}
 */
export const makeIcon = (name, content) => {
  // For performance reason we pre-compute some values, so that
  // they are not computed on each render of the icon component
  const kebabName = kebabCase(name)
  const iconName = `BIcon${pascalCase(name)}`
  const iconNameClass = `bi-${kebabName}`
  const iconTitle = kebabName.replace(/-/g, ' ')
  const svgContent = trim(content || '')

  return /*#__PURE__*/ Vue.extend({
    name: iconName,
    functional: true,
    props: omit(BVIconBaseProps, ['content']),
    render(h, { data, props }) {
      return h(
        BVIconBase,
        mergeData(
          // Defaults
          {
            props: { title: iconTitle },
            attrs: { 'aria-label': iconTitle }
          },
          // User data
          data,
          // Required data
          {
            staticClass: iconNameClass,
            props: { ...props, content: svgContent }
          }
        )
      )
    }
  })
}

import { Vue, mergeData } from '../../vue'
import { omit } from '../../utils/object'
import { kebabCase, pascalCase, trim } from '../../utils/string'
import { BVIconBase, props as BVIconBaseProps } from './icon-base'

const iconProps = omit(BVIconBaseProps, ['content'])

/**
 * Icon component generator function
 *
 * @param {string} icon name (minus the leading `BIcon`)
 * @param {string} raw `innerHTML` for SVG
 * @return {VueComponent}
 */
export const makeIcon = (name, content) => {
  // For performance reason we pre-compute some values, so that
  // they are not computed on each render of the icon component
  const kebabName = kebabCase(name)
  const iconName = `BIcon${pascalCase(name)}`
  const iconNameClass = `bi-${kebabName}`
  const iconTitle = kebabName.replace(/-/g, ' ')
  const svgContent = trim(content || '')

  return /*#__PURE__*/ Vue.extend({
    name: iconName,
    functional: true,
    props: iconProps,
    render(h, { data, props }) {
      return h(
        BVIconBase,
        mergeData(
          // Defaults
          {
            props: { title: iconTitle },
            attrs: { 'aria-label': iconTitle }
          },
          // User data
          data,
          // Required data
          {
            staticClass: iconNameClass,
            props: { ...props, content: svgContent }
          }
        )
      )
    }
  })
}

Speed up icons module import
Speed up icons module import

 ## What was the problem?
I observed that doing a simple import of bootstrap-vue:

```js
import BootstrapVue from 'bootstrap-vue';
```

takes hundreds of milliseconds (give or take, depending on user's CPU).

I tried to do some profiling and found out that most of the time is
spent in `icons` module, specifically in `makeIcon`:

![Screenshot from 2021-08-18 15-10-48](https://user-images.githubusercontent.com/1254342/129905080-619600e5-64e7-4151-8635-b885b654208e.png)

When zoomed it, you can see that most of the time is spent in functions `omit` and `Vue.extend`:

![Screenshot from 2021-08-18 15-11-24](https://user-images.githubusercontent.com/1254342/129905078-f230ecbe-7ee3-49a2-adb1-7b8f68cc2c2e.png)

Each call is just a few milliseconds, but there are hundreds of icons,
so it takes hundreds of milliseconds.

 ## What is the fix?

Don't call `omit` in each `makeIcon` call, but only once.

This speeds things up roughly by half. The other half would be to
somehow avoid repetitive cal of  `Vue.extend`, but I don't think that's
possible. At least not as easily as with `omit`.
