Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 28a86dcbff | ||
| 7cd826b052 | |||
|   | da20e34dc9 | ||
|   | a43b5a96bb | ||
|   | 48aaa262c1 | ||
| 660839d854 | |||
|   | 6d23d601a8 | ||
|   | 7405f2cb88 | 
| @@ -42,8 +42,8 @@ jobs: | ||||
|           push: true | ||||
|           tags: ${{ steps.meta.outputs.tags }} | ||||
|           labels: ${{ steps.meta.outputs.labels }} | ||||
|           cache-from: type=local,src=/cache | ||||
|           cache-to: type=local,dest=/cache,mode=max | ||||
|           cache-from: type=registry,ref=${{ secrets.REGISTRY_ENDPOINT }}/${{ github.repository_owner }}/litek:buildcache | ||||
|           cache-to: type=registry,ref=${{ secrets.REGISTRY_ENDPOINT }}/${{ github.repository_owner }}/litek:buildcache,mode=max | ||||
|           # platforms: linux/amd64,linux/arm64 | ||||
|           platforms: linux/amd64 | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,8 @@ WORKDIR /app | ||||
| COPY package.json pnpm-lock.yaml ./ | ||||
|  | ||||
| # 安装依赖 | ||||
| RUN pnpm install --frozen-lockfile | ||||
| RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ | ||||
|     pnpm install --frozen-lockfile | ||||
|  | ||||
| # 复制源代码 | ||||
| COPY . . | ||||
|   | ||||
| @@ -1,13 +1,16 @@ | ||||
| { | ||||
|   "name": "litek", | ||||
|   "private": true, | ||||
|   "version": "0.0.3", | ||||
|   "version": "0.0.7", | ||||
|   "type": "module", | ||||
|   "scripts": { | ||||
|     "dev": "vite", | ||||
|     "build": "tsc -b && vite build", | ||||
|     "lint": "eslint .", | ||||
|     "preview": "vite preview" | ||||
|     "preview": "vite preview", | ||||
|     "release:patch": "npm version patch && git push --follow-tags", | ||||
|     "release:minor": "npm version minor && git push --follow-tags", | ||||
|     "release:major": "npm version major && git push --follow-tags" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@radix-ui/react-dialog": "^1.1.15", | ||||
|   | ||||
							
								
								
									
										70
									
								
								src/components/tool/base64.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/components/tool/base64.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| import { useState, type FC } from "react"; | ||||
| import { Textarea } from "@/components/ui/textarea"; | ||||
| import { Button } from "@/components/ui/button"; | ||||
| import { toast } from "sonner"; | ||||
| import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"; | ||||
|  | ||||
| const Tool: FC = () => { | ||||
|   const [decoded, setDecoded] = useState<string>(""); | ||||
|   const [encoded, setEncoded] = useState<string>(""); | ||||
|  | ||||
|   const encode = () => { | ||||
|     try { | ||||
|       const encoded64 = btoa(decoded); | ||||
|       setEncoded(encoded64); | ||||
|       setDecoded(""); | ||||
|       toast.success("encoded successfully"); | ||||
|     } catch (error: unknown) { | ||||
|       if (error instanceof Error) { | ||||
|         toast.error(error.message); | ||||
|       } else { | ||||
|         toast.error("encoding failed"); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   const decode = () => { | ||||
|     try { | ||||
|       const decoded64 = atob(encoded); | ||||
|       setDecoded(decoded64); | ||||
|       setEncoded(""); | ||||
|       toast.success("decoded successfully"); | ||||
|     } catch (error: unknown) { | ||||
|       if (error instanceof Error) { | ||||
|         toast.error(error.message); | ||||
|       } else { | ||||
|         toast.error("decoding failed"); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <div className="h-[50vh] flex flex-row gap-4 pt-[20vh]"> | ||||
|       <Textarea | ||||
|         className="flex-1 resize-none" | ||||
|         placeholder="Enter the original text" | ||||
|         value={decoded} | ||||
|         onChange={(e) => setDecoded(e.target.value)} | ||||
|       /> | ||||
|       <div className="flex flex-col gap-2 justify-center"> | ||||
|         <Button onClick={encode}> | ||||
|           <ArrowRightIcon className="size-4" /> | ||||
|           Encode | ||||
|         </Button> | ||||
|         <Button onClick={decode}> | ||||
|           <ArrowLeftIcon className="size-4" /> | ||||
|           Decode | ||||
|         </Button> | ||||
|       </div> | ||||
|       <Textarea | ||||
|         className="flex-1 resize-none" | ||||
|         placeholder="Enter the Base64 encoded text" | ||||
|         value={encoded} | ||||
|         onChange={(e) => setEncoded(e.target.value)} | ||||
|       /> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| export default Tool; | ||||
|  | ||||
| @@ -1,8 +1,9 @@ | ||||
| import type { ReactNode } from 'react'; | ||||
| import { FileJson, Hash } from 'lucide-react' | ||||
| import { FileJson, Hash, Binary } from 'lucide-react' | ||||
|  | ||||
| import UUID from './uuid' | ||||
| import JSON from './json' | ||||
| import Base64 from './base64' | ||||
|  | ||||
| export interface Tool { | ||||
|   path: string; | ||||
| @@ -26,5 +27,12 @@ export const tools: Tool[] = [ | ||||
|     description: "Format and validate JSON", | ||||
|     icon: <FileJson />, | ||||
|     component: <JSON />, | ||||
|   }, | ||||
|   { | ||||
|     path: "base64", | ||||
|     name: "Base64 Encoder/Decoder", | ||||
|     description: "Encode and decode Base64", | ||||
|     icon: <Binary />, | ||||
|     component: <Base64 />, | ||||
|   } | ||||
| ]; | ||||
| @@ -7,12 +7,12 @@ import { AppSidebar } from "@/components/sidebar"; | ||||
| export const Layout: FC = () => ( | ||||
|   <SidebarProvider> | ||||
|     <AppSidebar /> | ||||
|     <div className="p-4 flex flex-col w-full h-[100vh]"> | ||||
|     <div className="p-4 flex flex-col w-full h-[100vh] overflow-hidden"> | ||||
|       <nav className="flex items-center justify-between"> | ||||
|         <SidebarTrigger className="size-10" /> | ||||
|         <div role="actions" /> | ||||
|       </nav> | ||||
|       <main className="flex-1 overflow-auto p-4"> | ||||
|       <main className="flex-1 overflow-auto p-4 overflow-hidden"> | ||||
|         <Outlet /> | ||||
|       </main> | ||||
|     </div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user