clean: remove unnecessary files, full i18n for base64 tools
This commit is contained in:
parent
421e4fcdb8
commit
13e79e2869
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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(" ");
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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"];
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
@ -21,7 +21,12 @@
|
||||
},
|
||||
"tools": {
|
||||
"base64": {
|
||||
"title": "Base64 tools - LuminaraUtils"
|
||||
"title": "Base64 tools - LuminaraUtils",
|
||||
"decode": "Decode",
|
||||
"encode": "Encode",
|
||||
"result": "Result: ",
|
||||
"copy": "Copy",
|
||||
"copied": "Copied"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,12 @@
|
||||
},
|
||||
"tools": {
|
||||
"base64": {
|
||||
"title": "Base64 工具"
|
||||
"title": "Base64 工具",
|
||||
"decode": "解码",
|
||||
"encode": "编码",
|
||||
"result": "结果:",
|
||||
"copy": "复制",
|
||||
"copied": "已复制"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sparkhome",
|
||||
"version": "4.17.0",
|
||||
"version": "4.17.1",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
@ -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");
|
||||
});
|
||||
});
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user