refactor(base64): split base64 text and file conversion in two tools + base64 to file
This commit is contained in:
		
							parent
							
								
									a70a0f83a1
								
							
						
					
					
						commit
						e6953d1b67
					
				
							
								
								
									
										20
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										20
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -25,6 +25,7 @@ | |||||||
|         "highlight.js": "^11.5.1", |         "highlight.js": "^11.5.1", | ||||||
|         "lodash": "^4.17.21", |         "lodash": "^4.17.21", | ||||||
|         "mathjs": "^10.6.0", |         "mathjs": "^10.6.0", | ||||||
|  |         "mime-types": "^2.1.35", | ||||||
|         "naive-ui": "^2.31.0", |         "naive-ui": "^2.31.0", | ||||||
|         "pinia": "^2.0.11", |         "pinia": "^2.0.11", | ||||||
|         "plausible-tracker": "^0.3.5", |         "plausible-tracker": "^0.3.5", | ||||||
| @ -40,6 +41,7 @@ | |||||||
|         "@types/bcryptjs": "^2.4.2", |         "@types/bcryptjs": "^2.4.2", | ||||||
|         "@types/crypto-js": "^4.1.1", |         "@types/crypto-js": "^4.1.1", | ||||||
|         "@types/jsdom": "^16.2.14", |         "@types/jsdom": "^16.2.14", | ||||||
|  |         "@types/mime-types": "^2.1.1", | ||||||
|         "@types/node": "^16.11.25", |         "@types/node": "^16.11.25", | ||||||
|         "@types/qrcode": "^1.4.2", |         "@types/qrcode": "^1.4.2", | ||||||
|         "@types/randombytes": "^2.0.0", |         "@types/randombytes": "^2.0.0", | ||||||
| @ -2248,6 +2250,12 @@ | |||||||
|       "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", |       "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", | ||||||
|       "dev": true |       "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": { |     "node_modules/@types/minimist": { | ||||||
|       "version": "1.2.2", |       "version": "1.2.2", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", |       "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", | ||||||
| @ -7703,7 +7711,6 @@ | |||||||
|       "version": "1.52.0", |       "version": "1.52.0", | ||||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", |       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", | ||||||
|       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", |       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">= 0.6" |         "node": ">= 0.6" | ||||||
|       } |       } | ||||||
| @ -7712,7 +7719,6 @@ | |||||||
|       "version": "2.1.35", |       "version": "2.1.35", | ||||||
|       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", |       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", | ||||||
|       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", |       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "mime-db": "1.52.0" |         "mime-db": "1.52.0" | ||||||
|       }, |       }, | ||||||
| @ -12847,6 +12853,12 @@ | |||||||
|       "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", |       "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", | ||||||
|       "dev": true |       "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": { |     "@types/minimist": { | ||||||
|       "version": "1.2.2", |       "version": "1.2.2", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", |       "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", | ||||||
| @ -16899,14 +16911,12 @@ | |||||||
|     "mime-db": { |     "mime-db": { | ||||||
|       "version": "1.52.0", |       "version": "1.52.0", | ||||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", |       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", | ||||||
|       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", |       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "mime-types": { |     "mime-types": { | ||||||
|       "version": "2.1.35", |       "version": "2.1.35", | ||||||
|       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", |       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", | ||||||
|       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", |       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", | ||||||
|       "dev": true, |  | ||||||
|       "requires": { |       "requires": { | ||||||
|         "mime-db": "1.52.0" |         "mime-db": "1.52.0" | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -47,6 +47,7 @@ | |||||||
|     "highlight.js": "^11.5.1", |     "highlight.js": "^11.5.1", | ||||||
|     "lodash": "^4.17.21", |     "lodash": "^4.17.21", | ||||||
|     "mathjs": "^10.6.0", |     "mathjs": "^10.6.0", | ||||||
|  |     "mime-types": "^2.1.35", | ||||||
|     "naive-ui": "^2.31.0", |     "naive-ui": "^2.31.0", | ||||||
|     "pinia": "^2.0.11", |     "pinia": "^2.0.11", | ||||||
|     "plausible-tracker": "^0.3.5", |     "plausible-tracker": "^0.3.5", | ||||||
| @ -62,6 +63,7 @@ | |||||||
|     "@types/bcryptjs": "^2.4.2", |     "@types/bcryptjs": "^2.4.2", | ||||||
|     "@types/crypto-js": "^4.1.1", |     "@types/crypto-js": "^4.1.1", | ||||||
|     "@types/jsdom": "^16.2.14", |     "@types/jsdom": "^16.2.14", | ||||||
|  |     "@types/mime-types": "^2.1.1", | ||||||
|     "@types/node": "^16.11.25", |     "@types/node": "^16.11.25", | ||||||
|     "@types/qrcode": "^1.4.2", |     "@types/qrcode": "^1.4.2", | ||||||
|     "@types/randombytes": "^2.0.0", |     "@types/randombytes": "^2.0.0", | ||||||
|  | |||||||
| @ -1,11 +1,17 @@ | |||||||
|  | import { extension as getExtensionFromMime } from 'mime-types'; | ||||||
| import type { Ref } from 'vue'; | 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 { |   return { | ||||||
|     download() { |     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'); |       const a = document.createElement('a'); | ||||||
|       a.href = source.value; |       a.href = source.value; | ||||||
|       a.download = filename; |       a.download = cleanFileName; | ||||||
|       a.click(); |       a.click(); | ||||||
|     }, |     }, | ||||||
|   }; |   }; | ||||||
|  | |||||||
| @ -1,9 +1,8 @@ | |||||||
| <template> | <template> | ||||||
|   <n-card title="Text to base64"> |   <n-card title="Base64 to file"> | ||||||
|     <n-input v-model:value="textInput" type="textarea" placeholder="Put your string here..." /> |     <n-input v-model:value="base64Input" type="textarea" placeholder="Put your base64 file string here..." rows="5" /> | ||||||
|     <n-input :value="textBase64" type="textarea" readonly /> |  | ||||||
|     <n-space justify="center"> |     <n-space justify="center"> | ||||||
|       <n-button secondary @click="copyTextBase64()"> Copy </n-button> |       <n-button secondary @click="download()"> Download file </n-button> | ||||||
|     </n-space> |     </n-space> | ||||||
|   </n-card> |   </n-card> | ||||||
| 
 | 
 | ||||||
| @ -17,7 +16,7 @@ | |||||||
|       </n-upload-dragger> |       </n-upload-dragger> | ||||||
|     </n-upload> |     </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-space justify="center"> | ||||||
|       <n-button secondary @click="copyFileBase64()"> Copy </n-button> |       <n-button secondary @click="copyFileBase64()"> Copy </n-button> | ||||||
|     </n-space> |     </n-space> | ||||||
| @ -26,14 +25,14 @@ | |||||||
| 
 | 
 | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { useCopy } from '@/composable/copy'; | import { useCopy } from '@/composable/copy'; | ||||||
| import { useBase64 } from '@vueuse/core'; | import { useDownloadFileFromBase64 } from '@/composable/downloadBase64'; | ||||||
| import { Upload } from '@vicons/tabler'; | import { Upload } from '@vicons/tabler'; | ||||||
| import { ref, type Ref } from 'vue'; | import { useBase64 } from '@vueuse/core'; | ||||||
| import type { UploadFileInfo } from 'naive-ui'; | import type { UploadFileInfo } from 'naive-ui'; | ||||||
|  | import { ref, type Ref } from 'vue'; | ||||||
| 
 | 
 | ||||||
| const textInput = ref(''); | const base64Input = ref(''); | ||||||
| const { base64: textBase64 } = useBase64(textInput); | const { download } = useDownloadFileFromBase64({ source: base64Input }); | ||||||
| const { copy: copyTextBase64 } = useCopy({ source: textBase64, text: 'Base64 string copied to the clipboard' }); |  | ||||||
| 
 | 
 | ||||||
| const fileList = ref(); | const fileList = ref(); | ||||||
| const fileInput = ref() as Ref<File>; | const fileInput = ref() as Ref<File>; | ||||||
| @ -2,11 +2,11 @@ import { FileDigit } from '@vicons/tabler'; | |||||||
| import { defineTool } from '../tool'; | import { defineTool } from '../tool'; | ||||||
| 
 | 
 | ||||||
| export const tool = defineTool({ | export const tool = defineTool({ | ||||||
|   name: 'Base64 converter', |   name: 'Base64 file converter', | ||||||
|   path: '/base64-converter', |   path: '/base64-converter', | ||||||
|   description: "Convert string, files or images into a it's base64 representation.", |   description: "Convert string, files or images into a it's base64 representation.", | ||||||
|   keywords: ['base64', 'converter', 'upload', 'image', 'file', 'conversion', 'web', 'data', 'format'], |   keywords: ['base64', 'converter', 'upload', 'image', 'file', 'conversion', 'web', 'data', 'format'], | ||||||
|   component: () => import('./base64-converter.vue'), |   component: () => import('./base64-file-converter.vue'), | ||||||
|   icon: FileDigit, |   icon: FileDigit, | ||||||
|   redirectFrom: ['/file-to-base64', '/base64-string-converter'], |   redirectFrom: ['/file-to-base64', '/base64-string-converter'], | ||||||
| }); | }); | ||||||
| @ -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> | ||||||
							
								
								
									
										12
									
								
								src/tools/base64-string-converter/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/base64-string-converter/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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'], | ||||||
|  | }); | ||||||
| @ -1,7 +1,8 @@ | |||||||
| import { LockOpen } from '@vicons/tabler'; | import { LockOpen } from '@vicons/tabler'; | ||||||
| import type { ToolCategory } from './tool'; | 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 basicAuthGenerator } from './basic-auth-generator'; | ||||||
| import { tool as bcrypt } from './bcrypt'; | import { tool as bcrypt } from './bcrypt'; | ||||||
| import { tool as bip39 } from './bip39-generator'; | import { tool as bip39 } from './bip39-generator'; | ||||||
| @ -43,7 +44,8 @@ export const toolsByCategory: ToolCategory[] = [ | |||||||
|       dateTimeConverter, |       dateTimeConverter, | ||||||
|       baseConverter, |       baseConverter, | ||||||
|       romanNumeralConverter, |       romanNumeralConverter, | ||||||
|       base64Converter, |       base64StringConverter, | ||||||
|  |       base64FileConverter, | ||||||
|       colorConverter, |       colorConverter, | ||||||
|       caseConverter, |       caseConverter, | ||||||
|     ], |     ], | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user