From 738d1f97fe16770d044f512d6c006a6fca457d67 Mon Sep 17 00:00:00 2001 From: nertc Date: Wed, 16 Apr 2025 15:33:26 +0400 Subject: [PATCH] Provide a truncated view of recent diaries --- app/views/diary_entries/_diary_entry.html.erb | 10 +++- app/views/diary_entries/_page.html.erb | 2 +- app/views/diary_entries/show.html.erb | 2 +- config/locales/en.yml | 1 + lib/rich_text.rb | 42 ++++++++++++++++ test/system/diary_entry_test.rb | 50 +++++++++++++++++++ 6 files changed, 104 insertions(+), 3 deletions(-) diff --git a/app/views/diary_entries/_diary_entry.html.erb b/app/views/diary_entries/_diary_entry.html.erb index 2d8243d1b..0905ce499 100644 --- a/app/views/diary_entries/_diary_entry.html.erb +++ b/app/views/diary_entries/_diary_entry.html.erb @@ -2,7 +2,15 @@ <%= render :partial => "diary_entry_heading", :object => diary_entry, :as => "diary_entry" %>
- <%= diary_entry.body.to_html %> + <% if truncated %> + <% truncated_entry = diary_entry.body.truncate_html(2000) %> + <%= truncated_entry[:html] %> + <% if truncated_entry[:truncated] %> +

… <%= link_to t(".full_entry"), diary_entry_path(diary_entry.user, diary_entry) %>

+ <% end %> + <% else %> + <%= diary_entry.body.to_html %> + <% end %>
<% if diary_entry.latitude and diary_entry.longitude %> diff --git a/app/views/diary_entries/_page.html.erb b/app/views/diary_entries/_page.html.erb index c44a5417e..9cba05d20 100644 --- a/app/views/diary_entries/_page.html.erb +++ b/app/views/diary_entries/_page.html.erb @@ -1,7 +1,7 @@

<%= t ".recent_entries" %>

- <%= render @entries %> + <%= render @entries, :truncated => true %> <%= render "shared/pagination", :newer_id => @newer_entries_id, diff --git a/app/views/diary_entries/show.html.erb b/app/views/diary_entries/show.html.erb index 9e3e7da65..c83189099 100644 --- a/app/views/diary_entries/show.html.erb +++ b/app/views/diary_entries/show.html.erb @@ -14,7 +14,7 @@ <% end %> -<%= render @entry %> +<%= render @entry, :truncated => false %> <%= social_share_buttons(:title => @entry.title, :url => diary_entry_url(@entry.user, @entry)) %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 16b967ead..67a342a5f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -608,6 +608,7 @@ en: diary_entry: posted_by_html: "Posted by %{link_user} on %{created} in %{language_link}." updated_at_html: "Last updated on %{updated}." + full_entry: See full entry comment_link: Comment on this entry reply_link: Send a message to the author comment_count: diff --git a/lib/rich_text.rb b/lib/rich_text.rb index 792497307..d5422b831 100644 --- a/lib/rich_text.rb +++ b/lib/rich_text.rb @@ -63,6 +63,48 @@ module RichText nil end + def truncate_html(max_length = nil, img_length = 1000) + html_doc = to_html + return html_doc if max_length.nil? + + doc = Nokogiri::HTML::DocumentFragment.parse(html_doc) + keep_or_discards = %w[p h1 h2 h3 h4 h5 h6 pre a table ul ol dl] + accumulated_length = 0 + exceeded_node_parent = nil + truncated = false + + doc.traverse do |node| + if accumulated_length >= max_length + if node == exceeded_node_parent + exceeded_node_parent = node.parent + node.remove if keep_or_discards.include?(node.name) + else + node.remove + end + next + end + + next unless node.children.empty? + + if node.text? + accumulated_length += node.text.length + elsif node.name == "img" + accumulated_length += img_length + end + + if accumulated_length >= max_length + truncated = true + exceeded_node_parent = node.parent + node.remove + end + end + + { + :truncated => truncated, + :html => doc.to_html.html_safe + } + end + protected def simple_format(text) diff --git a/test/system/diary_entry_test.rb b/test/system/diary_entry_test.rb index ba091c538..1cf72c964 100644 --- a/test/system/diary_entry_test.rb +++ b/test/system/diary_entry_test.rb @@ -74,4 +74,54 @@ class DiaryEntrySystemTest < ApplicationSystemTestCase assert_link "Diary Entries in Portuguese", :href => "/diary/pt" assert_no_link "Diary Entries in Russian" end + + test "should not be hidden on the list page" do + body = SecureRandom.alphanumeric(1998) + create(:diary_entry, :body => body) + + visit diary_entries_path + + assert_content body + assert_no_content I18n.t("diary_entries.diary_entry.full_entry") + end + + test "should be hidden on the list page" do + body = SecureRandom.alphanumeric(2000) + create(:diary_entry, :body => body) + + visit diary_entries_path + + assert_no_content body + assert_content I18n.t("diary_entries.diary_entry.full_entry") + end + + test "should be partially hidden on the list page" do + text1 = "a" * 500 + text2 = "b" * 500 + text3 = "c" * 999 + text4 = "dd" + text5 = "ff" + + body = "

#{text1}

#{text2}

#{text3}#{text4}

#{text5}

" + create(:diary_entry, :body => body) + + visit diary_entries_path + + assert_content text1 + assert_content text2 + assert_no_content text3 + assert_no_content text4 + assert_no_content text5 + assert_content I18n.t("diary_entries.diary_entry.full_entry") + end + + test "should not be hidden on the show page" do + body = SecureRandom.alphanumeric(2001) + diary_entry = create(:diary_entry, :body => body) + + visit diary_entry_path(diary_entry.user, diary_entry) + + assert_content body + assert_no_content I18n.t("diary_entries.diary_entry.full_entry") + end end -- 2.39.5