From 18fcc257e64148f262eff829558f827a85600759 Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Sat, 14 Oct 2023 00:53:34 +0800 Subject: [PATCH] feat: automatically discover icons (#29) * feat: automatically discover icons * docs: update --- README.md | 1 + example/tailwind.config.cjs | 4 +--- gen-types.mjs | 6 +++-- package.json | 3 ++- src/core.ts | 6 +++++ src/index.test.ts | 48 +++++++++++++++++++++++++++++++++++++ src/index.ts | 29 +++++++++++++++------- 7 files changed, 83 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c924995..8a532fc 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ module.exports = { plugins: [ iconsPlugin({ // Select the icon collections you want to use + // You can also ignore this option to automatically discover all icon collections you have installed collections: getIconCollections(["mdi", "lucide"]), }), ], diff --git a/example/tailwind.config.cjs b/example/tailwind.config.cjs index 186fda7..ce27112 100644 --- a/example/tailwind.config.cjs +++ b/example/tailwind.config.cjs @@ -1,8 +1,6 @@ module.exports = { content: ["./index.html"], plugins: [ - require("../dist").iconsPlugin({ - collections: require("../dist").getIconCollections(["heroicons"]), - }), + require("../dist").iconsPlugin(), ], } diff --git a/gen-types.mjs b/gen-types.mjs index 94bf113..d08e098 100644 --- a/gen-types.mjs +++ b/gen-types.mjs @@ -7,9 +7,11 @@ const collections = req("@iconify/json/collections.json") fs.writeFileSync( "types.ts", - `/** All the available icon collections when you have \`@iconify/json\` installed */\nexport type CollectionNames = ${Object.keys( + `export const availableCollectionNames = [${Object.keys( collections, ) .map((v) => JSON.stringify(v)) - .join("|")}`, + .join(", ")}] as const +/** All the available icon collections when you have \`@iconify/json\` installed */\nexport type CollectionNames = typeof availableCollectionNames[number] +`, ) diff --git a/package.json b/package.json index 81aa2fb..c5fe15b 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "build": "pnpm run build-fast --dts-resolve", "test": "vitest run", "prepublishOnly": "pnpm run build", - "gen-types": "node ./gen-types.mjs" + "gen-types": "node ./gen-types.mjs", + "prepare": "pnpm run gen-types" }, "license": "MIT", "devDependencies": { diff --git a/src/core.ts b/src/core.ts index 3f7119d..a7a94bd 100644 --- a/src/core.ts +++ b/src/core.ts @@ -46,6 +46,12 @@ function callerPath(): string | null { return result[1] } +export const isPackageExists = (id: string) => { + const p = callerPath() + const cwd = p ? path.dirname(p) : process.cwd() + return Boolean(localResolve(cwd, id)) +} + export const getIconCollections = ( include: CollectionNames[] | "all" = "all", ): Record => { diff --git a/src/index.test.ts b/src/index.test.ts index f0d47ba..f6b5e36 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -169,3 +169,51 @@ test("custom icon", () => { " `) }) + +test("set collection automatically", () => { + const processor = postcss([ + tailwindcss({ + config: { + content: [ + { + raw: "", + extension: "html", + }, + ], + plugins: [iconsPlugin()], + }, + }), + ]) + + const result = processor.process(` +.foo { + @apply i-heroicons-arrow-left; +} +`) + + expect(result.css).toMatchInlineSnapshot(` + " + .foo { + display: inline-block; + width: 1em; + height: 1em; + background-color: currentColor; + -webkit-mask: no-repeat center / 100%; + mask: no-repeat center / 100%; + -webkit-mask-image: var(--svg); + mask-image: var(--svg); + --svg: url(\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18'/%3E%3C/svg%3E\\") + } + " + `) + + expect(() => { + processor.process(` + .foo { + @apply i-mdi-home; + } + `).css + }).toThrowErrorMatchingInlineSnapshot( + '":3:5: The `i-mdi-home` class does not exist. If `i-mdi-home` is a custom class, make sure it is defined within a `@layer` directive."', + ) +}) diff --git a/src/index.ts b/src/index.ts index e9410fc..915adcd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,23 +1,36 @@ import { IconifyJSONIconsData } from "@iconify/types" import plugin from "tailwindcss/plugin.js" import { parseIconSet } from "@iconify/utils" -import { generateIconComponent, getIconCollections } from "./core" -import { CollectionNames } from "../types" +import { + generateIconComponent, + getIconCollections, + isPackageExists, +} from "./core" +import { CollectionNames, availableCollectionNames } from "../types" import { type Optional } from "./utils" import { IconsOptions } from "./types" export { getIconCollections, type CollectionNames } export type IconsPluginOptions = { - collections: Record> + collections?: Record> } & IconsOptions -export const iconsPlugin = ({ - collections, - ...options -}: IconsPluginOptions) => { - const { scale = 1, prefix = "i", extraProperties = {} } = options ?? {} +export const iconsPlugin = (iconsPluginOptions?: IconsPluginOptions) => { + const { + collections: propsCollections, + scale = 1, + prefix = "i", + extraProperties = {}, + } = iconsPluginOptions ?? {} + const collections = + propsCollections ?? + getIconCollections( + availableCollectionNames.filter((name) => + isPackageExists(`@iconify-json/${name}`), + ), + ) const components: Record> = {} for (const prefix of Object.keys(collections)) {