Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28a86dcbff | ||
| 7cd826b052 | |||
|
|
da20e34dc9 | ||
|
|
a43b5a96bb | ||
|
|
48aaa262c1 | ||
| 660839d854 | |||
|
|
6d23d601a8 | ||
|
|
7405f2cb88 |
@@ -42,8 +42,8 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=local,src=/cache
|
cache-from: type=registry,ref=${{ secrets.REGISTRY_ENDPOINT }}/${{ github.repository_owner }}/litek:buildcache
|
||||||
cache-to: type=local,dest=/cache,mode=max
|
cache-to: type=registry,ref=${{ secrets.REGISTRY_ENDPOINT }}/${{ github.repository_owner }}/litek:buildcache,mode=max
|
||||||
# platforms: linux/amd64,linux/arm64
|
# platforms: linux/amd64,linux/arm64
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ WORKDIR /app
|
|||||||
COPY package.json pnpm-lock.yaml ./
|
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 . .
|
COPY . .
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "litek",
|
"name": "litek",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.3",
|
"version": "0.0.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"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": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.15",
|
"@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 type { ReactNode } from 'react';
|
||||||
import { FileJson, Hash } from 'lucide-react'
|
import { FileJson, Hash, Binary } from 'lucide-react'
|
||||||
|
|
||||||
import UUID from './uuid'
|
import UUID from './uuid'
|
||||||
import JSON from './json'
|
import JSON from './json'
|
||||||
|
import Base64 from './base64'
|
||||||
|
|
||||||
export interface Tool {
|
export interface Tool {
|
||||||
path: string;
|
path: string;
|
||||||
@@ -26,5 +27,12 @@ export const tools: Tool[] = [
|
|||||||
description: "Format and validate JSON",
|
description: "Format and validate JSON",
|
||||||
icon: <FileJson />,
|
icon: <FileJson />,
|
||||||
component: <JSON />,
|
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 = () => (
|
export const Layout: FC = () => (
|
||||||
<SidebarProvider>
|
<SidebarProvider>
|
||||||
<AppSidebar />
|
<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">
|
<nav className="flex items-center justify-between">
|
||||||
<SidebarTrigger className="size-10" />
|
<SidebarTrigger className="size-10" />
|
||||||
<div role="actions" />
|
<div role="actions" />
|
||||||
</nav>
|
</nav>
|
||||||
<main className="flex-1 overflow-auto p-4">
|
<main className="flex-1 overflow-auto p-4 overflow-hidden">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user