我正在使用基于诺科吉里的助手来截断文本而不打破html标签:
require "rubygems"
require "nokogiri"
module TextHelper
def truncate_html(text, max_length, ellipsis = "...")
ellipsis_length = ellipsis.length
doc = Nokogiri::HTML::DocumentFragment.parse text
content_length = doc.inner_text.length
actual_length = max_length - ellipsis_length
content_length > actual_length ? doc.truncate(actual_length).inner_html + ellipsis : text.to_s
end
end
module NokogiriTruncator
module NodeWithChildren
def truncate(max_length)
return self if inner_text.length <= max_length
truncated_node = self.dup
truncated_node.children.remove
self.children.each do |node|
remaining_length = max_length - truncated_node.inner_text.length
break if remaining_length <= 0
truncated_node.add_child node.truncate(remaining_length)
end
truncated_node
end
end
module TextNode
def truncate(max_length)
Nokogiri::XML::Text.new(content[0..(max_length - 1)], parent)
end
end
end
Nokogiri::HTML::DocumentFragment.send(:include, NokogiriTruncator::NodeWithChildren)
Nokogiri::XML::Element.send(:include, NokogiriTruncator::NodeWithChildren)
Nokogiri::XML::Text.send(:include, NokogiriTruncator::TextNode)
on
content_length > actual_length ? doc.truncate(actual_length).inner_html + ellipsis : text.to_s
它在最后一个标签之后就附加了椭圆。
在我的视图上,我致电
<%= truncate_html(news.parsed_body, 700, "... Read more.").html_safe %>
问题是要解析的文本包裹在<p></p>
标签中,从而导致视图中断:
"Lorem Ipsum</p>
... Read More"
可以使用Nokogiri将椭圆附加到最后一个节点的最后一部分,因此最终输出变为:
"Loren Ipsum... Read More</p>
由于您没有提供任何输入数据,因此可以从中插入:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo bar baz</p>
</body>
</html>
EOT
paragraph = doc.at('p')
text = paragraph.text
text[4..-1] = '...'
paragraph.content = text
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html>
# >> <body>
# >> <p>foo ...</p>
# >> </body>
# >> </html>
您使它比实际要困难得多。Nokogiri足够聪明,可以知道我们是通过标记还是简单的文本,并且content
将根据其所在的不同而创建一个文本节点或元素。
此代码简单:
- 找到
p
标签。 - 从中提取文本。
- 用
'...'
替换给定点的文本。 - 用该文本替换段落的内容。
如果您只想附加到该文本,它变得更加容易:
paragraph = doc.at('p')
paragraph.content = paragraph.text + ' ...Read more.'
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html>
# >> <body>
# >> <p>foo bar baz ...Read more.</p>
# >> </body>
# >> </html>