feat(tool): nanoid generator

This commit is contained in:
Albert Asaftei 2024-05-31 16:02:24 +02:00
parent b430baef40
commit 2dbc8fadd6
8 changed files with 6818 additions and 5154 deletions

8
components.d.ts vendored
View file

@ -126,25 +126,33 @@ declare module '@vue/runtime-core' {
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.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'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
NAlert: typeof import('naive-ui')['NAlert']
NanoidGenerator: typeof import('./src/tools/nanoid-generator/nanoid-generator.vue')['default']
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
NCode: typeof import('naive-ui')['NCode'] NCode: typeof import('naive-ui')['NCode']
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDivider: typeof import('naive-ui')['NDivider'] NDivider: typeof import('naive-ui')['NDivider']
NEllipsis: typeof import('naive-ui')['NEllipsis'] NEllipsis: typeof import('naive-ui')['NEllipsis']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem'] NFormItem: typeof import('naive-ui')['NFormItem']
NGi: typeof import('naive-ui')['NGi'] NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid'] NGrid: typeof import('naive-ui')['NGrid']
NH1: typeof import('naive-ui')['NH1'] NH1: typeof import('naive-ui')['NH1']
NH3: typeof import('naive-ui')['NH3'] NH3: typeof import('naive-ui')['NH3']
NIcon: typeof import('naive-ui')['NIcon'] NIcon: typeof import('naive-ui')['NIcon']
NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
NInputNumber: typeof import('naive-ui')['NInputNumber'] NInputNumber: typeof import('naive-ui')['NInputNumber']
NLabel: typeof import('naive-ui')['NLabel'] NLabel: typeof import('naive-ui')['NLabel']
NLayout: typeof import('naive-ui')['NLayout'] NLayout: typeof import('naive-ui')['NLayout']
NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NLayoutSider: typeof import('naive-ui')['NLayoutSider']
NMenu: typeof import('naive-ui')['NMenu'] NMenu: typeof import('naive-ui')['NMenu']
NScrollbar: typeof import('naive-ui')['NScrollbar'] NScrollbar: typeof import('naive-ui')['NScrollbar']
NSlider: typeof import('naive-ui')['NSlider']
NSpin: typeof import('naive-ui')['NSpin'] NSpin: typeof import('naive-ui')['NSpin']
NSwitch: typeof import('naive-ui')['NSwitch']
NText: typeof import('naive-ui')['NText']
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] 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'] 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'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']

View file

@ -352,6 +352,22 @@ tools:
title: UUIDs generator title: UUIDs generator
description: A Universally Unique Identifier (UUID) is a 128-bit number used to identify information in computer systems. The number of possible UUIDs is 16^32, which is 2^128 or about 3.4x10^38 (which is a lot!). description: A Universally Unique Identifier (UUID) is a 128-bit number used to identify information in computer systems. The number of possible UUIDs is 16^32, which is 2^128 or about 3.4x10^38 (which is a lot!).
nanoid-generator:
title: NanoIDs generator
description: Generate random, unique, and URL-friendly IDs for your applications.
uppercase: Uppercase
lowercase: Lowercase
numbers: Numbers
symbols: Symbols
excludeLookalikes: Exclude lookalikes
length: Length
quantity: Quantity
copied: NanoID copied to the clipboard
button:
copy: Copy
refresh: Refresh
ipv4-address-converter: ipv4-address-converter:
title: IPv4 address converter title: IPv4 address converter
description: Convert an IP address into decimal, binary, hexadecimal, or even an IPv6 representation of it. description: Convert an IP address into decimal, binary, hexadecimal, or even an IPv6 representation of it.

View file

@ -74,6 +74,8 @@
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"monaco-editor": "^0.43.0", "monaco-editor": "^0.43.0",
"naive-ui": "^2.35.0", "naive-ui": "^2.35.0",
"nanoid": "^5.0.7",
"nanoid-dictionary": "^4.3.0",
"netmask": "^2.0.2", "netmask": "^2.0.2",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"oui-data": "^1.0.10", "oui-data": "^1.0.10",

11735
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
import { tool as base64FileConverter } from './base64-file-converter'; import { tool as base64FileConverter } from './base64-file-converter';
import { tool as base64StringConverter } from './base64-string-converter'; import { tool as base64StringConverter } from './base64-string-converter';
import { tool as basicAuthGenerator } from './basic-auth-generator'; import { tool as basicAuthGenerator } from './basic-auth-generator';
import { tool as nanoidGenerator } from './nanoid-generator';
import { tool as asciiTextDrawer } from './ascii-text-drawer'; import { tool as asciiTextDrawer } from './ascii-text-drawer';
@ -85,7 +86,7 @@ import { tool as yamlViewer } from './yaml-viewer';
export const toolsByCategory: ToolCategory[] = [ export const toolsByCategory: ToolCategory[] = [
{ {
name: 'Crypto', name: 'Crypto',
components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker], components: [tokenGenerator, hashText, bcrypt, uuidGenerator, nanoidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker],
}, },
{ {
name: 'Converter', name: 'Converter',

View file

@ -0,0 +1,13 @@
import { Fingerprint } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.nanoid-generator.title'),
path: '/nanoid-generator',
description: translate('tools.nanoid-generator.description'),
keywords: ['nanoid', 'generator'],
component: () => import('./nanoid-generator.vue'),
icon: Fingerprint,
createdAt: new Date('2024-05-31'),
});

View file

@ -0,0 +1,39 @@
import { customAlphabet, nanoid } from 'nanoid';
import { lowercase, nolookalikes, numbers, uppercase } from 'nanoid-dictionary';
const symbols = '-_';
export function createNanoid({
length = 21,
withLowercase = true,
withUppercase = true,
withNumbers = true,
withSymbols = true,
excludeLookalikes = false,
}: {
length?: number
withLowercase?: boolean
withUppercase?: boolean
withNumbers?: boolean
withSymbols?: boolean
excludeLookalikes?: boolean
}) {
let alphabet = '';
if (!withLowercase && !withUppercase && !withNumbers && !excludeLookalikes && !withSymbols) {
return nanoid(length);
}
if (excludeLookalikes) {
alphabet = [nolookalikes, withSymbols ? symbols : ''].join('');
}
alphabet = [
withLowercase ? lowercase : '',
withUppercase ? uppercase : '',
withNumbers ? numbers : '',
withSymbols ? symbols : '',
].join('');
return customAlphabet(alphabet, length);
}

View file

@ -0,0 +1,156 @@
<script setup lang="ts">
import { InfoCircle } from '@vicons/tabler';
import { createNanoid } from './nanoid-generator.service';
import { computedRefreshable } from '@/composable/computedRefreshable';
import { withDefaultOnError } from '@/utils/defaults';
import { useCopy } from '@/composable/copy';
import { useQueryParam } from '@/composable/queryParams';
const count = useQueryParam({ name: 'count', defaultValue: 1 });
const length = useQueryParam({ name: 'length', defaultValue: 21 });
const withUppercase = useQueryParam({ name: 'uppercase', defaultValue: true });
const withLowercase = useQueryParam({ name: 'lowercase', defaultValue: true });
const withNumbers = useQueryParam({ name: 'numbers', defaultValue: true });
const withSymbols = useQueryParam({ name: 'symbols', defaultValue: true });
const excludeLookalikes = useQueryParam({ name: 'no-lookalikes', defaultValue: false });
const { t } = useI18n();
const [nanoIds, refreshNanoIds] = computedRefreshable(() =>
withDefaultOnError(
() =>
Array.from({ length: count.value }, (_ignored) => {
const nanoId = createNanoid({
length: length.value,
withUppercase: withUppercase.value,
withLowercase: withLowercase.value,
withNumbers: withNumbers.value,
withSymbols: withSymbols.value,
excludeLookalikes: excludeLookalikes.value,
});
return nanoId();
}).join('\n'),
'',
),
);
const { copy } = useCopy({ source: nanoIds, text: 'NanoIds copied to the clipboard' });
</script>
<template>
<div>
<n-form label-placement="left" label-width="140">
<div mb-8 flex justify-center gap-8>
<div class="column">
<div>
<n-text>{{ t('tools.nanoid-generator.uppercase') }}</n-text>
<c-tooltip
tooltip="ABCDEFGHIJKLMNOPQRSTUVWXYZ" position="bottom"
>
<n-icon size="20" :component="InfoCircle" />
</c-tooltip>
<n-switch v-model:value="withUppercase" />
</div>
<div>
<n-text>{{ t('tools.nanoid-generator.lowercase') }}</n-text>
<c-tooltip
tooltip="abcdefghijklmnopqrstuvwxyz" position="bottom"
>
<n-icon size="20" :component="InfoCircle" />
</c-tooltip>
<n-switch v-model:value="withLowercase" />
</div>
</div>
<div class="column">
<div>
<n-text>
{{ t('tools.nanoid-generator.numbers') }}
</n-text>
<c-tooltip
tooltip="0123456789" position="bottom"
>
<n-icon size="20" :component="InfoCircle" />
</c-tooltip>
<n-switch v-model:value="withNumbers" />
</div>
<div>
<n-text>
{{ t('tools.nanoid-generator.symbols') }}
</n-text>
<c-tooltip
tooltip="-_" position="bottom"
>
<n-icon size="20" :component="InfoCircle" />
</c-tooltip>
<n-switch v-model:value="withSymbols" />
</div>
</div>
<div class="column">
<div>
<n-text>
{{ t('tools.nanoid-generator.excludeLookalikes') }}
</n-text>
<c-tooltip
tooltip="1lI0Oouv5Ss2Z" position="bottom"
>
<n-icon size="20" :component="InfoCircle" />
</c-tooltip>
<n-switch v-model:value="excludeLookalikes" />
</div>
</div>
</div>
</n-form>
<div mb-2 flex items-center>
<span w-100px>{{ t('tools.nanoid-generator.length') }}</span>
<n-input-number v-model:value="length" flex-1 :min="1" :max="100" placeholder="NanoId Length" />
</div>
<div mb-2 flex items-center>
<span w-100px>{{ t('tools.nanoid-generator.quantity') }}</span>
<n-input-number v-model:value="count" flex-1 :min="1" :max="50" placeholder="NanoIds quantity" />
</div>
<c-input-text
style="text-align: center; font-family: monospace"
:value="nanoIds"
placeholder="Your uuids"
rows="1"
autosize
readonly
raw-text
multiline
monospace
my-3
class="uuid-display"
/>
<div flex justify-center gap-3>
<c-button autofocus @click="copy()">
{{ t('tools.nanoid-generator.button.copy') }}
</c-button>
<c-button @click="refreshNanoIds">
{{ t('tools.nanoid-generator.button.refresh') }}
</c-button>
</div>
</div>
</template>
<style scoped lang="less">
.n-icon {
margin-right: 8px;
}
.n-text {
margin-right: 8px;
}
.column {
display: flex;
flex-direction: column;
gap: 8px;
}
</style>