From fe349ad69b6a14e0f4b56bef12a6d800c7e6fa1f Mon Sep 17 00:00:00 2001 From: sharevb Date: Sun, 3 Mar 2024 11:37:09 +0100 Subject: [PATCH 1/5] feat(new tool): ascii art generator (#886) * feat(new tool): ascii art generator Fix #829 ; Text ASCII Art Generator (using figlet) * fix: make fonts list searchable * refactor(ascii-generator): updated tool definition * refactor(ascii-generator): equilibrate ui --------- Co-authored-by: Corentin Thomasset --- components.d.ts | 30 +----- package.json | 2 + pnpm-lock.yaml | 16 ++++ .../ascii-text-drawer/ascii-text-drawer.vue | 93 +++++++++++++++++++ src/tools/ascii-text-drawer/index.ts | 12 +++ src/tools/index.ts | 14 ++- 6 files changed, 139 insertions(+), 28 deletions(-) create mode 100644 src/tools/ascii-text-drawer/ascii-text-drawer.vue create mode 100644 src/tools/ascii-text-drawer/index.ts diff --git a/components.d.ts b/components.d.ts index fabbe793..e31119b3 100644 --- a/components.d.ts +++ b/components.d.ts @@ -12,6 +12,7 @@ declare module '@vue/runtime-core' { '404.page': typeof import('./src/pages/404.page.vue')['default'] About: typeof import('./src/pages/About.vue')['default'] App: typeof import('./src/App.vue')['default'] + AsciiTextDrawer: typeof import('./src/tools/ascii-text-drawer/ascii-text-drawer.vue')['default'] 'Base.layout': typeof import('./src/layouts/base.layout.vue')['default'] Base64FileConverter: typeof import('./src/tools/base64-file-converter/base64-file-converter.vue')['default'] Base64StringConverter: typeof import('./src/tools/base64-string-converter/base64-string-converter.vue')['default'] @@ -88,28 +89,17 @@ declare module '@vue/runtime-core' { HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default'] IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.vue')['default'] 'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default'] - 'IconMdi:contentCopy': typeof import('~icons/mdi/content-copy')['default'] 'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default'] - IconMdiArrowDown: typeof import('~icons/mdi/arrow-down')['default'] - IconMdiArrowRightBottom: typeof import('~icons/mdi/arrow-right-bottom')['default'] - IconMdiCamera: typeof import('~icons/mdi/camera')['default'] IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default'] IconMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default'] IconMdiClose: typeof import('~icons/mdi/close')['default'] IconMdiContentCopy: typeof import('~icons/mdi/content-copy')['default'] - IconMdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default'] - IconMdiDownload: typeof import('~icons/mdi/download')['default'] IconMdiEye: typeof import('~icons/mdi/eye')['default'] IconMdiEyeOff: typeof import('~icons/mdi/eye-off')['default'] IconMdiHeart: typeof import('~icons/mdi/heart')['default'] - IconMdiPause: typeof import('~icons/mdi/pause')['default'] - IconMdiPlay: typeof import('~icons/mdi/play')['default'] - IconMdiRecord: typeof import('~icons/mdi/record')['default'] - IconMdiRefresh: typeof import('~icons/mdi/refresh')['default'] IconMdiSearch: typeof import('~icons/mdi/search')['default'] IconMdiTranslate: typeof import('~icons/mdi/translate')['default'] IconMdiTriangleDown: typeof import('~icons/mdi/triangle-down')['default'] - IconMdiVideo: typeof import('~icons/mdi/video')['default'] InputCopyable: typeof import('./src/components/InputCopyable.vue')['default'] IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default'] Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default'] @@ -136,39 +126,25 @@ declare module '@vue/runtime-core' { MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] - NAlert: typeof import('naive-ui')['NAlert'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] - NCheckbox: typeof import('naive-ui')['NCheckbox'] NCode: typeof import('naive-ui')['NCode'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] - NColorPicker: typeof import('naive-ui')['NColorPicker'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] - NDatePicker: typeof import('naive-ui')['NDatePicker'] NDivider: typeof import('naive-ui')['NDivider'] - NDynamicInput: typeof import('naive-ui')['NDynamicInput'] NEllipsis: typeof import('naive-ui')['NEllipsis'] - NForm: typeof import('naive-ui')['NForm'] NFormItem: typeof import('naive-ui')['NFormItem'] NGi: typeof import('naive-ui')['NGi'] NGrid: typeof import('naive-ui')['NGrid'] NH1: typeof import('naive-ui')['NH1'] - NH2: typeof import('naive-ui')['NH2'] NH3: typeof import('naive-ui')['NH3'] NIcon: typeof import('naive-ui')['NIcon'] - NImage: typeof import('naive-ui')['NImage'] - NInputGroup: typeof import('naive-ui')['NInputGroup'] - NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel'] NInputNumber: typeof import('naive-ui')['NInputNumber'] + NLabel: typeof import('naive-ui')['NLabel'] NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] - NProgress: typeof import('naive-ui')['NProgress'] NScrollbar: typeof import('naive-ui')['NScrollbar'] - NSlider: typeof import('naive-ui')['NSlider'] - NStatistic: typeof import('naive-ui')['NStatistic'] - NSwitch: typeof import('naive-ui')['NSwitch'] - NTable: typeof import('naive-ui')['NTable'] - NTag: typeof import('naive-ui')['NTag'] + NSpin: typeof import('naive-ui')['NSpin'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] diff --git a/package.json b/package.json index 65f29dbd..fd6c02e6 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@tiptap/pm": "2.1.6", "@tiptap/starter-kit": "2.1.6", "@tiptap/vue-3": "2.0.3", + "@types/figlet": "^1.5.8", "@vicons/material": "^0.12.0", "@vicons/tabler": "^0.12.0", "@vueuse/core": "^10.3.0", @@ -57,6 +58,7 @@ "date-fns": "^2.29.3", "dompurify": "^3.0.6", "emojilib": "^3.0.10", + "figlet": "^1.7.0", "figue": "^1.2.0", "fuse.js": "^6.6.2", "highlight.js": "^11.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a6f7c32f..bd6c38c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: '@tiptap/vue-3': specifier: 2.0.3 version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.6)(vue@3.3.4) + '@types/figlet': + specifier: ^1.5.8 + version: 1.5.8 '@vicons/material': specifier: ^0.12.0 version: 0.12.0 @@ -71,6 +74,9 @@ dependencies: emojilib: specifier: ^3.0.10 version: 3.0.10 + figlet: + specifier: ^1.7.0 + version: 1.7.0 figue: specifier: ^1.2.0 version: 1.2.0 @@ -2902,6 +2908,10 @@ packages: /@types/estree@1.0.0: resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + /@types/figlet@1.5.8: + resolution: {integrity: sha512-G22AUvy4Tl95XLE7jmUM8s8mKcoz+Hr+Xm9W90gJsppJq9f9tHvOGkrpn4gRX0q/cLtBdNkWtWCKDg2UDZoZvQ==} + dev: false + /@types/fs-extra@11.0.1: resolution: {integrity: sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==} dependencies: @@ -5585,6 +5595,12 @@ packages: web-streams-polyfill: 3.2.1 dev: true + /figlet@1.7.0: + resolution: {integrity: sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==} + engines: {node: '>= 0.4.0'} + hasBin: true + dev: false + /figue@1.2.0: resolution: {integrity: sha512-CXKr12kiNWjKtUK3X+YHeXKepn80s9Rg6pgZXoLQYEybgwaGJ9uGW4DrBrVK30ZWZf1mcvTbXF56AcovG7gLVw==} dependencies: diff --git a/src/tools/ascii-text-drawer/ascii-text-drawer.vue b/src/tools/ascii-text-drawer/ascii-text-drawer.vue new file mode 100644 index 00000000..9a6520a4 --- /dev/null +++ b/src/tools/ascii-text-drawer/ascii-text-drawer.vue @@ -0,0 +1,93 @@ + + + diff --git a/src/tools/ascii-text-drawer/index.ts b/src/tools/ascii-text-drawer/index.ts new file mode 100644 index 00000000..cc1ba86c --- /dev/null +++ b/src/tools/ascii-text-drawer/index.ts @@ -0,0 +1,12 @@ +import { Artboard } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'ASCII Art Text Generator', + path: '/ascii-text-drawer', + description: 'Create ASCII art text with many fonts and styles.', + keywords: ['ascii', 'asciiart', 'text', 'drawer'], + component: () => import('./ascii-text-drawer.vue'), + icon: Artboard, + createdAt: new Date('2024-03-03'), +}); diff --git a/src/tools/index.ts b/src/tools/index.ts index 2a477ed2..492ec6f5 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,7 +1,11 @@ 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 asciiTextDrawer } from './ascii-text-drawer'; + import { tool as textToUnicode } from './text-to-unicode'; + import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as numeronymGenerator } from './numeronym-generator'; import { tool as macAddressGenerator } from './mac-address-generator'; @@ -159,7 +163,15 @@ export const toolsByCategory: ToolCategory[] = [ }, { name: 'Text', - components: [loremIpsumGenerator, textStatistics, emojiPicker, stringObfuscator, textDiff, numeronymGenerator], + components: [ + loremIpsumGenerator, + textStatistics, + emojiPicker, + stringObfuscator, + textDiff, + numeronymGenerator, + asciiTextDrawer, + ], }, { name: 'Data', From d3b32cc14ee127f2a996c5ab0957e20ddc36dd5e Mon Sep 17 00:00:00 2001 From: sharevb Date: Mon, 11 Mar 2024 11:19:32 +0100 Subject: [PATCH 2/5] feat(new tool): Outlook Safelink Decoder (#911) * feat(new tool): Outlook Safelink Decoder Fix #897 * Use native URL parsing Co-authored-by: Corentin THOMASSET * Update src/tools/safelink-decoder/index.ts --------- Co-authored-by: Corentin THOMASSET --- src/tools/index.ts | 3 +- src/tools/safelink-decoder/index.ts | 12 +++++++ .../safelink-decoder.service.test.ts | 21 ++++++++++++ .../safelink-decoder.service.ts | 7 ++++ .../safelink-decoder/safelink-decoder.vue | 32 +++++++++++++++++++ 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/tools/safelink-decoder/index.ts create mode 100644 src/tools/safelink-decoder/safelink-decoder.service.test.ts create mode 100644 src/tools/safelink-decoder/safelink-decoder.service.ts create mode 100644 src/tools/safelink-decoder/safelink-decoder.vue diff --git a/src/tools/index.ts b/src/tools/index.ts index 492ec6f5..aa861c93 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -5,7 +5,7 @@ import { tool as basicAuthGenerator } from './basic-auth-generator'; import { tool as asciiTextDrawer } from './ascii-text-drawer'; import { tool as textToUnicode } from './text-to-unicode'; - +import { tool as safelinkDecoder } from './safelink-decoder'; import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as numeronymGenerator } from './numeronym-generator'; import { tool as macAddressGenerator } from './mac-address-generator'; @@ -127,6 +127,7 @@ export const toolsByCategory: ToolCategory[] = [ userAgentParser, httpStatusCodes, jsonDiff, + safelinkDecoder, ], }, { diff --git a/src/tools/safelink-decoder/index.ts b/src/tools/safelink-decoder/index.ts new file mode 100644 index 00000000..ef865108 --- /dev/null +++ b/src/tools/safelink-decoder/index.ts @@ -0,0 +1,12 @@ +import { Mailbox } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Outlook Safelink decoder', + path: '/safelink-decoder', + description: 'Decode Outlook SafeLink links', + keywords: ['outlook', 'safelink', 'decoder'], + component: () => import('./safelink-decoder.vue'), + icon: Mailbox, + createdAt: new Date('2024-03-11'), +}); diff --git a/src/tools/safelink-decoder/safelink-decoder.service.test.ts b/src/tools/safelink-decoder/safelink-decoder.service.test.ts new file mode 100644 index 00000000..b601f01e --- /dev/null +++ b/src/tools/safelink-decoder/safelink-decoder.service.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest'; +import { decodeSafeLinksURL } from './safelink-decoder.service'; + +describe('safelink-decoder', () => { + describe('decodeSafeLinksURL', () => { + describe('decode outlook safelink urls', () => { + it('should decode basic safelink urls', () => { + expect(decodeSafeLinksURL('https://aus01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3Dsafelink%26rlz%3D1&data=05%7C02%7C%7C1ed07253975b46da1d1508dc3443752a%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638442711583216725%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=%2BQY0HBnnxfI7pzZoxzlhZdDvYu80LwQB0zUUjrffVnk%3D&reserved=0')) + .toBe('https://www.google.com/search?q=safelink&rlz=1'); + }); + it('should decode encoded safelink urls', () => { + expect(decodeSafeLinksURL('https://aus01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3Dsafelink%26rlz%3D1&data=05%7C02%7C%7C1ed07253975b46da1d1508dc3443752a%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638442711583216725%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=%2BQY0HBnnxfI7pzZoxzlhZdDvYu80LwQB0zUUjrffVnk%3D&reserved=0')) + .toBe('https://www.google.com/search?q=safelink&rlz=1'); + }); + it('throw on not outlook safelink urls', () => { + expect(() => decodeSafeLinksURL('https://google.com')) + .toThrow('Invalid SafeLinks URL provided'); + }); + }); + }); +}); diff --git a/src/tools/safelink-decoder/safelink-decoder.service.ts b/src/tools/safelink-decoder/safelink-decoder.service.ts new file mode 100644 index 00000000..96be00ab --- /dev/null +++ b/src/tools/safelink-decoder/safelink-decoder.service.ts @@ -0,0 +1,7 @@ +export function decodeSafeLinksURL(safeLinksUrl: string) { + if (!safeLinksUrl.match(/\.safelinks\.protection\.outlook\.com/)) { + throw new Error('Invalid SafeLinks URL provided'); + } + + return new URL(safeLinksUrl).searchParams.get('url'); +} diff --git a/src/tools/safelink-decoder/safelink-decoder.vue b/src/tools/safelink-decoder/safelink-decoder.vue new file mode 100644 index 00000000..01337eb2 --- /dev/null +++ b/src/tools/safelink-decoder/safelink-decoder.vue @@ -0,0 +1,32 @@ + + + From 23f82d956a8af21e176f7268c9414244168bd4eb Mon Sep 17 00:00:00 2001 From: sharevb Date: Mon, 15 Apr 2024 09:43:12 +0200 Subject: [PATCH 3/5] fix(bcrypt tool): allow salt rounds up to 100 (#987) * fix(bcrypt tool): allow salt rounds up to 100 Previously max salt rounds was 10 * chore(github workflows): ci and e2e tests: try updating to node 20 --- .github/workflows/ci.yml | 2 +- .github/workflows/e2e-tests.yml | 2 +- playwright.config.ts | 4 ++-- src/tools/bcrypt/bcrypt.vue | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5c67208..4dd9ffb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - run: corepack enable - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 20 cache: 'pnpm' - name: Install dependencies diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index b5b04096..13b787ef 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 20 cache: 'pnpm' - name: Get Playwright version diff --git a/playwright.config.ts b/playwright.config.ts index 3caa0612..5257c526 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -9,7 +9,7 @@ const useWebServer = process.env.NO_WEB_SERVER !== 'true'; */ export default defineConfig({ testDir: './src', - testMatch: /.*\.e2e\.(spec\.)?ts/, + testMatch: /\.e2e\.(spec\.)?ts$/, /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ @@ -57,7 +57,7 @@ export default defineConfig({ && { webServer: { command: 'npm run preview', - url: 'http://127.0.0.1:5050', + url: 'http://localhost:5050', reuseExistingServer: !isCI, }, } diff --git a/src/tools/bcrypt/bcrypt.vue b/src/tools/bcrypt/bcrypt.vue index c28c20bf..d4881299 100644 --- a/src/tools/bcrypt/bcrypt.vue +++ b/src/tools/bcrypt/bcrypt.vue @@ -28,7 +28,7 @@ const compareMatch = computed(() => compareSync(compareString.value, compareHash mb-2 /> - + From 9eac9cb2a9d23619b0d3c044f1bc1385aab427e4 Mon Sep 17 00:00:00 2001 From: sharevb Date: Mon, 22 Apr 2024 08:45:51 +0200 Subject: [PATCH 4/5] fix(integer base converter): support bigint (#872) --- .../integer-base-converter.model.test.ts | 3 +++ .../integer-base-converter.model.ts | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/tools/integer-base-converter/integer-base-converter.model.test.ts b/src/tools/integer-base-converter/integer-base-converter.model.test.ts index d0387b64..c7d7db79 100644 --- a/src/tools/integer-base-converter/integer-base-converter.model.test.ts +++ b/src/tools/integer-base-converter/integer-base-converter.model.test.ts @@ -11,6 +11,9 @@ describe('integer-base-converter', () => { expect(convertBase({ value: '10100101', fromBase: 2, toBase: 16 })).toEqual('a5'); expect(convertBase({ value: '192654', fromBase: 10, toBase: 8 })).toEqual('570216'); expect(convertBase({ value: 'zz', fromBase: 64, toBase: 10 })).toEqual('2275'); + expect(convertBase({ value: '42540766411283223938465490632011909384', fromBase: 10, toBase: 10 })).toEqual('42540766411283223938465490632011909384'); + expect(convertBase({ value: '42540766411283223938465490632011909384', fromBase: 10, toBase: 16 })).toEqual('20010db8000085a300000000ac1f8908'); + expect(convertBase({ value: '20010db8000085a300000000ac1f8908', fromBase: 16, toBase: 10 })).toEqual('42540766411283223938465490632011909384'); }); }); }); diff --git a/src/tools/integer-base-converter/integer-base-converter.model.ts b/src/tools/integer-base-converter/integer-base-converter.model.ts index b4470e57..da0fe77f 100644 --- a/src/tools/integer-base-converter/integer-base-converter.model.ts +++ b/src/tools/integer-base-converter/integer-base-converter.model.ts @@ -5,16 +5,16 @@ export function convertBase({ value, fromBase, toBase }: { value: string; fromBa let decValue = value .split('') .reverse() - .reduce((carry: number, digit: string, index: number) => { + .reduce((carry: bigint, digit: string, index: number) => { if (!fromRange.includes(digit)) { throw new Error(`Invalid digit "${digit}" for base ${fromBase}.`); } - return (carry += fromRange.indexOf(digit) * fromBase ** index); - }, 0); + return (carry += BigInt(fromRange.indexOf(digit)) * BigInt(fromBase) ** BigInt(index)); + }, 0n); let newValue = ''; while (decValue > 0) { - newValue = toRange[decValue % toBase] + newValue; - decValue = (decValue - (decValue % toBase)) / toBase; + newValue = toRange[Number(decValue % BigInt(toBase))] + newValue; + decValue = (decValue - (decValue % BigInt(toBase))) / BigInt(toBase); } return newValue || '0'; } From cb5b462e119d4231b5c07b4ef0ca24ec84ceee8b Mon Sep 17 00:00:00 2001 From: Pavel Gordon Date: Mon, 29 Apr 2024 11:58:08 +0200 Subject: [PATCH 5/5] fix(url-encoder, validation): typo in validation of url-encoder.vue #1024 --- src/tools/url-encoder/url-encoder.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/url-encoder/url-encoder.vue b/src/tools/url-encoder/url-encoder.vue index c43f8193..19025190 100644 --- a/src/tools/url-encoder/url-encoder.vue +++ b/src/tools/url-encoder/url-encoder.vue @@ -23,7 +23,7 @@ const decodeInput = ref('Hello%20world%20%3A)'); const decodeOutput = computed(() => withDefaultOnError(() => decodeURIComponent(decodeInput.value), '')); const decodeValidation = useValidation({ - source: encodeInput, + source: decodeInput, rules: [ { validator: value => isNotThrowing(() => decodeURIComponent(value)),