【问题标题】:Add text just before the closing tag using Nokogiri使用 Nokogiri 在结束标记之前添加文本
【发布时间】:2015-05-10 19:19:16
【问题描述】:

我正在使用基于 Nokogiri 的助手来截断文本而不破坏 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)

开启

content_length > actual_length ? doc.truncate(actual_length).inner_html + ellipsis : text.to_s

它在最后一个标签之后附加一个椭圆。

在我看来,我打电话给

<%= truncate_html(news.parsed_body, 700, "... Read more.").html_safe %>

问题是正在解析的文本被包裹在&lt;p&gt;&lt;/p&gt;标签中,导致视图中断:

"Lorem Ipsum</p>
... Read More"

是否可以使用Nokogiri将椭圆附加到最后一个节点的最后部分,所以最终输出变为:

"Loren Ipsum... Read More</p>

【问题讨论】:

  • 不要将truncate_html 放在您的视图中。预处理控制器中的数据,将其分配给变量并在视图中仅访问该变量。

标签: ruby-on-rails ruby nokogiri


【解决方案1】:

由于您没有提供任何输入数据,因此您可以从中进行插值:

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 将根据它是创建一个文本节点还是一个元素。

这段代码很简单:

  1. 找到p标签。
  2. 从中提取文本。
  3. 用'...'替换从给定点到结尾的文本。
  4. 用该文本替换段落的内容。

如果您只想附加到该文本,它会变得更加容易:

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多