diff --git a/package-lock.json b/package-lock.json index 2541496..350e32f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -88,6 +88,7 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -303,6 +304,7 @@ "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" @@ -314,6 +316,7 @@ "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -1233,6 +1236,7 @@ "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1286,6 +1290,7 @@ "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1468,6 +1473,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.42", "caniuse-lite": "^1.0.30001803", @@ -1723,6 +1729,7 @@ "integrity": "sha512-GVTD7s1vdIl6UYvAfriOPeY1Df8LIZjfofLvHwde+erDHGGuHyuM6xoxRxmHiebhYuD2p1vN4wWh0XzPARSGDQ==", "dev": true, "license": "MIT", + "peer": true, "workspaces": [ "packages/*" ], @@ -2666,7 +2673,6 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", "license": "MIT", - "peer": true, "dependencies": { "dompurify": "3.2.7", "marked": "14.0.0" @@ -2677,7 +2683,6 @@ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", "license": "(MPL-2.0 OR Apache-2.0)", - "peer": true, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -2687,7 +2692,6 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", "license": "MIT", - "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -2835,6 +2839,7 @@ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2871,6 +2876,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", @@ -2949,6 +2955,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -2958,6 +2965,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -3214,7 +3222,8 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tapable": { "version": "2.3.3", @@ -3320,6 +3329,7 @@ "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", @@ -3557,6 +3567,7 @@ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/public/sitemap.xml b/public/sitemap.xml index 390f242..b5ff185 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -130,21 +130,15 @@ weekly 0.7 - - https://dev-tasks-beta.vercel.app/devutilities/json - 2026-06-27 - weekly - 0.7 - https://dev-tasks-beta.vercel.app/devutilities/json-yaml-csv-xml - 2026-06-27 + 2026-07-22 weekly 0.7 https://dev-tasks-beta.vercel.app/devutilities/markdown - 2026-06-27 + 2026-07-22 weekly 0.7 @@ -156,13 +150,7 @@ https://dev-tasks-beta.vercel.app/devutilities/base64 - 2026-06-27 - weekly - 0.7 - - - https://dev-tasks-beta.vercel.app/devutilities/base64-image - 2026-06-27 + 2026-07-22 weekly 0.7 @@ -186,13 +174,7 @@ https://dev-tasks-beta.vercel.app/devutilities/jwt - 2026-06-27 - weekly - 0.7 - - - https://dev-tasks-beta.vercel.app/devutilities/jwt-encode - 2026-06-27 + 2026-07-22 weekly 0.7 @@ -228,7 +210,7 @@ https://dev-tasks-beta.vercel.app/devutilities/text-case - 2026-06-27 + 2026-07-22 weekly 0.7 @@ -250,12 +232,7 @@ weekly 0.7 - - https://dev-tasks-beta.vercel.app/devutilities/markdown-table-generator - 2026-06-27 - weekly - 0.7 - + https://dev-tasks-beta.vercel.app/devutilities/url-parser 2026-06-27 @@ -292,12 +269,7 @@ weekly 0.7 - - https://dev-tasks-beta.vercel.app/devutilities/string-inspector - 2026-06-27 - weekly - 0.7 - + https://dev-tasks-beta.vercel.app/devutilities/number-base-converter 2026-06-27 @@ -342,7 +314,7 @@ https://dev-tasks-beta.vercel.app/devutilities/svg-optimizer - 2026-06-27 + 2026-07-22 weekly 0.7 @@ -376,12 +348,7 @@ weekly 0.7 - - https://dev-tasks-beta.vercel.app/devutilities/word-counter - 2026-07-01 - weekly - 0.7 - + https://dev-tasks-beta.vercel.app/devutilities/sql-converter 2026-07-01 @@ -466,12 +433,7 @@ weekly 0.7 - - https://dev-tasks-beta.vercel.app/devutilities/text-list-cleaner - 2026-07-16 - weekly - 0.7 - + https://dev-tasks-beta.vercel.app/devutilities/shape-divider 2026-07-16 diff --git a/src/App.jsx b/src/App.jsx index 124e9a1..6dfe075 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -31,7 +31,6 @@ import DeleteHistoryResource from "./pages/ResourceHub/resourcehub/DeleteHistory import ListResources from "./pages/ResourceHub/resourcehub/ListResources"; // Dev Utilities Imports -import Base64Image from "./pages/DevUtilities/devutilities/Base64Image"; import Base64Url from "./pages/DevUtilities/devutilities/Base64Url"; import BcryptGenerator from "./pages/DevUtilities/devutilities/BcryptGenerator"; import BorderImageGenerator from "./pages/DevUtilities/devutilities/BorderImageGenerator"; @@ -52,17 +51,14 @@ import FlexboxGridGenerator from "./pages/DevUtilities/devutilities/FlexboxGridG import HashGenerator from "./pages/DevUtilities/devutilities/HashGenerator"; import HtmlEntityConverter from "./pages/DevUtilities/devutilities/HtmlEntityConverter"; import HtmlMultiConverter from "./pages/DevUtilities/devutilities/HtmlMultiConverter"; -import JsonFormatter from "./pages/DevUtilities/devutilities/JsonFormatter"; +import JsonYamlCsvXmlConverter from "./pages/DevUtilities/devutilities/JsonYamlCsvXmlConverter"; import JsonPathEvaluator from "./pages/DevUtilities/devutilities/JsonPathEvaluator"; import JsonSchemaValidator from "./pages/DevUtilities/devutilities/JsonSchemaValidator"; -import JsonYamlCsvXmlConverter from "./pages/DevUtilities/devutilities/JsonYamlCsvXmlConverter"; import JwtDecoder from "./pages/DevUtilities/devutilities/JwtDecoder"; -import JwtEncoder from "./pages/DevUtilities/devutilities/JwtEncoder"; import XmlValidator from "./pages/DevUtilities/devutilities/XmlValidator"; import KeycodeInspector from "./pages/DevUtilities/devutilities/KeycodeInspector"; import LoremIpsumGenerator from "./pages/DevUtilities/devutilities/LoremIpsumGenerator"; import MarkdownPreviewer from "./pages/DevUtilities/devutilities/MarkdownPreviewer"; -import MarkdownTableGenerator from "./pages/DevUtilities/devutilities/MarkdownTableGenerator"; import MockJsonGenerator from "./pages/DevUtilities/devutilities/MockJsonDataGenerator"; import NumberBaseConverter from "./pages/DevUtilities/devutilities/NumberBaseConverter"; import PasswordGenerator from "./pages/DevUtilities/devutilities/PasswordGenerator"; @@ -71,10 +67,8 @@ import RegexTester from "./pages/DevUtilities/devutilities/RegexTester"; import ShapeDividerGenerator from "./pages/DevUtilities/devutilities/ShapeDividerGenerator"; import SqlFormatter from "./pages/DevUtilities/devutilities/SqlFormatter"; import SqlSchemaConverter from "./pages/DevUtilities/devutilities/SqlSchemaConverter"; -import StringInspector from "./pages/DevUtilities/devutilities/StringInspector"; import SubnetCalculator from "./pages/DevUtilities/devutilities/SubnetCalculator"; import SvgOptimizer from "./pages/DevUtilities/devutilities/SvgOptimizer"; -import SvgToDataUri from "./pages/DevUtilities/devutilities/SvgToDataUri"; import SlugGenerator from "./pages/DevUtilities/devutilities/SlugGenerator"; import TextCaseConverter from "./pages/DevUtilities/devutilities/TextCaseConverter"; import TimestampConverter from "./pages/DevUtilities/devutilities/TimestampConverter"; @@ -82,8 +76,6 @@ import TokenGenerator from "./pages/DevUtilities/devutilities/TokenGenerator"; import UrlParserBuilder from "./pages/DevUtilities/devutilities/UrlParserBuilder"; import UserAgentParser from "./pages/DevUtilities/devutilities/UserAgentParser"; import UuidGenerator from "./pages/DevUtilities/devutilities/UuidGenerator"; -import WordCounter from "./pages/DevUtilities/devutilities/WordCounter"; -import TextListCleaner from "./pages/DevUtilities/devutilities/TextListCleaner"; import GitCommandBuilder from "./pages/DevUtilities/devutilities/GitCommandBuilder"; import ImageOptimizer from "./pages/DevUtilities/devutilities/ImageOptimizer"; import ColorPaletteExtractor from "./pages/DevUtilities/devutilities/ColorPaletteExtractor"; @@ -408,7 +400,10 @@ function AppInner({ toggleHUD, hudVisible }) { path="/devutilities/css-unit-converter" element={} /> - } /> + } + /> } @@ -446,7 +441,7 @@ function AppInner({ toggleHUD, hudVisible }) { } /> } + element={} /> } /> } /> - } /> + } + /> } /> } /> } /> @@ -486,7 +484,7 @@ function AppInner({ toggleHUD, hudVisible }) { /> } + element={} /> } /> } + element={} /> } + element={} /> } + element={} /> } + element={} /> } /> + } diff --git a/src/config/sidebarSections.js b/src/config/sidebarSections.js index 3bfe950..43df62e 100644 --- a/src/config/sidebarSections.js +++ b/src/config/sidebarSections.js @@ -143,13 +143,8 @@ const SIDEBAR_SECTIONS = [ description: "Inspect keyboard events in real time.", }, { - label: "JSON Formatter", - description: "Format and validate JSON", - path: "/devutilities/json", - }, - { - label: "JSON YAML CSV XML Converter", - description: "Convert JSON, YAML, CSV and XML formats", + label: "JSON & Data Format Suite", + description: "Format, beautify, minify, and convert JSON, YAML, CSV and XML data", path: "/devutilities/json-yaml-csv-xml", }, { @@ -173,30 +168,20 @@ const SIDEBAR_SECTIONS = [ path: "/devutilities/sql", }, { - label: "Markdown Previewer", - description: "Preview markdown syntax", + label: "Markdown Studio", + description: "Preview markdown syntax and build tables visually", path: "/devutilities/markdown", }, - { - label: "Markdown Table Generator", - description: "Build markdown tables visually", - path: "/devutilities/markdown-table-generator", - }, { label: "Regex Tester", description: "Test expressions", path: "/devutilities/regex", }, { - label: "Text Case Converter", - description: "Convert text into different cases", + label: "Text Processing Suite", + description: "Convert string cases, inspect text layout, analyze word densities, and sort/clean lists", path: "/devutilities/text-case", }, - { - label: "String Inspector", - description: "Analyze character, word, sentence, and paragraph counts", - path: "/devutilities/string-inspector", - }, { label: "Diff Checker", description: @@ -204,15 +189,10 @@ const SIDEBAR_SECTIONS = [ path: "/devutilities/diff", }, { - label: "Base64 / URL", - description: "Encode and decode", + label: "Base64 & URL Converter Suite", + description: "Encode/decode text base64, URL components, and image files offline", path: "/devutilities/base64", }, - { - label: "Base64 Image", - description: "Encode/decode images with Base64", - path: "/devutilities/base64-image", - }, { label: "Morse Code Converter", description: "Convert text and Morse code", @@ -282,13 +262,8 @@ const SIDEBAR_SECTIONS = [ path: "/devutilities/bcrypt", }, { - label: "JWT Encoder", - description: "Create and sign JWT tokens", - path: "/devutilities/jwt-encode", - }, - { - label: "JWT Decoder", - description: "Inspect tokens", + label: "JWT Studio", + description: "Decode, sign, and encode JWT tokens offline", path: "/devutilities/jwt", }, { @@ -363,17 +338,10 @@ const SIDEBAR_SECTIONS = [ path: "/devutilities/cron", }, { - label: "SVG Optimizer & React JSX Generator", - description: - "Optimize, clean, and convert SVG code into optimized React JSX/TSX components instantly.", + label: "SVG Toolkit", + description: "Optimize SVGs, generate React JSX components, and compile Data URIs", path: "/devutilities/svg-optimizer", }, - { - label: "SVG to Data URI Converter", - description: - "Convert raw SVG markup into optimized CSS background-image statements and data URIs.", - path: "/devutilities/svg-to-data-uri", - }, { label: "Password Generator", description: @@ -407,18 +375,6 @@ const SIDEBAR_SECTIONS = [ "Generate production-ready Dockerfile and docker-compose.yml configurations client-side.", path: "/devutilities/docker-generator", }, - { - label: "Word Counter", - description: "Character & word count tool", - path: "/devutilities/word-counter", - }, - - { - label: "Text List Cleaner", - description: "Sort, clean, and remove duplicate text lines", - path: "/devutilities/text-list-cleaner", - }, - { label: "SQL Schema Converter", description: diff --git a/src/index.css b/src/index.css index 064f474..9f3a1bc 100644 --- a/src/index.css +++ b/src/index.css @@ -118,4 +118,15 @@ html, body, #root { .navbar-layout-content { scroll-behavior: smooth; +} + +/* Style selected/highlighted text globally to ensure high contrast legibility */ +::selection { + background-color: #18181b !important; /* zinc-900 */ + color: #ffffff !important; /* white */ +} + +.dark ::selection { + background-color: #f4f4f5 !important; /* zinc-100 */ + color: #09090b !important; /* zinc-950 */ } \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx index b9a1a6d..8a2d658 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -3,6 +3,34 @@ import { createRoot } from 'react-dom/client' import './index.css' import App from './App.jsx' +// Styled ASCII Art and Info in Console +console.log( + `%c _____ _____ _ \n` + + `%c | __ \\ |_ _| | | \n` + + `%c | | | | ___ _ __ | | __ _ ___ __| | __ ___\n` + + `%c | | | |/ _ \\ \\ / / | | / _\` / __|/ _\` |/ / __/\n` + + `%c | |__| | __/\\ V / | || (_| \\__ \\ (_| <\\__ \\\n` + + `%c |_____/ \\___| \\_/ |_| \\__,_|___/\\__,_|_\\_\\___/\n\n` + + `%cWelcome to Dev Tasks! πŸ› οΈ\n` + + `%cThis is a beginner-friendly open-source React project open for contributions. Feel free to fork the repo, pick any Good First Issue or Help Wanted task, and submit a pull request. UI improvements, features, bug fixes, and docs updates are welcome. Let’s build and learn πŸš€\n\n` + + `%c- Website: %chttps://dev-tasks-beta.vercel.app/\n` + + `%c- Repository: %chttps://github.com/shamilahmdt/devtasks\n` + + `%c- Contributing: %chttps://github.com/shamilahmdt/devtasks/blob/main/CONTRIBUTING.md\n` + + `%c- License: %cMIT\n`, + 'color: #a1a1aa; font-weight: bold;', + 'color: #a1a1aa; font-weight: bold;', + 'color: #a1a1aa; font-weight: bold;', + 'color: #a1a1aa; font-weight: bold;', + 'color: #a1a1aa; font-weight: bold;', + 'color: #a1a1aa; font-weight: bold;', + 'color: #e8e8ea; font-weight: bold; font-size: 13px;', + 'color: #94a3b8; line-height: 1.4;', + 'color: #a1a1aa;', 'color: #38bdf8; text-decoration: underline;', + 'color: #a1a1aa;', 'color: #38bdf8; text-decoration: underline;', + 'color: #a1a1aa;', 'color: #38bdf8; text-decoration: underline;', + 'color: #a1a1aa;', 'color: #e8e8ea; font-weight: bold;' +); + createRoot(document.getElementById('root')).render( diff --git a/src/pages/DevUtilities/DevUtilities.jsx b/src/pages/DevUtilities/DevUtilities.jsx index 9bce24d..580ec6c 100644 --- a/src/pages/DevUtilities/DevUtilities.jsx +++ b/src/pages/DevUtilities/DevUtilities.jsx @@ -72,9 +72,9 @@ const DevUtilities = () => { ), }, { - title: "Base64 / URL Encoder & Decoder", + title: "Base64 & URL Converter Suite", description: - "Encode and decode Base64 strings and URL components completely offline.", + "Encode and decode Base64 strings, URL components, and image files completely offline.", path: "/devutilities/base64", icon: ( @@ -94,10 +94,10 @@ const DevUtilities = () => { ), }, { - title: "SVG Optimizer & React JSX Generator", + title: "SVG Toolkit", description: - "Optimize, clean, and convert SVG code into optimized React JSX/TSX components instantly.", - keywords: "jsx react component tsx", + "Optimize, clean, and convert SVG code into optimized React JSX/TSX components or Data URIs.", + keywords: "jsx react component tsx svg data uri", path: "/devutilities/svg-optimizer", icon: ( { description: "Convert raw SVG markup into optimized CSS background-image statements and data URIs.", keywords: "svg uri css base64 image encode", - path: "/devutilities/svg-to-data-uri", + path: "/devutilities/svg-optimizer", icon: ( { ), }, { - title: "JSON Formatter", + title: "JSON & Data Format Suite", description: - "Validate JSON string formats, structure code outputs, beautify spacing, or minify data.", - path: "/devutilities/json", + "Format, validate, beautify, minify, and convert JSON, YAML, CSV and XML data.", + path: "/devutilities/json-yaml-csv-xml", icon: ( { ), }, { - title: "JWT Decoder", + title: "JWT Studio", description: - "Decode and inspect JSON Web Token header and payload data directly in the browser, completely offline.", + "Decode, inspect, edit, sign, and encode JSON Web Token header and payload data offline.", path: "/devutilities/jwt", icon: ( { title: "JWT Encoder", description: "Encode and inspect JSON Web Token header and payload data directly in the browser, completely offline.", - path: "/devutilities/jwt-encode", + path: "/devutilities/jwt", icon: ( { ), }, { - title: "Text Case Converter", + title: "Text Processing Suite", description: - "Convert text into camelCase, snake_case, kebab-case, PascalCase, title case, URL slug, and inspect text metrics.", + "Convert string cases, inspect layout metrics, analyze word densities, and clean/sort lists.", path: "/devutilities/text-case", icon: ( { ), }, - { - title: "Base64 Image Encoder & Decoder", - description: - "Encode images to Base64 strings and decode Base64 back to images. Drag & drop support, fully offline.", - path: "/devutilities/base64-image", - icon: ( - - - - ), - }, + { title: "Timestamp", description: @@ -636,9 +616,9 @@ const DevUtilities = () => { }, { - title: "Markdown Previewer", + title: "Markdown Studio", description: - "Write markdown and instantly preview rendered HTML output with support for headings, lists, links, code blocks, and more.", + "Write markdown and instantly preview rendered HTML output, or build markdown tables visually.", path: "/devutilities/markdown", icon: ( { title: "Markdown Table Generator", description: "Build markdown tables visually or convert CSV and TSV data instantly.", - path: "/devutilities/markdown-table-generator", + path: "/devutilities/markdown", icon: ( { title: "String Inspector", description: "Analyze character, word, sentence, and paragraph counts, byte size, reading/speaking time, and word frequency density.", - path: "/devutilities/string-inspector", + path: "/devutilities/text-case", icon: ( { { title: "Word Counter", description: "Count characters and words in your text instantly.", - path: "/devutilities/word-counter", + path: "/devutilities/text-case", icon: ( { "Sort lines, remove duplicates, trim whitespace, and remove empty lines completely offline.", keywords: "text list sort lines duplicates deduplicate clean trim whitespace", - path: "/devutilities/text-list-cleaner", + path: "/devutilities/text-case", icon: ( { - const { dark } = useTheme(); - const [mode, setMode] = useState("encode"); // encode | decode - const [inputText, setInputText] = useState(""); // Base64 string for decode - const [outputText, setOutputText] = useState(""); // Base64 output for encode - const [previewSrc, setPreviewSrc] = useState(""); // image preview - const [fileInfo, setFileInfo] = useState(null); // { name, size, type } - const fileInputRef = useRef(null); - - const resetAll = () => { - setInputText(""); - setOutputText(""); - setPreviewSrc(""); - setFileInfo(null); - }; - - // === ENCODE: image file β†’ Base64 === - const handleFileChange = (e) => { - const file = e.target.files[0]; - if (!file) return; - - // Validate it's an image - if (!file.type.startsWith("image/")) { - toast.error("Please select an image file."); - return; - } - - setFileInfo({ - name: file.name, - size: file.size, - type: file.type, - }); - - const reader = new FileReader(); - reader.onload = () => { - const base64 = reader.result; // data:image/png;base64,... - setOutputText(base64); - setPreviewSrc(base64); - toast.success("Image encoded to Base64!"); - }; - reader.onerror = () => { - toast.error("Failed to read the image file."); - }; - reader.readAsDataURL(file); - }; - - const handleDrop = (e) => { - e.preventDefault(); - const file = e.dataTransfer.files[0]; - if (file) { - // Create a synthetic event-like object - const syntheticEvent = { target: { files: [file] } }; - handleFileChange(syntheticEvent); - } - }; - - const handleDragOver = (e) => { - e.preventDefault(); - }; - - const handleCopyOutput = async () => { - if (!outputText) return; - try { - await navigator.clipboard.writeText(outputText); - toast.success("Copied to clipboard"); - } catch { - toast.error("Failed to copy"); - } - }; - - // === DECODE: Base64 string β†’ image preview === - const handleDecode = () => { - if (!inputText.trim()) { - toast.error("Please enter a Base64 string."); - return; - } - - let base64 = inputText.trim(); - // Support both data:image/...;base64,... and raw base64 - if (base64.startsWith("data:image/")) { - // Already a data URL, use directly - } else { - // Raw base64 β€” try to detect image type from signature - const signatures = { - "/9j/": "image/jpeg", - "iVBORw0KGgo": "image/png", - "R0lGOD": "image/gif", - "UklGR": "image/webp", - "Qk": "image/bmp", - }; - let mime = "image/png"; // default - for (const [sig, m] of Object.entries(signatures)) { - if (base64.startsWith(sig)) { - mime = m; - break; - } - } - base64 = `data:${mime};base64,${base64}`; - } - - setPreviewSrc(base64); - setOutputText(base64); - toast.success("Base64 decoded to image!"); - }; - - const handleDownloadImage = () => { - if (!previewSrc) return; - const a = document.createElement("a"); - a.href = previewSrc; - const ext = previewSrc.includes("image/png") - ? "png" - : previewSrc.includes("image/jpeg") - ? "jpg" - : previewSrc.includes("image/gif") - ? "gif" - : previewSrc.includes("image/webp") - ? "webp" - : "png"; - a.download = `image.${ext}`; - a.click(); - toast.success("Download started!"); - }; - - const handleSampleBase64 = () => { - // A tiny 1x1 red PNG as a sample - setInputText( - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==", - ); - setPreviewSrc(""); - setOutputText(""); - }; - - const formatBytes = (bytes) => { - if (bytes < 1024) return `${bytes} B`; - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; - return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; - }; - - return ( -
- Base64 Image Encoder & Decoder | DevTasks - - -
- {/* Header */} -
-
-
- - - - - -

- Base64 Image Encoder & Decoder -

-
- - {/* Mode Selector */} -
- {[ - { key: "encode", label: "Encode" }, - { key: "decode", label: "Decode" }, - ].map((opt) => ( - - ))} -
-
-
- - {/* Content Area */} -
- {mode === "encode" ? ( - /* ── ENCODE MODE ── */ -
- {/* LEFT: Drop Zone */} -
- -
fileInputRef.current?.click()} - className={`flex-1 min-h-[256px] flex flex-col items-center justify-center gap-3 p-6 rounded-xl border-2 border-dashed cursor-pointer transition-colors ${ - dark - ? "border-zinc-700 bg-zinc-950 hover:border-zinc-500" - : "border-neutral-300 bg-neutral-50 hover:border-neutral-400" - }`} - > - - - - - Drop an image or click to browse - - - Supports PNG, JPEG, GIF, WebP, BMP, SVG - - -
- {fileInfo && ( -
- {fileInfo.name} β€”{" "} - {formatBytes(fileInfo.size)} ({fileInfo.type}) -
- )} -
- - {/* RIGHT: Preview + Base64 Output */} -
- {/* Preview */} -
- -
- {previewSrc ? ( - Preview - ) : ( - - Image preview will appear here - - )} -
-
- - {/* Base64 Output */} -
-
- - {outputText && ( - - {formatBytes(outputText.length)} chars - - )} -
- + > + {MODES.map((opt) => ( + + ))} +
- {/* RIGHT COLUMN: Output */} -
-
- +
+
+
+ + +
+
-
- {/* Action Buttons (Centered at bottom) */} -
- {actionButtons.map((btn) => ( +
+ + + - ))} +
-
+ )} + + {/* ── Tab 2: Image to/from Base64 ── */} + {activeTab === "image" && ( +
+
+
+ {[ + { key: "encode", label: "Encode Image" }, + { key: "decode", label: "Decode Base64" }, + ].map((opt) => ( + + ))} +
+
+ + {imageMode === "encode" ? ( +
+ {/* Upload Section */} +
+ +
fileInputRef.current?.click()} + className={`flex-1 min-h-[256px] flex flex-col items-center justify-center gap-3 p-6 rounded-xl border-2 border-dashed cursor-pointer transition-colors ${ + dark + ? "border-zinc-700 bg-zinc-950 hover:border-zinc-500" + : "border-neutral-300 bg-neutral-50 hover:border-neutral-400" + }`} + > + + + + + Drop an image or click to browse + + + Supports PNG, JPEG, GIF, WebP, BMP, SVG + + +
+ {imgFileInfo && ( +
+ {imgFileInfo.name} β€”{" "} + {formatBytes(imgFileInfo.size)} ({imgFileInfo.type}) +
+ )} +
+ + {/* Preview & String Output */} +
+
+ +
+ {imgPreviewSrc ? ( + Preview + ) : ( + + Image preview will appear here + + )} +
+
+ +
+
+ + {imgOutputText && ( + + {formatBytes(imgOutputText.length)} chars + + )} +
+