Skip to content

Commit

Permalink
feat: add customComponent option (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
jd1378 authored Jul 18, 2023
1 parent 187501d commit 0974476
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 5 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ export default defineNuxtConfig({
})
```

You can also use your own custom component instead of the built-in `nuxt-icon` component using the `customComponent` option.
This custom component must have `icon` property, just like the `nuxt-icon` component [provided by nuxt-svgo](https://github.com/cpsoinos/nuxt-svgo/blob/main/src/runtime/components/nuxt-icon.vue).

Example:

```typescript
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
modules: ['nuxt-svgo'],
svgo: {
customComponent: 'YourComponent'
}
})
```

By default module registers all icons inside `autoImportPath` globally. This may be unwanted behavior as it generates chunks for each icon to be used globally, which will result in huge amount of files if you have many icons. If you want to disable global registration simply use `global: false` in module options:

```typescript
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nuxt-svgo",
"version": "3.3.0",
"version": "3.4.0",
"packageManager": "pnpm@8.6.8",
"description": "Nuxt module to load optimized SVG files as Vue components",
"keywords": [
Expand Down
4 changes: 4 additions & 0 deletions playground/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
16 changes: 13 additions & 3 deletions src/loaders/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import urlEncodeSvg from 'mini-svg-data-uri'

export interface SvgLoaderOptions {
autoImportPath?: string
/** The name of component in CapitalCase that will be used in `componentext` import type. defaults to `NuxtIcon` */
customComponent: string
defaultImport?:
| 'url'
| 'url_encode'
Expand All @@ -28,9 +30,17 @@ export function svgLoader(options?: SvgLoaderOptions) {
svgo,
defaultImport,
explicitImportsOnly,
autoImportPath
autoImportPath,
customComponent
} = options || {}

const normalizedCustomComponent = customComponent.includes('-')
? customComponent
.split('-')
.map((c) => c[0].toUpperCase() + c.substring(1).toLowerCase())
.join('')
: customComponent

const autoImportPathNormalized =
autoImportPath && autoImportPath.replaceAll(/^\.*(?=[/\\])/g, '')

Expand Down Expand Up @@ -109,10 +119,10 @@ export function svgLoader(options?: SvgLoaderOptions) {

if (importType === 'componentext') {
code =
`import {NuxtIcon} from "#components";\nimport {h} from "vue";\n` +
`import {${normalizedCustomComponent}} from "#components";\nimport {h} from "vue";\n` +
code

code += `\nexport default { render() { return h(NuxtIcon, {icon: {render}}) } }`
code += `\nexport default { render() { return h(${normalizedCustomComponent}, {icon: {render}}) } }`
return code
} else {
return `${code}\nexport default { render: render }`
Expand Down
3 changes: 2 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const nuxtSvgo: NuxtModule<ModuleOptions> = defineNuxtModule({
defaultImport: 'componentext',
autoImportPath: './assets/icons/',
svgoConfig: undefined,
global: true
global: true,
customComponent: 'NuxtIcon'
},
async setup(options) {
const { resolvePath, resolve } = createResolver(import.meta.url)
Expand Down
35 changes: 35 additions & 0 deletions test/componentext.options.custom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { fileURLToPath } from 'node:url'
import { describe, it, expect } from 'vitest'
import { setup, $fetch } from '@nuxt/test-utils'
import type { NuxtConfig } from 'nuxt/schema'
import type { ModuleOptions } from '../src/module'

describe('defaultImport: componentext', async () => {
await setup({
rootDir: fileURLToPath(new URL('./fixtures/component', import.meta.url)),
nuxtConfig: {
svgo: {
defaultImport: 'componentext',
customComponent: 'TestWrapper'
} as ModuleOptions
} as NuxtConfig
})

it('renders the svg as TestWrapper component', async () => {
const html = await $fetch('/')
expect(html).toContain(`test-icon`)
expect(html).toContain(`test--fill`)
})

it('renders the svg from assets/icons folder', async () => {
// Get response to a server-rendered page with `$fetch`.
const html = await $fetch('/')

expect(html).toContain(
'><path d="M13.5 1.515a3 3 0 0 0-3 0L3 5.845a2 2 0 0 0-1 1.732V21a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-6h4v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V7.577a2 2 0 0 0-1-1.732l-7.5-4.33z"></path></svg>'
)
expect(html).toContain(
'><path d="M13.5 1.515a3 3 0 0 0-3 0L3 5.845a2 2 0 0 0-1 1.732V21a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-6h4v6"></path></svg>'
)
})
})
46 changes: 46 additions & 0 deletions test/fixtures/component/components/TestWrapper.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<component
:is="icon"
:class="{
'test-icon': fontControlled,
'test--fill': !filled
}"
/>
</template>

<script lang="ts">
// file imported from https://github.com/gitFoxCode/nuxt-icons/blob/89e53649e5868c31fc97869918ede96504ae1a04/src/runtime/components/nuxt-icon.vue
// with modifications
export default {
props: {
filled: {
type: Boolean,
required: false,
default: false
},
fontControlled: {
type: Boolean,
required: false,
default: true
},
icon: {
type: Object,
required: true
}
}
}
</script>

<style>
.test-icon {
width: 1em;
height: 1em;
margin-bottom: 0.125em;
vertical-align: middle;
}
.test--fill,
.test--fill * {
fill: currentColor;
}
</style>

0 comments on commit 0974476

Please sign in to comment.