clean: remove unnecessary files, full i18n for base64 tools

This commit is contained in:
Alikia2x 2024-06-19 17:32:50 +08:00
parent 421e4fcdb8
commit 13e79e2869
12 changed files with 31 additions and 169 deletions

View File

@ -8,11 +8,12 @@ import normalizeHex from "@/lib/normalizeHex";
import { validBase64 } from "@/lib/onesearch/baseCheck";
import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
//@ts-ignore
import { utoa, atou } from "unicode-encode";
export default function Base64() {
const t = useTranslations("tools");
const [mode, setMode] = useState("Encode");
const t = useTranslations("tools.base64");
const [mode, setMode] = useState(t("encode"));
const [message, setMessage] = useState("");
const [messageResult, setMessageResult] = useState("");
const [isHex, setHex] = useState(false);
@ -22,7 +23,7 @@ export default function Base64() {
setType("");
setInfo("");
setHex(false);
if (mode == "Encode") {
if (mode == t("encode")) {
setMessageResult(utoa(message));
} else {
if (validBase64(message)) {
@ -45,20 +46,20 @@ export default function Base64() {
}, [mode, message]);
return (
<div>
<h1 className="text-3xl font-semibold">{t("base64.title")}</h1>
<Switcher items={["Encode", "Decode"]} selected={mode} setSelected={setMode} class="mt-4" />
<h1 className="text-3xl font-semibold">{t("title")}</h1>
<Switcher items={[t("encode"), t("decode")]} selected={mode} setSelected={setMode} class="mt-4 font-medium text-lg" />
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
className="w-full h-80 mt-4 p-4 rounded-lg bg-zinc-100 dark:bg-zinc-800 resize-none outline-none duration-200 transition-colors-opacity border-2 border-transparent focus:border-zinc-600 dark:focus:border-zinc-300"
/>
<div className="w-full h-12 mt-4">
<span className="w-fit text-2xl font-bold leading-10">Result:</span>
<span className="w-fit text-2xl font-bold leading-10">{t('result')}</span>
<button
onClick={() => {
copyToClipboard(messageResult);
setType("info");
setInfo("Copied");
setInfo(t("copied"));
setTimeout(() => {
setInfo("");
setType("");
@ -66,17 +67,18 @@ export default function Base64() {
}}
className="absolute right-0 w-fit h-10 rounded-md leading-10 bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-300 hover:dark:bg-zinc-700 px-5 z-10 cursor-pointer duration-300"
>
Copy
{t('copy')}
</button>
</div>
<Notice type={type} info={info} class="mt-4" />
<div
className={`empty:py-0 mt-6 w-full h-fit rounded-md leading-10 bg-zinc-100 dark:bg-zinc-800 py-2 px-5 z-10 cursor-pointer duration-100 break-all ${
className={`empty:py-0 mt-6 w-full h-fit rounded-md bg-zinc-100 dark:bg-zinc-800
py-4 px-5 z-10 text-base leading-7 duration-300 break-all whitespace-pre-wrap ${
isHex ? "font-mono" : ""
}`}
>
{messageResult}
</div>
<Notice type={type} info={info} class="mt-4" />
</div>
);
}

View File

@ -23,7 +23,7 @@ export default function Notice(props: { type: string; info: string; class?: stri
<div
className={`relative ${props.class} ${
typeToColor[props.type]
} rounded-md w-full min-h-12 h-fit empty:px-0 px-4 z-20 cursor-pointer duration-100 `}
} rounded-md w-full min-h-12 h-fit empty:px-0 px-4 z-20 cursor-pointer duration-100 text-white`}
>
<Icon className="text-2xl mt-3" icon={typeToIcon[props.type]} />
<span className="absolute text-base mt-3 ml-1">{props.info}</span>

View File

@ -1,32 +0,0 @@
import { NLPResult } from "../onesearch/NLPResult";
import { stopwords } from "./stopwords";
export class NLP {
result: NLPResult;
constructor(
public query: String,
public task: String,
public intentionKeywords?: String[],
) {
this.result = new NLPResult();
}
public removeStopwords(extraStopwords: string[] = [], disableDefault: boolean = false){
const list = disableDefault ? extraStopwords : stopwords.concat(extraStopwords);
if (list.includes(this.query.trim())) {
this.query = "";
}
for (let word of list){
this.query = this.query.replace(new RegExp(`\\b${word}\\b`, 'gi'), '');
}
}
public extractSlots(str: string, useNER = false): string[]{
const slots: string[] = [];
return slots;
}
public trim() {
this.query = this.query.trim();
const wordList = this.query.split(" ").filter(word => word !== "");
this.query = wordList.join(" ");
}
}

View File

@ -1,7 +0,0 @@
export default function slotExtract(str: string, keywords: string[]) {
let r = str;
for (let keyword of keywords) {
r = r.replace(keyword, "");
}
return r.trim();
}

View File

@ -1,3 +0,0 @@
export const stopwords = ["a","about","above","after","again","against","all","am","an","and","any","are","aren't","as","at","be","because","been","before","being","below","between","both","but","by","can't","cannot","could","couldn't","did","didn't","do","does","doesn't","doing","don't","down","during","each","few","for","from","further","had","hadn't","has","hasn't","have","haven't","having","he","he'd","he'll","he's","her","here","here's","hers","herself","him","himself","his","how","how's","i","i'd","i'll","i'm","i've","if","in","into","is","isn't","it","it's","its","itself","let's","me","more","most","mustn't","my","myself","no","nor","not","of","off","on","once","only","or","other","ought","our","ours","ourselves","out","over","own","please","same","shan't","she","she'd","she'll","she's","should","shouldn't","so","some","such","than","that","that's","the","their","theirs","them","themselves","then","there","there's","these","they","they'd","they'll","they're","they've","this","those","through","to","too","under","until","up","very","was","wasn't","we","we'd","we'll","we're","we've","were","weren't","what","what's","when","when's","where","where's","which","while","who","who's","whom","why","why's","with","won't","would","wouldn't","you","you'd","you'll","you're","you've","your","yours","yourself","yourselves"];
export const convertStopwords = ["transform", "change", "translate", "convert"];

View File

@ -1,90 +1,3 @@
import slotExtract from "../nlp/extract";
import removeStopwords from "../nlp/stopwords";
import { NLPResult } from "./NLPResult";
import { Kbd } from "@nextui-org/react";
interface KeywordsDict {
[key: string]: number;
}
interface IntentionsDict {
[key: string]: number;
}
export function validBase64(str: string) {
return str.length % 4 == 0 && /^[A-Za-z0-9+/]+[=]{0,2}$/.test(str);
}
export function base64NLP(str: string) {
const keywords: KeywordsDict = {
base64: 1,
b64: 0.95,
base: 0.5
};
let result = new NLPResult(null, null, 0.0, 0.0);
for (let keyword of Object.keys(keywords)) {
const pos = str.trim().indexOf(keyword);
const l = str.length;
const w = str.split(" ").length;
if (w > 1 && (pos === 0 || pos == l)) {
result.probability += keywords[keyword];
break;
}
}
const intentions: IntentionsDict = {
decode: 0.1,
encode: 1
};
for (let intention of Object.keys(intentions)) {
const pos = str.trim().indexOf(intention);
const w = str.split(" ").length;
if (w > 1 && pos !== -1) {
result.confidence += intentions[intention];
result.intention = `base64.${intention}`;
break;
}
}
let processedQuery = str;
if (result.intention === "base64.encode") {
const blacklist = Object.keys(keywords).concat(Object.keys(intentions)).concat(["convert", "turn"]);
processedQuery = slotExtract(str, blacklist);
} else if (result.intention === "base64.decode") {
processedQuery = removeStopwords(str, Object.keys(keywords).concat(Object.keys(intentions))).trim();
}
if (result.intention === "base64.decode") {
if (validBase64(processedQuery)) {
result.confidence = 1;
} else {
result.confidence = 0;
}
} else if (validBase64(processedQuery) && result.intention !== "base64.encode") {
result.intention = "base64.decode";
result.confidence += Math.max(1 / Math.log2(1 / processedQuery.length) + 1, 0);
result.probability += Math.max(1 / Math.log2(1 / processedQuery.length) + 1, 0);
}
switch (result.intention) {
case "base64.encode":
result.suggestion = btoa(processedQuery);
result.prompt = (
<span>
Base64 Encode (Hit <Kbd keys={["enter"]}></Kbd> to copy):
</span>
);
break;
case "base64.decode":
if (result.confidence > 0.1) result.suggestion = atob(processedQuery);
result.prompt = (
<span>
Base64 Decode (Hit <Kbd keys={["enter"]}></Kbd> to copy):
</span>
);
break;
default:
break;
}
return result;
}
}

View File

@ -1,3 +1,3 @@
export const SPARKHOME_VERSION="4.17.0";
export const CLIENT_VERSION="4.17.0";
export const SPARKHOME_VERSION="4.17.1";
export const CLIENT_VERSION="4.17.1";
export const NEXT_API_VERSION="4.14.3";

View File

@ -21,7 +21,12 @@
},
"tools": {
"base64": {
"title": "Base64 tools - LuminaraUtils"
"title": "Base64 tools - LuminaraUtils",
"decode": "Decode",
"encode": "Encode",
"result": "Result: ",
"copy": "Copy",
"copied": "Copied"
}
}
}

View File

@ -18,7 +18,12 @@
},
"tools": {
"base64": {
"title": "Base64 工具"
"title": "Base64 工具",
"decode": "解码",
"encode": "编码",
"result": "结果:",
"copy": "复制",
"copied": "已复制"
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "sparkhome",
"version": "4.17.0",
"version": "4.17.1",
"private": false,
"scripts": {
"dev": "next dev",

View File

@ -1,18 +0,0 @@
import { NLP } from "@/lib/nlp/base";
import { convertStopwords } from "@/lib/nlp/stopwords";
import { describe, expect, test } from "@jest/globals";
describe("Test 1", () => {
test("basic", () => {
const nlp = new NLP("please", "remove-stopword");
nlp.removeStopwords();
expect(nlp.query).toBe("");
});
test("convert something", () => {
const nlp = new NLP("please convert 1cm to m", "remove-stopword");
nlp.removeStopwords(convertStopwords);
nlp.trim();
expect(nlp.query).toBe("1cm m");
});
});

View File

@ -1,11 +1,8 @@
import { base64NLP } from "@/lib/onesearch/baseCheck";
import { validBase64 } from "@/lib/onesearch/baseCheck";
import { describe, expect, test } from "@jest/globals";
describe("To auto-detect the intention of decoding an base64 string", () => {
test("Implicit declaration", () => {
expect(base64NLP("base64 encode encode MjM6MjQgQXByIDI1LCAyMDI0").intention).toBe("base64.encode");
expect(base64NLP("base64 encode encode MjM6MjQgQXByIDI1LCAyMDI0").suggestion).toBe(
"ZW5jb2RlIE1qTTZNalFnUVhCeUlESTFMQ0F5TURJMA=="
);
expect(validBase64("MjM6MjQgQXByIDI1LCAyMDI0")).toBe(true);
});
});