From 5c4d775e2d0f2aaf0a7e427ec2eab774ae19ec07 Mon Sep 17 00:00:00 2001 From: Corentin THOMASSET Date: Tue, 12 Sep 2023 00:57:42 +0200 Subject: [PATCH] feat(new tool): ULID generator (#623) --- components.d.ts | 3 + package.json | 1 + pnpm-lock.yaml | 8 +++ src/tools/index.ts | 3 +- src/tools/ulid-generator/index.ts | 12 ++++ .../ulid-generator/ulid-generator.e2e.spec.ts | 23 ++++++++ src/tools/ulid-generator/ulid-generator.vue | 46 +++++++++++++++ .../c-buttons-select.demo.vue | 14 +++++ .../c-buttons-select.types.ts | 5 ++ src/ui/c-buttons-select/c-buttons-select.vue | 59 +++++++++++++++++++ src/ui/c-tooltip/c-tooltip.vue | 1 + 11 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/tools/ulid-generator/index.ts create mode 100644 src/tools/ulid-generator/ulid-generator.e2e.spec.ts create mode 100644 src/tools/ulid-generator/ulid-generator.vue create mode 100644 src/ui/c-buttons-select/c-buttons-select.demo.vue create mode 100644 src/ui/c-buttons-select/c-buttons-select.types.ts create mode 100644 src/ui/c-buttons-select/c-buttons-select.vue diff --git a/components.d.ts b/components.d.ts index f51e12cd..1a5ce1a9 100644 --- a/components.d.ts +++ b/components.d.ts @@ -25,6 +25,8 @@ declare module '@vue/runtime-core' { CaseConverter: typeof import('./src/tools/case-converter/case-converter.vue')['default'] CButton: typeof import('./src/ui/c-button/c-button.vue')['default'] 'CButton.demo': typeof import('./src/ui/c-button/c-button.demo.vue')['default'] + CButtonsSelect: typeof import('./src/ui/c-buttons-select/c-buttons-select.vue')['default'] + 'CButtonsSelect.demo': typeof import('./src/ui/c-buttons-select/c-buttons-select.demo.vue')['default'] CCard: typeof import('./src/ui/c-card/c-card.vue')['default'] 'CCard.demo': typeof import('./src/ui/c-card/c-card.demo.vue')['default'] CDiffEditor: typeof import('./src/ui/c-diff-editor/c-diff-editor.vue')['default'] @@ -183,6 +185,7 @@ declare module '@vue/runtime-core' { TomlToYaml: typeof import('./src/tools/toml-to-yaml/toml-to-yaml.vue')['default'] 'Tool.layout': typeof import('./src/layouts/tool.layout.vue')['default'] ToolCard: typeof import('./src/components/ToolCard.vue')['default'] + UlidGenerator: typeof import('./src/tools/ulid-generator/ulid-generator.vue')['default'] UrlEncoder: typeof import('./src/tools/url-encoder/url-encoder.vue')['default'] UrlParser: typeof import('./src/tools/url-parser/url-parser.vue')['default'] UserAgentParser: typeof import('./src/tools/user-agent-parser/user-agent-parser.vue')['default'] diff --git a/package.json b/package.json index de225511..d3ec93bf 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "randombytes": "^2.1.0", "sql-formatter": "^13.0.0", "ua-parser-js": "^1.0.35", + "ulid": "^2.3.0", "unicode-emoji-json": "^0.4.0", "unplugin-auto-import": "^0.16.4", "uuid": "^9.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9eae9b35..65579a34 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,6 +134,9 @@ dependencies: ua-parser-js: specifier: ^1.0.35 version: 1.0.35 + ulid: + specifier: ^2.3.0 + version: 2.3.0 unicode-emoji-json: specifier: ^0.4.0 version: 0.4.0 @@ -8246,6 +8249,11 @@ packages: /ufo@1.1.2: resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} + /ulid@2.3.0: + resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} + hasBin: true + dev: false + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: diff --git a/src/tools/index.ts b/src/tools/index.ts index aa380745..cc5f42ee 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,6 +1,7 @@ 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 ulidGenerator } from './ulid-generator'; import { tool as ibanValidatorAndParser } from './iban-validator-and-parser'; import { tool as stringObfuscator } from './string-obfuscator'; import { tool as textDiff } from './text-diff'; @@ -74,7 +75,7 @@ import { tool as xmlFormatter } from './xml-formatter'; export const toolsByCategory: ToolCategory[] = [ { name: 'Crypto', - components: [tokenGenerator, hashText, bcrypt, uuidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser], + components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser], }, { name: 'Converter', diff --git a/src/tools/ulid-generator/index.ts b/src/tools/ulid-generator/index.ts new file mode 100644 index 00000000..6a5408dd --- /dev/null +++ b/src/tools/ulid-generator/index.ts @@ -0,0 +1,12 @@ +import { SortDescendingNumbers } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'ULID generator', + path: '/ulid-generator', + description: 'Generate random Universally Unique Lexicographically Sortable Identifier (ULID).', + keywords: ['ulid', 'generator', 'random', 'id', 'alphanumeric', 'identity', 'token', 'string', 'identifier', 'unique'], + component: () => import('./ulid-generator.vue'), + icon: SortDescendingNumbers, + createdAt: new Date('2023-09-11'), +}); diff --git a/src/tools/ulid-generator/ulid-generator.e2e.spec.ts b/src/tools/ulid-generator/ulid-generator.e2e.spec.ts new file mode 100644 index 00000000..34473376 --- /dev/null +++ b/src/tools/ulid-generator/ulid-generator.e2e.spec.ts @@ -0,0 +1,23 @@ +import { expect, test } from '@playwright/test'; + +const ULID_REGEX = /[0-9A-Z]{26}/; + +test.describe('Tool - ULID generator', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/ulid-generator'); + }); + + test('Has correct title', async ({ page }) => { + await expect(page).toHaveTitle('ULID generator - IT Tools'); + }); + + test('the refresh button generates a new ulid', async ({ page }) => { + const ulid = await page.getByTestId('ulids').textContent(); + expect(ulid?.trim()).toMatch(ULID_REGEX); + + await page.getByTestId('refresh').click(); + const newUlid = await page.getByTestId('ulids').textContent(); + expect(ulid?.trim()).not.toBe(newUlid?.trim()); + expect(newUlid?.trim()).toMatch(ULID_REGEX); + }); +}); diff --git a/src/tools/ulid-generator/ulid-generator.vue b/src/tools/ulid-generator/ulid-generator.vue new file mode 100644 index 00000000..06e695ef --- /dev/null +++ b/src/tools/ulid-generator/ulid-generator.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/ui/c-buttons-select/c-buttons-select.demo.vue b/src/ui/c-buttons-select/c-buttons-select.demo.vue new file mode 100644 index 00000000..dea15289 --- /dev/null +++ b/src/ui/c-buttons-select/c-buttons-select.demo.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/ui/c-buttons-select/c-buttons-select.types.ts b/src/ui/c-buttons-select/c-buttons-select.types.ts new file mode 100644 index 00000000..ccb110d4 --- /dev/null +++ b/src/ui/c-buttons-select/c-buttons-select.types.ts @@ -0,0 +1,5 @@ +import type { CSelectOption } from '../c-select/c-select.types'; + +export type CButtonSelectOption = CSelectOption & { + tooltip?: string +}; diff --git a/src/ui/c-buttons-select/c-buttons-select.vue b/src/ui/c-buttons-select/c-buttons-select.vue new file mode 100644 index 00000000..38fff66f --- /dev/null +++ b/src/ui/c-buttons-select/c-buttons-select.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/ui/c-tooltip/c-tooltip.vue b/src/ui/c-tooltip/c-tooltip.vue index 24c586b8..095315fb 100644 --- a/src/ui/c-tooltip/c-tooltip.vue +++ b/src/ui/c-tooltip/c-tooltip.vue @@ -13,6 +13,7 @@ const isTargetHovered = useElementHover(targetRef);