diff options
author | 2022-07-25 23:21:42 +0200 | |
---|---|---|
committer | 2022-07-25 23:21:42 +0200 | |
commit | e6953d1b67b81a6d3c19973b706f29637c421f98 (patch) | |
tree | b4a2717bb5e8cb05fa0955fb53a1558f68678e63 | |
parent | a70a0f83a1c500247194182f33be40526c0f0def (diff) | |
download | it-tools-e6953d1b67b81a6d3c19973b706f29637c421f98.tar.gz it-tools-e6953d1b67b81a6d3c19973b706f29637c421f98.tar.zst it-tools-e6953d1b67b81a6d3c19973b706f29637c421f98.zip |
refactor(base64): split base64 text and file conversion in two tools + base64 to file
-rw-r--r-- | package-lock.json | 20 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/composable/downloadBase64.ts | 10 | ||||
-rw-r--r-- | src/tools/base64-file-converter/base64-file-converter.vue (renamed from src/tools/base64-converter/base64-converter.vue) | 19 | ||||
-rw-r--r-- | src/tools/base64-file-converter/index.ts (renamed from src/tools/base64-converter/index.ts) | 4 | ||||
-rw-r--r-- | src/tools/base64-string-converter/base64-string-converter.vue | 65 | ||||
-rw-r--r-- | src/tools/base64-string-converter/index.ts | 12 | ||||
-rw-r--r-- | src/tools/index.ts | 6 |
8 files changed, 117 insertions, 21 deletions
diff --git a/package-lock.json b/package-lock.json index 0017706..cbfa6e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "highlight.js": "^11.5.1", "lodash": "^4.17.21", "mathjs": "^10.6.0", + "mime-types": "^2.1.35", "naive-ui": "^2.31.0", "pinia": "^2.0.11", "plausible-tracker": "^0.3.5", @@ -40,6 +41,7 @@ "@types/bcryptjs": "^2.4.2", "@types/crypto-js": "^4.1.1", "@types/jsdom": "^16.2.14", + "@types/mime-types": "^2.1.1", "@types/node": "^16.11.25", "@types/qrcode": "^1.4.2", "@types/randombytes": "^2.0.0", @@ -2248,6 +2250,12 @@ "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", "dev": true }, + "node_modules/@types/mime-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -7703,7 +7711,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -7712,7 +7719,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -12847,6 +12853,12 @@ "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", "dev": true }, + "@types/mime-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", + "dev": true + }, "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -16899,14 +16911,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } diff --git a/package.json b/package.json index 17b49d6..a8d64bf 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "highlight.js": "^11.5.1", "lodash": "^4.17.21", "mathjs": "^10.6.0", + "mime-types": "^2.1.35", "naive-ui": "^2.31.0", "pinia": "^2.0.11", "plausible-tracker": "^0.3.5", @@ -62,6 +63,7 @@ "@types/bcryptjs": "^2.4.2", "@types/crypto-js": "^4.1.1", "@types/jsdom": "^16.2.14", + "@types/mime-types": "^2.1.1", "@types/node": "^16.11.25", "@types/qrcode": "^1.4.2", "@types/randombytes": "^2.0.0", diff --git a/src/composable/downloadBase64.ts b/src/composable/downloadBase64.ts index e5b621f..d2ea576 100644 --- a/src/composable/downloadBase64.ts +++ b/src/composable/downloadBase64.ts @@ -1,11 +1,17 @@ +import { extension as getExtensionFromMime } from 'mime-types'; import type { Ref } from 'vue'; -export function useDownloadFileFromBase64({ source, filename = 'file' }: { source: Ref<string>; filename?: string }) { +export function useDownloadFileFromBase64({ source, filename }: { source: Ref<string>; filename?: string }) { return { download() { + const base64 = source.value; + const mimeType = base64.match(/data:(.*?);base64/i)?.[1] ?? 'text/plain'; + console.log({ mimeType }); + const cleanFileName = filename ?? `file.${getExtensionFromMime(mimeType)}`; + const a = document.createElement('a'); a.href = source.value; - a.download = filename; + a.download = cleanFileName; a.click(); }, }; diff --git a/src/tools/base64-converter/base64-converter.vue b/src/tools/base64-file-converter/base64-file-converter.vue index 307ea2f..88371a0 100644 --- a/src/tools/base64-converter/base64-converter.vue +++ b/src/tools/base64-file-converter/base64-file-converter.vue @@ -1,9 +1,8 @@ <template> - <n-card title="Text to base64"> - <n-input v-model:value="textInput" type="textarea" placeholder="Put your string here..." /> - <n-input :value="textBase64" type="textarea" readonly /> + <n-card title="Base64 to file"> + <n-input v-model:value="base64Input" type="textarea" placeholder="Put your base64 file string here..." rows="5" /> <n-space justify="center"> - <n-button secondary @click="copyTextBase64()"> Copy </n-button> + <n-button secondary @click="download()"> Download file </n-button> </n-space> </n-card> @@ -17,7 +16,7 @@ </n-upload-dragger> </n-upload> - <n-input :value="fileBase64" type="textarea" readonly /> + <n-input :value="fileBase64" type="textarea" readonly placeholder="File in ase64 will be here" /> <n-space justify="center"> <n-button secondary @click="copyFileBase64()"> Copy </n-button> </n-space> @@ -26,14 +25,14 @@ <script setup lang="ts"> import { useCopy } from '@/composable/copy'; -import { useBase64 } from '@vueuse/core'; +import { useDownloadFileFromBase64 } from '@/composable/downloadBase64'; import { Upload } from '@vicons/tabler'; -import { ref, type Ref } from 'vue'; +import { useBase64 } from '@vueuse/core'; import type { UploadFileInfo } from 'naive-ui'; +import { ref, type Ref } from 'vue'; -const textInput = ref(''); -const { base64: textBase64 } = useBase64(textInput); -const { copy: copyTextBase64 } = useCopy({ source: textBase64, text: 'Base64 string copied to the clipboard' }); +const base64Input = ref(''); +const { download } = useDownloadFileFromBase64({ source: base64Input }); const fileList = ref(); const fileInput = ref() as Ref<File>; diff --git a/src/tools/base64-converter/index.ts b/src/tools/base64-file-converter/index.ts index aa8980d..ba312ec 100644 --- a/src/tools/base64-converter/index.ts +++ b/src/tools/base64-file-converter/index.ts @@ -2,11 +2,11 @@ import { FileDigit } from '@vicons/tabler'; import { defineTool } from '../tool'; export const tool = defineTool({ - name: 'Base64 converter', + name: 'Base64 file converter', path: '/base64-converter', description: "Convert string, files or images into a it's base64 representation.", keywords: ['base64', 'converter', 'upload', 'image', 'file', 'conversion', 'web', 'data', 'format'], - component: () => import('./base64-converter.vue'), + component: () => import('./base64-file-converter.vue'), icon: FileDigit, redirectFrom: ['/file-to-base64', '/base64-string-converter'], }); diff --git a/src/tools/base64-string-converter/base64-string-converter.vue b/src/tools/base64-string-converter/base64-string-converter.vue new file mode 100644 index 0000000..c38c7ce --- /dev/null +++ b/src/tools/base64-string-converter/base64-string-converter.vue @@ -0,0 +1,65 @@ +<template> + <n-card title="String to base64"> + <n-form-item label="String to encode"> + <n-input v-model:value="textInput" type="textarea" placeholder="Put your string here..." rows="5" /> + </n-form-item> + + <n-form-item label="Base64 of string"> + <n-input + :value="base64Output" + type="textarea" + readonly + placeholder="The base64 encoding of your string will be here" + rows="5" + /> + </n-form-item> + + <n-space justify="center"> + <n-button secondary @click="copyTextBase64()"> Copy base64 </n-button> + </n-space> + </n-card> + + <n-card title="Base64 to string"> + <n-form-item + label="Base64 string to decode" + :validation-status="b64Validation.status" + :feedback="b64Validation.message" + > + <n-input v-model:value="base64Input" type="textarea" placeholder="Your base64 string..." rows="5" /> + </n-form-item> + + <n-form-item label="Decoded string"> + <n-input :value="textOutput" type="textarea" readonly placeholder="The decoded string will be here" rows="5" /> + </n-form-item> + + <n-space justify="center"> + <n-button secondary @click="copyText()"> Copy decoded string </n-button> + </n-space> + </n-card> +</template> + +<script setup lang="ts"> +import { useCopy } from '@/composable/copy'; +import { useValidation } from '@/composable/validation'; +import { computed, ref } from 'vue'; + +const textInput = ref(''); +const base64Output = computed(() => window.btoa(textInput.value)); +const { copy: copyTextBase64 } = useCopy({ source: base64Output, text: 'Base64 string copied to the clipboard' }); + +const base64Input = ref(''); +const textOutput = computed(() => { + try { + return window.atob(base64Input.value); + } catch (_) { + return ''; + } +}); +const { copy: copyText } = useCopy({ source: textOutput, text: 'String copied to the clipboard' }); +const b64Validation = useValidation({ + source: base64Input, + rules: [{ message: 'Invalid base64 string', validator: (value) => true || window.atob(value) }], +}); +</script> + +<style lang="less" scoped></style> diff --git a/src/tools/base64-string-converter/index.ts b/src/tools/base64-string-converter/index.ts new file mode 100644 index 0000000..0dd9bee --- /dev/null +++ b/src/tools/base64-string-converter/index.ts @@ -0,0 +1,12 @@ +import { FileDigit } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Base64 string encoder/decoder', + path: '/base64-string-converter', + description: 'Simply encode and decode string into a their base64 representation.', + keywords: ['base64', 'converter', 'conversion', 'web', 'data', 'format', 'atob', 'btoa'], + component: () => import('./base64-string-converter.vue'), + icon: FileDigit, + redirectFrom: ['/file-to-base64', '/base64-converter'], +}); diff --git a/src/tools/index.ts b/src/tools/index.ts index 18c04b7..5a218f3 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,7 +1,8 @@ import { LockOpen } from '@vicons/tabler'; import type { ToolCategory } from './tool'; -import { tool as base64Converter } from './base64-converter'; +import { tool as base64FileConverter } from './base64-file-converter'; +import { tool as base64StringConverter } from './base64-string-converter'; import { tool as basicAuthGenerator } from './basic-auth-generator'; import { tool as bcrypt } from './bcrypt'; import { tool as bip39 } from './bip39-generator'; @@ -43,7 +44,8 @@ export const toolsByCategory: ToolCategory[] = [ dateTimeConverter, baseConverter, romanNumeralConverter, - base64Converter, + base64StringConverter, + base64FileConverter, colorConverter, caseConverter, ], |