diff --git a/package.json b/package.json
index 4567c49..02f2c2e 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.0",
"react-icons": "^4.7.1",
+ "react-json-pretty": "^2.2.0",
"react-markdown": "^9.0.1",
"react-modal": "^3.16.1",
"react-router-dom": "^6.25.1",
diff --git a/src/components/DevAreaTools/JSONFormatter.jsx b/src/components/DevAreaTools/JSONFormatter.jsx
new file mode 100644
index 0000000..5e21031
--- /dev/null
+++ b/src/components/DevAreaTools/JSONFormatter.jsx
@@ -0,0 +1,72 @@
+import React, { useState } from 'react';
+import { Input, Button, Alert } from 'antd';
+import JSONPretty from 'react-json-pretty'; // You might need to install this library for pretty JSON output
+import 'react-json-pretty/themes/monikai.css'; // Optional: import a theme for JSONPretty
+import { toast } from 'sonner';
+
+const JSONFormatter = () => {
+ const [jsonInput, setJsonInput] = useState('');
+ const [formattedJson, setFormattedJson] = useState(null);
+ const [error, setError] = useState('');
+
+ const handleFormat = () => {
+ try {
+ const parsedJson = JSON.parse(jsonInput);
+ setFormattedJson(parsedJson);
+ setError('');
+ } catch (err) {
+ setError('Invalid JSON format');
+ setFormattedJson(null);
+ }
+ };
+
+ const handleClear = () => {
+ setJsonInput('');
+ setFormattedJson(null);
+ setError('');
+ };
+
+ const handleCopy = () => {
+ if (formattedJson) {
+ navigator.clipboard.writeText(JSON.stringify(formattedJson, null, 2))
+ .then(() => {
+ toast.success('JSON copied to clipboard');
+ })
+ .catch(err => alert('Failed to copy JSON: ' + err));
+ } else {
+ alert('Nothing to copy');
+ }
+ };
+
+ return (
+
+
JSON Formatter
+
setJsonInput(e.target.value)}
+ placeholder="Paste your JSON here"
+ autoSize={{ minRows: 10 }}
+ className='mb-4 dark:bg-dark dark:text-white'
+ />
+
+
+
+
+
+ {error && }
+ {formattedJson && (
+
+ navigator.clipboard.writeText(JSON.stringify(data, null, 2))} />
+
+ )}
+
+ );
+};
+
+export default JSONFormatter;
diff --git a/src/components/DevAreaTools/MarkDownEditor.jsx b/src/components/DevAreaTools/MarkDownEditor.jsx
new file mode 100644
index 0000000..454fd99
--- /dev/null
+++ b/src/components/DevAreaTools/MarkDownEditor.jsx
@@ -0,0 +1,104 @@
+import React, { useState } from 'react';
+import ReactMarkdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
+import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
+import { a11yDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
+import { Input, Button } from 'antd';
+import Layout from '../Layout/Layout';
+
+const MarkDownEditor = () => {
+ const [content, setContent] = useState("");
+
+ const handleDownload = () => {
+ const blob = new Blob([content], { type: 'text/markdown;charset=utf-8' });
+ const url = URL.createObjectURL(blob);
+ const link = document.createElement('a');
+ link.href = url;
+ link.download = 'document.md';
+ link.click();
+ URL.revokeObjectURL(url);
+ };
+
+ return (
+
+
+ setContent(e.target.value)}
+ placeholder="Enter markdown here"
+ autoSize={{ minRows: 20 }}
+ className='min-h-screen dark:bg-black text-sm md:text-base dark:text-white p-4 !outline-none placeholder:font-semibold'
+ />
+
+
+
+
+
+ {String(children).replace(/\n$/, '')}
+
+ ) : (
+
+ {children}
+
+ );
+ },
+ blockquote({ node, children }) {
+ return {children}
;
+ },
+ li({ node, children }) {
+ return {children};
+ },
+ ul({ node, children }) {
+ return ;
+ },
+ ol({ node, children }) {
+ return {children}
;
+ },
+ img({ node, src, alt }) {
+ return ;
+ },
+ h1({ node, children }) {
+ return {children}
;
+ },
+ h2({ node, children }) {
+ return {children}
;
+ },
+ h3({ node, children }) {
+ return {children}
;
+ },
+ h4({ node, children }) {
+ return {children}
;
+ },
+ h5({ node, children }) {
+ return {children}
;
+ },
+ h6({ node, children }) {
+ return {children}
;
+ }
+ }}
+ >
+ {content}
+
+
+
+ );
+};
+
+export default MarkDownEditor;
diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx
index 1b4b4b0..25a371c 100644
--- a/src/components/Header/Header.jsx
+++ b/src/components/Header/Header.jsx
@@ -36,6 +36,11 @@ function Header({notice }) {
link: "/doc",
icon: ,
},
+ {
+ name: "DevArea",
+ link: "/devarea",
+ icon: ,
+ },
{
name: "Resources",
link: "/resources",
diff --git a/src/components/Search/SearchInput.jsx b/src/components/Search/SearchInput.jsx
index 03171e1..0c3e6aa 100644
--- a/src/components/Search/SearchInput.jsx
+++ b/src/components/Search/SearchInput.jsx
@@ -48,17 +48,17 @@ function SearchInput({ search, setSearch, setType }) {
className="flex items-center border border-primary gap-4 py-2 px-6 rounded-lg w-11/12 md:w-4/6"
>
- {
- setSearch(e.target.value);
- setType("");
- }}
-/>
+ {
+ setSearch(e.target.value);
+ setType("");
+ }}
+ />
},
+ {
+ path: '/devarea',
+ element:
+ },
+ {
+ path: '/devarea/:tool',
+ element:
+ },
{
path: '/contributors',
element:
@@ -45,6 +56,7 @@ const router = createBrowserRouter(
ReactDOM.createRoot(document.getElementById("root")).render(
+
);
diff --git a/src/pages/DevArea/DevTools.jsx b/src/pages/DevArea/DevTools.jsx
new file mode 100644
index 0000000..e9e4923
--- /dev/null
+++ b/src/pages/DevArea/DevTools.jsx
@@ -0,0 +1,18 @@
+import { useParams } from "react-router-dom";
+import Layout from "../../components/Layout/Layout";
+import MarkDownEditor from "../../components/DevAreaTools/MarkDownEditor";
+import JSONFormatter from "../../components/DevAreaTools/JSONFormatter";
+
+const DevTools = () => {
+ const { tool } = useParams();
+
+ const tools = {
+ markdown: ,
+ "json-formatter":
+ }
+
+
+ return {tools[tool]};
+};
+
+export default DevTools;
diff --git a/src/pages/DevArea/index.jsx b/src/pages/DevArea/index.jsx
new file mode 100644
index 0000000..6f85c0b
--- /dev/null
+++ b/src/pages/DevArea/index.jsx
@@ -0,0 +1,73 @@
+import { Link } from "react-router-dom";
+import MainTitle from "../../components/Common/MainTitle";
+import Layout from "../../components/Layout/Layout";
+import { FaArrowRight } from "react-icons/fa";
+
+const DevArea = () => {
+ const tools = [
+ {
+ name: "Markdown",
+ link: "/devarea/markdown",
+ isAvailable: true
+ },
+ {
+ name: "JSON Formatter",
+ link: "/devarea/json-formatter",
+ isAvailable: true
+ },
+ {
+ name: "Base64 Encoder/Decoder",
+ link: "/devarea/base64",
+ isAvailable: false
+ },
+ {
+ name: "JWT Decoder",
+ link: "/devarea/jwt",
+ isAvailable: false
+ },
+ {
+ name: "URL Encoder/Decoder",
+ link: "/devarea/url",
+ isAvailable: false
+ },
+ {
+ name: "XML Formatter",
+ link: "/devarea/xml-formatter",
+ isAvailable: false
+ },
+ {
+ name: "YAML Formatter",
+ link: "/devarea/yaml-formatter",
+ isAvailable: false
+ },
+ {
+ name: "CSV Formatter",
+ link: "/devarea/csv-formatter",
+ isAvailable: false
+ },
+ ]
+ return
+
+
+
+
+ {tools.map((tool, index) => (
+ tool.isAvailable ?
+
+ {tool.name}
+
+
+ :
+
+ {tool.name}
+
+ ))}
+
+
+
+ ;
+};
+
+export default DevArea;
diff --git a/yarn.lock b/yarn.lock
index 6a2a6e4..83be36a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2740,6 +2740,13 @@ react-is@^18.2.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
+react-json-pretty@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/react-json-pretty/-/react-json-pretty-2.2.0.tgz#9ba907d2b08d87e90456d87b6025feeceb8f63cf"
+ integrity sha512-3UMzlAXkJ4R8S4vmkRKtvJHTewG4/rn1Q18n0zqdu/ipZbUPLVZD+QwC7uVcD/IAY3s8iNVHlgR2dMzIUS0n1A==
+ dependencies:
+ prop-types "^15.6.2"
+
react-lifecycles-compat@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"