npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unocss-iconify-helper

v1.0.10

Published

Dev-only Iconify icon picker for UnoCSS. Framework-agnostic Vite plugin — works with Vue, React, Svelte, etc.

Readme

unocss-iconify-helper

专为 UnoCSS + Vite 项目设计的开发时图标选择器与预设增强工具。框架无关,支持 Vue、React、Svelte、Vanilla 等一切 Vite 项目。

English | 中文


为什么会有这个项目?

在使用 UnoCSS + Iconify 开发时,有几个痛点:

1. 图标难查找 Iconify 有数百个图标库、数十万个图标。每次想用一个图标都要打开 icones.js.org 搜索,找到后还要手动拼出 i-{prefix}-{name} 的 class 名称,来回切换很低效。

2. 图标库管理混乱,影响团队一致性和构建体积 随着项目迭代,不同开发者会引入不同的图标库——有人用 mdi、有人用 tabler、有人用 heroicons。没有任何工具告诉你当前项目实际用到了哪些 @iconify-json/* 包。图标库越多,开发时下载的 JSON 越大,风格也越不统一。最好的状态是:整个项目只用一两个图标库,保持视觉风格统一,同时最小化依赖

3. pnpm workspace + Windows 下 autoInstall 静默失败(特定场景) 如果你在 Windows 上使用 pnpm workspace,@unocss/preset-iconsautoInstall: true 会因为内部 mlly 库拿到的是 Windows 路径(D:\...)而非合法的 file:// URL,导致图标包解析失败、图标无法显示。

这个包解决了上述问题:

  • 快捷键(默认 Ctrl+I)唤出浮层图标选择器,搜索即用,点击自动复制 UnoCSS class
  • 自动扫描源码,识别项目已用到的图标库,在选择器中优先展示项目已用库,引导团队复用而非随意引入新库;并按图标库筛选搜索结果,减少干扰
  • 重写了 presetIcons 的集合加载机制,用 createRequire + Proxy 完全绕开 mlly,在 pnpm workspace + Windows 下也能正常使用;首次遇到未安装的图标包时自动调用包管理器安装

安装

pnpm add -D unocss-iconify-helper

使用

1. Vite 插件

// vite.config.ts
import { defineConfig } from 'vite'
import UnoCSS from 'unocss/vite'
import { iconifyHelperPlugin } from 'unocss-iconify-helper/vite'

export default defineConfig({
  plugins: [
    UnoCSS(),
    iconifyHelperPlugin(),   // 仅 dev 模式生效,production 自动禁用
  ],
})

配置项(均为 helper 特有,非 Vite 原生配置):

| 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | hotkey | string | 'ctrl+i' | 唤出快捷键,格式如 'meta+shift+i' | | extraCollections | Record<string, string> | {} | 额外图标库(名 → 说明),与扫描结果合并显示在面板 | | scanDirs | string[] | ['src'] | 扫描源码的目录 | | scanExts | string[] | ['.vue','.ts',...] | 扫描的文件后缀 | | apiEndpoints | string[] | 见下方 | Iconify API 端点列表(详见下方说明) |

apiEndpoints 说明

弹窗头部有一个 API 节点切换按钮,用户可在运行时切换搜索来源,选择记录于 localStorage

内置默认列表(三个节点服务内容完全一致,背后服务器不同,可在主节点不通时切换):

https://api.iconify.design   ← 主节点(默认)
https://api.simplesvg.com    ← 备用节点 1
https://api.unisvg.com       ← 备用节点 2

传入 apiEndpoints完全覆盖内置列表(不合并),数组第一项即默认节点:

iconifyHelperPlugin({
  // 使用私有部署的 Iconify API,移除官方节点
  apiEndpoints: ['https://iconify.your-company.com'],
})

2. UnoCSS 预设

// uno.config.ts
import { defineConfig, presetUno } from 'unocss'
import { presetIconifyHelper } from 'unocss-iconify-helper/unocss'

export default defineConfig({
  presets: [
    presetUno(),
    presetIconifyHelper(),
    // 可覆盖任意选项:
    // presetIconifyHelper({ autoInstall: false, scale: 1, warn: true }),
  ],
})

presetIconifyHelper 接受所有 @unocss/preset-icons 原生选项(直接透传),同时对部分选项提供了增强行为或不同的默认值:

Helper 增强项(与原生 presetIcons 行为有差异):

| 参数 | 类型 | 默认值 | 与原生的差异 | |------|------|--------|------------| | autoInstall | boolean \| fn | true | 由 createRequire + Proxy 实现,绕开 mlly;在 pnpm workspace + Windows 下也能正常运行 | | collections | Record<string, ...> | 自动检测 | 启动时自动扫描 node_modules/@iconify-json/*,无需手动配置;用户传入的值优先级更高 |

覆盖了原生默认值的项:

| 参数 | 原生默认值 | 本包默认值 | 说明 | |------|-----------|-----------|------| | scale | 1 | 1.2 | 图标略微放大,在正文中显示更清晰 | | extraProperties | {} | {display:'inline-block','vertical-align':'middle'} | 图标默认内联对齐 |

其余透传项(与原生完全一致,直接参考 presetIcons 文档):

modeprefixwarnunitlayerprocessorcustomizationsiconifyCollectionsNames 等,用法与 presetIcons 完全相同。

无需提前安装 @iconify-json/* 第一次遇到新图标库时自动安装,并写入 package.json,后续启动直接从本地加载。


工作原理

图标选择器(Vite 插件)

Vite dev server
  ├── configureServer  →  GET /__iph_client
  │     window.__IHP_CONFIG__ = { hotkey, collections }   ← 运行时配置
  │   + dist/client.min.js                                ← 纯 JS 弹窗(IIFE,无框架依赖)
  │
  ├── transformIndexHtml  →  注入 <script src="/__iph_client" defer>
  │
  └── handleHotUpdate  →  server.ws.send('iph:collections', {...})
                           ↑ 客户端通过 WebSocket 监听,无刷新更新筛选列表

客户端脚本(src/client/index.ts)由 esbuild 打包为自包含 IIFE,无任何运行时依赖。调用 Iconify API 搜索图标,点击后写入剪贴板。

自动加载预设(presetIconifyHelper

标准 presetIcons 在 Windows + pnpm workspace 下依赖 mlly 解析 @iconify-json/* 路径,而 mlly 收到的是 D:\... 格式的路径而非合法的 file:// URL,导致静默失败。

presetIconifyHelper 通过两层机制解决:

第一层 — 预扫描(快速路径,零网络请求): 启动时扫描 node_modules/@iconify-json/,用 Node 原生 createRequire 直接加载,构造 collections 映射后传给 presetIcons,完全绕开 mlly

第二层 — Proxy 动态加载(按需安装路径): collections 被封装为 JavaScript Proxy,拦截所有 prefix 访问。遇到未知前缀(如 i-phosphor-star 中的 phosphor)时:

Proxy.get('phosphor')
  ↓
createRequire('@iconify-json/phosphor')  →  找不到
  ↓
向上遍历目录树检测包管理器(pnpm-lock.yaml / yarn.lock / bun.lockb)
  ↓
execSync('pnpm add -D @iconify-json/phosphor', { cwd, shell })
  ↓
createRequire('@iconify-json/phosphor')  →  成功  →  返回 IconifyJSON

同一 prefix 的并发请求共享同一个 Promise,确保只安装一次。


局限性

  • 仅限开发时iconifyHelperPlugin 在 production 构建中自动禁用;presetIconifyHelper 是构建时安全的
  • 需要 Node.js 环境:自动安装依赖 child_process.execSync,无 Node 环境(如纯浏览器/SSR)应传入 autoInstall: false
  • 首次安装有延迟:安装新图标包时会阻塞事件循环几秒;后续启动瞬间完成
  • 图标搜索需要网络:弹窗搜索调用 https://api.iconify.design,开发时需要能访问外网

License

MIT


unocss-iconify-helper (English)

A dev-only icon picker and preset enhancer for UnoCSS + Vite projects. Framework-agnostic — works with Vue, React, Svelte, Vanilla, and any Vite-based project.

Why does this exist?

Three pain points when working with UnoCSS + Iconify:

1. Hard to find icons Iconify has hundreds of collections and hundreds of thousands of icons. Every time you need one, you open icones.js.org, search, and manually type out i-{prefix}-{name}. Slow and error-prone.

2. Scattered icon collections hurt consistency and build size As a project grows, different developers pull in different icon libraries — one uses mdi, another tabler, another heroicons. No tool tells you which @iconify-json/* packages are actually in use. The more collections, the larger the dev downloads, and the less visually consistent the UI. The ideal: the whole project uses one or two icon libraries, keeping the style unified and dependencies minimal.

3. autoInstall silently fails on Windows + pnpm workspaces (specific scenario) On Windows with pnpm workspace, @unocss/preset-icons's autoInstall: true silently fails — internally, mlly receives a raw Windows path (D:\...) instead of a proper file:// URL, so icon package resolution breaks.

This package addresses all three:

  • A hotkey (Ctrl+I by default) opens a floating icon picker — search, click, UnoCSS class copied
  • Auto-scans source files to detect used icon collections; shows them first in the picker to guide team members toward reusing existing libraries rather than pulling in new ones; supports filtering by collection
  • Reimplements the collection loading mechanism using createRequire + Proxy, bypassing mlly entirely; works on Windows + pnpm workspaces; auto-installs missing packages on first use

Install

pnpm add -D unocss-iconify-helper

Usage

Vite Plugin

// vite.config.ts
import { defineConfig } from 'vite'
import UnoCSS from 'unocss/vite'
import { iconifyHelperPlugin } from 'unocss-iconify-helper/vite'

export default defineConfig({
  plugins: [
    UnoCSS(),
    iconifyHelperPlugin(),   // auto-disabled in production
  ],
})

| Option | Type | Default | Description | |--------|------|---------|-------------| | hotkey | string | 'ctrl+i' | Trigger hotkey, e.g. 'meta+shift+i' | | extraCollections | Record<string, string> | {} | Extra collections to always show in the picker | | scanDirs | string[] | ['src'] | Directories to scan for used icon classes | | scanExts | string[] | ['.vue','.ts',...] | File extensions to scan | | apiEndpoints | string[] | 3 official endpoints | Ordered list of Iconify API endpoints. First item is the default. Providing this list replaces (not merges with) the built-in list. A switcher button in the picker header lets users cycle through them; the choice is persisted to localStorage. |

Built-in default list (all serve identical data, different servers):

https://api.iconify.design   ← default
https://api.simplesvg.com
https://api.unisvg.com

UnoCSS Preset

// uno.config.ts
import { defineConfig, presetUno } from 'unocss'
import { presetIconifyHelper } from 'unocss-iconify-helper/unocss'

export default defineConfig({
  presets: [
    presetUno(),
    presetIconifyHelper(),
  ],
})

Passes all options through to @unocss/preset-icons. Differences from native behavior:

Enhanced options:

| Option | Type | Default | Difference from native | |--------|------|---------|----------------------| | autoInstall | boolean \| fn | true | Implemented via createRequire + Proxy; bypasses mlly; works on Windows + pnpm | | collections | Record<string, ...> | auto-detected | Auto-scans node_modules/@iconify-json/* at startup; user-provided values take precedence |

Different defaults:

| Option | Native default | This package | Note | |--------|---------------|-------------|------| | scale | 1 | 1.2 | Slightly larger for better inline readability | | extraProperties | {} | {display:'inline-block','vertical-align':'middle'} | Sensible inline alignment |

All other presetIcons options (mode, prefix, warn, unit, layer, processor, customizations, etc.) work exactly as documented in the official presetIcons docs.

You do not need to pre-install @iconify-json/* packages. They are installed on first use and persisted to package.json.

How It Works

Icon picker (Vite plugin)

The plugin injects a <script src="/__iph_client"> tag. The endpoint serves a runtime config object (window.__IHP_CONFIG__) followed by the minified IIFE client bundle. The client calls the Iconify API for search and writes the selected class to the clipboard. Collection updates are pushed via Vite's WebSocket without a page reload.

Auto-install preset

At startup, presetIconifyHelper scans node_modules/@iconify-json/ with createRequire and builds a static collections map (Layer 1). The map is wrapped in a Proxy (Layer 2) that intercepts unknown prefix lookups, detects the package manager by walking up the directory tree for lock files, runs the install command, and loads the result via createRequire — never touching mlly.

Limitations

  • Dev-only: the Vite plugin is disabled in production; the preset is build-time safe
  • Requires Node.js: autoInstall uses child_process.execSync; pass autoInstall: false in non-Node environments
  • First-use latency: installing a new collection blocks the event loop for a few seconds; subsequent starts are instant
  • Icon search requires internet: the picker calls https://api.iconify.design

License

MIT