diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/index.ts | 2 | ||||
-rw-r--r-- | src/tools/text-to-binary/index.ts | 12 | ||||
-rw-r--r-- | src/tools/text-to-binary/text-to-binary.e2e.spec.ts | 25 | ||||
-rw-r--r-- | src/tools/text-to-binary/text-to-binary.models.test.ts | 32 | ||||
-rw-r--r-- | src/tools/text-to-binary/text-to-binary.models.ts | 22 | ||||
-rw-r--r-- | src/tools/text-to-binary/text-to-binary.vue | 42 |
6 files changed, 135 insertions, 0 deletions
diff --git a/src/tools/index.ts b/src/tools/index.ts index cc5f42e..e6df8cc 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,6 +1,7 @@ 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 textToBinary } from './text-to-binary'; import { tool as ulidGenerator } from './ulid-generator'; import { tool as ibanValidatorAndParser } from './iban-validator-and-parser'; import { tool as stringObfuscator } from './string-obfuscator'; @@ -88,6 +89,7 @@ export const toolsByCategory: ToolCategory[] = [ colorConverter, caseConverter, textToNatoAlphabet, + textToBinary, yamlToJson, yamlToToml, jsonToYaml, diff --git a/src/tools/text-to-binary/index.ts b/src/tools/text-to-binary/index.ts new file mode 100644 index 0000000..40ac93d --- /dev/null +++ b/src/tools/text-to-binary/index.ts @@ -0,0 +1,12 @@ +import { Binary } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Text to ASCII binary', + path: '/text-to-binary', + description: 'Convert text to its ASCII binary representation and vice versa.', + keywords: ['text', 'to', 'binary', 'converter', 'encode', 'decode', 'ascii'], + component: () => import('./text-to-binary.vue'), + icon: Binary, + createdAt: new Date('2023-10-15'), +}); diff --git a/src/tools/text-to-binary/text-to-binary.e2e.spec.ts b/src/tools/text-to-binary/text-to-binary.e2e.spec.ts new file mode 100644 index 0000000..2b4e431 --- /dev/null +++ b/src/tools/text-to-binary/text-to-binary.e2e.spec.ts @@ -0,0 +1,25 @@ +import { expect, test } from '@playwright/test'; + +test.describe('Tool - Text to ASCII binary', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/text-to-binary'); + }); + + test('Has correct title', async ({ page }) => { + await expect(page).toHaveTitle('Text to ASCII binary - IT Tools'); + }); + + test('Text to binary conversion', async ({ page }) => { + await page.getByTestId('text-to-binary-input').fill('it-tools'); + const binary = await page.getByTestId('text-to-binary-output').inputValue(); + + expect(binary).toEqual('01101001 01110100 00101101 01110100 01101111 01101111 01101100 01110011'); + }); + + test('Binary to text conversion', async ({ page }) => { + await page.getByTestId('binary-to-text-input').fill('01101001 01110100 00101101 01110100 01101111 01101111 01101100 01110011'); + const text = await page.getByTestId('binary-to-text-output').inputValue(); + + expect(text).toEqual('it-tools'); + }); +}); diff --git a/src/tools/text-to-binary/text-to-binary.models.test.ts b/src/tools/text-to-binary/text-to-binary.models.test.ts new file mode 100644 index 0000000..e4269b5 --- /dev/null +++ b/src/tools/text-to-binary/text-to-binary.models.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from 'vitest'; +import { convertAsciiBinaryToText, convertTextToAsciiBinary } from './text-to-binary.models'; + +describe('text-to-binary', () => { + describe('convertTextToAsciiBinary', () => { + it('a text string is converted to its ascii binary representation', () => { + expect(convertTextToAsciiBinary('A')).toBe('01000001'); + expect(convertTextToAsciiBinary('hello')).toBe('01101000 01100101 01101100 01101100 01101111'); + expect(convertTextToAsciiBinary('')).toBe(''); + }); + it('the separator between octets can be changed', () => { + expect(convertTextToAsciiBinary('hello', { separator: '' })).toBe('0110100001100101011011000110110001101111'); + }); + }); + + describe('convertAsciiBinaryToText', () => { + it('an ascii binary string is converted to its text representation', () => { + expect(convertAsciiBinaryToText('01101000 01100101 01101100 01101100 01101111')).toBe('hello'); + expect(convertAsciiBinaryToText('01000001')).toBe('A'); + expect(convertTextToAsciiBinary('')).toBe(''); + }); + + it('the given binary string is cleaned before conversion', () => { + expect(convertAsciiBinaryToText(' 01000 001garbage')).toBe('A'); + }); + + it('throws an error if the given binary string as no complete octet', () => { + expect(() => convertAsciiBinaryToText('010000011')).toThrow('Invalid binary string'); + expect(() => convertAsciiBinaryToText('1')).toThrow('Invalid binary string'); + }); + }); +}); diff --git a/src/tools/text-to-binary/text-to-binary.models.ts b/src/tools/text-to-binary/text-to-binary.models.ts new file mode 100644 index 0000000..ad9699a --- /dev/null +++ b/src/tools/text-to-binary/text-to-binary.models.ts @@ -0,0 +1,22 @@ +export { convertTextToAsciiBinary, convertAsciiBinaryToText }; + +function convertTextToAsciiBinary(text: string, { separator = ' ' }: { separator?: string } = {}): string { + return text + .split('') + .map(char => char.charCodeAt(0).toString(2).padStart(8, '0')) + .join(separator); +} + +function convertAsciiBinaryToText(binary: string): string { + const cleanBinary = binary.replace(/[^01]/g, ''); + + if (cleanBinary.length % 8) { + throw new Error('Invalid binary string'); + } + + return cleanBinary + .split(/(\d{8})/) + .filter(Boolean) + .map(binary => String.fromCharCode(Number.parseInt(binary, 2))) + .join(''); +} diff --git a/src/tools/text-to-binary/text-to-binary.vue b/src/tools/text-to-binary/text-to-binary.vue new file mode 100644 index 0000000..37aa9be --- /dev/null +++ b/src/tools/text-to-binary/text-to-binary.vue @@ -0,0 +1,42 @@ +<script setup lang="ts"> +import { convertAsciiBinaryToText, convertTextToAsciiBinary } from './text-to-binary.models'; +import { withDefaultOnError } from '@/utils/defaults'; +import { useCopy } from '@/composable/copy'; +import { isNotThrowing } from '@/utils/boolean'; + +const inputText = ref(''); +const binaryFromText = computed(() => convertTextToAsciiBinary(inputText.value)); +const { copy: copyBinary } = useCopy({ source: binaryFromText }); + +const inputBinary = ref(''); +const textFromBinary = computed(() => withDefaultOnError(() => convertAsciiBinaryToText(inputBinary.value), '')); +const inputBinaryValidationRules = [ + { + validator: (value: string) => isNotThrowing(() => convertAsciiBinaryToText(value)), + message: 'Binary should be a valid ASCII binary string with multiples of 8 bits', + }, +]; +const { copy: copyText } = useCopy({ source: textFromBinary }); +</script> + +<template> + <c-card title="Text to ASCII binary"> + <c-input-text v-model:value="inputText" multiline placeholder="e.g. 'Hello world'" label="Enter text to convert to binary" autosize autofocus raw-text test-id="text-to-binary-input" /> + <c-input-text v-model:value="binaryFromText" label="Binary from your text" multiline raw-text readonly mt-2 placeholder="The binary representation of your text will be here" test-id="text-to-binary-output" /> + <div mt-2 flex justify-center> + <c-button :disabled="!binaryFromText" @click="copyBinary()"> + Copy binary to clipboard + </c-button> + </div> + </c-card> + + <c-card title="ASCII binary to text"> + <c-input-text v-model:value="inputBinary" multiline placeholder="e.g. '01001000 01100101 01101100 01101100 01101111'" label="Enter binary to convert to text" autosize raw-text :validation-rules="inputBinaryValidationRules" test-id="binary-to-text-input" /> + <c-input-text v-model:value="textFromBinary" label="Text from your binary" multiline raw-text readonly mt-2 placeholder="The text representation of your binary will be here" test-id="binary-to-text-output" /> + <div mt-2 flex justify-center> + <c-button :disabled="!textFromBinary" @click="copyText()"> + Copy text to clipboard + </c-button> + </div> + </c-card> +</template> |