Skip to content

Commit f61db56

Browse files
committed
1 parent cb5b462 commit f61db56

File tree

8 files changed

+312
-8
lines changed

8 files changed

+312
-8
lines changed

components.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ declare module '@vue/runtime-core' {
126126
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
127127
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
128128
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
129+
NA: typeof import('naive-ui')['NA']
129130
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
131+
NCheckbox: typeof import('naive-ui')['NCheckbox']
130132
NCode: typeof import('naive-ui')['NCode']
131133
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
132134
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
@@ -144,7 +146,9 @@ declare module '@vue/runtime-core' {
144146
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
145147
NMenu: typeof import('naive-ui')['NMenu']
146148
NScrollbar: typeof import('naive-ui')['NScrollbar']
149+
NSpace: typeof import('naive-ui')['NSpace']
147150
NSpin: typeof import('naive-ui')['NSpin']
151+
NTable: typeof import('naive-ui')['NTable']
148152
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
149153
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
150154
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']
@@ -154,11 +158,13 @@ declare module '@vue/runtime-core' {
154158
PhoneParserAndFormatter: typeof import('./src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue')['default']
155159
QrCodeGenerator: typeof import('./src/tools/qr-code-generator/qr-code-generator.vue')['default']
156160
RandomPortGenerator: typeof import('./src/tools/random-port-generator/random-port-generator.vue')['default']
161+
RegexTester: typeof import('./src/tools/regex-tester/regex-tester.vue')['default']
157162
ResultRow: typeof import('./src/tools/ipv4-range-expander/result-row.vue')['default']
158163
RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default']
159164
RouterLink: typeof import('vue-router')['RouterLink']
160165
RouterView: typeof import('vue-router')['RouterView']
161166
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
167+
SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default']
162168
SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
163169
SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default']
164170
SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default']

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
"pinia": "^2.0.34",
8181
"plausible-tracker": "^0.3.8",
8282
"qrcode": "^1.5.1",
83+
"randexp": "^0.5.3",
8384
"sql-formatter": "^13.0.0",
8485
"ua-parser-js": "^1.0.35",
8586
"ulid": "^2.3.0",

pnpm-lock.yaml

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

src/composable/queryParams.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useRouteQuery } from '@vueuse/router';
22
import { computed } from 'vue';
3+
import { useStorage } from '@vueuse/core';
34

4-
export { useQueryParam };
5+
export { useQueryParam, useQueryParamOrStorage };
56

67
const transformers = {
78
number: {
@@ -33,3 +34,31 @@ function useQueryParam<T>({ name, defaultValue }: { name: string; defaultValue:
3334
},
3435
});
3536
}
37+
38+
function useQueryParamOrStorage<T>({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue?: T }) {
39+
const type = typeof defaultValue;
40+
const transformer = transformers[type as keyof typeof transformers] ?? transformers.string;
41+
42+
const storageRef = useStorage(storageName, defaultValue);
43+
const storageDefaultValue = storageRef.value ?? defaultValue;
44+
45+
const proxy = useRouteQuery(name, transformer.toQuery(storageDefaultValue as never));
46+
47+
const ref = computed<T>({
48+
get() {
49+
return transformer.fromQuery(proxy.value) as unknown as T;
50+
},
51+
set(value) {
52+
proxy.value = transformer.toQuery(value as never);
53+
},
54+
});
55+
56+
watch(
57+
ref,
58+
(newValue) => {
59+
storageRef.value = newValue;
60+
},
61+
);
62+
63+
return ref;
64+
}

src/composable/validation.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import _ from 'lodash';
33
import { type Ref, reactive, watch } from 'vue';
44

55
type ValidatorReturnType = unknown;
6+
type GetErrorMessageReturnType = string;
67

78
export interface UseValidationRule<T> {
89
validator: (value: T) => ValidatorReturnType
10+
getErrorMessage?: (value: T) => GetErrorMessageReturnType
911
message: string
1012
}
1113

@@ -24,6 +26,15 @@ export function isFalsyOrHasThrown(cb: () => ValidatorReturnType): boolean {
2426
}
2527
}
2628

29+
export function getErrorMessageOrThrown(cb: () => GetErrorMessageReturnType): string {
30+
try {
31+
return cb() || '';
32+
}
33+
catch (e: any) {
34+
return e.toString();
35+
}
36+
}
37+
2738
export interface ValidationAttrs {
2839
feedback: string
2940
validationStatus: string | undefined
@@ -61,7 +72,13 @@ export function useValidation<T>({
6172

6273
for (const rule of get(rules)) {
6374
if (isFalsyOrHasThrown(() => rule.validator(source.value))) {
64-
state.message = rule.message;
75+
if (rule.getErrorMessage) {
76+
const getErrorMessage = rule.getErrorMessage;
77+
state.message = rule.message.replace('{0}', getErrorMessageOrThrown(() => getErrorMessage(source.value)));
78+
}
79+
else {
80+
state.message = rule.message;
81+
}
6582
state.status = 'error';
6683
}
6784
}

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer';
66

77
import { tool as textToUnicode } from './text-to-unicode';
88
import { tool as safelinkDecoder } from './safelink-decoder';
9+
import { tool as regexTester } from './regex-tester';
910
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
1011
import { tool as numeronymGenerator } from './numeronym-generator';
1112
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -148,6 +149,7 @@ export const toolsByCategory: ToolCategory[] = [
148149
dockerRunToDockerComposeConverter,
149150
xmlFormatter,
150151
yamlViewer,
152+
regexTester,
151153
],
152154
},
153155
{

src/tools/regex-tester/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Language } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Regex Tester',
6+
path: '/regex-tester',
7+
description: 'Regex Tester',
8+
keywords: ['regex', 'tester', 'sample', 'expression'],
9+
component: () => import('./regex-tester.vue'),
10+
icon: Language,
11+
createdAt: new Date('2024-04-20'),
12+
});

0 commit comments

Comments
 (0)