Merge branch 'main' into feature/text/diff

This commit is contained in:
rusconn
2024-10-24 20:50:16 +09:00
committed by GitHub
12 changed files with 89 additions and 105 deletions

View File

@@ -1,9 +1,9 @@
"use client";
import { useCallback, useState } from "react";
import { decode, encode, isValid } from "js-base64";
import { toolGroups } from "@/config/tools";
import { decode, encode } from "@/lib/base64";
import { Textarea, TextareaProps } from "@/components/ui/textarea";
import * as Button from "@/components/buttons";
import { ControlMenu } from "@/components/control-menu";
@@ -24,10 +24,10 @@ export default function Page() {
}, []);
const setFormByEncoded = useCallback((text: string) => {
const newDecoded = decode(text);
const newDecoded = decode(text) ?? "";
setForm({
decoded: isValid(text) && !newDecoded.includes("<22>") ? newDecoded : "",
decoded: newDecoded.includes("<22>") ? "" : newDecoded,
encoded: text,
});
}, []);

View File

@@ -1,6 +1,6 @@
"use client";
import { useCallback, useState } from "react";
import { useCallback, useMemo, useState } from "react";
import { toolGroups } from "@/config/tools";
import { safeJsonParse } from "@/lib/json";
@@ -25,7 +25,7 @@ export default function Page() {
const [indentation, setIndentation] = useState(indentations.two);
const [input, setInput] = useState('{\n"foo":"bar"\n}');
const parsed = safeJsonParse(input);
const parsed = useMemo(() => safeJsonParse(input), [input]);
const output = parsed.map(x => JSON.stringify(x, null, indentation)).unwrapOr("");
const clearInput = useCallback(() => setInput(""), []);

View File

@@ -1,7 +1,10 @@
"use client";
import { useCallback, useState } from "react";
import createHash from "create-hash";
import { useCallback, useMemo, useState } from "react";
import MD5 from "crypto-js/md5";
import SHA1 from "crypto-js/sha1";
import SHA256 from "crypto-js/sha256";
import SHA512 from "crypto-js/sha512";
import { toolGroups } from "@/config/tools";
import { Input } from "@/components/ui/input";
@@ -19,10 +22,10 @@ export default function Page() {
const [uppercase, setUppercase] = useState(false);
const [input, setInput] = useState("Hello there !");
const newMd5 = createHash("md5").update(input).digest("hex");
const newSha1 = createHash("sha1").update(input).digest("hex");
const newSha256 = createHash("sha256").update(input).digest("hex");
const newSha512 = createHash("sha512").update(input).digest("hex");
const newMd5 = useMemo(() => MD5(input).toString(), [input]);
const newSha1 = useMemo(() => SHA1(input).toString(), [input]);
const newSha256 = useMemo(() => SHA256(input).toString(), [input]);
const newSha512 = useMemo(() => SHA512(input).toString(), [input]);
const md5 = uppercase ? newMd5.toUpperCase() : newMd5;
const sha1 = uppercase ? newSha1.toUpperCase() : newSha1;

View File

@@ -1,7 +1,6 @@
"use client";
import { useCallback, useState } from "react";
import { range } from "fp-ts/NonEmptyArray";
import { useCallback, useMemo, useState } from "react";
import { toolGroups } from "@/config/tools";
import { uuid } from "@/lib/uuid";
@@ -39,7 +38,7 @@ export default function Page() {
const [uuids, setUuids] = useState<string[]>([]);
const ref = useAutoScroll<HTMLTextAreaElement>([uuids]);
const uuidsString = uuids.join("\n");
const uuidsString = useMemo(() => uuids.join("\n"), [uuids]);
const clearUuids = useCallback(() => setUuids([]), []);
@@ -58,7 +57,7 @@ export default function Page() {
}, []);
const onGenerateClick = () => {
const newUuids = range(1, generates).map(_ => uuid(uuidVersion, hyphens, uppercase));
const newUuids = Array.from({ length: generates }, () => uuid(uuidVersion, hyphens, uppercase));
setUuids([...uuids, ...newUuids]);
};

View File

@@ -1,5 +1,3 @@
import { chunksOf, intersperse } from "fp-ts/Array";
const match = (regex: RegExp) => (x: string) => regex.test(x);
export const isDecimal = match(/^[0-9]*$/);
@@ -8,10 +6,16 @@ export const isOctal = match(/^[0-7]*$/);
export const isBinary = match(/^[0-1]*$/);
const formatNumber = (digits: number, sep: string) => (s: string) => {
const a = [...s].reverse();
const b = chunksOf(digits)(a);
const c = intersperse([sep])(b);
return c.flat().reverse().join("");
const head = ((s.length - 1) % digits) + 1;
const buf = [];
buf.push(s.substring(0, head));
for (let i = head; i < s.length; i += digits) {
buf.push(sep, s.substring(i, i + digits));
}
return buf.join("");
};
export const formatDecimal = formatNumber(3, ",");

14
lib/base64.ts Normal file
View File

@@ -0,0 +1,14 @@
export const encode = (s: string) => {
const bytes = new TextEncoder().encode(s);
return btoa(String.fromCharCode(...bytes));
};
export const decode = (base64: string) => {
try {
const binString = atob(base64);
const bytes = Uint8Array.from(binString, c => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
} catch {
return undefined;
}
};

View File

@@ -37,11 +37,9 @@
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"cmdk": "^0.2.0",
"create-hash": "^1.2.0",
"fp-ts": "^2.16.0",
"crypto-js": "^4.2.0",
"fuse.js": "^6.6.2",
"html-escaper": "^3.0.3",
"js-base64": "^3.7.5",
"js-yaml": "^4.1.0",
"jwt-decode": "^3.1.2",
"lucide-react": "^0.221.0",
@@ -62,7 +60,7 @@
"@ianvs/prettier-plugin-sort-imports": "^4.0.1",
"@next/bundle-analyzer": "13.5.4",
"@playwright/test": "^1.39.0",
"@types/create-hash": "^1.2.2",
"@types/crypto-js": "^4.2.2",
"@types/html-escaper": "^3.0.0",
"@types/js-yaml": "^4.0.5",
"@types/node": "~18.16.16",

120
pnpm-lock.yaml generated
View File

@@ -1,5 +1,9 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
'@monaco-editor/react':
specifier: ^4.5.1
@@ -37,21 +41,15 @@ dependencies:
cmdk:
specifier: ^0.2.0
version: 0.2.0(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
create-hash:
specifier: ^1.2.0
version: 1.2.0
fp-ts:
specifier: ^2.16.0
version: 2.16.0
crypto-js:
specifier: ^4.2.0
version: 4.2.0
fuse.js:
specifier: ^6.6.2
version: 6.6.2
html-escaper:
specifier: ^3.0.3
version: 3.0.3
js-base64:
specifier: ^3.7.5
version: 3.7.5
js-yaml:
specifier: ^4.1.0
version: 4.1.0
@@ -108,9 +106,9 @@ devDependencies:
'@playwright/test':
specifier: ^1.39.0
version: 1.39.0
'@types/create-hash':
specifier: ^1.2.2
version: 1.2.2
'@types/crypto-js':
specifier: ^4.2.2
version: 4.2.2
'@types/html-escaper':
specifier: ^3.0.0
version: 3.0.0
@@ -1552,10 +1550,8 @@ packages:
tslib: 2.6.2
dev: false
/@types/create-hash@1.2.2:
resolution: {integrity: sha512-Fg8/kfMJObbETFU/Tn+Y0jieYewryLrbKwLCEIwPyklZZVY2qB+64KFjhplGSw+cseZosfFXctXO+PyIYD8iZQ==}
dependencies:
'@types/node': 18.16.16
/@types/crypto-js@4.2.2:
resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
dev: true
/@types/html-escaper@3.0.0:
@@ -2171,13 +2167,6 @@ packages:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
dev: false
/cipher-base@1.0.4:
resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==}
dependencies:
inherits: 2.0.4
safe-buffer: 5.2.1
dev: false
/class-variance-authority@0.6.0(typescript@5.0.4):
resolution: {integrity: sha512-qdRDgfjx3GRb9fpwpSvn+YaidnT7IUJNe4wt5/SWwM+PmUwJUhQRk/8zAyNro0PmVfmen2635UboTjIBXXxy5A==}
peerDependencies:
@@ -2309,16 +2298,6 @@ packages:
/convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
/create-hash@1.2.0:
resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==}
dependencies:
cipher-base: 1.0.4
inherits: 2.0.4
md5.js: 1.3.5
ripemd160: 2.0.2
sha.js: 2.4.11
dev: false
/cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'}
@@ -2328,6 +2307,10 @@ packages:
which: 2.0.2
dev: true
/crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
dev: false
/cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
@@ -2830,6 +2813,35 @@ packages:
- supports-color
dev: true
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-node@0.3.9)(eslint@8.41.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
eslint: '*'
eslint-import-resolver-node: '*'
eslint-import-resolver-typescript: '*'
eslint-import-resolver-webpack: '*'
peerDependenciesMeta:
'@typescript-eslint/parser':
optional: true
eslint:
optional: true
eslint-import-resolver-node:
optional: true
eslint-import-resolver-typescript:
optional: true
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.7(eslint@8.41.0)(typescript@5.0.4)
debug: 3.2.7
eslint: 8.41.0
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
dev: true
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
@@ -2882,7 +2894,7 @@ packages:
doctrine: 2.1.0
eslint: 8.41.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.7)(eslint-import-resolver-node@0.3.9)(eslint@8.41.0)
has: 1.0.4
is-core-module: 2.13.0
is-glob: 4.0.3
@@ -3181,10 +3193,6 @@ packages:
is-callable: 1.2.7
dev: true
/fp-ts@2.16.0:
resolution: {integrity: sha512-bLq+KgbiXdTEoT1zcARrWEpa5z6A/8b7PcDW7Gef3NSisQ+VS7ll2Xbf1E+xsgik0rWub/8u0qP/iTTjj+PhxQ==}
dev: false
/fraction.js@4.2.0:
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
dev: true
@@ -3444,15 +3452,6 @@ packages:
engines: {node: '>= 0.4.0'}
dev: true
/hash-base@3.1.0:
resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==}
engines: {node: '>=4'}
dependencies:
inherits: 2.0.4
readable-stream: 3.6.2
safe-buffer: 5.2.1
dev: false
/html-escaper@3.0.3:
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
dev: false
@@ -3740,10 +3739,6 @@ packages:
resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==}
hasBin: true
/js-base64@3.7.5:
resolution: {integrity: sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==}
dev: false
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -3859,14 +3854,6 @@ packages:
react: 18.2.0
dev: false
/md5.js@1.3.5:
resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==}
dependencies:
hash-base: 3.1.0
inherits: 2.0.4
safe-buffer: 5.2.1
dev: false
/merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
dev: true
@@ -4677,13 +4664,6 @@ packages:
glob: 7.2.3
dev: true
/ripemd160@2.0.2:
resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==}
dependencies:
hash-base: 3.1.0
inherits: 2.0.4
dev: false
/run-applescript@5.0.0:
resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==}
engines: {node: '>=12'}
@@ -4785,14 +4765,6 @@ packages:
has-property-descriptors: 1.0.0
dev: true
/sha.js@2.4.11:
resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==}
hasBin: true
dependencies:
inherits: 2.0.4
safe-buffer: 5.2.1
dev: false
/sharp@0.32.1:
resolution: {integrity: sha512-kQTFtj7ldpUqSe8kDxoGLZc1rnMFU0AO2pqbX6pLy3b7Oj8ivJIdoKNwxHVQG2HN6XpHPJqCSM2nsma2gOXvOg==}
engines: {node: '>=14.15.0'}

View File

@@ -1,6 +0,0 @@
import { expect, test } from "@playwright/test";
test("VRT", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveScreenshot();
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB