@@ -10,4 +10,72 @@ def dojo_count_label(count)
1010 def total_dojos_count ( dojos )
1111 dojos . sum ( &:counter )
1212 end
13+
14+ # 道場のノート欄でリンクを保持しながらテキストを切り詰める
15+ def truncate_with_preserved_links ( text , length : 60 )
16+ return text if text . blank?
17+
18+ # まずリンクを自動検出してHTMLに変換
19+ html_with_links = Rinku . auto_link ( text )
20+
21+ # HTMLをパースする
22+ doc = Nokogiri ::HTML ::DocumentFragment . parse ( html_with_links )
23+
24+ # 表示用のテキストの長さを計算
25+ visible_text = doc . text
26+
27+ if visible_text . length <= length
28+ # 切り詰める必要がない場合はそのまま返す
29+ return html_with_links . html_safe
30+ end
31+
32+ # 切り詰める必要がある場合
33+ result = ""
34+ current_length = 0
35+
36+ doc . children . each do |node |
37+ if node . text?
38+ # 通常のテキストノード
39+ remaining_length = length - current_length
40+ if node . content . length > remaining_length
41+ result += node . content [ 0 , remaining_length ] + "..."
42+ break
43+ else
44+ result += node . content
45+ current_length += node . content . length
46+ end
47+ elsif node . name == 'a'
48+ # リンクノード
49+ link_text = node . text
50+ remaining_length = length - current_length
51+
52+ if link_text . length > remaining_length
53+ # リンクのテキスト部分を切り詰める(href属性は保持)
54+ truncated_text = link_text [ 0 , remaining_length ] + "..."
55+ result += %Q(<a href="#{ node [ 'href' ] } ">#{ truncated_text } </a>)
56+ break
57+ else
58+ result += node . to_html
59+ current_length += link_text . length
60+ end
61+ else
62+ # その他のHTMLノード
63+ node_text = node . text
64+ remaining_length = length - current_length
65+
66+ if node_text . length > remaining_length
67+ # このノード内でも切り詰めが必要
68+ result += node . text [ 0 , remaining_length ] + "..."
69+ break
70+ else
71+ result += node . to_html
72+ current_length += node_text . length
73+ end
74+ end
75+
76+ break if current_length >= length
77+ end
78+
79+ result . html_safe
80+ end
1381end
0 commit comments