From 1b564e7591a23592f6bb641ea83f1cf36eb4c872 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 21:48:40 +0000 Subject: [PATCH 01/10] Add Base Converter tool --- app/Http/Controllers/ToolController.php | 11 + resources/views/home.blade.php | 5 + .../views/tools/base-converter.blade.php | 335 ++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 32 +- 5 files changed, 380 insertions(+), 5 deletions(-) create mode 100644 resources/views/tools/base-converter.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 13d83e9..686e23d 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -75,6 +75,12 @@ public function index(): View 'route' => 'tools.regex', 'icon' => 'regex', ], + [ + 'name' => 'Base Converter', + 'description' => 'Convert between binary, octal, decimal, and hex', + 'route' => 'tools.base-converter', + 'icon' => 'calculator', + ], ]; return view('home', compact('tools')); @@ -134,4 +140,9 @@ public function regex(): View { return view('tools.regex'); } + + public function baseConverter(): View + { + return view('tools.base-converter'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index c2600f0..2ac5d9b 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -90,6 +90,11 @@ @break + @case('calculator') + + + + @break @endswitch
diff --git a/resources/views/tools/base-converter.blade.php b/resources/views/tools/base-converter.blade.php new file mode 100644 index 0000000..d871911 --- /dev/null +++ b/resources/views/tools/base-converter.blade.php @@ -0,0 +1,335 @@ +@extends('layouts.app') + +@section('title', 'Base Converter - Binary, Octal, Decimal, Hex | Dev Tools') +@section('meta_description', 'Free online number base converter. Convert between binary, octal, decimal, and hexadecimal. Instant conversion with bit visualization.') +@section('meta_keywords', 'base converter, binary converter, hex converter, octal converter, decimal to binary, binary to hex, number base, radix converter') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Base Converter

+

Convert between binary, octal, decimal, and hexadecimal

+
+ ← Back +
+ +
+ +
+ +
+
+ + 0-1 +
+
+ + +
+

+
+ + +
+
+ + 0-7 +
+
+ + +
+

+
+ + +
+
+ + 0-9 +
+
+ + +
+

+
+ + +
+
+ + 0-9, A-F +
+
+ + +
+

+
+ + + +
+ + +
+ +
+ +
+ +
+

Enter a number to see bit visualization

+

+ bits +

+
+ + +
+ +
+ + + + +
+
+ + +
+ +
+
+ Binary: + 0b +
+
+ Octal: + 0o +
+
+ Decimal: + +
+
+ Hex: + 0x +
+
+

Enter a number to see formatted output

+
+ + +
+

Base Reference

+
+

Binary (2): Uses 0 and 1

+

Octal (8): Uses 0-7

+

Decimal (10): Uses 0-9

+

Hexadecimal (16): Uses 0-9 and A-F

+
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 7c8961e..480c649 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,6 +17,7 @@ Route::get('/url', [ToolController::class, 'url'])->name('url'); Route::get('/code-editor', [ToolController::class, 'codeEditor'])->name('code-editor'); Route::get('/regex', [ToolController::class, 'regex'])->name('regex'); + Route::get('/base-converter', [ToolController::class, 'baseConverter'])->name('base-converter'); }); // Static Pages @@ -38,6 +39,7 @@ ['loc' => route('tools.url'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.code-editor'), 'priority' => '0.9', 'changefreq' => 'monthly'], ['loc' => route('tools.regex'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.base-converter'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index 71c4bf8..a788080 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -29,6 +29,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('URL Encoder'); $response->assertSee('Code Editor'); $response->assertSee('Regex Tester'); + $response->assertSee('Base Converter'); } public function test_home_page_has_tool_links(): void @@ -46,6 +47,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.url') . '"', false); $response->assertSee('href="' . route('tools.code-editor') . '"', false); $response->assertSee('href="' . route('tools.regex') . '"', false); + $response->assertSee('href="' . route('tools.base-converter') . '"', false); } public function test_csv_tool_page_loads(): void @@ -252,9 +254,29 @@ public function test_regex_tool_has_required_elements(): void $response->assertSee('Match Details'); } + public function test_base_converter_page_loads(): void + { + $response = $this->get('/tools/base-converter'); + + $response->assertStatus(200); + $response->assertSee('Base Converter'); + $response->assertSee('Convert between binary, octal, decimal, and hexadecimal'); + } + + public function test_base_converter_has_required_elements(): void + { + $response = $this->get('/tools/base-converter'); + + $response->assertStatus(200); + $response->assertSee('Binary'); + $response->assertSee('Octal'); + $response->assertSee('Decimal'); + $response->assertSee('Hexadecimal'); + } + public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter']; foreach ($pages as $page) { $response = $this->get($page); @@ -266,7 +288,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter']; foreach ($pages as $page) { $response = $this->get($page); @@ -279,7 +301,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter']; foreach ($pages as $page) { $response = $this->get($page); @@ -292,7 +314,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -345,7 +367,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter']; foreach ($pages as $page) { $response = $this->get($page); From da33552a5858978ce1558df1ff8b0206eb469f41 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 21:26:25 +0000 Subject: [PATCH 02/10] Add Slug Generator tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convert text to URL-friendly slugs - Separator options: hyphen, underscore, dot, none - Case options: lowercase, uppercase, preserve - Transliterate accented characters (é → e, ñ → n) - Option to remove numbers - Optional length limit - URL preview with generated slug - Example texts for quick testing - Client-side only implementation --- app/Http/Controllers/ToolController.php | 11 + resources/views/home.blade.php | 5 + .../views/tools/slug-generator.blade.php | 328 ++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 32 +- 5 files changed, 373 insertions(+), 5 deletions(-) create mode 100644 resources/views/tools/slug-generator.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 686e23d..3ce0abe 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -81,6 +81,12 @@ public function index(): View 'route' => 'tools.base-converter', 'icon' => 'calculator', ], + [ + 'name' => 'Slug Generator', + 'description' => 'Convert text to URL-friendly slugs', + 'route' => 'tools.slug-generator', + 'icon' => 'slug', + ], ]; return view('home', compact('tools')); @@ -145,4 +151,9 @@ public function baseConverter(): View { return view('tools.base-converter'); } + + public function slugGenerator(): View + { + return view('tools.slug-generator'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 2ac5d9b..ba4c82f 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -95,6 +95,11 @@ @break + @case('slug') + + + + @break @endswitch
diff --git a/resources/views/tools/slug-generator.blade.php b/resources/views/tools/slug-generator.blade.php new file mode 100644 index 0000000..9e07b15 --- /dev/null +++ b/resources/views/tools/slug-generator.blade.php @@ -0,0 +1,328 @@ +@extends('layouts.app') + +@section('title', 'Slug Generator - Create URL-Friendly Slugs | Dev Tools') +@section('meta_description', 'Free online slug generator. Convert text to URL-friendly slugs. Customize separators, case, and transliteration options.') +@section('meta_keywords', 'slug generator, url slug, seo slug, friendly url, text to slug, slug maker, url generator, permalink generator') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Slug Generator

+

Convert text to URL-friendly slugs

+
+ ← Back +
+ +
+ +
+
+ + +

+ characters +

+
+ + +
+ + +
+ +
+ +
+ + + + +
+
+ + +
+ +
+ + + +
+
+ + +
+ + + +
+ + characters +
+
+
+
+
+ + +
+
+ +
+ + +
+

+ characters +

+
+ + +
+ +
+ https://example.com/ +
+
+ + +
+ +
+ + + +
+
+ + +
+

What is a Slug?

+

+ A slug is a URL-friendly version of a string, typically used in permalinks. It contains only lowercase letters, numbers, and hyphens, making URLs more readable and SEO-friendly. +

+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 480c649..08d35ce 100644 --- a/routes/web.php +++ b/routes/web.php @@ -18,6 +18,7 @@ Route::get('/code-editor', [ToolController::class, 'codeEditor'])->name('code-editor'); Route::get('/regex', [ToolController::class, 'regex'])->name('regex'); Route::get('/base-converter', [ToolController::class, 'baseConverter'])->name('base-converter'); + Route::get('/slug-generator', [ToolController::class, 'slugGenerator'])->name('slug-generator'); }); // Static Pages @@ -40,6 +41,7 @@ ['loc' => route('tools.code-editor'), 'priority' => '0.9', 'changefreq' => 'monthly'], ['loc' => route('tools.regex'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.base-converter'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.slug-generator'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index a788080..acf5c6d 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -30,6 +30,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('Code Editor'); $response->assertSee('Regex Tester'); $response->assertSee('Base Converter'); + $response->assertSee('Slug Generator'); } public function test_home_page_has_tool_links(): void @@ -48,6 +49,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.code-editor') . '"', false); $response->assertSee('href="' . route('tools.regex') . '"', false); $response->assertSee('href="' . route('tools.base-converter') . '"', false); + $response->assertSee('href="' . route('tools.slug-generator') . '"', false); } public function test_csv_tool_page_loads(): void @@ -274,9 +276,29 @@ public function test_base_converter_has_required_elements(): void $response->assertSee('Hexadecimal'); } + public function test_slug_generator_page_loads(): void + { + $response = $this->get('/tools/slug-generator'); + + $response->assertStatus(200); + $response->assertSee('Slug Generator'); + $response->assertSee('Convert text to URL-friendly slugs'); + } + + public function test_slug_generator_has_required_elements(): void + { + $response = $this->get('/tools/slug-generator'); + + $response->assertStatus(200); + $response->assertSee('Input Text'); + $response->assertSee('Generated Slug'); + $response->assertSee('Separator'); + $response->assertSee('Hyphen'); + } + public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; foreach ($pages as $page) { $response = $this->get($page); @@ -288,7 +310,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; foreach ($pages as $page) { $response = $this->get($page); @@ -301,7 +323,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; foreach ($pages as $page) { $response = $this->get($page); @@ -314,7 +336,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -367,7 +389,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator']; foreach ($pages as $page) { $response = $this->get($page); From f4d7776520de7e30e8715e797225003b912089b0 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 21:22:16 +0000 Subject: [PATCH 03/10] Add Color Picker tool - Visual color picker with HTML5 color input - Convert between HEX, RGB, HSL, and CMYK formats - Color harmony: complementary, triadic, analogous colors - Generate shades and tints - Display color info: brightness, luminance, suggested text color - Quick-select common colors palette - Copy color values to clipboard - Random color generator - Client-side only implementation --- app/Http/Controllers/ToolController.php | 11 + resources/views/home.blade.php | 5 + resources/views/tools/color-picker.blade.php | 490 +++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 33 +- 5 files changed, 536 insertions(+), 5 deletions(-) create mode 100644 resources/views/tools/color-picker.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 3ce0abe..525647c 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -87,6 +87,12 @@ public function index(): View 'route' => 'tools.slug-generator', 'icon' => 'slug', ], + [ + 'name' => 'Color Picker', + 'description' => 'Pick colors and convert between HEX, RGB, HSL, CMYK', + 'route' => 'tools.color-picker', + 'icon' => 'color', + ], ]; return view('home', compact('tools')); @@ -156,4 +162,9 @@ public function slugGenerator(): View { return view('tools.slug-generator'); } + + public function colorPicker(): View + { + return view('tools.color-picker'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index ba4c82f..5218b34 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -100,6 +100,11 @@ @break + @case('color') + + + + @break @endswitch
diff --git a/resources/views/tools/color-picker.blade.php b/resources/views/tools/color-picker.blade.php new file mode 100644 index 0000000..d3cde18 --- /dev/null +++ b/resources/views/tools/color-picker.blade.php @@ -0,0 +1,490 @@ +@extends('layouts.app') + +@section('title', 'Color Picker & Converter - HEX, RGB, HSL, CMYK | Dev Tools') +@section('meta_description', 'Free online color picker and converter. Convert between HEX, RGB, HSL, and CMYK color formats. Generate color palettes and complementary colors.') +@section('meta_keywords', 'color picker, color converter, hex to rgb, rgb to hex, hsl converter, cmyk converter, color palette, color tool, web colors') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Color Picker & Converter

+

Convert between HEX, RGB, HSL, and CMYK formats

+
+ ← Back +
+ +
+ +
+ +
+ + +
+ +
+
+
+
+ +
+ + +
+
+ + +
+ + +
+ +
+ +
+ + +
+
+ + +
+ +
+
+ + + +
+ +
+

+
+ + +
+ +
+
+ + + +
+ +
+

+
+ + +
+ +
+
+ + + + +
+ +
+

+
+
+
+
+ + +
+ +
+ + +
+ +
+ +
+
+
+
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ +

Click any color to copy its HEX value

+
+ + +
+ + +
+
+ Brightness: + +
+
+ Luminance: + +
+
+ Suggested Text: + +
+
+
+ + +
+ + +
+ +
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 08d35ce..429b128 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,6 +19,7 @@ Route::get('/regex', [ToolController::class, 'regex'])->name('regex'); Route::get('/base-converter', [ToolController::class, 'baseConverter'])->name('base-converter'); Route::get('/slug-generator', [ToolController::class, 'slugGenerator'])->name('slug-generator'); + Route::get('/color-picker', [ToolController::class, 'colorPicker'])->name('color-picker'); }); // Static Pages @@ -42,6 +43,7 @@ ['loc' => route('tools.regex'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.base-converter'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.slug-generator'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.color-picker'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index acf5c6d..4787717 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -31,6 +31,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('Regex Tester'); $response->assertSee('Base Converter'); $response->assertSee('Slug Generator'); + $response->assertSee('Color Picker'); } public function test_home_page_has_tool_links(): void @@ -50,6 +51,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.regex') . '"', false); $response->assertSee('href="' . route('tools.base-converter') . '"', false); $response->assertSee('href="' . route('tools.slug-generator') . '"', false); + $response->assertSee('href="' . route('tools.color-picker') . '"', false); } public function test_csv_tool_page_loads(): void @@ -296,9 +298,30 @@ public function test_slug_generator_has_required_elements(): void $response->assertSee('Hyphen'); } + public function test_color_picker_page_loads(): void + { + $response = $this->get('/tools/color-picker'); + + $response->assertStatus(200); + $response->assertSee('Color Picker'); + $response->assertSee('Convert between HEX, RGB, HSL, and CMYK'); + } + + public function test_color_picker_has_required_elements(): void + { + $response = $this->get('/tools/color-picker'); + + $response->assertStatus(200); + $response->assertSee('HEX'); + $response->assertSee('RGB'); + $response->assertSee('HSL'); + $response->assertSee('CMYK'); + $response->assertSee('Color Harmony'); + } + public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; foreach ($pages as $page) { $response = $this->get($page); @@ -310,7 +333,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; foreach ($pages as $page) { $response = $this->get($page); @@ -323,7 +346,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; foreach ($pages as $page) { $response = $this->get($page); @@ -336,7 +359,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -389,7 +412,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; foreach ($pages as $page) { $response = $this->get($page); From 08d04fd1e893a26ab7edb0b1d072f2000b8fbb62 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 20:53:36 +0000 Subject: [PATCH 04/10] Add QR Code Generator tool - Generate QR codes from text, URLs, email, phone, SMS, WiFi - Customizable size (128-512px) and colors - Error correction level options (L, M, Q, H) - Download as PNG or SVG - Copy QR code image to clipboard - Quick templates for common use cases - Client-side only using qrcode.js library --- app/Http/Controllers/ToolController.php | 11 + resources/views/home.blade.php | 6 + resources/views/tools/qr-code.blade.php | 416 ++++++++++++++++++++++++ routes/web.php | 8 + tests/Feature/WebRoutesTest.php | 39 ++- 5 files changed, 475 insertions(+), 5 deletions(-) create mode 100644 resources/views/tools/qr-code.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 525647c..3e134d5 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -93,6 +93,12 @@ public function index(): View 'route' => 'tools.color-picker', 'icon' => 'color', ], + [ + 'name' => 'QR Code Generator', + 'description' => 'Generate QR codes for URLs, text, and more', + 'route' => 'tools.qr-code', + 'icon' => 'qrcode', + ], ]; return view('home', compact('tools')); @@ -167,4 +173,9 @@ public function colorPicker(): View { return view('tools.color-picker'); } + + public function qrCode(): View + { + return view('tools.qr-code'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 5218b34..c73b6d2 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -90,6 +90,7 @@ @break + @case('calculator') @@ -103,6 +104,11 @@ @case('color') + + @case('qrcode') + + + @break @endswitch diff --git a/resources/views/tools/qr-code.blade.php b/resources/views/tools/qr-code.blade.php new file mode 100644 index 0000000..f48406f --- /dev/null +++ b/resources/views/tools/qr-code.blade.php @@ -0,0 +1,416 @@ +@extends('layouts.app') + +@section('title', 'QR Code Generator - Create QR Codes Online Free | Dev Tools') +@section('meta_description', 'Free online QR code generator. Create QR codes for URLs, text, email, phone numbers. Customize colors and size. Download as PNG instantly.') +@section('meta_keywords', 'qr code generator, create qr code, qr code maker, free qr code, qr code online, generate qr code, custom qr code, qr code download') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

QR Code Generator

+

Generate QR codes for URLs, text, and more

+
+ ← Back +
+ +
+ +
+
+ + +

+ characters +

+
+ + +
+ +
+ + + + + +
+
+ + +
+ + +
+ +
+ + +
+ 128px + 512px +
+
+ + +
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ + +
+ + +
+
+
+
+ + +
+
+ + +
+ +
+ + +
+ + +
+ + + +
+
+
+ + +
+

About QR Codes

+
+

URL: Link directly to websites

+

Email: Use mailto:email@example.com

+

Phone: Use tel:+1234567890

+

SMS: Use sms:+1234567890?body=message

+

WiFi: Use WIFI:T:WPA;S:NetworkName;P:Password;;

+
+
+ + +
+

Error Correction Levels

+
    +
  • L (Low): 7% - Smallest QR code
  • +
  • M (Medium): 15% - Good balance
  • +
  • Q (Quartile): 25% - Better recovery
  • +
  • H (High): 30% - Best for logos
  • +
+
+
+
+
+@endsection + +@push('scripts') + + +@endpush diff --git a/routes/web.php b/routes/web.php index 429b128..b56ba8d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,9 +17,13 @@ Route::get('/url', [ToolController::class, 'url'])->name('url'); Route::get('/code-editor', [ToolController::class, 'codeEditor'])->name('code-editor'); Route::get('/regex', [ToolController::class, 'regex'])->name('regex'); + Route::get('/base-converter', [ToolController::class, 'baseConverter'])->name('base-converter'); Route::get('/slug-generator', [ToolController::class, 'slugGenerator'])->name('slug-generator'); Route::get('/color-picker', [ToolController::class, 'colorPicker'])->name('color-picker'); + + Route::get('/qr-code', [ToolController::class, 'qrCode'])->name('qr-code'); + }); // Static Pages @@ -41,9 +45,13 @@ ['loc' => route('tools.url'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.code-editor'), 'priority' => '0.9', 'changefreq' => 'monthly'], ['loc' => route('tools.regex'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.base-converter'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.slug-generator'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.color-picker'), 'priority' => '0.8', 'changefreq' => 'monthly'], + + ['loc' => route('tools.qr-code'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index 4787717..766edc0 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -29,9 +29,13 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('URL Encoder'); $response->assertSee('Code Editor'); $response->assertSee('Regex Tester'); + $response->assertSee('Base Converter'); $response->assertSee('Slug Generator'); $response->assertSee('Color Picker'); + + $response->assertSee('QR Code Generator'); + } public function test_home_page_has_tool_links(): void @@ -49,9 +53,13 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.url') . '"', false); $response->assertSee('href="' . route('tools.code-editor') . '"', false); $response->assertSee('href="' . route('tools.regex') . '"', false); + $response->assertSee('href="' . route('tools.base-converter') . '"', false); $response->assertSee('href="' . route('tools.slug-generator') . '"', false); $response->assertSee('href="' . route('tools.color-picker') . '"', false); + + $response->assertSee('href="' . route('tools.qr-code') . '"', false); + } public function test_csv_tool_page_loads(): void @@ -258,6 +266,7 @@ public function test_regex_tool_has_required_elements(): void $response->assertSee('Match Details'); } + public function test_base_converter_page_loads(): void { $response = $this->get('/tools/base-converter'); @@ -317,11 +326,31 @@ public function test_color_picker_has_required_elements(): void $response->assertSee('HSL'); $response->assertSee('CMYK'); $response->assertSee('Color Harmony'); + + public function test_qr_code_tool_page_loads(): void + { + $response = $this->get('/tools/qr-code'); + + $response->assertStatus(200); + $response->assertSee('QR Code Generator'); + $response->assertSee('Generate QR codes for URLs, text, and more'); + } + + public function test_qr_code_tool_has_required_elements(): void + { + $response = $this->get('/tools/qr-code'); + + $response->assertStatus(200); + $response->assertSee('Content'); + $response->assertSee('Quick Templates'); + $response->assertSee('Download PNG'); + $response->assertSee('Error Correction'); + } public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; foreach ($pages as $page) { $response = $this->get($page); @@ -333,7 +362,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; foreach ($pages as $page) { $response = $this->get($page); @@ -346,7 +375,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; foreach ($pages as $page) { $response = $this->get($page); @@ -359,7 +388,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -412,7 +441,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; foreach ($pages as $page) { $response = $this->get($page); From 22e03b9983c6fd5d592ded85e51da2cc53748242 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 20:39:53 +0000 Subject: [PATCH 05/10] Add HTML Entity Encoder tool - Encode text to HTML entities (named, numeric, hex formats) - Decode HTML entities back to text - Option to encode all characters or only special characters - Common entities reference panel with clickable items - Entity reference table organized by categories - Statistics showing input/output lengths --- app/Http/Controllers/ToolController.php | 11 + resources/views/home.blade.php | 3 + resources/views/tools/html-entity.blade.php | 419 ++++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 30 +- 5 files changed, 460 insertions(+), 5 deletions(-) create mode 100644 resources/views/tools/html-entity.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 3e134d5..bdbe302 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -99,6 +99,12 @@ public function index(): View 'route' => 'tools.qr-code', 'icon' => 'qrcode', ], + [ + 'name' => 'HTML Entity Encoder', + 'description' => 'Encode/decode HTML entities and special characters', + 'route' => 'tools.html-entity', + 'icon' => 'html-entity', + ], ]; return view('home', compact('tools')); @@ -178,4 +184,9 @@ public function qrCode(): View { return view('tools.qr-code'); } + + public function htmlEntity(): View + { + return view('tools.html-entity'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index c73b6d2..22b824b 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -109,6 +109,9 @@ + @case('html-entity') + + @break @endswitch diff --git a/resources/views/tools/html-entity.blade.php b/resources/views/tools/html-entity.blade.php new file mode 100644 index 0000000..b253fd2 --- /dev/null +++ b/resources/views/tools/html-entity.blade.php @@ -0,0 +1,419 @@ +@extends('layouts.app') + +@section('title', 'HTML Entity Encoder/Decoder - Free Online Tool | Dev Tools') +@section('meta_description', 'Free online HTML entity encoder and decoder. Convert special characters to HTML entities and decode them back. Supports named and numeric entities.') +@section('meta_keywords', 'html entity encoder, html entity decoder, encode html, decode html entities, html special characters, free html tool') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

HTML Entity Encoder/Decoder

+

Encode special characters to HTML entities or decode them back to text

+
+ ← Back +
+ + +
+
+
+ Encoding Mode: + +
+ +
+
+ +
+ +
+
+
+ + +
+ +
+ +
+
+ + +
+
+
+ + +
+
+ +
+ +
+
+ + + + +
+
+
+ Input length: +
+
+ Output length: +
+
+
+
+
+ + +
+

Common HTML Entities

+
+ +
+
+ + +
+

Entity Reference

+ +
+
+ + + + + +
+ +
+ + + + + + + + + + + + + +
CharacterNamedNumericHexDescription
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index b56ba8d..d9ffa41 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,7 @@ Route::get('/qr-code', [ToolController::class, 'qrCode'])->name('qr-code'); + Route::get('/html-entity', [ToolController::class, 'htmlEntity'])->name('html-entity'); }); // Static Pages @@ -52,6 +53,7 @@ ['loc' => route('tools.qr-code'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.html-entity'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index 766edc0..4cd4af2 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -36,6 +36,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('QR Code Generator'); + $response->assertSee('HTML Entity Encoder'); } public function test_home_page_has_tool_links(): void @@ -60,6 +61,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.qr-code') . '"', false); + $response->assertSee('href="' . route('tools.html-entity') . '"', false); } public function test_csv_tool_page_loads(): void @@ -346,11 +348,29 @@ public function test_qr_code_tool_has_required_elements(): void $response->assertSee('Download PNG'); $response->assertSee('Error Correction'); + public function test_html_entity_tool_page_loads(): void + { + $response = $this->get('/tools/html-entity'); + + $response->assertStatus(200); + $response->assertSee('HTML Entity Encoder/Decoder'); + $response->assertSee('Encode special characters to HTML entities or decode them back to text'); + } + + public function test_html_entity_tool_has_required_elements(): void + { + $response = $this->get('/tools/html-entity'); + + $response->assertStatus(200); + $response->assertSee('Encode'); + $response->assertSee('Decode'); + $response->assertSee('Common HTML Entities'); + $response->assertSee('Entity Reference'); } public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; foreach ($pages as $page) { $response = $this->get($page); @@ -362,7 +382,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; foreach ($pages as $page) { $response = $this->get($page); @@ -375,7 +395,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; foreach ($pages as $page) { $response = $this->get($page); @@ -388,7 +408,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -441,7 +461,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; foreach ($pages as $page) { $response = $this->get($page); From e26a01ee8a9a95f6595a1daaf5a1bd961031d6a6 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 20:33:53 +0000 Subject: [PATCH 06/10] Add Text Case Converter tool - Convert text between 13 different case formats - Supports: lowercase, UPPERCASE, Title Case, Sentence case - Programming cases: camelCase, PascalCase, snake_case, kebab-case - Additional: CONSTANT_CASE, dot.case, path/case - Fun modes: aLtErNaTiNg, Inverse Case - Real-time character/word/line statistics - Quick action buttons for common conversions - Client-side only implementation using Alpine.js --- app/Http/Controllers/ToolController.php | 7 + resources/views/home.blade.php | 4 + resources/views/tools/text-case.blade.php | 305 ++++++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 25 ++ 5 files changed, 343 insertions(+) create mode 100644 resources/views/tools/text-case.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index bdbe302..8718fb8 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -104,6 +104,10 @@ public function index(): View 'description' => 'Encode/decode HTML entities and special characters', 'route' => 'tools.html-entity', 'icon' => 'html-entity', + 'name' => 'Text Case Converter', + 'description' => 'Convert text to camelCase, snake_case, and more', + 'route' => 'tools.text-case', + 'icon' => 'text-case', ], ]; @@ -188,5 +192,8 @@ public function qrCode(): View public function htmlEntity(): View { return view('tools.html-entity'); + public function textCase(): View + { + return view('tools.text-case'); } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 22b824b..7257a33 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -112,6 +112,10 @@ @case('html-entity') + @case('text-case') + + + @break @endswitch diff --git a/resources/views/tools/text-case.blade.php b/resources/views/tools/text-case.blade.php new file mode 100644 index 0000000..039cdd3 --- /dev/null +++ b/resources/views/tools/text-case.blade.php @@ -0,0 +1,305 @@ +@extends('layouts.app') + +@section('title', 'Text Case Converter - camelCase, snake_case, Title Case | Dev Tools') +@section('meta_description', 'Free online text case converter. Convert text to lowercase, UPPERCASE, Title Case, camelCase, snake_case, kebab-case, PascalCase, and more.') +@section('meta_keywords', 'text case converter, camelcase converter, snake case, kebab case, title case, uppercase, lowercase, pascal case, text transformer') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Text Case Converter

+

Convert text between different case formats

+
+ ← Back +
+ +
+
+
+
+ + +
+ +
+
+ characters + words + lines +
+
+
+ +
+
+ + +
+ +
+
+ +
+
+

Convert To

+
+ +
+
+ +
+

Quick Actions

+
+ + + + +
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index d9ffa41..2497e14 100644 --- a/routes/web.php +++ b/routes/web.php @@ -25,6 +25,7 @@ Route::get('/qr-code', [ToolController::class, 'qrCode'])->name('qr-code'); Route::get('/html-entity', [ToolController::class, 'htmlEntity'])->name('html-entity'); + Route::get('/text-case', [ToolController::class, 'textCase'])->name('text-case'); }); // Static Pages @@ -54,6 +55,7 @@ ['loc' => route('tools.qr-code'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.html-entity'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.text-case'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index 4cd4af2..a537f09 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -37,6 +37,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('QR Code Generator'); $response->assertSee('HTML Entity Encoder'); + $response->assertSee('Text Case Converter'); } public function test_home_page_has_tool_links(): void @@ -62,6 +63,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.qr-code') . '"', false); $response->assertSee('href="' . route('tools.html-entity') . '"', false); + $response->assertSee('href="' . route('tools.text-case') . '"', false); } public function test_csv_tool_page_loads(): void @@ -366,11 +368,30 @@ public function test_html_entity_tool_has_required_elements(): void $response->assertSee('Decode'); $response->assertSee('Common HTML Entities'); $response->assertSee('Entity Reference'); + public function test_text_case_tool_page_loads(): void + { + $response = $this->get('/tools/text-case'); + + $response->assertStatus(200); + $response->assertSee('Text Case Converter'); + $response->assertSee('Convert text between different case formats'); + } + + public function test_text_case_tool_has_required_elements(): void + { + $response = $this->get('/tools/text-case'); + + $response->assertStatus(200); + $response->assertSee('Input Text'); + $response->assertSee('Convert To'); + $response->assertSee('camelCase'); + $response->assertSee('snake_case'); } public function test_all_pages_have_navigation(): void { $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; foreach ($pages as $page) { $response = $this->get($page); @@ -383,6 +404,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; foreach ($pages as $page) { $response = $this->get($page); @@ -396,6 +418,7 @@ public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; foreach ($pages as $page) { $response = $this->get($page); @@ -409,6 +432,7 @@ public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -462,6 +486,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/text-case']; foreach ($pages as $page) { $response = $this->get($page); From ae48144eb928d1a621aa7889fb1f18a17c820223 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 17:25:47 +0000 Subject: [PATCH 07/10] Add Password Generator tool - Generate secure random passwords using crypto.getRandomValues() - Configurable length (4-64 characters) - Character options: uppercase, lowercase, numbers, symbols - Exclude ambiguous characters option (0OIl1) - Password strength indicator with visual bar - Quick presets: PIN, Simple, Strong, Paranoid - Bulk generation (up to 50 passwords) - Password history with copy functionality --- app/Http/Controllers/ToolController.php | 7 + resources/views/home.blade.php | 3 + .../views/tools/password-generator.blade.php | 446 ++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 25 + 5 files changed, 483 insertions(+) create mode 100644 resources/views/tools/password-generator.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 8718fb8..f6009dd 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -108,6 +108,10 @@ public function index(): View 'description' => 'Convert text to camelCase, snake_case, and more', 'route' => 'tools.text-case', 'icon' => 'text-case', + 'name' => 'Password Generator', + 'description' => 'Generate secure random passwords', + 'route' => 'tools.password', + 'icon' => 'key', ], ]; @@ -195,5 +199,8 @@ public function htmlEntity(): View public function textCase(): View { return view('tools.text-case'); + public function password(): View + { + return view('tools.password-generator'); } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 7257a33..d2b06c4 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -116,6 +116,9 @@ + @case('key') + + @break @endswitch diff --git a/resources/views/tools/password-generator.blade.php b/resources/views/tools/password-generator.blade.php new file mode 100644 index 0000000..c87db0c --- /dev/null +++ b/resources/views/tools/password-generator.blade.php @@ -0,0 +1,446 @@ +@extends('layouts.app') + +@section('title', 'Password Generator - Secure Random Passwords | Dev Tools') +@section('meta_description', 'Free online secure password generator. Create strong, random passwords with customizable length and character options. Uses cryptographic randomness.') +@section('meta_keywords', 'password generator, secure password, random password, strong password, password creator, crypto random, password tool') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Password Generator

+

Generate secure random passwords

+
+ ← Back +
+ +
+
+
+ +
+
+ +
+ + +
+
+
+ +
+
+ Strength + +
+
+
+
+
+ + +
+ +
+
+ + +
+
+ +
+
+ +
+

Bulk Generate

+
+ + +
+
+
+ + +
+
+ +
+
+
+
+ +
+
+

Options

+ +
+
+ + +
+ 4 + 64 +
+
+ +
+ + + + + + + + + +
+
+
+ +
+

Quick Presets

+
+ + + + +
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 2497e14..414e8bf 100644 --- a/routes/web.php +++ b/routes/web.php @@ -26,6 +26,7 @@ Route::get('/html-entity', [ToolController::class, 'htmlEntity'])->name('html-entity'); Route::get('/text-case', [ToolController::class, 'textCase'])->name('text-case'); + Route::get('/password', [ToolController::class, 'password'])->name('password'); }); // Static Pages @@ -56,6 +57,7 @@ ['loc' => route('tools.html-entity'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.text-case'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.password'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index a537f09..f5426e5 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -38,6 +38,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('HTML Entity Encoder'); $response->assertSee('Text Case Converter'); + $response->assertSee('Password Generator'); } public function test_home_page_has_tool_links(): void @@ -64,6 +65,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.html-entity') . '"', false); $response->assertSee('href="' . route('tools.text-case') . '"', false); + $response->assertSee('href="' . route('tools.password') . '"', false); } public function test_csv_tool_page_loads(): void @@ -386,12 +388,31 @@ public function test_text_case_tool_has_required_elements(): void $response->assertSee('Convert To'); $response->assertSee('camelCase'); $response->assertSee('snake_case'); + public function test_password_tool_page_loads(): void + { + $response = $this->get('/tools/password'); + + $response->assertStatus(200); + $response->assertSee('Password Generator'); + $response->assertSee('Generate secure random passwords'); + } + + public function test_password_tool_has_required_elements(): void + { + $response = $this->get('/tools/password'); + + $response->assertStatus(200); + $response->assertSee('Generated Password'); + $response->assertSee('Strength'); + $response->assertSee('Options'); + $response->assertSee('Quick Presets'); } public function test_all_pages_have_navigation(): void { $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; foreach ($pages as $page) { $response = $this->get($page); @@ -405,6 +426,7 @@ public function test_all_pages_have_theme_toggle(): void { $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; foreach ($pages as $page) { $response = $this->get($page); @@ -419,6 +441,7 @@ public function test_all_pages_load_vite_assets(): void // Code editor uses standalone template without Vite $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; foreach ($pages as $page) { $response = $this->get($page); @@ -433,6 +456,7 @@ public function test_all_tool_pages_have_back_link(): void // Code editor uses standalone template with home link instead of back $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -487,6 +511,7 @@ public function test_pages_have_csrf_token(): void { $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/text-case']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/password']; foreach ($pages as $page) { $response = $this->get($page); From deed4f6ec9f0bef2abff84ecb232128b04709288 Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 15:50:09 +0000 Subject: [PATCH 08/10] Add Lorem Ipsum Generator tool - Generate placeholder text by paragraphs, sentences, or words - Configurable count with slider control - Option to start with classic "Lorem ipsum dolor sit amet..." - Real-time statistics (paragraphs, sentences, words, characters) - Copy to clipboard and download as TXT - Client-side only implementation using Alpine.js --- app/Http/Controllers/ToolController.php | 7 + resources/views/home.blade.php | 3 + resources/views/tools/lorem-ipsum.blade.php | 304 ++++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 25 ++ 5 files changed, 341 insertions(+) create mode 100644 resources/views/tools/lorem-ipsum.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index f6009dd..a02002b 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -112,6 +112,10 @@ public function index(): View 'description' => 'Generate secure random passwords', 'route' => 'tools.password', 'icon' => 'key', + 'name' => 'Lorem Ipsum Generator', + 'description' => 'Generate placeholder text for designs', + 'route' => 'tools.lorem', + 'icon' => 'text', ], ]; @@ -202,5 +206,8 @@ public function textCase(): View public function password(): View { return view('tools.password-generator'); + public function lorem(): View + { + return view('tools.lorem-ipsum'); } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index d2b06c4..a2c95b2 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -119,6 +119,9 @@ @case('key') + @case('text') + + @break @endswitch diff --git a/resources/views/tools/lorem-ipsum.blade.php b/resources/views/tools/lorem-ipsum.blade.php new file mode 100644 index 0000000..a62ae33 --- /dev/null +++ b/resources/views/tools/lorem-ipsum.blade.php @@ -0,0 +1,304 @@ +@extends('layouts.app') + +@section('title', 'Lorem Ipsum Generator - Placeholder Text Generator | Dev Tools') +@section('meta_description', 'Free online Lorem Ipsum generator. Generate placeholder text by paragraphs, sentences, or words. Perfect for mockups, wireframes, and design projects.') +@section('meta_keywords', 'lorem ipsum generator, placeholder text, dummy text, lipsum, filler text, mockup text, design placeholder, random text generator') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Lorem Ipsum Generator

+

Generate placeholder text for designs and mockups

+
+ ← Back +
+ +
+
+
+

Options

+ +
+
+ +
+ +
+
+ +
+ + +
+ 1 + +
+
+ +
+ + +
+ + +
+
+ +
+

Statistics

+
+
+
+
Paragraphs
+
+
+
+
Sentences
+
+
+
+
Words
+
+
+
+
Characters
+
+
+
+
+ +
+
+
+ +
+ + +
+
+
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 414e8bf..ee52f7f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -27,6 +27,7 @@ Route::get('/html-entity', [ToolController::class, 'htmlEntity'])->name('html-entity'); Route::get('/text-case', [ToolController::class, 'textCase'])->name('text-case'); Route::get('/password', [ToolController::class, 'password'])->name('password'); + Route::get('/lorem', [ToolController::class, 'lorem'])->name('lorem'); }); // Static Pages @@ -58,6 +59,7 @@ ['loc' => route('tools.html-entity'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.text-case'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.password'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.lorem'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index f5426e5..a8989b0 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -39,6 +39,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('HTML Entity Encoder'); $response->assertSee('Text Case Converter'); $response->assertSee('Password Generator'); + $response->assertSee('Lorem Ipsum Generator'); } public function test_home_page_has_tool_links(): void @@ -66,6 +67,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.html-entity') . '"', false); $response->assertSee('href="' . route('tools.text-case') . '"', false); $response->assertSee('href="' . route('tools.password') . '"', false); + $response->assertSee('href="' . route('tools.lorem') . '"', false); } public function test_csv_tool_page_loads(): void @@ -406,6 +408,24 @@ public function test_password_tool_has_required_elements(): void $response->assertSee('Strength'); $response->assertSee('Options'); $response->assertSee('Quick Presets'); + public function test_lorem_tool_page_loads(): void + { + $response = $this->get('/tools/lorem'); + + $response->assertStatus(200); + $response->assertSee('Lorem Ipsum Generator'); + $response->assertSee('Generate placeholder text'); + } + + public function test_lorem_tool_has_required_elements(): void + { + $response = $this->get('/tools/lorem'); + + $response->assertStatus(200); + $response->assertSee('Paragraphs'); + $response->assertSee('Sentences'); + $response->assertSee('Words'); + $response->assertSee('Generate'); } public function test_all_pages_have_navigation(): void @@ -413,6 +433,7 @@ public function test_all_pages_have_navigation(): void $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; foreach ($pages as $page) { $response = $this->get($page); @@ -427,6 +448,7 @@ public function test_all_pages_have_theme_toggle(): void $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; foreach ($pages as $page) { $response = $this->get($page); @@ -442,6 +464,7 @@ public function test_all_pages_load_vite_assets(): void $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/lorem']; foreach ($pages as $page) { $response = $this->get($page); @@ -457,6 +480,7 @@ public function test_all_tool_pages_have_back_link(): void $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/lorem']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -512,6 +536,7 @@ public function test_pages_have_csrf_token(): void $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/text-case']; $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/password']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; foreach ($pages as $page) { $response = $this->get($page); From ed47802915938272dff24f6ae658b7856f227dad Mon Sep 17 00:00:00 2001 From: jalel Date: Sun, 14 Dec 2025 15:39:40 +0000 Subject: [PATCH 09/10] Add Cron Expression Parser tool - Parse and validate cron expressions with human-readable explanations - Display field breakdown (minute, hour, day, month, weekday) - Calculate and show next 5 scheduled run times - Include common patterns library for quick reference - Add syntax reference panel for cron special characters - Client-side only implementation using Alpine.js --- app/Http/Controllers/ToolController.php | 7 + resources/views/home.blade.php | 3 + resources/views/tools/cron-parser.blade.php | 547 ++++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 25 + 5 files changed, 584 insertions(+) create mode 100644 resources/views/tools/cron-parser.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index a02002b..629968c 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -116,6 +116,10 @@ public function index(): View 'description' => 'Generate placeholder text for designs', 'route' => 'tools.lorem', 'icon' => 'text', + 'name' => 'Cron Parser', + 'description' => 'Parse and explain cron expressions', + 'route' => 'tools.cron', + 'icon' => 'clock', ], ]; @@ -209,5 +213,8 @@ public function password(): View public function lorem(): View { return view('tools.lorem-ipsum'); + public function cron(): View + { + return view('tools.cron-parser'); } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index a2c95b2..fed9b9f 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -122,6 +122,9 @@ @case('text') + @case('clock') + + @break @endswitch diff --git a/resources/views/tools/cron-parser.blade.php b/resources/views/tools/cron-parser.blade.php new file mode 100644 index 0000000..475ef07 --- /dev/null +++ b/resources/views/tools/cron-parser.blade.php @@ -0,0 +1,547 @@ +@extends('layouts.app') + +@section('title', 'Cron Expression Parser - Explain & Validate Cron Jobs | Dev Tools') +@section('meta_description', 'Free online cron expression parser. Understand cron syntax, validate expressions, see next run times, and get human-readable explanations of your cron schedules.') +@section('meta_keywords', 'cron parser, cron expression, cron validator, cron schedule, crontab, cron syntax, cron job, cron generator, cron explainer, cron next run') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Cron Expression Parser

+

Parse and explain cron expressions with next run times

+
+ ← Back +
+ +
+
+
+ +
+ + +
+ +
+ +
+
+ +
+

Human Readable

+

+
+ +
+
+ + + + +
+
+ +
+

Field Breakdown

+
+ +
+
+ +
+

Next Run Times

+
+ +
+
+
+ +
+
+

Common Patterns

+
+ +
+
+ +
+

Syntax Reference

+
+
+

Field Values

+ + + + + + + + + + + + + + + + + + + + + + + +
Minute0-59
Hour0-23
Day of Month1-31
Month1-12
Day of Week0-6 (Sun-Sat)
+
+
+

Special Characters

+ + + + + + + + + + + + + + + + + + + +
*Any value
,Value list (1,3,5)
-Range (1-5)
/Step (*/15)
+
+
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index ee52f7f..ee8cb4e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -28,6 +28,7 @@ Route::get('/text-case', [ToolController::class, 'textCase'])->name('text-case'); Route::get('/password', [ToolController::class, 'password'])->name('password'); Route::get('/lorem', [ToolController::class, 'lorem'])->name('lorem'); + Route::get('/cron', [ToolController::class, 'cron'])->name('cron'); }); // Static Pages @@ -60,6 +61,7 @@ ['loc' => route('tools.text-case'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.password'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.lorem'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.cron'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index a8989b0..5cd285b 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -40,6 +40,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('Text Case Converter'); $response->assertSee('Password Generator'); $response->assertSee('Lorem Ipsum Generator'); + $response->assertSee('Cron Parser'); } public function test_home_page_has_tool_links(): void @@ -68,6 +69,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.text-case') . '"', false); $response->assertSee('href="' . route('tools.password') . '"', false); $response->assertSee('href="' . route('tools.lorem') . '"', false); + $response->assertSee('href="' . route('tools.cron') . '"', false); } public function test_csv_tool_page_loads(): void @@ -426,6 +428,24 @@ public function test_lorem_tool_has_required_elements(): void $response->assertSee('Sentences'); $response->assertSee('Words'); $response->assertSee('Generate'); + public function test_cron_tool_page_loads(): void + { + $response = $this->get('/tools/cron'); + + $response->assertStatus(200); + $response->assertSee('Cron Expression Parser'); + $response->assertSee('Parse and explain cron expressions'); + } + + public function test_cron_tool_has_required_elements(): void + { + $response = $this->get('/tools/cron'); + + $response->assertStatus(200); + $response->assertSee('Cron Expression'); + $response->assertSee('Common Patterns'); + $response->assertSee('Syntax Reference'); + $response->assertSee('Next Run Times'); } public function test_all_pages_have_navigation(): void @@ -434,6 +454,7 @@ public function test_all_pages_have_navigation(): void $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -449,6 +470,7 @@ public function test_all_pages_have_theme_toggle(): void $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -465,6 +487,7 @@ public function test_all_pages_load_vite_assets(): void $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/lorem']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -481,6 +504,7 @@ public function test_all_tool_pages_have_back_link(): void $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/lorem']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/cron']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -537,6 +561,7 @@ public function test_pages_have_csrf_token(): void $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/text-case']; $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/password']; $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); From cd213db84327185aa12058fb65852d8b83ecbcfd Mon Sep 17 00:00:00 2001 From: jalel Date: Mon, 15 Dec 2025 00:41:42 +0000 Subject: [PATCH 10/10] Fix syntax errors in merged tool files Resolve missing closing braces in ToolController methods and closing tags in home.blade.php icon cases. Also fix duplicate array assignments in WebRoutesTest by consolidating all tool pages into single arrays. --- app/Http/Controllers/ToolController.php | 16 ++++++++++ resources/views/home.blade.php | 14 +++++++-- tests/Feature/WebRoutesTest.php | 40 ++++++++++--------------- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 629968c..eb8c3a2 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -104,18 +104,26 @@ public function index(): View 'description' => 'Encode/decode HTML entities and special characters', 'route' => 'tools.html-entity', 'icon' => 'html-entity', + ], + [ 'name' => 'Text Case Converter', 'description' => 'Convert text to camelCase, snake_case, and more', 'route' => 'tools.text-case', 'icon' => 'text-case', + ], + [ 'name' => 'Password Generator', 'description' => 'Generate secure random passwords', 'route' => 'tools.password', 'icon' => 'key', + ], + [ 'name' => 'Lorem Ipsum Generator', 'description' => 'Generate placeholder text for designs', 'route' => 'tools.lorem', 'icon' => 'text', + ], + [ 'name' => 'Cron Parser', 'description' => 'Parse and explain cron expressions', 'route' => 'tools.cron', @@ -204,15 +212,23 @@ public function qrCode(): View public function htmlEntity(): View { return view('tools.html-entity'); + } + public function textCase(): View { return view('tools.text-case'); + } + public function password(): View { return view('tools.password-generator'); + } + public function lorem(): View { return view('tools.lorem-ipsum'); + } + public function cron(): View { return view('tools.cron-parser'); diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index fed9b9f..2a21f80 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -104,24 +104,34 @@ @case('color') - + + @break @case('qrcode') - + + @break @case('html-entity') + + @break @case('text-case') + + @break @case('key') + + @break @case('text') + + @break @case('clock') diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index 5cd285b..ae1bc1b 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -336,6 +336,7 @@ public function test_color_picker_has_required_elements(): void $response->assertSee('HSL'); $response->assertSee('CMYK'); $response->assertSee('Color Harmony'); + } public function test_qr_code_tool_page_loads(): void { @@ -355,6 +356,7 @@ public function test_qr_code_tool_has_required_elements(): void $response->assertSee('Quick Templates'); $response->assertSee('Download PNG'); $response->assertSee('Error Correction'); + } public function test_html_entity_tool_page_loads(): void { @@ -374,6 +376,8 @@ public function test_html_entity_tool_has_required_elements(): void $response->assertSee('Decode'); $response->assertSee('Common HTML Entities'); $response->assertSee('Entity Reference'); + } + public function test_text_case_tool_page_loads(): void { $response = $this->get('/tools/text-case'); @@ -392,6 +396,8 @@ public function test_text_case_tool_has_required_elements(): void $response->assertSee('Convert To'); $response->assertSee('camelCase'); $response->assertSee('snake_case'); + } + public function test_password_tool_page_loads(): void { $response = $this->get('/tools/password'); @@ -410,6 +416,8 @@ public function test_password_tool_has_required_elements(): void $response->assertSee('Strength'); $response->assertSee('Options'); $response->assertSee('Quick Presets'); + } + public function test_lorem_tool_page_loads(): void { $response = $this->get('/tools/lorem'); @@ -428,6 +436,8 @@ public function test_lorem_tool_has_required_elements(): void $response->assertSee('Sentences'); $response->assertSee('Words'); $response->assertSee('Generate'); + } + public function test_cron_tool_page_loads(): void { $response = $this->get('/tools/cron'); @@ -450,11 +460,7 @@ public function test_cron_tool_has_required_elements(): void public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -466,11 +472,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/text-case']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/password']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -483,11 +485,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/lorem']; - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/cron']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -500,11 +498,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/text-case']; - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/password']; - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/lorem']; - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/cron']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/regex', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -557,11 +551,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity']; - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/text-case']; - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/password']; - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/lorem']; - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/base-converter', '/tools/slug-generator', '/tools/color-picker', '/tools/qr-code', '/tools/html-entity', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page);