diff --git a/src/tools/otp-code-generator-and-validator/token-display.vue b/src/tools/otp-code-generator-and-validator/token-display.vue
index 5313b0be..317f0831 100644
--- a/src/tools/otp-code-generator-and-validator/token-display.vue
+++ b/src/tools/otp-code-generator-and-validator/token-display.vue
@@ -11,7 +11,7 @@ const { tokens } = toRefs(props);
-
+
Previous
@@ -22,60 +22,24 @@ const { tokens } = toRefs(props);
Next
-
-
-
-
- {{ tokens.previous }}
-
-
- {{ previousCopied ? 'Copied !' : 'Copy previous OTP' }}
-
-
-
-
- {{ tokens.current }}
-
-
- {{ currentCopied ? 'Copied !' : 'Copy current OTP' }}
-
-
-
-
- {{
- tokens.next
- }}
-
-
- {{ nextCopied ? 'Copied !' : 'Copy next OTP' }}
-
-
+
+
+
+ {{ tokens.previous }}
+
+
+
+
+ {{ tokens.current }}
+
+
+
+
+ {{ tokens.next }}
+
+
+
-
-
diff --git a/src/tools/pdf-signature-checker/components/pdf-signature-details.vue b/src/tools/pdf-signature-checker/components/pdf-signature-details.vue
new file mode 100644
index 00000000..c39f6168
--- /dev/null
+++ b/src/tools/pdf-signature-checker/components/pdf-signature-details.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
diff --git a/src/tools/pdf-signature-checker/index.ts b/src/tools/pdf-signature-checker/index.ts
new file mode 100644
index 00000000..54563979
--- /dev/null
+++ b/src/tools/pdf-signature-checker/index.ts
@@ -0,0 +1,12 @@
+import { defineTool } from '../tool';
+import FileCertIcon from '~icons/mdi/file-certificate-outline';
+
+export const tool = defineTool({
+ name: 'PDF signature checker',
+ path: '/pdf-signature-checker',
+ description: 'Verify the signatures of a PDF file. A signed PDF file contains one or more signatures that may be used to determine whether the contents of the file have been altered since the file was signed.',
+ keywords: ['pdf', 'signature', 'checker', 'verify', 'validate', 'sign'],
+ component: () => import('./pdf-signature-checker.vue'),
+ icon: FileCertIcon,
+ createdAt: new Date('2023-12-09'),
+});
diff --git a/src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts b/src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts
new file mode 100644
index 00000000..8e9a2870
--- /dev/null
+++ b/src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts
@@ -0,0 +1,11 @@
+import { expect, test } from '@playwright/test';
+
+test.describe('Tool - Pdf signature checker', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto('/pdf-signature-checker');
+ });
+
+ test('Has correct title', async ({ page }) => {
+ await expect(page).toHaveTitle('PDF signature checker - IT Tools');
+ });
+});
diff --git a/src/tools/pdf-signature-checker/pdf-signature-checker.types.ts b/src/tools/pdf-signature-checker/pdf-signature-checker.types.ts
new file mode 100644
index 00000000..6932509c
--- /dev/null
+++ b/src/tools/pdf-signature-checker/pdf-signature-checker.types.ts
@@ -0,0 +1,39 @@
+export interface SignatureInfo {
+ verified: boolean
+ authenticity: boolean
+ integrity: boolean
+ expired: boolean
+ meta: {
+ certs: {
+ clientCertificate?: boolean
+ issuedBy: {
+ commonName: string
+ organizationalUnitName?: string
+ organizationName: string
+ countryName?: string
+ localityName?: string
+ stateOrProvinceName?: string
+ }
+ issuedTo: {
+ commonName: string
+ serialNumber?: string
+ organizationalUnitName?: string
+ organizationName: string
+ countryName?: string
+ localityName?: string
+ stateOrProvinceName?: string
+ }
+ validityPeriod: {
+ notBefore: string
+ notAfter: string
+ }
+ pemCertificate: string
+ }[]
+ signatureMeta: {
+ reason: string
+ contactInfo: string | null
+ location: string
+ name: string | null
+ }
+ }
+}
diff --git a/src/tools/pdf-signature-checker/pdf-signature-checker.vue b/src/tools/pdf-signature-checker/pdf-signature-checker.vue
new file mode 100644
index 00000000..02206164
--- /dev/null
+++ b/src/tools/pdf-signature-checker/pdf-signature-checker.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+
+ {{ formatBytes(file.size) }}
+
+
+
+
+
+ No signatures found in the provided file.
+
+
+
+
+
+
+
+
+ Signature {{ index + 1 }} certificates :
+
+
+
+
+
+
diff --git a/src/tools/text-to-binary/index.ts b/src/tools/text-to-binary/index.ts
new file mode 100644
index 00000000..40ac93d6
--- /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 00000000..2b4e4313
--- /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 00000000..e4269b50
--- /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 00000000..ad9699af
--- /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 00000000..37aa9bea
--- /dev/null
+++ b/src/tools/text-to-binary/text-to-binary.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+ Copy binary to clipboard
+
+
+
+
+
+
+
+
+
+ Copy text to clipboard
+
+
+
+
diff --git a/src/tools/token-generator/index.ts b/src/tools/token-generator/index.ts
index bed5f009..44923e79 100644
--- a/src/tools/token-generator/index.ts
+++ b/src/tools/token-generator/index.ts
@@ -1,12 +1,12 @@
import { ArrowsShuffle } from '@vicons/tabler';
import { defineTool } from '../tool';
+import { translate } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'Token generator',
+ name: translate('tools.token-generator.title'),
path: '/token-generator',
- description:
- 'Generate random string with the chars you want: uppercase or lowercase letters, numbers and/or symbols.',
- keywords: ['token', 'random', 'string', 'alphanumeric', 'symbols', 'number', 'letters', 'lowercase', 'uppercase'],
+ description: translate('tools.token-generator.description'),
+ keywords: ['token', 'random', 'string', 'alphanumeric', 'symbols', 'number', 'letters', 'lowercase', 'uppercase', 'password'],
component: () => import('./token-generator.tool.vue'),
icon: ArrowsShuffle,
});
diff --git a/src/tools/token-generator/locales/en.yml b/src/tools/token-generator/locales/en.yml
index c2c03232..7a06f3dd 100644
--- a/src/tools/token-generator/locales/en.yml
+++ b/src/tools/token-generator/locales/en.yml
@@ -6,4 +6,10 @@ tools:
uppercase: Uppercase (ABC...)
lowercase: Lowercase (abc...)
numbers: Numbers (123...)
- symbols: Symbols (!-;...)
\ No newline at end of file
+ symbols: Symbols (!-;...)
+ length: Length
+ tokenPlaceholder: 'The token...'
+ copied: Token copied to the clipboard
+ button:
+ copy: Copy
+ refresh: Refresh
\ No newline at end of file
diff --git a/src/tools/token-generator/locales/fr.yml b/src/tools/token-generator/locales/fr.yml
index e5f40d4d..e9605567 100644
--- a/src/tools/token-generator/locales/fr.yml
+++ b/src/tools/token-generator/locales/fr.yml
@@ -1,9 +1,16 @@
tools:
token-generator:
title: Générateur de token
- description: Génère une chaîne aléatoire avec les caractères que vous voulez, lettres majuscules ou minuscules, chiffres et/ou symboles.
-
+ description: >-
+ Génère une chaîne aléatoire avec les caractères que vous voulez, lettres
+ majuscules ou minuscules, chiffres et/ou symboles.
uppercase: Majuscules (ABC...)
lowercase: Minuscules (abc...)
numbers: Chiffres (123...)
symbols: Symboles (!-;...)
+ button:
+ copy: Copier
+ refresh: Rafraichir
+ copied: Le token a été copié
+ length: Longueur
+ tokenPlaceholder: Le token...
diff --git a/src/tools/token-generator/token-generator.tool.vue b/src/tools/token-generator/token-generator.tool.vue
index 1019a83b..fe53edcd 100644
--- a/src/tools/token-generator/token-generator.tool.vue
+++ b/src/tools/token-generator/token-generator.tool.vue
@@ -21,7 +21,7 @@ const [token, refreshToken] = computedRefreshable(() =>
}),
);
-const { copy } = useCopy({ source: token, text: 'Token copied to the clipboard' });
+const { copy } = useCopy({ source: token, text: t('tools.token-generator.copied') });
@@ -51,14 +51,14 @@ const { copy } = useCopy({ source: token, text: 'Token copied to the clipboard'