Merge 8fdb31b55b into 67094980c9
				
					
				
			This commit is contained in:
		
						commit
						58ad2a2b87
					
				| @ -41,8 +41,10 @@ | |||||||
|     "@tiptap/pm": "2.1.6", |     "@tiptap/pm": "2.1.6", | ||||||
|     "@tiptap/starter-kit": "2.1.6", |     "@tiptap/starter-kit": "2.1.6", | ||||||
|     "@tiptap/vue-3": "2.0.3", |     "@tiptap/vue-3": "2.0.3", | ||||||
|     "@types/markdown-it": "^13.0.7", |  | ||||||
|     "@types/figlet": "^1.5.8", |     "@types/figlet": "^1.5.8", | ||||||
|  |     "@types/markdown-it": "^13.0.7", | ||||||
|  |     "@types/utf8": "^3.0.3", | ||||||
|  |     "@unicode/unicode-15.1.0": "^1.6.0", | ||||||
|     "@vicons/material": "^0.12.0", |     "@vicons/material": "^0.12.0", | ||||||
|     "@vicons/tabler": "^0.12.0", |     "@vicons/tabler": "^0.12.0", | ||||||
|     "@vueuse/core": "^10.3.0", |     "@vueuse/core": "^10.3.0", | ||||||
| @ -89,6 +91,7 @@ | |||||||
|     "ulid": "^2.3.0", |     "ulid": "^2.3.0", | ||||||
|     "unicode-emoji-json": "^0.4.0", |     "unicode-emoji-json": "^0.4.0", | ||||||
|     "unplugin-auto-import": "^0.16.4", |     "unplugin-auto-import": "^0.16.4", | ||||||
|  |     "utf8": "^3.0.0", | ||||||
|     "uuid": "^9.0.0", |     "uuid": "^9.0.0", | ||||||
|     "vue": "^3.3.4", |     "vue": "^3.3.4", | ||||||
|     "vue-i18n": "^9.9.1", |     "vue-i18n": "^9.9.1", | ||||||
| @ -136,6 +139,7 @@ | |||||||
|     "unplugin-icons": "^0.17.0", |     "unplugin-icons": "^0.17.0", | ||||||
|     "unplugin-vue-components": "^0.25.0", |     "unplugin-vue-components": "^0.25.0", | ||||||
|     "vite": "^4.4.9", |     "vite": "^4.4.9", | ||||||
|  |     "vite-plugin-node-polyfills": "^0.22.0", | ||||||
|     "vite-plugin-pwa": "^0.16.0", |     "vite-plugin-pwa": "^0.16.0", | ||||||
|     "vite-plugin-vue-markdown": "^0.23.5", |     "vite-plugin-vue-markdown": "^0.23.5", | ||||||
|     "vite-svg-loader": "^4.0.0", |     "vite-svg-loader": "^4.0.0", | ||||||
|  | |||||||
							
								
								
									
										647
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										647
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -2,6 +2,7 @@ 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 emailNormalizer } from './email-normalizer'; | import { tool as emailNormalizer } from './email-normalizer'; | ||||||
|  | import { tool as unicodeSearch } from './unicode-search'; | ||||||
| 
 | 
 | ||||||
| import { tool as asciiTextDrawer } from './ascii-text-drawer'; | import { tool as asciiTextDrawer } from './ascii-text-drawer'; | ||||||
| 
 | 
 | ||||||
| @ -135,6 +136,7 @@ export const toolsByCategory: ToolCategory[] = [ | |||||||
|       httpStatusCodes, |       httpStatusCodes, | ||||||
|       jsonDiff, |       jsonDiff, | ||||||
|       safelinkDecoder, |       safelinkDecoder, | ||||||
|  |       unicodeSearch, | ||||||
|     ], |     ], | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/tools/unicode-search/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/unicode-search/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | import { FileText } from '@vicons/tabler'; | ||||||
|  | import { defineTool } from '../tool'; | ||||||
|  | 
 | ||||||
|  | export const tool = defineTool({ | ||||||
|  |   name: 'Unicode Search', | ||||||
|  |   path: '/unicode-search', | ||||||
|  |   description: 'Search in Unicode Characters', | ||||||
|  |   keywords: ['unicode', 'search'], | ||||||
|  |   component: () => import('./unicode-search.vue'), | ||||||
|  |   icon: FileText, | ||||||
|  |   createdAt: new Date('2024-08-15'), | ||||||
|  | }); | ||||||
							
								
								
									
										122
									
								
								src/tools/unicode-search/unicode-search.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/tools/unicode-search/unicode-search.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,122 @@ | |||||||
|  | <script setup lang="ts"> | ||||||
|  | import unicodeNames from '@unicode/unicode-15.1.0/Names/index.js'; | ||||||
|  | import unicodeCategories from '@unicode/unicode-15.1.0/General_Category'; | ||||||
|  | import utf8 from 'utf8'; | ||||||
|  | 
 | ||||||
|  | import { useFuzzySearch } from '@/composable/fuzzySearch'; | ||||||
|  | import useDebouncedRef from '@/composable/debouncedref'; | ||||||
|  | 
 | ||||||
|  | function toPaddedHex(num: number) { | ||||||
|  |   return num.toString(16).padStart(4, '0').toUpperCase(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function toUTF8(codePoint: number) { | ||||||
|  |   const utf8String = utf8.encode(String.fromCodePoint(codePoint)); | ||||||
|  |   return [...utf8String].map(c => `\\x${c.codePointAt(0)?.toString(16).toUpperCase()}`); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const searchQuery = useDebouncedRef('', 500); | ||||||
|  | const parsedSearchQuery = computed(() => { | ||||||
|  |   const parsedRegex = /^\s*(?:\&#x(?<hex1>[\da-f]+);|\&#(?<dec>\d+);|(?:U\+|\\u)?\s*(?<hex2>[\da-f]+))\s*$/gi; // NOSONAR | ||||||
|  |   const parsedQuery = parsedRegex.exec(searchQuery.value); | ||||||
|  |   if (parsedQuery) { | ||||||
|  |     if (parsedQuery.groups?.hex1 || parsedQuery.groups?.hex2) { | ||||||
|  |       return `=${toPaddedHex(Number.parseInt(parsedQuery.groups.hex1 || parsedQuery.groups.hex2, 16))}`; | ||||||
|  |     } | ||||||
|  |     if (parsedQuery.groups?.dec) { | ||||||
|  |       return `=${toPaddedHex(Number.parseInt(parsedQuery.groups.dec, 10))}`; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return searchQuery.value; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const unicodeSearchData = [...unicodeNames].map(([codePoint, characterName]) => { | ||||||
|  |   const hex = toPaddedHex(codePoint); | ||||||
|  |   return { | ||||||
|  |     codePoint, | ||||||
|  |     characterName: `${characterName} (U+${hex})`, | ||||||
|  |     hex, | ||||||
|  |   }; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const { searchResult } = useFuzzySearch({ | ||||||
|  |   search: parsedSearchQuery, | ||||||
|  |   data: unicodeSearchData, | ||||||
|  |   options: { | ||||||
|  |     keys: ['characterName', 'hex'], | ||||||
|  |     threshold: 0.2, | ||||||
|  |     isCaseSensitive: false, | ||||||
|  |     minMatchCharLength: 3, | ||||||
|  |     useExtendedSearch: true, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div mx-auto max-w-2400px important:flex-1> | ||||||
|  |     <div flex items-center gap-3> | ||||||
|  |       <c-input-text | ||||||
|  |         v-model:value="searchQuery" | ||||||
|  |         placeholder="Search Unicode by name (e.g. 'zero width') or code point..." | ||||||
|  |         mx-auto max-w-600px | ||||||
|  |       > | ||||||
|  |         <template #prefix> | ||||||
|  |           <icon-mdi-search mr-6px color-black op-70 dark:color-white /> | ||||||
|  |         </template> | ||||||
|  |       </c-input-text> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|  |     <div v-if="searchQuery.trim().length > 0"> | ||||||
|  |       <div | ||||||
|  |         v-if="searchResult.length === 0" | ||||||
|  |         mt-4 | ||||||
|  |         text-20px | ||||||
|  |         font-bold | ||||||
|  |       > | ||||||
|  |         No results | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <div v-else> | ||||||
|  |         <div mt-4 text-20px font-bold> | ||||||
|  |           Search result | ||||||
|  |         </div> | ||||||
|  | 
 | ||||||
|  |         <n-table> | ||||||
|  |           <thead> | ||||||
|  |             <th>UCOD</th> | ||||||
|  |             <th>Display/UTF8</th> | ||||||
|  |             <th style="width:30%"> | ||||||
|  |               Category | ||||||
|  |             </th> | ||||||
|  |             <th>Html</th> | ||||||
|  |             <th style="width:30%"> | ||||||
|  |               Name | ||||||
|  |             </th> | ||||||
|  |           </thead> | ||||||
|  |           <tbody> | ||||||
|  |             <tr v-for="(result, ix) in searchResult" :key="ix"> | ||||||
|  |               <td> | ||||||
|  |                 <input-copyable :value="`U+${toPaddedHex(result.codePoint)}`" mb-1 /> | ||||||
|  |                 <!-- //NOSONAR --><n-a :href="`https://unicodeplus.com/U+${toPaddedHex(result.codePoint)}`" target="_blank"> | ||||||
|  |                   > More info | ||||||
|  |                 </n-a> | ||||||
|  |               </td> | ||||||
|  |               <td> | ||||||
|  |                 <input-copyable :value="String.fromCodePoint(result.codePoint)" mb-1 /> | ||||||
|  |                 <input-copyable :value="toUTF8(result.codePoint)" /> | ||||||
|  |               </td> | ||||||
|  |               <td> | ||||||
|  |                 <input-copyable :value="unicodeCategories.get(result.codePoint)" /> | ||||||
|  |               </td> | ||||||
|  |               <td> | ||||||
|  |                 <input-copyable :value="`\&\#x${toPaddedHex(result.codePoint)};`" mb-1 /> | ||||||
|  |                 <input-copyable :value="`\&\#${result.codePoint};`" /> | ||||||
|  |               </td> | ||||||
|  |               <td><input-copyable :value="result.characterName" /></td> | ||||||
|  |             </tr> | ||||||
|  |           </tbody> | ||||||
|  |         </n-table> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
							
								
								
									
										9
									
								
								src/tools/unicode-search/unicode.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/tools/unicode-search/unicode.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | declare module '@unicode/unicode-15.1.0/Names/index.js'{ | ||||||
|  |     const unicode: HashSet<number, string>; | ||||||
|  |     export default unicode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | declare module '@unicode/unicode-15.1.0/General_Category'{ | ||||||
|  |     const unicode: HashSet<number, string>; | ||||||
|  |     export default unicode; | ||||||
|  | } | ||||||
| @ -15,6 +15,7 @@ import { VitePWA } from 'vite-plugin-pwa'; | |||||||
| import markdown from 'vite-plugin-vue-markdown'; | import markdown from 'vite-plugin-vue-markdown'; | ||||||
| import svgLoader from 'vite-svg-loader'; | import svgLoader from 'vite-svg-loader'; | ||||||
| import { configDefaults } from 'vitest/config'; | import { configDefaults } from 'vitest/config'; | ||||||
|  | import { nodePolyfills } from 'vite-plugin-node-polyfills'; | ||||||
| 
 | 
 | ||||||
| const baseUrl = process.env.BASE_URL ?? '/'; | const baseUrl = process.env.BASE_URL ?? '/'; | ||||||
| 
 | 
 | ||||||
| @ -97,6 +98,7 @@ export default defineConfig({ | |||||||
|       resolvers: [NaiveUiResolver(), IconsResolver({ prefix: 'icon' })], |       resolvers: [NaiveUiResolver(), IconsResolver({ prefix: 'icon' })], | ||||||
|     }), |     }), | ||||||
|     Unocss(), |     Unocss(), | ||||||
|  |     nodePolyfills(), | ||||||
|   ], |   ], | ||||||
|   base: baseUrl, |   base: baseUrl, | ||||||
|   resolve: { |   resolve: { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user