Skip to content

Commit d7ad5bd

Browse files
committed
Merge branch 'feat/unicode-search' into chore/all-my-stuffs
# Conflicts: # package.json # pnpm-lock.yaml # src/tools/index.ts # vite.config.ts
2 parents 2250824 + 8fdb31b commit d7ad5bd

File tree

6 files changed

+166
-1
lines changed

6 files changed

+166
-1
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@
8989
"@types/memorystream": "^0.3.4",
9090
"@types/sshpk": "^1.17.4",
9191
"@unicode/unicode-15.1.0": "^1.5.2",
92+
"@types/figlet": "^1.5.8",
93+
"@types/markdown-it": "^13.0.7",
94+
"@types/utf8": "^3.0.3",
95+
"@unicode/unicode-15.1.0": "^1.6.0",
9296
"@vicons/material": "^0.12.0",
9397
"@vicons/tabler": "^0.12.0",
9498
"@vueuse/core": "^10.11.1",
@@ -232,6 +236,7 @@
232236
"ulid": "^2.3.0",
233237
"unicode-emoji-json": "^0.4.0",
234238
"unplugin-auto-import": "^0.16.4",
239+
"utf8": "^3.0.0",
235240
"uuid": "^9.0.0",
236241
"vite-plugin-node-polyfills": "^0.22.0",
237242
"vite-plugin-node-polyfills": "^0.21.0",

pnpm-lock.yaml

Lines changed: 16 additions & 1 deletion
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
@@ -40,6 +40,7 @@ import { tool as sslCertConverter } from './ssl-cert-converter';
4040
import { tool as stacktracePrettier } from './stacktrace-prettier';
4141
import { tool as dataTransferRateConverter } from './data-transfer-rate-converter';
4242
import { tool as dataStorageUnitConverter } from './data-storage-unit-converter';
43+
import { tool as unicodeSearch } from './unicode-search';
4344

4445
import { tool as cssXpathConverter } from './css-xpath-converter';
4546
import { tool as cssSelectorsMemo } from './css-selectors-memo';
@@ -277,6 +278,7 @@ export const toolsByCategory: ToolCategory[] = [
277278
phpArrayToJson,
278279
maliciousLinksTester,
279280
torrentToMagnet,
281+
unicodeSearch,
280282
],
281283
},
282284
{

src/tools/unicode-search/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { FileText } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Unicode Search',
6+
path: '/unicode-search',
7+
description: 'Search in Unicode Characters',
8+
keywords: ['unicode', 'search'],
9+
component: () => import('./unicode-search.vue'),
10+
icon: FileText,
11+
createdAt: new Date('2024-08-15'),
12+
});
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<script setup lang="ts">
2+
import unicodeNames from '@unicode/unicode-15.1.0/Names/index.js';
3+
import unicodeCategories from '@unicode/unicode-15.1.0/General_Category';
4+
import utf8 from 'utf8';
5+
6+
import { useFuzzySearch } from '@/composable/fuzzySearch';
7+
import useDebouncedRef from '@/composable/debouncedref';
8+
9+
function toPaddedHex(num: number) {
10+
return num.toString(16).padStart(4, '0').toUpperCase();
11+
}
12+
13+
function toUTF8(codePoint: number) {
14+
const utf8String = utf8.encode(String.fromCodePoint(codePoint));
15+
return [...utf8String].map(c => `\\x${c.codePointAt(0)?.toString(16).toUpperCase()}`);
16+
}
17+
18+
const searchQuery = useDebouncedRef('', 500);
19+
const parsedSearchQuery = computed(() => {
20+
const parsedRegex = /^\s*(?:\&#x(?<hex1>[\da-f]+);|\&#(?<dec>\d+);|(?:U\+|\\u)?\s*(?<hex2>[\da-f]+))\s*$/gi; // NOSONAR
21+
const parsedQuery = parsedRegex.exec(searchQuery.value);
22+
if (parsedQuery) {
23+
if (parsedQuery.groups?.hex1 || parsedQuery.groups?.hex2) {
24+
return `=${toPaddedHex(Number.parseInt(parsedQuery.groups.hex1 || parsedQuery.groups.hex2, 16))}`;
25+
}
26+
if (parsedQuery.groups?.dec) {
27+
return `=${toPaddedHex(Number.parseInt(parsedQuery.groups.dec, 10))}`;
28+
}
29+
}
30+
return searchQuery.value;
31+
});
32+
33+
const unicodeSearchData = [...unicodeNames].map(([codePoint, characterName]) => {
34+
const hex = toPaddedHex(codePoint);
35+
return {
36+
codePoint,
37+
characterName: `${characterName} (U+${hex})`,
38+
hex,
39+
};
40+
});
41+
42+
const { searchResult } = useFuzzySearch({
43+
search: parsedSearchQuery,
44+
data: unicodeSearchData,
45+
options: {
46+
keys: ['characterName', 'hex'],
47+
threshold: 0.2,
48+
isCaseSensitive: false,
49+
minMatchCharLength: 3,
50+
useExtendedSearch: true,
51+
},
52+
});
53+
</script>
54+
55+
<template>
56+
<div mx-auto max-w-2400px important:flex-1>
57+
<div flex items-center gap-3>
58+
<c-input-text
59+
v-model:value="searchQuery"
60+
placeholder="Search Unicode by name (e.g. 'zero width') or code point..."
61+
mx-auto max-w-600px
62+
>
63+
<template #prefix>
64+
<icon-mdi-search mr-6px color-black op-70 dark:color-white />
65+
</template>
66+
</c-input-text>
67+
</div>
68+
69+
<div v-if="searchQuery.trim().length > 0">
70+
<div
71+
v-if="searchResult.length === 0"
72+
mt-4
73+
text-20px
74+
font-bold
75+
>
76+
No results
77+
</div>
78+
79+
<div v-else>
80+
<div mt-4 text-20px font-bold>
81+
Search result
82+
</div>
83+
84+
<n-table>
85+
<thead>
86+
<th>UCOD</th>
87+
<th>Display/UTF8</th>
88+
<th style="width:30%">
89+
Category
90+
</th>
91+
<th>Html</th>
92+
<th style="width:30%">
93+
Name
94+
</th>
95+
</thead>
96+
<tbody>
97+
<tr v-for="(result, ix) in searchResult" :key="ix">
98+
<td>
99+
<input-copyable :value="`U+${toPaddedHex(result.codePoint)}`" mb-1 />
100+
<!-- //NOSONAR --><n-a :href="`https://unicodeplus.com/U+${toPaddedHex(result.codePoint)}`" target="_blank">
101+
&gt; More info
102+
</n-a>
103+
</td>
104+
<td>
105+
<input-copyable :value="String.fromCodePoint(result.codePoint)" mb-1 />
106+
<input-copyable :value="toUTF8(result.codePoint)" />
107+
</td>
108+
<td>
109+
<input-copyable :value="unicodeCategories.get(result.codePoint)" />
110+
</td>
111+
<td>
112+
<input-copyable :value="`\&\#x${toPaddedHex(result.codePoint)};`" mb-1 />
113+
<input-copyable :value="`\&\#${result.codePoint};`" />
114+
</td>
115+
<td><input-copyable :value="result.characterName" /></td>
116+
</tr>
117+
</tbody>
118+
</n-table>
119+
</div>
120+
</div>
121+
</div>
122+
</template>

src/tools/unicode-search/unicode.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
declare module '@unicode/unicode-15.1.0/Names/index.js'{
2+
const unicode: HashSet<number, string>;
3+
export default unicode;
4+
}
5+
6+
declare module '@unicode/unicode-15.1.0/General_Category'{
7+
const unicode: HashSet<number, string>;
8+
export default unicode;
9+
}

0 commit comments

Comments
 (0)