From 935828dabbcf3f2e96d5b6072f2ec30ffcbeb4e7 Mon Sep 17 00:00:00 2001 From: A1Gard Date: Thu, 19 Sep 2024 03:19:05 +0330 Subject: [PATCH] added table of content [SEO] --- app/Helpers/Helper.php | 95 +++++++++++++++++++ app/Http/Controllers/Admin/PostController.php | 1 + app/Models/Post.php | 10 ++ composer.json | 1 + .../2024_05_07_123414_create_posts_table.php | 1 + resources/lang/fa.json | 1 + .../views/admin/posts/post-form.blade.php | 12 ++- .../post/PostSidebar/PostSidebar.blade.php | 9 +- .../post/SimplePost/SimplePost.blade.php | 8 +- 9 files changed, 135 insertions(+), 3 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 48babdb..6e1e603 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1271,3 +1271,98 @@ function sendingSMS($text, $number, $args) return true; } + +/** + * table of content generator + * @param $html + * @return array + */ +function generateTOC($html) { + // Load HTML into a DOMDocument for parsing + $doc = new DOMDocument(); + @$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); + + $toc = ''; + $tocItems = []; + $lastH2 = ''; + $lastH3 = ''; + $idCounter = 0; + + // Fetch all headings in the document + $headings = $doc->getElementsByTagName('*'); + + foreach ($headings as $heading) { + if (in_array($heading->nodeName, ['h2', 'h3'])) { + // Generate a unique ID for each heading + $id = generateHeadingID($heading->nodeValue, $idCounter); + $idCounter++; + $heading->setAttribute('id', $id); + + if ($heading->nodeName === 'h2') { + $tocItems[] = [ + 'title' => $heading->nodeValue, + 'id' => $id, + 'children' => [] + ]; + $lastH2 = $heading->nodeValue; // Update last H2 title + $lastH3 = ''; // Reset last H3 + } elseif ($heading->nodeName === 'h3') { + if ($lastH2) { + // Create a new child entry for the last H2 + $tocItems[count($tocItems) - 1]['children'][] = [ + 'title' => $heading->nodeValue, + 'id' => $id, + ]; + $lastH3 = $heading->nodeValue; // Update last H3 title + } + } + } + } + + // Create the TOC HTML + $toc .= buildTOC($tocItems); + + // Return the modified HTML and the TOC + return [$toc, $doc->saveHTML()]; +} + +/** + * generate heading ID for table of content + * @param $text + * @param $counter + * @return string + */ +function generateHeadingID($text, $counter) { + // Convert to lowercase and replace non-alphanumeric characters with dashes + $id = strtolower(preg_replace('/[^a-zA-Z0-9]+/', '-', $text)); + + // Remove leading and trailing dashes + $id = trim($id, '-'); + + // Ensure the ID is not empty + if (empty($id)) { + $id = 'heading'; + } + + // Add the counter to ensure uniqueness + $id .= '-' . $counter; + + return $id; +} + +// The buildTOC function remains unchanged +function buildTOC($items) { + $html = ''; + return $html; +} diff --git a/app/Http/Controllers/Admin/PostController.php b/app/Http/Controllers/Admin/PostController.php index 735f459..8de63b4 100644 --- a/app/Http/Controllers/Admin/PostController.php +++ b/app/Http/Controllers/Admin/PostController.php @@ -58,6 +58,7 @@ class PostController extends XController $post->group_id = $request->input('group_id'); $post->user_id = auth()->id(); $post->is_pinned = $request->has('is_pin'); + $post->table_of_contents = $request->has('table_of_contents'); $post->icon = $request->input('icon'); if ($post->hash == null) { diff --git a/app/Models/Post.php b/app/Models/Post.php index ff7713e..d646db6 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -196,4 +196,14 @@ RESULT; return implode(',', $this->tags()->pluck('name')->toArray()); } } + + public function tableOfContents(){ + list($toc, $modifiedHtml) = generateTOC($this->body); + return $toc; + } + + public function bodyContent(){ + list($toc, $modifiedHtml) = generateTOC($this->body); + return $modifiedHtml; + } } diff --git a/composer.json b/composer.json index 486ef42..97158d9 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "license": "GPL-3.0-or-later", "require": { "php": "^8.2", + "ext-dom": "*", "carlos-meneses/laravel-mpdf": "^2.1", "chillerlan/php-qrcode": "^5.0", "dpsoft/mellat": "^1.1", diff --git a/database/migrations/2024_05_07_123414_create_posts_table.php b/database/migrations/2024_05_07_123414_create_posts_table.php index 48dd4f7..1a0a69b 100644 --- a/database/migrations/2024_05_07_123414_create_posts_table.php +++ b/database/migrations/2024_05_07_123414_create_posts_table.php @@ -26,6 +26,7 @@ return new class extends Migration $table->unsignedInteger('like')->default(0); $table->unsignedInteger('dislike')->default(0); $table->string('icon', 128)->nullable(); + $table->boolean('table_of_contents')->default(0); $table->softDeletes(); $table->timestamps(); diff --git a/resources/lang/fa.json b/resources/lang/fa.json index 6b6aa0f..4d22cd7 100644 --- a/resources/lang/fa.json +++ b/resources/lang/fa.json @@ -418,6 +418,7 @@ "Successfully Invoices": "", "Summary": "خلاصه", "System notification": "پیام سیستم", + "Table of contents": "فهرست عناوین", "Tag": "برچسب", "Tags": "برچسب‌ها", "Tags list": "فهرست برچسب‌ها", diff --git a/resources/views/admin/posts/post-form.blade.php b/resources/views/admin/posts/post-form.blade.php index 224cf9d..7f5b0c3 100644 --- a/resources/views/admin/posts/post-form.blade.php +++ b/resources/views/admin/posts/post-form.blade.php @@ -103,13 +103,23 @@ placeholder="{{__('Title')}}" value="{{old('title',$item->title??null)}}"/> -
+
+
+
+
+ table_of_contents??0) != 0) + checked + @endif type="checkbox" id="table_of_contents"> + +
+
+

- {!! $post->body !!} + @if($post->table_of_contents) + {!! $post->tableOfContents() !!} + {!! $post->bodyContent() !!} + @else + + {!! $post->body !!} + @endif +
diff --git a/resources/views/segments/post/SimplePost/SimplePost.blade.php b/resources/views/segments/post/SimplePost/SimplePost.blade.php index 126e32e..da459c5 100644 --- a/resources/views/segments/post/SimplePost/SimplePost.blade.php +++ b/resources/views/segments/post/SimplePost/SimplePost.blade.php @@ -37,7 +37,13 @@ @endif
- {!! $post->body !!} + @if($post->table_of_contents) + {!! $post->tableOfContents() !!} + {!! $post->bodyContent() !!} + @else + + {!! $post->body !!} + @endif