From 6988db600ddfa3bd01917112926f1e069254433d Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Tue, 3 Jun 2025 21:40:58 +0200 Subject: [PATCH] add base64 encoding/decoding --- .../string/base64/base64.service.test.ts | 64 +++++++++++++ src/pages/tools/string/base64/index.tsx | 89 +++++++++++++++++++ src/pages/tools/string/base64/meta.ts | 13 +++ src/pages/tools/string/base64/service.ts | 7 ++ src/pages/tools/string/index.ts | 4 +- 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 src/pages/tools/string/base64/base64.service.test.ts create mode 100644 src/pages/tools/string/base64/index.tsx create mode 100644 src/pages/tools/string/base64/meta.ts create mode 100644 src/pages/tools/string/base64/service.ts diff --git a/src/pages/tools/string/base64/base64.service.test.ts b/src/pages/tools/string/base64/base64.service.test.ts new file mode 100644 index 0000000..8512379 --- /dev/null +++ b/src/pages/tools/string/base64/base64.service.test.ts @@ -0,0 +1,64 @@ +import { expect, describe, it } from 'vitest'; +import { base64 } from './service'; + +describe('base64', () => { + it('should encode a simple string using Base64 correctly', () => { + const input = 'hello'; + const result = base64(input, true); + expect(result).toBe('aGVsbG8='); + }); + + it('should decode a simple Base64-encoded string correctly', () => { + const input = 'aGVsbG8='; + const result = base64(input, false); + expect(result).toBe('hello'); + }); + + it('should handle special characters encoding correctly', () => { + const input = 'Hello, World!'; + const result = base64(input, true); + expect(result).toBe('SGVsbG8sIFdvcmxkIQ=='); + }); + + it('should handle special characters decoding correctly', () => { + const input = 'SGVsbG8sIFdvcmxkIQ=='; + const result = base64(input, false); + expect(result).toBe('Hello, World!'); + }); + + it('should handle an empty string encoding correctly', () => { + const input = ''; + const result = base64(input, true); + expect(result).toBe(''); + }); + + it('should handle an empty string decoding correctly', () => { + const input = ''; + const result = base64(input, false); + expect(result).toBe(''); + }); + + it('should handle a newline encoding correctly', () => { + const input = '\n'; + const result = base64(input, true); + expect(result).toBe('Cg=='); + }); + + it('should handle a newline decoding correctly', () => { + const input = 'Cg=='; + const result = base64(input, false); + expect(result).toBe('\n'); + }); + + it('should handle a string with symbols encoding correctly', () => { + const input = '!@#$%^&*()_+-='; + const result = base64(input, true); + expect(result).toBe('IUAjJCVeJiooKV8rLT0='); + }); + + it('should handle a string with mixed characters decoding correctly', () => { + const input = 'IUAjJCVeJiooKV8rLT0='; + const result = base64(input, false); + expect(result).toBe('!@#$%^&*()_+-='); + }); +}); diff --git a/src/pages/tools/string/base64/index.tsx b/src/pages/tools/string/base64/index.tsx new file mode 100644 index 0000000..61a579d --- /dev/null +++ b/src/pages/tools/string/base64/index.tsx @@ -0,0 +1,89 @@ +import { useState } from 'react'; +import ToolContent from '@components/ToolContent'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import { base64 } from './service'; +import { CardExampleType } from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { GetGroupsType } from '@components/options/ToolOptions'; +import { Box } from '@mui/material'; +import SimpleRadio from '@components/options/SimpleRadio'; + +interface InitialValuesType { + mode: 'encode' | 'decode'; +} + +const initialValues: InitialValuesType = { + mode: 'encode' +}; + +const exampleCards: CardExampleType[] = [ + { + title: 'Encode data in UTF-8 with Base64', + description: 'This example shows how to encode a simple text using Base64.', + sampleText: 'Hello, World!', + sampleResult: 'SGVsbG8sIFdvcmxkIQ==', + sampleOptions: { mode: 'encode' } + }, + { + title: 'Decode Base64-encoded data to UTF-8', + description: + 'This example shows how to decode data that was encoded with Base64.', + sampleText: 'SGVsbG8sIFdvcmxkIQ==', + sampleResult: 'Hello, World!', + sampleOptions: { mode: 'decode' } + } +]; + +export default function Base64({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + + const compute = (optionsValues: InitialValuesType, input: string) => { + if (input) setResult(base64(input, optionsValues.mode === 'encode')); + }; + + const getGroups: GetGroupsType = ({ + values, + updateField + }) => [ + { + title: 'Base64 Options', + component: ( + + updateField('mode', 'encode')} + checked={values.mode === 'encode'} + title={'Base64 Encode'} + /> + updateField('mode', 'decode')} + checked={values.mode === 'decode'} + title={'Base64 Decode'} + /> + + ) + } + ]; + + return ( + + } + resultComponent={} + initialValues={initialValues} + getGroups={getGroups} + toolInfo={{ + title: 'What is Base64?', + description: + 'Base64 is an encoding scheme that represents data in an ASCII string format by translating it into a radix-64 representation. Although it can be used to encode strings, it is commonly used to encode binary data for transmission over media that are designed to deal with textual data.' + }} + exampleCards={exampleCards} + input={input} + setInput={setInput} + compute={compute} + /> + ); +} diff --git a/src/pages/tools/string/base64/meta.ts b/src/pages/tools/string/base64/meta.ts new file mode 100644 index 0000000..2e0d104 --- /dev/null +++ b/src/pages/tools/string/base64/meta.ts @@ -0,0 +1,13 @@ +import { defineTool } from '@tools/defineTool'; +import { lazy } from 'react'; + +export const tool = defineTool('string', { + name: 'Base64', + path: 'base64', + icon: 'mdi:code-tags', + description: + 'A simple tool to encode or decode data using Base64, which is commonly used in web applications.', + shortDescription: 'Encode or decode data using Base64.', + keywords: ['base64'], + component: lazy(() => import('./index')) +}); diff --git a/src/pages/tools/string/base64/service.ts b/src/pages/tools/string/base64/service.ts new file mode 100644 index 0000000..b28fce4 --- /dev/null +++ b/src/pages/tools/string/base64/service.ts @@ -0,0 +1,7 @@ +import { Buffer } from 'buffer'; + +export function base64(input: string, encode: boolean): string { + return encode + ? Buffer.from(input, 'utf-8').toString('base64') + : Buffer.from(input, 'base64').toString('utf-8'); +} diff --git a/src/pages/tools/string/index.ts b/src/pages/tools/string/index.ts index b2aa502..758dd02 100644 --- a/src/pages/tools/string/index.ts +++ b/src/pages/tools/string/index.ts @@ -14,6 +14,7 @@ import { tool as stringJoin } from './join/meta'; import { tool as stringReplace } from './text-replacer/meta'; import { tool as stringRepeat } from './repeat/meta'; import { tool as stringTruncate } from './truncate/meta'; +import { tool as stringBase64 } from './base64/meta'; export const stringTools = [ stringSplit, @@ -31,5 +32,6 @@ export const stringTools = [ stringPalindrome, stringQuote, stringRotate, - stringRot13 + stringRot13, + stringBase64 ];