Skip to content

Commit

Permalink
feat(preset-icons,transformer-directives): allow add safe icons colle…
Browse files Browse the repository at this point in the history
…ctions (#4319)
userquin authored Dec 11, 2024
1 parent 6cc5f51 commit 6358f9a
Showing 4 changed files with 46 additions and 7 deletions.
7 changes: 7 additions & 0 deletions docs/presets/icons.md
Original file line number Diff line number Diff line change
@@ -442,6 +442,13 @@ Extra CSS properties applied to the generated CSS.
Emit warning when missing icons are matched.
### iconifyCollectionsNames
- Type: `string[]`
- Default: `undefined`
Additional `@iconify-json` collections to use. This option should be used when there are new `@iconify-json` collections not listed in the default icons preset collection names.
### collections
- Type: `Record<string, (() => Awaitable<IconifyJSON>) | undefined | CustomIconLoader | InlineCollection>`
24 changes: 18 additions & 6 deletions packages/preset-icons/src/core.ts
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ export function createPresetIcons(lookupIconLoader: (options: IconsOptions) => P
mode = 'auto',
prefix = 'i-',
warn = false,
iconifyCollectionsNames,
collections: customCollections,
extraProperties = {},
customizations = {},
@@ -87,7 +88,12 @@ export function createPresetIcons(lookupIconLoader: (options: IconsOptions) => P
iconLoader = iconLoader || await lookupIconLoader(options)

const usedProps = {}
const parsed = await parseIconWithLoader(body, iconLoader, { ...loaderOptions, usedProps })
const parsed = await parseIconWithLoader(
body,
iconLoader,
{ ...loaderOptions, usedProps },
iconifyCollectionsNames,
)

if (!parsed) {
if (warn && !flags.isESLint)
@@ -196,20 +202,26 @@ export function getEnvFlags() {
}
}

export async function parseIconWithLoader(body: string, loader: UniversalIconLoader, options: IconifyLoaderOptions = {}) {
export async function parseIconWithLoader(
body: string,
loader: UniversalIconLoader,
options: IconifyLoaderOptions = {},
safeCollectionsNames: string[] = [],
) {
let collection = ''
let name = ''
let svg: string | undefined

const allCollections = [
const allCollections = new Set<string>([
...icons,
...safeCollectionsNames,
...Object.keys(options.customCollections || {}),
]
])

if (body.includes(':')) {
[collection, name] = body.split(':')

if (!allCollections.includes(collection))
if (!allCollections.has(collection))
return

svg = await loader(collection, name, options)
@@ -219,7 +231,7 @@ export async function parseIconWithLoader(body: string, loader: UniversalIconLoa
for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
collection = parts.slice(0, i).join('-')

if (!allCollections.includes(collection))
if (!allCollections.has(collection))
continue

name = parts.slice(i).join('-')
14 changes: 14 additions & 0 deletions packages/preset-icons/src/types.ts
Original file line number Diff line number Diff line change
@@ -55,6 +55,20 @@ export interface IconsOptions {
*/
warn?: boolean

/**
* `@iconify-json` collections to use (will be also auto installed when missing and `autoInstall` enabled).
*
* This option should be used only when there are new `@iconify-json` collections not listed in the default icons preset collection names.
*
* Adding external collections will not work, you should use `FileSystemIconLoader` from
* `@iconify/utils/lib/loader/fs` or `createExternalPackageIconLoader` from
* `@iconify/utils/lib/loader/external-pkg` instead.
*
* @see https://unocss.dev/presets/icons#filesystemiconloader
* @see https://unocss.dev/presets/icons#externalpackageiconloader
*/
iconifyCollectionsNames?: string[]

/**
* In Node.js environment, the preset will search for the installed iconify dataset automatically.
* When using in the browser, this options is provided to provide dataset with custom loading mechanism.
8 changes: 7 additions & 1 deletion packages/transformer-directives/src/icon.ts
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ export async function transformIconString(uno: UnoGenerator, icon: string, color
collections: customCollections,
customizations = {},
autoInstall = false,
iconifyCollectionsNames,
collectionsNodeResolvePath,
unit,
} = presetIcons.options as IconsOptions
@@ -51,7 +52,12 @@ export async function transformIconString(uno: UnoGenerator, icon: string, color
for (const p of toArray(prefix)) {
if (icon.startsWith(p)) {
icon = icon.slice(p.length)
const parsed = await api.parseIconWithLoader(icon, loader, loaderOptions)
const parsed = await api.parseIconWithLoader(
icon,
loader,
loaderOptions,
iconifyCollectionsNames,
)
if (parsed)
return `url("data:image/svg+xml;utf8,${color ? api.encodeSvgForCss(parsed.svg).replace(/currentcolor/gi, color) : api.encodeSvgForCss(parsed.svg)}")`
}

0 comments on commit 6358f9a

Please sign in to comment.