From cc08ea589b0f9dffed62e426cf3866c3f97146e6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 30 Sep 2025 08:29:18 +0000
Subject: [PATCH 1/3] Initial plan
From c74d4667a104bf8a3006a37070a0f596827c5e84 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 30 Sep 2025 08:50:36 +0000
Subject: [PATCH 2/3] feat: Add 10 new educational tools using Svelte 5 runes
and shadcn components
Co-authored-by: Inglan <96573515+Inglan@users.noreply.github.com>
---
src/lib/navigation.ts | 40 +++
src/routes/+page.svelte | 12 +-
src/routes/tools/ascii-art/+page.svelte | 199 +++++++++++
.../tools/base64-converter/+page.svelte | 107 ++++++
src/routes/tools/color-picker/+page.svelte | 229 +++++++++++++
src/routes/tools/hash-generator/+page.svelte | 153 +++++++++
src/routes/tools/json-formatter/+page.svelte | 145 ++++++++
src/routes/tools/lorem-generator/+page.svelte | 303 +++++++++++++++++
.../tools/markdown-preview/+page.svelte | 314 ++++++++++++++++++
.../tools/qr-code-generator/+page.svelte | 67 ++++
src/routes/tools/regex-tester/+page.svelte | 282 ++++++++++++++++
src/routes/tools/url-tools/+page.svelte | 248 ++++++++++++++
12 files changed, 2098 insertions(+), 1 deletion(-)
create mode 100644 src/routes/tools/ascii-art/+page.svelte
create mode 100644 src/routes/tools/base64-converter/+page.svelte
create mode 100644 src/routes/tools/color-picker/+page.svelte
create mode 100644 src/routes/tools/hash-generator/+page.svelte
create mode 100644 src/routes/tools/json-formatter/+page.svelte
create mode 100644 src/routes/tools/lorem-generator/+page.svelte
create mode 100644 src/routes/tools/markdown-preview/+page.svelte
create mode 100644 src/routes/tools/qr-code-generator/+page.svelte
create mode 100644 src/routes/tools/regex-tester/+page.svelte
create mode 100644 src/routes/tools/url-tools/+page.svelte
diff --git a/src/lib/navigation.ts b/src/lib/navigation.ts
index 6e2eb5ad..c6710e22 100644
--- a/src/lib/navigation.ts
+++ b/src/lib/navigation.ts
@@ -67,6 +67,46 @@ export function createMainNavigation(
{
title: 'Stopwatch & Timer',
url: '/tools/stopwatch-timer'
+ },
+ {
+ title: 'QR Code Generator',
+ url: '/tools/qr-code-generator'
+ },
+ {
+ title: 'Base64 Converter',
+ url: '/tools/base64-converter'
+ },
+ {
+ title: 'JSON Formatter',
+ url: '/tools/json-formatter'
+ },
+ {
+ title: 'Color Picker',
+ url: '/tools/color-picker'
+ },
+ {
+ title: 'URL Tools',
+ url: '/tools/url-tools'
+ },
+ {
+ title: 'Hash Generator',
+ url: '/tools/hash-generator'
+ },
+ {
+ title: 'Lorem Generator',
+ url: '/tools/lorem-generator'
+ },
+ {
+ title: 'ASCII Art',
+ url: '/tools/ascii-art'
+ },
+ {
+ title: 'Markdown Preview',
+ url: '/tools/markdown-preview'
+ },
+ {
+ title: 'Regex Tester',
+ url: '/tools/regex-tester'
}
]
},
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index f7da8651..28798599 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -15,7 +15,17 @@
{ name: 'Word Counter', url: '/tools/word-counter' },
{ name: 'Password Generator', url: '/tools/password-generator' },
{ name: 'Random Number Generator', url: '/tools/random-number-generator' },
- { name: 'Stopwatch & Timer', url: '/tools/stopwatch-timer' }
+ { name: 'Stopwatch & Timer', url: '/tools/stopwatch-timer' },
+ { name: 'QR Code Generator', url: '/tools/qr-code-generator' },
+ { name: 'Base64 Converter', url: '/tools/base64-converter' },
+ { name: 'JSON Formatter', url: '/tools/json-formatter' },
+ { name: 'Color Picker', url: '/tools/color-picker' },
+ { name: 'URL Tools', url: '/tools/url-tools' },
+ { name: 'Hash Generator', url: '/tools/hash-generator' },
+ { name: 'Lorem Generator', url: '/tools/lorem-generator' },
+ { name: 'ASCII Art', url: '/tools/ascii-art' },
+ { name: 'Markdown Preview', url: '/tools/markdown-preview' },
+ { name: 'Regex Tester', url: '/tools/regex-tester' }
];
diff --git a/src/routes/tools/ascii-art/+page.svelte b/src/routes/tools/ascii-art/+page.svelte
new file mode 100644
index 00000000..4f873d44
--- /dev/null
+++ b/src/routes/tools/ascii-art/+page.svelte
@@ -0,0 +1,199 @@
+
+
+
+
+
+ ASCII Art Generator
+ Convert text into ASCII art using different fonts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if output}
+
+ {/if}
+
+
+ {#if output}
+
+ {/if}
+
+
+
Supported characters: A-Z, space, !, ?
+
Tip: Keep text short (max 20 characters) for best results
+
Note: ASCII art works best with monospace fonts
+
+
+
+
diff --git a/src/routes/tools/base64-converter/+page.svelte b/src/routes/tools/base64-converter/+page.svelte
new file mode 100644
index 00000000..2c8a9a5a
--- /dev/null
+++ b/src/routes/tools/base64-converter/+page.svelte
@@ -0,0 +1,107 @@
+
+
+
+
+
+ Base64 Encoder/Decoder
+ Encode text to Base64 or decode Base64 back to text
+
+
+
+
+ Encode
+ Decode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if outputText}
+
+ {/if}
+
+
+ {#if error}
+
+ {error}
+
+ {/if}
+
+ {#if outputText}
+
+
Result:
+
+
+ {/if}
+
+
+
diff --git a/src/routes/tools/color-picker/+page.svelte b/src/routes/tools/color-picker/+page.svelte
new file mode 100644
index 00000000..9ffa4ee1
--- /dev/null
+++ b/src/routes/tools/color-picker/+page.svelte
@@ -0,0 +1,229 @@
+
+
+
+
+
+ Color Picker & Palette
+ Pick colors and get values in different formats
+
+
+
+
+
+
+
+
+
Color Values
+
+
+
+
HEX:
+
+ {selectedColor.toUpperCase()}
+
+
+
+
+ {#if rgb()}
+
+
RGB:
+
+ rgb({rgb()?.r}, {rgb()?.g}, {rgb()?.b})
+
+
+
+ {/if}
+
+ {#if hsl()}
+
+
HSL:
+
+ hsl({hsl()?.h}, {hsl()?.s}%, {hsl()?.l}%)
+
+
+
+ {/if}
+
+
+
+
+
+ {#if complementaryColors().length > 0}
+
+
Complementary Color
+
+ {#each complementaryColors() as color}
+
+ {/each}
+
+
+ {/if}
+
+
+ {#if colorHistory.length > 0}
+
+
Recent Colors
+
+ {#each colorHistory as color}
+
+ {/each}
+
+
+ {/if}
+
+
+
diff --git a/src/routes/tools/hash-generator/+page.svelte b/src/routes/tools/hash-generator/+page.svelte
new file mode 100644
index 00000000..d61bfa50
--- /dev/null
+++ b/src/routes/tools/hash-generator/+page.svelte
@@ -0,0 +1,153 @@
+
+
+
+
+
+ Hash Generator
+ Generate MD5, SHA1, SHA256, and CRC32 hashes from text
+
+
+
+
+
+
+
+
+
+
+
+ {#if Object.keys(hashes).length > 0}
+
+
Generated Hashes:
+
+ {#each Object.entries(hashes) as [algorithm, hash]}
+
+
+ {algorithm}
+
+
+
+ {hash}
+
+
+ {/each}
+
+ {/if}
+
+ {#if inputText.trim()}
+
+
Input length: {inputText.length} characters
+
Input bytes: {new TextEncoder().encode(inputText).length} bytes
+
+ {/if}
+
+
+
Hash Information:
+
+ -
+ MD5: 128-bit hash, commonly used but not cryptographically secure
+
+ - SHA1: 160-bit hash, deprecated for cryptographic use
+ -
+ SHA256: 256-bit hash, part of SHA-2 family, cryptographically secure
+
+ -
+ CRC32: 32-bit checksum, used for error detection, not cryptographically
+ secure
+
+
+
+
+
+
diff --git a/src/routes/tools/json-formatter/+page.svelte b/src/routes/tools/json-formatter/+page.svelte
new file mode 100644
index 00000000..b2393183
--- /dev/null
+++ b/src/routes/tools/json-formatter/+page.svelte
@@ -0,0 +1,145 @@
+
+
+
+
+
+ JSON Formatter & Validator
+ Format, validate, and minify JSON data
+
+
+
+
+
+
Input JSON
+
+ {#if inputJson.trim()}
+
+ {isValid ? 'Valid' : 'Invalid'}
+
+ {/if}
+
+
+
+
+
+
+
Formatted Output
+
+
+
+
+ {#if error}
+
+ Error:
+ {error}
+
+ {/if}
+
+
+
+
+
+ {#if outputJson}
+
+ {/if}
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/tools/lorem-generator/+page.svelte b/src/routes/tools/lorem-generator/+page.svelte
new file mode 100644
index 00000000..1af41a2c
--- /dev/null
+++ b/src/routes/tools/lorem-generator/+page.svelte
@@ -0,0 +1,303 @@
+
+
+
+
+
+ Lorem Ipsum Generator
+ Generate placeholder text for your designs and layouts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if output}
+
+ {/if}
+
+
+ {#if output}
+
+
Generated Text:
+
+
+ {/if}
+
+
+
+ Tip: Lorem ipsum is placeholder text commonly used in the printing and typesetting
+ industry since the 1500s.
+
+ {#if output}
+
+ Generated:
+ {output.split(' ').length} words, {output.split(/[.!?]+/).filter((s) => s.trim())
+ .length} sentences
+
+ {/if}
+
+
+
+
diff --git a/src/routes/tools/markdown-preview/+page.svelte b/src/routes/tools/markdown-preview/+page.svelte
new file mode 100644
index 00000000..73177039
--- /dev/null
+++ b/src/routes/tools/markdown-preview/+page.svelte
@@ -0,0 +1,314 @@
+
+
+
+
+
+ Markdown Preview
+ Write markdown and see the live preview
+
+
+
+
+
+ Split View
+ Markdown Only
+ Preview Only
+
+
+
+
+
+
+
+
+
+
+
+
Markdown Input:
+
+
+
+
Live Preview:
+
+ {@html htmlOutput}
+
+
+
+
+
+
+
+
+
+
+ {@html htmlOutput}
+
+
+
+
+
+
+
+
diff --git a/src/routes/tools/qr-code-generator/+page.svelte b/src/routes/tools/qr-code-generator/+page.svelte
new file mode 100644
index 00000000..7144343d
--- /dev/null
+++ b/src/routes/tools/qr-code-generator/+page.svelte
@@ -0,0 +1,67 @@
+
+
+
+
+
+ QR Code Generator
+ Generate QR codes from text, URLs, or any other data
+
+
+
+
+
+
+
+
+
+
+
+ {#if qrCodeUrl}
+
+

+
+
+ {/if}
+
+
+
diff --git a/src/routes/tools/regex-tester/+page.svelte b/src/routes/tools/regex-tester/+page.svelte
new file mode 100644
index 00000000..64e06622
--- /dev/null
+++ b/src/routes/tools/regex-tester/+page.svelte
@@ -0,0 +1,282 @@
+
+
+
+
+
+ Regular Expression Tester
+ Test and debug regular expressions with live matching
+
+
+
+
+
+
+
+
+ {isValid ? 'Valid' : 'Invalid'}
+
+ {#if pattern && flags}
+ /{pattern}/{flags}
+ {/if}
+ {#if matches.length > 0}
+ {matches.length} match{matches.length !== 1 ? 'es' : ''}
+ {/if}
+
+
+ {#if error}
+
+ Error:
+ {error}
+
+ {/if}
+
+
+
+
Common Patterns:
+
+ {#each commonPatterns as commonPattern}
+
+ {/each}
+
+
+
+
+
+
+
+
+
+
+ {#if testString}
+
+
Text with Matches Highlighted:
+
+ {@html getHighlightedText()}
+
+
+ {/if}
+
+
+ {#if matches.length > 0}
+
+
Matches ({matches.length}):
+
+ {#each matches as match, index}
+
+
+ {match[0]}
+
+ Position: {match.index}
+
+
+ {#if match.length > 1}
+
+ Groups: {match
+ .slice(1)
+ .map((group, i) => `$${i + 1}: "${group}"`)
+ .join(', ')}
+
+ {/if}
+
+ {/each}
+
+
+ {/if}
+
+
+
+
+
+ {#if pattern}
+
+ {/if}
+ {#if matches.length > 0}
+
+ {/if}
+
+
+
+
+
+ Common flags: g (global), i (case-insensitive), m (multiline), s (dotall)
+
+
Tip: Use capture groups () to extract parts of matches
+
+
+
+
diff --git a/src/routes/tools/url-tools/+page.svelte b/src/routes/tools/url-tools/+page.svelte
new file mode 100644
index 00000000..df5db081
--- /dev/null
+++ b/src/routes/tools/url-tools/+page.svelte
@@ -0,0 +1,248 @@
+
+
+
+
+
+ URL Tools
+ Shorten URLs, expand short URLs, and analyze URL components
+
+
+
+
+ Shorten
+ Expand
+ Analyze
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if urlAnalysis()}
+
+
URL Components:
+
+
+ Protocol:
+ {urlAnalysis()?.protocol}
+
+
+ Hostname:
+ {urlAnalysis()?.hostname}
+
+ {#if urlAnalysis()?.port}
+
+ Port:
+ {urlAnalysis()?.port}
+
+ {/if}
+ {#if urlAnalysis()?.pathname && urlAnalysis()?.pathname !== '/'}
+
+ Path:
+ {urlAnalysis()?.pathname}
+
+ {/if}
+ {#if urlAnalysis()?.search}
+
+ Query:
+ {urlAnalysis()?.search}
+
+ {/if}
+ {#if urlAnalysis()?.hash}
+
+ Fragment:
+ {urlAnalysis()?.hash}
+
+ {/if}
+
+
+ {/if}
+
+
+
+
+
+ {#if outputUrl}
+
+ {/if}
+
+
+ {#if error}
+
+ {error}
+
+ {/if}
+
+ {#if outputUrl && outputUrl !== inputUrl}
+
+ {/if}
+
+
+
From 48a061a095358270cf9cde7397edbe6f171e37ad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 30 Sep 2025 09:13:52 +0000
Subject: [PATCH 3/3] fix: Address UI feedback - update copy buttons, remove
problematic features, fix layout issues
Co-authored-by: Inglan <96573515+Inglan@users.noreply.github.com>
---
src/routes/tools/ascii-art/+page.svelte | 60 +------
src/routes/tools/color-picker/+page.svelte | 15 +-
src/routes/tools/lorem-generator/+page.svelte | 64 ++-----
.../tools/markdown-preview/+page.svelte | 156 +++++++++---------
src/routes/tools/url-tools/+page.svelte | 50 +-----
5 files changed, 107 insertions(+), 238 deletions(-)
diff --git a/src/routes/tools/ascii-art/+page.svelte b/src/routes/tools/ascii-art/+page.svelte
index 4f873d44..72aea053 100644
--- a/src/routes/tools/ascii-art/+page.svelte
+++ b/src/routes/tools/ascii-art/+page.svelte
@@ -8,16 +8,9 @@
CardHeader,
CardTitle
} from '$lib/components/ui/card/index.js';
- import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger
- } from '$lib/components/ui/select/index.js';
let inputText = $state('');
let output = $state('');
- let font = $state('block');
// Simple ASCII art fonts
const fonts = {
@@ -51,38 +44,6 @@
' ': [' ', ' ', ' ', ' ', ' '],
'!': [' █ ', ' █ ', ' █ ', ' ', ' █ '],
'?': ['█████', ' █', ' ██ ', ' ', ' █ ']
- },
-
- small: {
- A: ['█▀█', '█▀█', '█▄█'],
- B: ['█▀▄', '█▀▄', '█▄▀'],
- C: ['▄▀█', '█▄▄', '▀▀▀'],
- D: ['█▀▄', '█▄█', '█▄▀'],
- E: ['█▀▀', '█▀▀', '█▄▄'],
- F: ['█▀▀', '█▀▀', '█▄▄'],
- G: ['▄▀█', '█▄█', '▀▀█'],
- H: ['█▄█', '█▀█', '█▄█'],
- I: ['█', '█', '█'],
- J: ['▄▄█', '▄▄█', '▀▀▀'],
- K: ['█▄▀', '██▄', '█▄█'],
- L: ['█▄▄', '█▄▄', '▀▀▀'],
- M: ['█▄█', '█▀█', '█▄█'],
- N: ['█▄█', '█▀█', '█▄█'],
- O: ['▄▀█', '█▄█', '▀▀▀'],
- P: ['█▀▄', '█▀▄', '█▄▄'],
- Q: ['▄▀█', '█▄█', '▀▀█'],
- R: ['█▀▄', '█▀▄', '█▄█'],
- S: ['▄▀▀', '▀▀▄', '▄▄▀'],
- T: ['▀█▀', '▄█▄', '▀▀▀'],
- U: ['█▄█', '█▄█', '▀▀▀'],
- V: ['█▄█', '▀█▀', '▄▀▄'],
- W: ['█▄█', '█▀█', '▀▄▀'],
- X: ['█▄█', '▀█▀', '█▄█'],
- Y: ['█▄█', '▀█▀', '▄▀▄'],
- Z: ['▀▀▀', '▄▀▄', '▀▀▀'],
- ' ': [' ', ' ', ' '],
- '!': ['█', '█', '█'],
- '?': ['▀▀', '▄▀', '▀▀']
}
};
@@ -92,7 +53,7 @@
return;
}
- const selectedFont = fonts[font as keyof typeof fonts];
+ const selectedFont = fonts.block;
const text = inputText.toUpperCase();
const lines: string[] = [];
@@ -133,7 +94,7 @@
output = '';
}
- // Generate ASCII art when input or font changes
+ // Auto-generate ASCII art when input changes
$effect(() => {
generateAsciiArt();
});
@@ -143,10 +104,10 @@
ASCII Art Generator
- Convert text into ASCII art using different fonts
+ Convert text into ASCII art
-
+
-
-
-
-
-
diff --git a/src/routes/tools/color-picker/+page.svelte b/src/routes/tools/color-picker/+page.svelte
index 9ffa4ee1..a788c1d5 100644
--- a/src/routes/tools/color-picker/+page.svelte
+++ b/src/routes/tools/color-picker/+page.svelte
@@ -9,6 +9,8 @@
CardTitle
} from '$lib/components/ui/card/index.js';
import { Badge } from '$lib/components/ui/badge/index.js';
+ import { toast } from 'svelte-sonner';
+ import Copy from '@lucide/svelte/icons/copy';
let selectedColor = $state('#3b82f6');
let colorHistory = $state
([]);
@@ -76,6 +78,7 @@
function copyToClipboard(value: string) {
navigator.clipboard.writeText(value);
+ toast.success('Color value copied to clipboard');
}
function generateRandomColor() {
@@ -143,9 +146,9 @@
HEX:
{selectedColor.toUpperCase()}
-
+
@@ -160,8 +163,9 @@
size="sm"
variant="ghost"
onclick={() => copyToClipboard(`rgb(${rgb()?.r}, ${rgb()?.g}, ${rgb()?.b})`)}
- >Copy
+
+
{/if}
@@ -177,8 +181,9 @@
size="sm"
variant="ghost"
onclick={() => copyToClipboard(`hsl(${hsl()?.h}, ${hsl()?.s}%, ${hsl()?.l}%)`)}
- >Copy
+
+
{/if}
diff --git a/src/routes/tools/lorem-generator/+page.svelte b/src/routes/tools/lorem-generator/+page.svelte
index 1af41a2c..ea549944 100644
--- a/src/routes/tools/lorem-generator/+page.svelte
+++ b/src/routes/tools/lorem-generator/+page.svelte
@@ -9,15 +9,8 @@
CardTitle
} from '$lib/components/ui/card/index.js';
import { Textarea } from '$lib/components/ui/textarea/index.js';
- import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger
- } from '$lib/components/ui/select/index.js';
let count = $state(5);
- let type = $state('paragraphs');
let output = $state('');
let startWithLorem = $state(true);
@@ -187,34 +180,16 @@
function generate() {
const results: string[] = [];
- switch (type) {
- case 'words':
- const words = getRandomWords(count, startWithLorem);
- results.push(words.join(' '));
- break;
-
- case 'sentences':
- for (let i = 0; i < count; i++) {
- const sentence =
- i === 0 && startWithLorem
- ? generateSentence().replace(/^Lorem/i, 'Lorem ipsum')
- : generateSentence();
- results.push(sentence);
- }
- break;
-
- case 'paragraphs':
- for (let i = 0; i < count; i++) {
- let paragraph = generateParagraph();
- if (i === 0 && startWithLorem) {
- paragraph = paragraph.replace(/^[A-Za-z]+/, 'Lorem ipsum');
- }
- results.push(paragraph);
- }
- break;
+ // Always generate paragraphs
+ for (let i = 0; i < count; i++) {
+ let paragraph = generateParagraph();
+ if (i === 0 && startWithLorem) {
+ paragraph = paragraph.replace(/^[A-Za-z]+/, 'Lorem ipsum');
+ }
+ results.push(paragraph);
}
- output = results.join(type === 'paragraphs' ? '\n\n' : '\n');
+ output = results.join('\n\n');
}
function copyToClipboard() {
@@ -242,26 +217,12 @@
Generate placeholder text for your designs and layouts
-
+
-
+
-
-
-
-
-
diff --git a/src/routes/tools/markdown-preview/+page.svelte b/src/routes/tools/markdown-preview/+page.svelte
index 73177039..139e8bcd 100644
--- a/src/routes/tools/markdown-preview/+page.svelte
+++ b/src/routes/tools/markdown-preview/+page.svelte
@@ -165,13 +165,13 @@ That's a horizontal rule above this text.
-
+
Markdown Preview
Write markdown and see the live preview
-
-
+
+
Split View
@@ -186,16 +186,16 @@ That's a horizontal rule above this text.
-
-
+
+
Markdown Input:
-
+
Live Preview:
-
+
-
+
@@ -226,89 +226,89 @@ That's a horizontal rule above this text.
diff --git a/src/routes/tools/url-tools/+page.svelte b/src/routes/tools/url-tools/+page.svelte
index df5db081..67e59aff 100644
--- a/src/routes/tools/url-tools/+page.svelte
+++ b/src/routes/tools/url-tools/+page.svelte
@@ -55,38 +55,6 @@
}
}
- async function expandUrl() {
- if (!inputUrl.trim()) return;
-
- if (!isValidUrl(inputUrl)) {
- error = 'Please enter a valid URL';
- return;
- }
-
- loading = true;
- error = '';
-
- try {
- // For URL expansion, we'll use a simple fetch to follow redirects
- const response = await fetch(
- `https://httpbin.org/redirect-to?url=${encodeURIComponent(inputUrl)}`,
- {
- method: 'HEAD',
- redirect: 'follow'
- }
- );
-
- outputUrl = response.url;
- } catch (e) {
- // Fallback: just show the input URL as many short URLs don't allow CORS
- outputUrl = inputUrl;
- error =
- 'Could not expand URL due to CORS restrictions. The URL might be valid but cannot be expanded in the browser.';
- } finally {
- loading = false;
- }
- }
-
function clearAll() {
inputUrl = '';
outputUrl = '';
@@ -124,13 +92,12 @@
URL Tools
- Shorten URLs, expand short URLs, and analyze URL components
+ Shorten URLs and analyze URL components
-
+
Shorten
- Expand
Analyze
@@ -147,19 +114,6 @@
-
-
-
-
-
-
-