Closed XEngine closed 3 weeks ago
Maybe you can try the following code
const { iconsPlugin } = require("@egoist/tailwindcss-icons");
const fs = require("fs");
const path = require("path");
function getCollection(dir, name) {
const files = fs.readdirSync(dir);
const collection = {
[name]: {
icons: {},
},
};
let stat;
for (const file of files) {
const filePath = `${dir}/${file}`;
try {
stat = fs.lstatSync(filePath);
} catch (err) {
continue;
}
if (stat.isFile()) {
const svg = fs.readFileSync(filePath, "utf-8");
const filename = path.basename(file, ".svg");
collection[name].icons[filename] = {
body: svg.replace(/<svg[^>]*>/, "").replace(/<\/svg>/, ""),
width: 24,
height: 24,
};
}
}
return collection;
}
const collections = getCollection("./src/icons", "custom");
module.exports = {
content: ["./src/**/*.{ts,tsx}"],
plugins: [iconsPlugin({ collections })],
};
Maybe you can try the following code
const { iconsPlugin } = require("@egoist/tailwindcss-icons"); const fs = require("fs"); const path = require("path"); function getCollection(dir, name) { const files = fs.readdirSync(dir); const collection = { [name]: { icons: {}, }, }; let stat; for (const file of files) { const filePath = `${dir}/${file}`; try { stat = fs.lstatSync(filePath); } catch (err) { continue; } if (stat.isFile()) { const svg = fs.readFileSync(filePath, "utf-8"); const filename = path.basename(file, ".svg"); collection[name].icons[filename] = { body: svg.replace(/<svg[^>]*>/, "").replace(/<\/svg>/, ""), width: 24, height: 24, }; } } return collection; } const collections = getCollection("./src/icons", "custom"); module.exports = { content: ["./src/**/*.{ts,tsx}"], plugins: [iconsPlugin({ collections })], };
Thank you! It looks pretty much awesome, I also made a something close to that
function FileSystemIconLoader(dir, transform) {
const files = readdirSync(dir).filter(f => f.endsWith('.svg'));
const result = new Map()
files.forEach(file => {
const filename = join(dir, file);
const stat = lstatSync(filename);
if (stat.isFile()) {
let svg = new SVG(readFileSync(filename, "utf-8"));
// Clean up and optimise icons
try {
cleanupSVG(svg);
parseColors(svg, {
defaultColor: 'currentColor',
callback: (attr, colorStr, color) => {
return !color || isEmptyColor(color) ? colorStr : 'currentColor';
},
});
runSVGO(svg);
} catch (err) {
// Invalid icon
console.error(`Error parsing ${name}:`, err);
return;
}
result.set(camelToKebab(file.replace('.svg', '')), {
body: svg.getBody(),
width: svg.viewBox.width,
height: svg.viewBox.height,
top: svg.viewBox.top,
left: svg.viewBox.left,
})
}
})
return {icons: Object.fromEntries(result)}
}
and then use it like :
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: {
regular: FileSystemIconLoader(path.resolve(__dirname, './icons/regular')),
bold: FileSystemIconLoader(path.resolve(__dirname, './icons/bold')),
misc: FileSystemIconLoader(path.resolve(__dirname, './icons/misc')),
duotone: FileSystemIconLoader(path.resolve(__dirname, './icons/duotone')),
typography: FileSystemIconLoader(path.resolve(__dirname, './icons/typography')),
...getIconCollections(['solar'])
},
}),
Here's one way I've implemented it, just for your reference.
First, you need to install @iconify/tools and @iconify/utils.
npm install @iconify/tools @iconify/utils --save
import { cleanupSVG, importDirectorySync, isEmptyColor, parseColors, runSVGO } from '@iconify/tools'
import { compareColors, stringToColor } from '@iconify/utils/lib/colors'
function getCollections(dir) {
// Import icons
const iconSet = importDirectorySync(dir, {
includeSubDirs: false,
})
// Validate, clean up, fix palette and optimise
iconSet.forEachSync((name, type) => {
if (type !== 'icon')
return
const svg = iconSet.toSVG(name)
if (!svg) {
// Invalid icon
iconSet.remove(name)
return
}
// Clean up and optimise icons
try {
// Clean up icon code
cleanupSVG(svg)
// Change color to `currentColor`
// Skip this step if icon has hardcoded palette
const blackColor = stringToColor('black')
const whiteColor = stringToColor('white')
parseColors(svg, {
defaultColor: 'currentColor',
callback: (attr, colorStr, color) => {
if (!color) {
// Color cannot be parsed!
throw new Error(`Invalid color: "${colorStr}" in attribute ${attr}`)
}
if (isEmptyColor(color)) {
// Color is empty: 'none' or 'transparent'. Return as is
return color
}
// Change black to 'currentColor'
if (compareColors(color, blackColor))
return 'currentColor'
// Remove shapes with white color
if (compareColors(color, whiteColor))
return 'remove'
// Icon is not monotone
return color
},
})
// Optimise
runSVGO(svg)
}
catch (err) {
// Invalid icon
console.error(`Error parsing ${name}:`, err)
iconSet.remove(name)
return
}
// Update icon
iconSet.fromSVG(name, svg)
})
// Export
return iconSet.export()
}
Is it possible to load svg files from filesystem like this one in unocss?