Merge remote-tracking branch 'origin/main' into feat/regex-tester

This commit is contained in:
ShareVB 2024-09-04 21:59:50 +02:00
commit f1f2da79c0
12 changed files with 284 additions and 110 deletions

View file

@ -0,0 +1,65 @@
<script setup lang="ts">
import { normalizeEmail } from 'email-normalizer';
import { withDefaultOnError } from '@/utils/defaults';
import { useCopy } from '@/composable/copy';
const emails = ref('');
const normalizedEmails = computed(() => {
if (!emails.value) {
return '';
}
return emails.value
.split('\n')
.map((email) => {
return withDefaultOnError(() => normalizeEmail({ email }), `Unable to parse email: ${email}`);
})
.join('\n');
});
const { copy } = useCopy({ source: normalizedEmails, text: 'Normalized emails copied to the clipboard', createToast: true });
</script>
<template>
<div>
<div class="mb-2">
Raw emails to normalize:
</div>
<c-input-text
v-model:value="emails"
placeholder="Put your emails here (one per line)..."
rows="3"
multiline
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
autofocus
monospace
/>
<div class="mb-2 mt-4">
Normalized emails:
</div>
<c-input-text
:value="normalizedEmails"
placeholder="Normalized emails will appear here..."
rows="3"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
multiline
readonly
monospace
/>
<div class="mt-4 flex justify-center gap-2">
<c-button @click="emails = ''">
Clear emails
</c-button>
<c-button :disabled="!normalizedEmails" @click="copy()">
Copy normalized emails
</c-button>
</div>
</div>
</template>

View file

@ -0,0 +1,12 @@
import { Mail } from '@vicons/tabler';
import { defineTool } from '../tool';
export const tool = defineTool({
name: 'Email normalizer',
path: '/email-normalizer',
description: 'Normalize email addresses to a standard format for easier comparison. Useful for deduplication and data cleaning.',
keywords: ['email', 'normalizer'],
component: () => import('./email-normalizer.vue'),
icon: Mail,
createdAt: new Date('2024-08-15'),
});

View file

@ -1,11 +1,14 @@
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 emailNormalizer } from './email-normalizer';
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 xmlToJson } from './xml-to-json';
import { tool as jsonToXml } from './json-to-xml';
import { tool as regexTester } from './regex-tester';
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
import { tool as numeronymGenerator } from './numeronym-generator';
@ -108,6 +111,8 @@ export const toolsByCategory: ToolCategory[] = [
listConverter,
tomlToJson,
tomlToYaml,
xmlToJson,
jsonToXml,
],
},
{
@ -149,6 +154,7 @@ export const toolsByCategory: ToolCategory[] = [
dockerRunToDockerComposeConverter,
xmlFormatter,
yamlViewer,
emailNormalizer,
regexTester,
],
},

View file

@ -0,0 +1,12 @@
import { Braces } from '@vicons/tabler';
import { defineTool } from '../tool';
export const tool = defineTool({
name: 'JSON to XML',
path: '/json-to-xml',
description: 'Convert JSON to XML',
keywords: ['json', 'xml'],
component: () => import('./json-to-xml.vue'),
icon: Braces,
createdAt: new Date('2024-08-09'),
});

View file

@ -0,0 +1,32 @@
<script setup lang="ts">
import convert from 'xml-js';
import JSON5 from 'json5';
import { withDefaultOnError } from '@/utils/defaults';
import type { UseValidationRule } from '@/composable/validation';
const defaultValue = '{"a":{"_attributes":{"x":"1.234","y":"It\'s"}}}';
function transformer(value: string) {
return withDefaultOnError(() => {
return convert.js2xml(JSON5.parse(value), { compact: true });
}, '');
}
const rules: UseValidationRule<string>[] = [
{
validator: (v: string) => v === '' || JSON5.parse(v),
message: 'Provided JSON is not valid.',
},
];
</script>
<template>
<format-transformer
input-label="Your JSON content"
:input-default="defaultValue"
input-placeholder="Paste your JSON content here..."
output-label="Converted XML"
output-language="xml"
:transformer="transformer"
:input-validation-rules="rules"
/>
</template>

View file

@ -2,6 +2,7 @@
import { generateLoremIpsum } from './lorem-ipsum-generator.service';
import { useCopy } from '@/composable/copy';
import { randIntFromInterval } from '@/utils/random';
import { computedRefreshable } from '@/composable/computedRefreshable';
const paragraphs = ref(1);
const sentences = ref([3, 8]);
@ -9,7 +10,7 @@ const words = ref([8, 15]);
const startWithLoremIpsum = ref(true);
const asHTML = ref(false);
const loremIpsumText = computed(() =>
const [loremIpsumText, refreshLoremIpsum] = computedRefreshable(() =>
generateLoremIpsum({
paragraphCount: paragraphs.value,
asHTML: asHTML.value,
@ -18,6 +19,7 @@ const loremIpsumText = computed(() =>
startWithLoremIpsum: startWithLoremIpsum.value,
}),
);
const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to the clipboard' });
</script>
@ -41,10 +43,13 @@ const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to
<c-input-text :value="loremIpsumText" multiline placeholder="Your lorem ipsum..." readonly mt-5 rows="5" />
<div mt-5 flex justify-center>
<div mt-5 flex justify-center gap-3>
<c-button autofocus @click="copy()">
Copy
</c-button>
<c-button @click="refreshLoremIpsum">
Refresh
</c-button>
</div>
</c-card>
</template>

View file

@ -175,7 +175,7 @@ watchEffect(
<pre style="white-space: pre-wrap; word-break: break-all;">{{ sample }}</pre>
</c-card>
<c-card title="Regex Diagram" style="overflow-x: scroll;" mt-3>
<c-card title="Regex Diagram" style="overflow-x: scroll;" mt-3>
<svg ref="visualizerSVG" />
</c-card>
</div>

View file

@ -0,0 +1,12 @@
import { Braces } from '@vicons/tabler';
import { defineTool } from '../tool';
export const tool = defineTool({
name: 'XML to JSON',
path: '/xml-to-json',
description: 'Convert XML to JSON',
keywords: ['xml', 'json'],
component: () => import('./xml-to-json.vue'),
icon: Braces,
createdAt: new Date('2024-08-09'),
});

View file

@ -0,0 +1,32 @@
<script setup lang="ts">
import convert from 'xml-js';
import { isValidXML } from '../xml-formatter/xml-formatter.service';
import { withDefaultOnError } from '@/utils/defaults';
import type { UseValidationRule } from '@/composable/validation';
const defaultValue = '<a x="1.234" y="It\'s"/>';
function transformer(value: string) {
return withDefaultOnError(() => {
return JSON.stringify(convert.xml2js(value, { compact: true }), null, 2);
}, '');
}
const rules: UseValidationRule<string>[] = [
{
validator: isValidXML,
message: 'Provided XML is not valid.',
},
];
</script>
<template>
<format-transformer
input-label="Your XML content"
:input-default="defaultValue"
input-placeholder="Paste your XML content here..."
output-label="Converted JSON"
output-language="json"
:transformer="transformer"
:input-validation-rules="rules"
/>
</template>