Skip to content

Instantly share code, notes, and snippets.

@mortezasabihi
Last active September 2, 2025 12:08
Show Gist options
  • Select an option

  • Save mortezasabihi/515d080d6ad268ff6c6a01fb2d973346 to your computer and use it in GitHub Desktop.

Select an option

Save mortezasabihi/515d080d6ad268ff6c6a01fb2d973346 to your computer and use it in GitHub Desktop.
A Node.js script that converts SVG files in a directory to Vue components, using the filename as the component name and replacing spaces with hyphens.
const fs = require("fs");
const path = require("path");
const prettier = require("prettier");
const { DOMParser, XMLSerializer } = require("xmldom");
const ICONS_DIRECTORY = path.join(__dirname, "icons");
const EXPORT_DIRECTORY = path.join(__dirname, "components");
fs.readdir(ICONS_DIRECTORY, function (err, files) {
if (err) {
console.error(err);
return;
}
const svgFiles = files.filter((file) => path.extname(file) === ".svg");
svgFiles.forEach((file) => {
const componentName = path.parse(file).name.replace(/\s/g, "-");
const componentPath = path.join(EXPORT_DIRECTORY, componentName + ".vue");
const svgData = fs.readFileSync(path.join(ICONS_DIRECTORY, file), "utf8");
const parser = new DOMParser();
const doc = parser.parseFromString(svgData, "image/svg+xml");
// Replace width and height attributes values with 1em
const widthAttr = doc.documentElement.getAttribute("width");
if (widthAttr) {
doc.documentElement.setAttribute("width", "1em");
}
const heightAttr = doc.documentElement.getAttribute("height");
if (heightAttr) {
doc.documentElement.setAttribute("height", "1em");
}
// Replace stroke attribute value with currentColor in root element
const strokeAttr = doc.documentElement.getAttribute("stroke");
if (strokeAttr) {
doc.documentElement.setAttribute("stroke", "currentColor");
}
// Replace fill attribute value with currentColor if it's not "none"
const fillAttr = doc.documentElement.getAttribute("fill");
if (fillAttr && fillAttr !== "none") {
doc.documentElement.setAttribute("fill", "currentColor");
}
// Replace stroke attribute value with currentColor in child elements
const elements = doc.documentElement.getElementsByTagName("*");
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const strokeAttr = element.getAttribute("stroke");
if (strokeAttr) {
element.setAttribute("stroke", "currentColor");
}
}
const serializer = new XMLSerializer();
const svgString = serializer.serializeToString(doc.documentElement);
const vueComponent = `
<template>
${svgString}
</template>
<script>
export default {
name: '${componentName}'
}
</script>
`;
const formattedVueComponent = prettier.format(vueComponent, {
parser: "vue",
});
if (!fs.existsSync(EXPORT_DIRECTORY)) {
fs.mkdirSync(EXPORT_DIRECTORY);
}
fs.writeFile(componentPath, formattedVueComponent, function (err) {
if (err) {
console.error(err);
return;
}
console.log(`Converted ${file} to ${componentName}.vue`);
});
});
});
@Daenara
Copy link

Daenara commented Sep 2, 2025

In case someone else strumbles over this:
xmldom moved their npm repository, so to get newer versions use @xmldom/xmldom instead of xmldom. I tested version 0.9.8 and it still worked fine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment