0

HTML文字列をスキャンし、それをprawnpdf用にフォーマットするメソッドがあります:

def format_for_prawn(pdf, string, colour)
  body = Nokogiri::HTML::DocumentFragment.parse(string)
  result = body.xpath('./*|./text()')
  result.each do |breaker|
    if breaker.name == "h3"
      pdf.fill_color colour
      pdf.text breaker.text.to_s, :size => 16
      pdf.move_down 5
    else
      pdf.fill_color '#444444'
      pdf.text breaker.text.to_s, :size => 10, :leading => 1
      pdf.move_down 10
    end
  end
end

それは<h3>sに最適です。段落の途中<b>(または同様の) タグが見つかった場合、新しい段落が開始されます。これは、Nokogiri が文字列を壊した場所であるためです。これは正しい動作です。

新しい段落になるpdf.textnew を呼び出す代わりに、太字の文字列を最後の関数に追加するにはどうすればよいですか?pdf.text

私はそれから配列を作ることを考えましたが、それは<h3>s で順番が狂います。

どんな助けでも大歓迎です。

4

1 に答える 1

1

私の最初の考えは、否定的な一致を行うことでした:

body.xpath( './node()[not(self::b)]' )

悲しいことに、これは<b>それを無視するのではなく除外します:

> body = Nokogiri::HTML::DocumentFragment.parse %(<h3><b>foo</b></h3><h3>bar</h3>fooz<b>baz</b>whatever); true

> body.xpath( './node()[not(self::b)]' ).to_a
[
    [0] <h3>
  <b>foo</b>
</h3>,
    [1] <h3>bar</h3>,
    [2] fooz,
    [3] whatever
]

したがって、バッファを使用する以外に選択肢はありません。ここでは、最初にノードを反復処理して、新しい行が必要かどうかに関するバッファを作成し、次にこのバッファを反復して行を pdf に追加します。

buffer = []

body.xpath( './node()' ).each do |node|
  if %w[text b].include? node.name
    # add to previous line or create one
    buffer << [] unless buffer.count
    buffer.last << { node: node }
  else
    # set content and create a new line
    buffer << [ { node: node, title: node.name == 'h3' } ]
    buffer << []
  end
end

# Now, each first level item in buffer is a line,
# containing elements we just have to concatenate text of
# to pass to `pdf#text`
buffer.each do |line|
  text = line.map do |part|
    node = part[ :node ]
    inner = node.text.to_s
    # restore <b> tag if you want bold style in pdf
    node.name == 'b' ? "<b>#{inner}</b>" : inner
  end.join

  if line.first
    if line.first[ :title ]
      pdf.fill_color colour
      pdf.text text, :size => 16
      pdf.move_down 5
    else
      pdf.fill_color '#444444'
      # inline_format ensure basic html formating is used, <b> in our case
      # See http://prawn.majesticseacreature.com/docs/0.11.1/Prawn/Text.html#method-i-text
      pdf.text text, size: 10, leading: 1, inline_format: true
      pdf.move_down 10
    end
  end    
end

もちろん、これはすべて、元の html を制御できないことを考慮したものです。それ以外の場合は、テキストノードを内部<p>または何かに配置する必要があり、問題は発生しません。

于 2013-09-26T07:30:45.803 に答える