From 09dff085088047e04f8b4becaa13b2b9878091e3 Mon Sep 17 00:00:00 2001 From: jalel Date: Mon, 15 Dec 2025 10:03:22 +0000 Subject: [PATCH] Add Sort Lines tool --- app/Http/Controllers/ToolController.php | 11 + resources/views/home.blade.php | 5 + resources/views/tools/sort-lines.blade.php | 351 +++++++++++++++++++++ routes/web.php | 2 + tests/Feature/WebRoutesTest.php | 33 +- 5 files changed, 397 insertions(+), 5 deletions(-) create mode 100644 resources/views/tools/sort-lines.blade.php diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index d0a6454..682b4c9 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -147,6 +147,12 @@ public function index(): View 'route' => 'tools.diff', 'icon' => 'diff', ], + [ + 'name' => 'Sort Lines', + 'description' => 'Sort, deduplicate, reverse, and shuffle lines', + 'route' => 'tools.sort-lines', + 'icon' => 'sort', + ], ]; return view('home', compact('tools')); @@ -266,4 +272,9 @@ public function diff(): View { return view('tools.diff'); } + + public function sortLines(): View + { + return view('tools.sort-lines'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 4e1851a..972ddb3 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -151,6 +151,11 @@ @break + @case('sort') + + + + @break @endswitch
diff --git a/resources/views/tools/sort-lines.blade.php b/resources/views/tools/sort-lines.blade.php new file mode 100644 index 0000000..ba2cd1d --- /dev/null +++ b/resources/views/tools/sort-lines.blade.php @@ -0,0 +1,351 @@ +@extends('layouts.app') + +@section('title', 'Sort Lines - Sort, Dedupe, Reverse, Shuffle Text | Dev Tools') +@section('meta_description', 'Free online line sorter. Sort lines alphabetically, numerically, remove duplicates, reverse order, or shuffle randomly. Fast and private - no data stored.') +@section('meta_keywords', 'sort lines, line sorter, sort text, remove duplicates, dedupe lines, reverse lines, shuffle lines, alphabetical sort, natural sort') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Sort Lines

+

Sort, deduplicate, reverse, and shuffle text lines

+
+ ← Back +
+ +
+
+
+
+ +
+ + +
+
+ +
+
+ lines + unique + duplicates +
+
+
+ +
+
+ + +
+ +
+
+ lines +
+
+
+
+ +
+
+

Sort Options

+
+ +
+
+ +
+

Options

+
+ + + +
+
+ +
+

Quick Actions

+
+ + + + +
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 63e04f2..de71750 100644 --- a/routes/web.php +++ b/routes/web.php @@ -29,6 +29,7 @@ Route::get('/jwt', [ToolController::class, 'jwt'])->name('jwt'); Route::get('/timestamp', [ToolController::class, 'timestamp'])->name('timestamp'); Route::get('/diff', [ToolController::class, 'diff'])->name('diff'); + Route::get('/sort-lines', [ToolController::class, 'sortLines'])->name('sort-lines'); }); // Static Pages @@ -62,6 +63,7 @@ ['loc' => route('tools.jwt'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.timestamp'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.diff'), 'priority' => '0.8', 'changefreq' => 'monthly'], + ['loc' => route('tools.sort-lines'), '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 d99e52e..b4c1203 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -41,6 +41,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('JWT Decoder'); $response->assertSee('Timestamp Converter'); $response->assertSee('Diff Checker'); + $response->assertSee('Sort Lines'); } public function test_home_page_has_tool_links(): void @@ -70,6 +71,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.jwt') . '"', false); $response->assertSee('href="' . route('tools.timestamp') . '"', false); $response->assertSee('href="' . route('tools.diff') . '"', false); + $response->assertSee('href="' . route('tools.sort-lines') . '"', false); } public function test_csv_tool_page_loads(): void @@ -516,9 +518,30 @@ public function test_diff_tool_has_required_elements(): void $response->assertSee('Compare'); } + public function test_sort_lines_page_loads(): void + { + $response = $this->get('/tools/sort-lines'); + + $response->assertStatus(200); + $response->assertSee('Sort Lines'); + $response->assertSee('Sort, deduplicate, reverse, and shuffle text lines'); + } + + public function test_sort_lines_has_required_elements(): void + { + $response = $this->get('/tools/sort-lines'); + + $response->assertStatus(200); + $response->assertSee('Input Text'); + $response->assertSee('Sort Options'); + $response->assertSee('Sort A-Z'); + $response->assertSee('Remove Duplicates'); + $response->assertSee('Shuffle'); + } + 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', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron', '/tools/jwt', '/tools/timestamp', '/tools/diff']; + $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', '/tools/jwt', '/tools/timestamp', '/tools/diff', '/tools/sort-lines']; foreach ($pages as $page) { $response = $this->get($page); @@ -530,7 +553,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', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron', '/tools/jwt', '/tools/timestamp', '/tools/diff']; + $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', '/tools/jwt', '/tools/timestamp', '/tools/diff', '/tools/sort-lines']; foreach ($pages as $page) { $response = $this->get($page); @@ -543,7 +566,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', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron', '/tools/jwt', '/tools/timestamp', '/tools/diff']; + $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', '/tools/jwt', '/tools/timestamp', '/tools/diff', '/tools/sort-lines']; foreach ($pages as $page) { $response = $this->get($page); @@ -556,7 +579,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', '/tools/text-case', '/tools/password', '/tools/lorem', '/tools/cron', '/tools/jwt', '/tools/timestamp', '/tools/diff']; + $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', '/tools/jwt', '/tools/timestamp', '/tools/diff', '/tools/sort-lines']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -609,7 +632,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/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', '/tools/jwt', '/tools/timestamp', '/tools/diff']; + $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', '/tools/jwt', '/tools/timestamp', '/tools/diff', '/tools/sort-lines']; foreach ($pages as $page) { $response = $this->get($page);