Skip to content

Commit 95708f1

Browse files
committed
Merge branch 'up/feat/nanoid-generator' into chore/all-my-stuffs
2 parents 1ed8f60 + 2dbc8fa commit 95708f1

File tree

7 files changed

+251
-4
lines changed

7 files changed

+251
-4
lines changed

locales/en.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,22 @@ tools:
357357
title: UUIDs generator
358358
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!).
359359

360+
nanoid-generator:
361+
title: NanoIDs generator
362+
description: Generate random, unique, and URL-friendly IDs for your applications.
363+
uppercase: Uppercase
364+
lowercase: Lowercase
365+
numbers: Numbers
366+
symbols: Symbols
367+
excludeLookalikes: Exclude lookalikes
368+
length: Length
369+
quantity: Quantity
370+
copied: NanoID copied to the clipboard
371+
button:
372+
copy: Copy
373+
refresh: Refresh
374+
375+
360376
ipv4-address-converter:
361377
title: IPv4 address converter
362378
description: Convert an IP address into decimal, binary, hexadecimal, or even an IPv6 representation of it.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@
177177
"monaco-editor": "^0.43.0",
178178
"morsee": "^1.0.9",
179179
"naive-ui": "^2.35.0",
180+
"nanoid": "^5.0.7",
181+
"nanoid-dictionary": "^4.3.0",
180182
"netmask": "^2.0.2",
181183
"netstack.js": "^2.0.0",
182184
"nginx-config-formatter": "^1.4.5",

pnpm-lock.yaml

Lines changed: 23 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ import { tool as torrentToMagnet } from './torrent-to-magnet';
107107
import { tool as ttlCalculator } from './ttl-calculator';
108108
import { tool as unicodeFormatter } from './unicode-formatter';
109109
import { tool as raidCalculator } from './raid-calculator';
110+
import { tool as nanoidGenerator } from './nanoid-generator';
110111

111112
import { tool as asciiTextDrawer } from './ascii-text-drawer';
112113

@@ -245,6 +246,7 @@ export const toolsByCategory: ToolCategory[] = [
245246
bcrypt,
246247
uuidGenerator,
247248
ulidGenerator,
249+
nanoidGenerator,
248250
cypher,
249251
bip39,
250252
hmacGenerator,

src/tools/nanoid-generator/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Fingerprint } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
import { translate } from '@/plugins/i18n.plugin';
4+
5+
export const tool = defineTool({
6+
name: translate('tools.nanoid-generator.title'),
7+
path: '/nanoid-generator',
8+
description: translate('tools.nanoid-generator.description'),
9+
keywords: ['nanoid', 'generator'],
10+
component: () => import('./nanoid-generator.vue'),
11+
icon: Fingerprint,
12+
createdAt: new Date('2024-05-31'),
13+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { customAlphabet, nanoid } from 'nanoid';
2+
import { lowercase, nolookalikes, numbers, uppercase } from 'nanoid-dictionary';
3+
4+
const symbols = '-_';
5+
6+
export function createNanoid({
7+
length = 21,
8+
withLowercase = true,
9+
withUppercase = true,
10+
withNumbers = true,
11+
withSymbols = true,
12+
excludeLookalikes = false,
13+
}: {
14+
length?: number
15+
withLowercase?: boolean
16+
withUppercase?: boolean
17+
withNumbers?: boolean
18+
withSymbols?: boolean
19+
excludeLookalikes?: boolean
20+
}) {
21+
let alphabet = '';
22+
23+
if (!withLowercase && !withUppercase && !withNumbers && !excludeLookalikes && !withSymbols) {
24+
return nanoid(length);
25+
}
26+
27+
if (excludeLookalikes) {
28+
alphabet = [nolookalikes, withSymbols ? symbols : ''].join('');
29+
}
30+
31+
alphabet = [
32+
withLowercase ? lowercase : '',
33+
withUppercase ? uppercase : '',
34+
withNumbers ? numbers : '',
35+
withSymbols ? symbols : '',
36+
].join('');
37+
38+
return customAlphabet(alphabet, length);
39+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<script setup lang="ts">
2+
import { InfoCircle } from '@vicons/tabler';
3+
import { createNanoid } from './nanoid-generator.service';
4+
import { computedRefreshable } from '@/composable/computedRefreshable';
5+
import { withDefaultOnError } from '@/utils/defaults';
6+
import { useCopy } from '@/composable/copy';
7+
import { useQueryParam } from '@/composable/queryParams';
8+
9+
const count = useQueryParam({ name: 'count', defaultValue: 1 });
10+
const length = useQueryParam({ name: 'length', defaultValue: 21 });
11+
const withUppercase = useQueryParam({ name: 'uppercase', defaultValue: true });
12+
const withLowercase = useQueryParam({ name: 'lowercase', defaultValue: true });
13+
const withNumbers = useQueryParam({ name: 'numbers', defaultValue: true });
14+
const withSymbols = useQueryParam({ name: 'symbols', defaultValue: true });
15+
const excludeLookalikes = useQueryParam({ name: 'no-lookalikes', defaultValue: false });
16+
17+
const { t } = useI18n();
18+
19+
const [nanoIds, refreshNanoIds] = computedRefreshable(() =>
20+
withDefaultOnError(
21+
() =>
22+
Array.from({ length: count.value }, (_ignored) => {
23+
const nanoId = createNanoid({
24+
length: length.value,
25+
withUppercase: withUppercase.value,
26+
withLowercase: withLowercase.value,
27+
withNumbers: withNumbers.value,
28+
withSymbols: withSymbols.value,
29+
excludeLookalikes: excludeLookalikes.value,
30+
});
31+
32+
return nanoId();
33+
}).join('\n'),
34+
'',
35+
),
36+
);
37+
38+
const { copy } = useCopy({ source: nanoIds, text: 'NanoIds copied to the clipboard' });
39+
</script>
40+
41+
<template>
42+
<div>
43+
<n-form label-placement="left" label-width="140">
44+
<div mb-8 flex justify-center gap-8>
45+
<div class="column">
46+
<div>
47+
<n-text>{{ t('tools.nanoid-generator.uppercase') }}</n-text>
48+
<c-tooltip
49+
tooltip="ABCDEFGHIJKLMNOPQRSTUVWXYZ" position="bottom"
50+
>
51+
<n-icon size="20" :component="InfoCircle" />
52+
</c-tooltip>
53+
<n-switch v-model:value="withUppercase" />
54+
</div>
55+
56+
<div>
57+
<n-text>{{ t('tools.nanoid-generator.lowercase') }}</n-text>
58+
<c-tooltip
59+
tooltip="abcdefghijklmnopqrstuvwxyz" position="bottom"
60+
>
61+
<n-icon size="20" :component="InfoCircle" />
62+
</c-tooltip>
63+
<n-switch v-model:value="withLowercase" />
64+
</div>
65+
</div>
66+
67+
<div class="column">
68+
<div>
69+
<n-text>
70+
{{ t('tools.nanoid-generator.numbers') }}
71+
</n-text>
72+
<c-tooltip
73+
tooltip="0123456789" position="bottom"
74+
>
75+
<n-icon size="20" :component="InfoCircle" />
76+
</c-tooltip>
77+
<n-switch v-model:value="withNumbers" />
78+
</div>
79+
80+
<div>
81+
<n-text>
82+
{{ t('tools.nanoid-generator.symbols') }}
83+
</n-text>
84+
<c-tooltip
85+
tooltip="-_" position="bottom"
86+
>
87+
<n-icon size="20" :component="InfoCircle" />
88+
</c-tooltip>
89+
<n-switch v-model:value="withSymbols" />
90+
</div>
91+
</div>
92+
<div class="column">
93+
<div>
94+
<n-text>
95+
{{ t('tools.nanoid-generator.excludeLookalikes') }}
96+
</n-text>
97+
<c-tooltip
98+
tooltip="1lI0Oouv5Ss2Z" position="bottom"
99+
>
100+
<n-icon size="20" :component="InfoCircle" />
101+
</c-tooltip>
102+
<n-switch v-model:value="excludeLookalikes" />
103+
</div>
104+
</div>
105+
</div>
106+
</n-form>
107+
108+
<div mb-2 flex items-center>
109+
<span w-100px>{{ t('tools.nanoid-generator.length') }}</span>
110+
<n-input-number v-model:value="length" flex-1 :min="1" :max="100" placeholder="NanoId Length" />
111+
</div>
112+
<div mb-2 flex items-center>
113+
<span w-100px>{{ t('tools.nanoid-generator.quantity') }}</span>
114+
<n-input-number v-model:value="count" flex-1 :min="1" :max="50" placeholder="NanoIds quantity" />
115+
</div>
116+
117+
<c-input-text
118+
style="text-align: center; font-family: monospace"
119+
:value="nanoIds"
120+
placeholder="Your uuids"
121+
rows="1"
122+
autosize
123+
readonly
124+
raw-text
125+
multiline
126+
monospace
127+
my-3
128+
class="uuid-display"
129+
/>
130+
131+
<div flex justify-center gap-3>
132+
<c-button autofocus @click="copy()">
133+
{{ t('tools.nanoid-generator.button.copy') }}
134+
</c-button>
135+
<c-button @click="refreshNanoIds">
136+
{{ t('tools.nanoid-generator.button.refresh') }}
137+
</c-button>
138+
</div>
139+
</div>
140+
</template>
141+
142+
<style scoped lang="less">
143+
.n-icon {
144+
margin-right: 8px;
145+
}
146+
147+
.n-text {
148+
margin-right: 8px;
149+
}
150+
151+
.column {
152+
display: flex;
153+
flex-direction: column;
154+
gap: 8px;
155+
}
156+
</style>

0 commit comments

Comments
 (0)