feat: add hash generator

This commit is contained in:
rusconn
2022-04-02 10:21:39 +09:00
parent 3d2c74804e
commit 8e79da00f3
8 changed files with 598 additions and 361 deletions

View File

@@ -24,6 +24,7 @@
"@mui/icons-material": "^5.5.1",
"@mui/material": "^5.5.1",
"ace-builds": "^1.4.14",
"create-hash": "^1.2.0",
"fast-deep-equal": "^3.1.3",
"fp-ts": "^2.11.9",
"fuse.js": "^6.5.3",
@@ -39,6 +40,7 @@
},
"devDependencies": {
"@emotion/babel-plugin": "^11.7.2",
"@types/create-hash": "^1.2.2",
"@types/node": "^16.11.45",
"@types/react": "17.0.41",
"@typescript-eslint/eslint-plugin": "^5.15.0",

View File

@@ -0,0 +1,36 @@
import { FontDownload } from "@mui/icons-material";
import { FormControlLabel, Switch } from "@mui/material";
import { SwitchBaseProps } from "@mui/material/internal/SwitchBase";
import { memo } from "react";
import { Configurations } from "@/components/common";
type SwitchChecked = NonNullable<SwitchBaseProps["checked"]>;
type OnSwitchChange = NonNullable<SwitchBaseProps["onChange"]>;
type Props = {
uppercase: SwitchChecked;
onCaseChange: OnSwitchChange;
};
const StyledComponent = ({ uppercase, onCaseChange }: Props) => (
<Configurations
configurations={[
{
icon: <FontDownload />,
title: "Uppercase",
input: (
<FormControlLabel
labelPlacement="start"
label={uppercase ? "On" : "Off"}
control={<Switch checked={uppercase} onChange={onCaseChange} />}
/>
),
},
]}
/>
);
export const Component = memo(StyledComponent);
export default Component;

View File

@@ -0,0 +1,95 @@
import { Stack } from "@mui/material";
import createHash from "create-hash"; // smaller bundle size than Node.js standard library
import { ComponentPropsWithoutRef, memo, useCallback, useState } from "react";
import { Main, MainItem, TextField } from "@/components/common";
import Configuration from "./Configuration";
type TextFieldValue = ComponentPropsWithoutRef<typeof TextField>["value"];
type OnTextFieldChange = NonNullable<ComponentPropsWithoutRef<typeof TextField>["onChange"]>;
type Props = {
input: TextFieldValue;
md5: TextFieldValue;
sha1: TextFieldValue;
sha256: TextFieldValue;
sha512: TextFieldValue;
onInputChange: OnTextFieldChange;
} & ComponentPropsWithoutRef<typeof Configuration>;
const StyledComponent = ({
uppercase,
input,
md5,
sha1,
sha256,
sha512,
onCaseChange,
onInputChange,
}: Props) => (
<Main title="Hash Generator">
<MainItem title="Configuration">
<Configuration {...{ uppercase, onCaseChange }} />
</MainItem>
<MainItem title="Input">
<TextField multiline rows={5} value={input} onChange={onInputChange} />
</MainItem>
<Stack spacing={1}>
<MainItem title="MD5">
<TextField value={md5} InputProps={{ readOnly: true }} />
</MainItem>
<MainItem title="SHA1">
<TextField value={sha1} InputProps={{ readOnly: true }} />
</MainItem>
<MainItem title="SHA256">
<TextField value={sha256} InputProps={{ readOnly: true }} />
</MainItem>
<MainItem title="SHA512">
<TextField value={sha512} InputProps={{ readOnly: true }} />
</MainItem>
</Stack>
</Main>
);
export const Component = memo(StyledComponent);
const Container = () => {
const [uppercase, setUppercase] = useState(false);
const [input, setInput] = useState("Hello there !");
const onCaseChange: Props["onCaseChange"] = useCallback((_e, checked) => {
setUppercase(checked);
}, []);
const onInputChange: Props["onInputChange"] = useCallback(({ currentTarget: { value } }) => {
setInput(value);
}, []);
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 md5 = uppercase ? newMd5.toUpperCase() : newMd5;
const sha1 = uppercase ? newSha1.toUpperCase() : newSha1;
const sha256 = uppercase ? newSha256.toUpperCase() : newSha256;
const sha512 = uppercase ? newSha512.toUpperCase() : newSha512;
return (
<Component
{...{
uppercase,
input,
md5,
sha1,
sha256,
sha512,
onCaseChange,
onInputChange,
}}
/>
);
};
export default Container;

View File

@@ -0,0 +1,3 @@
import Content from "./Content";
export { Content };

View File

@@ -112,8 +112,8 @@ const toolGroups = [
longTitle: "Hash Generator",
description: "Calculate MD5, SHA1, SHA256 and SHA512 hash from text data",
keywords: "hash generator md5 sha1 sha256 sha512",
href: pagesPath.$url(),
disabled: true,
href: pagesPath.generators.hash.$url(),
disabled: false,
},
{
icon: <Numbers />,

View File

@@ -47,6 +47,14 @@ export const pagesPath = {
}),
},
},
generators: {
hash: {
$url: (url?: { hash?: string }) => ({
pathname: "/generators/hash" as const,
hash: url?.hash,
}),
},
},
search: {
$url: (url?: { hash?: string }) => ({ pathname: "/search" as const, hash: url?.hash }),
},

View File

@@ -0,0 +1,7 @@
import type { NextPage } from "next";
import { Content } from "@/components/pages/generators/hash";
const Page: NextPage = Content;
export default Page;

804
yarn.lock

File diff suppressed because it is too large Load Diff