⚙️ Create clipboard, download, downloadSvg & parse svg utilities

This commit is contained in:
pheralb
2025-08-25 14:24:44 +01:00
parent f53d5418b6
commit 6761716dca
5 changed files with 175 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
export const clipboard = (content: string) => {
navigator.clipboard.writeText(content);
};
+23
View File
@@ -0,0 +1,23 @@
type MimeType = "image/svg+xml" | "application/zip";
interface Download {
content: string | Blob;
filename: string;
mimeType: MimeType;
}
export const download = ({ content, filename, mimeType }: Download) => {
const blob =
typeof content === "string"
? new Blob([content], { type: mimeType })
: content;
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
};
+102
View File
@@ -0,0 +1,102 @@
import type { iSVG } from "@/types/svg";
import JSZip from "jszip";
import { download } from "@/utils/download";
import { getSource } from "@/templates/getSource";
import { getPrefixFromSvgUrl, prefixSvgIds } from "@/utils/prefixSvgIds";
interface DownloadResult {
success: boolean;
message: string;
}
interface DownloadSvg {
url: string;
}
interface DownloadAllVariants {
svgInfo: iSVG;
lightRoute: string;
darkRoute: string;
isWordmark?: boolean;
}
export const downloadSvg = async ({
url,
}: DownloadSvg): Promise<DownloadResult> => {
try {
let content = await getSource({
url: url,
});
if (url) {
content = prefixSvgIds(content, getPrefixFromSvgUrl(url));
}
download({
content: content || "",
filename: url?.split("/").pop() || "",
mimeType: "image/svg+xml",
});
return {
success: true,
message: "SVG downloaded successfully",
};
} catch (error) {
console.error("❌ utils/downloadSvg - Error downloading SVG:", error);
return {
success: false,
message: "Error downloading SVG",
};
}
};
export const downloadAllVariants = async ({
svgInfo,
lightRoute,
darkRoute,
isWordmark,
}: DownloadAllVariants): Promise<boolean> => {
try {
const zip = new JSZip();
let lightSvg = await getSource({
url: lightRoute,
});
let darkSvg = await getSource({
url: darkRoute,
});
lightSvg = prefixSvgIds(
lightSvg,
svgInfo.title.toLowerCase() + (isWordmark ? "_wordmark_light" : "_light"),
);
darkSvg = prefixSvgIds(
darkSvg,
svgInfo.title.toLowerCase() + (isWordmark ? "_wordmark_dark" : "_dark"),
);
if (isWordmark) {
zip.file(`${svgInfo.title}_wordmark_light.svg`, lightSvg);
zip.file(`${svgInfo.title}_wordmark_dark.svg`, darkSvg);
} else {
zip.file(`${svgInfo.title}_light.svg`, lightSvg);
zip.file(`${svgInfo.title}_dark.svg`, darkSvg);
}
zip.generateAsync({ type: "blob" }).then((content) => {
download({
content,
filename: isWordmark
? `${svgInfo.title}_wordmark_light_dark.zip`
: `${svgInfo.title}_light_dark.zip`,
mimeType: "application/zip",
});
});
return true;
} catch (error) {
console.error(
"❌ utils/downloadSvg - Error downloading all variants:",
error,
);
return false;
}
};
+27
View File
@@ -0,0 +1,27 @@
export const parseSvgContent = (
content: string,
framework: "Vue" | "Svelte",
) => {
if (content.includes("<?xml")) {
content = content.replace(/<\?xml[^>]*\?>/i, "");
}
const styleTagRegex = /<style[^>]*>([\s\S]*?)<\/style>/gi;
const styles = [];
let matched;
while ((matched = styleTagRegex.exec(content)) !== null) {
styles.push(matched[1]);
}
const templateContent = content.replace(styleTagRegex, "");
const componentStyle = styles.length
? `<style${framework === "Vue" ? " scoped" : ""}>\n${styles.join("\n")}\n</style>`
: "";
return {
componentStyle,
templateContent,
};
};
+20
View File
@@ -0,0 +1,20 @@
import { optimize } from "svgo";
export const getPrefixFromSvgUrl = (svgUrl: string) => {
return svgUrl.split("/").pop()!.replace(".svg", "").split("-").join("_");
};
export const prefixSvgIds = (content: string, prefix: string): string => {
const result = optimize(content, {
plugins: [
{
name: "prefixIds",
params: {
prefix,
},
},
],
multipass: false,
});
return (result as { data: string }).data;
};