Skip to content

Commit c8dbec7

Browse files
committed
feat(New tool): Image to CSS
FIx CorentinTh#530
1 parent b430bae commit c8dbec7

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { stringToUrl } from 'svg-to-url';
2+
3+
export type CSSType = 'Background' | 'Border' | 'ListItemBullet' | 'Url';
4+
5+
function fileToDataUrl(file: File) {
6+
return new Promise<string>((resolve, reject) => {
7+
const reader = new FileReader();
8+
reader.readAsDataURL(file);
9+
reader.onload = () => resolve(reader.result?.toString() ?? '');
10+
reader.onerror = error => reject(error);
11+
});
12+
}
13+
14+
function svgToDataUrl(image: string) {
15+
const getUrlFromSvgString = stringToUrl({});
16+
return getUrlFromSvgString(image);
17+
}
18+
19+
export async function imageToCSS(
20+
image: File | string,
21+
type: CSSType,
22+
) {
23+
const dataURI = image instanceof File ? await fileToDataUrl(image) : svgToDataUrl(image);
24+
switch (type) {
25+
case 'Background':
26+
return `background-image: url(${dataURI});`;
27+
case 'Border':
28+
return `border-image-source: url(${dataURI});`;
29+
case 'ListItemBullet':
30+
return `li{\n list-style-image: ${dataURI};\n}\nli::marker{\n font-size: 1.5em;\n}'}`;
31+
default:
32+
return `url(${dataURI})`;
33+
}
34+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<script setup lang="ts">
2+
import type { Ref } from 'vue';
3+
import { type CSSType, imageToCSS } from './image-to-css.service';
4+
import TextareaCopyable from '@/components/TextareaCopyable.vue';
5+
6+
const typeOptions = [
7+
{ label: 'Background', value: 'Background' },
8+
{ label: 'Border', value: 'Border' },
9+
{ label: 'ListItem Bullet', value: 'ListItemBullet' },
10+
{ label: 'CSS Data Url', value: 'Url' },
11+
];
12+
13+
const type = ref('Background');
14+
const svgContent = ref('');
15+
const fileInput = ref() as Ref<File | null>;
16+
const cssCode = computedAsync(async () => {
17+
try {
18+
return (await imageToCSS(fileInput.value || svgContent.value, type.value as CSSType));
19+
}
20+
catch (e: any) {
21+
return e.toString();
22+
}
23+
});
24+
25+
async function onUpload(file: File) {
26+
if (file) {
27+
fileInput.value = file;
28+
}
29+
}
30+
31+
watch(svgContent, (_, newValue) => {
32+
if (newValue !== '') {
33+
fileInput.value = null;
34+
}
35+
});
36+
</script>
37+
38+
<template>
39+
<div>
40+
<c-file-upload
41+
title="Drag and drop an image here, or click to select a file"
42+
paste-image
43+
@file-upload="onUpload"
44+
/>
45+
<n-p>OR</n-p>
46+
47+
<c-input-text
48+
v-model:value="svgContent"
49+
label="SVG Content"
50+
placeholder="Paste your SVG content here"
51+
mb-2
52+
/>
53+
54+
<n-divider />
55+
56+
<c-select
57+
v-model:value="type"
58+
label-position="top"
59+
label="CSS Type:"
60+
:options="typeOptions"
61+
placeholder="Select CSS Type"
62+
/>
63+
64+
<n-divider />
65+
66+
<div>
67+
<h3>CSS Code</h3>
68+
<TextareaCopyable
69+
:value="cssCode"
70+
:word-wrap="true"
71+
/>
72+
</div>
73+
</div>
74+
</template>
75+
76+
<style lang="less" scoped>
77+
::v-deep(.n-upload-trigger) {
78+
width: 100%;
79+
}
80+
</style>

src/tools/image-to-css/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { BrandCss3 } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Image to CSS',
6+
path: '/image-to-css',
7+
description: 'Convert image to CSS (url, background, ...)',
8+
keywords: ['image', 'css'],
9+
component: () => import('./image-to-css.vue'),
10+
icon: BrandCss3,
11+
createdAt: new Date('2024-05-11'),
12+
});

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer';
66

77
import { tool as textToUnicode } from './text-to-unicode';
88
import { tool as safelinkDecoder } from './safelink-decoder';
9+
import { tool as imageToCss } from './image-to-css';
910
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
1011
import { tool as numeronymGenerator } from './numeronym-generator';
1112
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -128,6 +129,7 @@ export const toolsByCategory: ToolCategory[] = [
128129
httpStatusCodes,
129130
jsonDiff,
130131
safelinkDecoder,
132+
imageToCss,
131133
],
132134
},
133135
{

0 commit comments

Comments
 (0)