aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/index.ts6
-rw-r--r--src/tools/url-encoder/index.ts11
-rw-r--r--src/tools/url-encoder/url-encoder.vue100
3 files changed, 117 insertions, 0 deletions
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 7350523..7cfa07e 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -10,6 +10,7 @@ import { tool as bip39 } from './bip39-generator';
import { tool as dateTimeConverter } from './date-time-converter';
import { tool as gitMemo } from './git-memo';
import { tool as baseConverter } from './integer-base-converter';
+import { tool as urlEncoder } from './url-encoder';
export const toolsByCategory: ToolCategory[] = [
{
@@ -23,6 +24,11 @@ export const toolsByCategory: ToolCategory[] = [
components: [dateTimeConverter, baseConverter, romanNumeralConverter],
},
{
+ name: 'Web',
+ icon: LockOpen,
+ components: [urlEncoder],
+ },
+ {
name: 'Development',
icon: LockOpen,
components: [gitMemo],
diff --git a/src/tools/url-encoder/index.ts b/src/tools/url-encoder/index.ts
new file mode 100644
index 0000000..a748124
--- /dev/null
+++ b/src/tools/url-encoder/index.ts
@@ -0,0 +1,11 @@
+import { Link } from '@vicons/tabler';
+import type { ITool } from '../Tool';
+
+export const tool: ITool = {
+ name: 'Encode/decode url formatted strings',
+ path: '/url-encoder',
+ description: 'Encode to url-encoded format (also known as "percent-encoded") or decode from it.',
+ keywords: ['url', 'encode', 'decode', 'percent', '%20', 'format'],
+ component: () => import('./url-encoder.vue'),
+ icon: Link,
+};
diff --git a/src/tools/url-encoder/url-encoder.vue b/src/tools/url-encoder/url-encoder.vue
new file mode 100644
index 0000000..221184d
--- /dev/null
+++ b/src/tools/url-encoder/url-encoder.vue
@@ -0,0 +1,100 @@
+<template>
+ <n-space item-style="flex:1">
+ <n-card title="Encode">
+ <n-form-item label="Your string :" :feedback="encodedValidation.message"
+ :validation-status="encodedValidation.status">
+ <n-input v-model:value="encodeInput" type="textarea" placeholder="The string to encode"
+ :autosize="{ minRows: 3 }" />
+ </n-form-item>
+
+ <n-form-item label="Your string encoded :">
+ <n-input :value="encodeOutput" type="textarea" readonly placeholder="Your string encoded"
+ :autosize="{ minRows: 3 }" />
+ </n-form-item>
+
+ <n-space justify="center">
+ <n-button @click="copyEncoded" secondary>Copy</n-button>
+ </n-space>
+ </n-card>
+ <n-card title="Encode">
+ <n-form-item label="Your encode string :" :feedback="decodeValidation.message"
+ :validation-status="decodeValidation.status">
+ <n-input v-model:value="decodeInput" type="textarea" placeholder="The string to decode"
+ :autosize="{ minRows: 3 }" />
+ </n-form-item>
+
+ <n-form-item label="Your string decoded :">
+ <n-input :value="decodeOutput" type="textarea" readonly placeholder="Your string decoded"
+ :autosize="{ minRows: 3 }" />
+ </n-form-item>
+
+ <n-space justify="center">
+ <n-button @click="copyDecoded" secondary>Copy</n-button>
+ </n-space>
+ </n-card>
+ </n-space>
+</template>
+
+<script setup lang="ts">
+import { useCopy } from '@/composable/copy';
+import { useValidation } from '@/composable/validation';
+import { computed, ref } from 'vue'
+
+const encodeInput = ref('Hello world :)')
+const encodeOutput = computed(() => {
+ try {
+ return encodeURIComponent(encodeInput.value)
+ } catch (_) {
+ return ''
+ }
+})
+
+const encodedValidation = useValidation({
+ source: encodeInput, rules: [{
+ validator: (value) => {
+ try {
+ encodeURIComponent(value)
+ return true
+ } catch (_) {
+ return false
+ }
+ },
+ message: 'Impossible to parse this string'
+ }]
+})
+
+const { copy: copyEncoded } = useCopy({ source: encodeOutput, text: 'Encoded string copied to the clipboard' })
+
+
+const decodeInput = ref('Hello%20world%20%3A)')
+
+const decodeOutput = computed(() => {
+ try {
+ return decodeURIComponent(decodeInput.value)
+ } catch (_) {
+ return ''
+ }
+})
+
+const decodeValidation = useValidation({
+ source: encodeInput, rules: [{
+ validator: (value) => {
+ try {
+ decodeURIComponent(value)
+ return true
+ } catch (_) {
+ return false
+ }
+ },
+ message: 'Impossible to parse this string'
+ }]
+})
+
+const { copy: copyDecoded } = useCopy({ source: decodeOutput, text: 'Decoded string copied to the clipboard' })
+
+
+
+</script>
+
+<style lang="scss" scoped>
+</style> \ No newline at end of file