mirror of
https://github.com/pheralb/svgl.git
synced 2025-12-29 08:01:36 +08:00
⚙️ Create clipboard, download, downloadSvg & parse svg utilities
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export const clipboard = (content: string) => {
|
||||
navigator.clipboard.writeText(content);
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user