レール:記事のティーザー/抜粋を取得する
-
22-08-2019 - |
質問
ニュース記事をリストするページがあります。ページの長さを減らすために、ティーザー (記事の最初の 200 単語 / 600 文字) のみを表示し、その後「詳細...」リンクを表示します。このリンクをクリックすると、残りの部分が展開されます。 jQuery/JavaScript の方法で記事を作成します。さて、すべてを理解し、貼り付けページで次のヘルパー メソッドを見つけました。これにより、ニュース記事 (文字列) が単語の途中で切り刻まれないようにすることができます。
def shorten (string, count = 30)
if string.length >= count
shortened = string[0, count]
splitted = shortened.split(/\s/)
words = splitted.length
splitted[0, words-1].join(" ") + ' ...'
else
string
end
end
私が抱えている問題は、DB から取得したニュース記事の本文が HTML 形式であることです。したがって、運が悪いと、上記のヘルパーは記事の文字列を HTML タグの真ん中で切り刻んで、そこに「more...」という文字列を挿入します (例:"" の間)、ページ上の HTML が破損します。
これを回避する方法はありますか、または HTML 文字列から抜粋/ティーザーを生成するために使用できるプラグインはありますか?
解決 3
のおかげであなたの答えのためにたくさん! しかし、その間に私は完全に自分の目的に合った jQueryのHTMLトランケータプラグインに、つまずいそして、クライアント側への切り捨てを移します。これは、任意の容易に取得していない: - )
他のヒント
次の組み合わせを使用できます。 消毒する そして 切り詰める.
truncate("And they found that many people were sleeping better.",
:omission => "... (continued)", :length => 15)
# => And they found... (continued)
私はブログ投稿があり、簡単な抜粋を表示したいだけの同様のタスクを実行しています。したがって、私の見解では、私は単に次のようにします。
sanitize(truncate(blog_post.body, length: 150))
これにより、HTML タグが取り除かれ、最初の 150 文字が得られ、ビューで処理されるため、MVC フレンドリーになります。
幸運を!
私の答えは、作業を行う必要があります。元の質問は(ERR、私が尋ねた)マークダウンを切り捨てについてだったが、それが動作するはずですので、私は、その切り捨てHTMLに値下げを変換してしまっています。
あなたのサイトは、多くのトラフィックを取得する場合、あなたは(ポストが作成/更新されたときに、おそらく、あなたがデータベースに抜粋を格納することができ?)の抜粋をキャッシュする必要があります。もちろん、これはまた、ユーザーが変更する可能性を意味しますか自分の抜粋を入力してください。
使用方法:
>> puts "<p><b><a href=\"hi\">Something</a></p>".truncate_html(5, at_end = "...")
=> <p><b><a href="hi">Someth...</a></b></p>
..と(他の回答からコピーされた)コード:
require 'rexml/parsers/pullparser'
class String
def truncate_html(len = 30, at_end = nil)
p = REXML::Parsers::PullParser.new(self)
tags = []
new_len = len
results = ''
while p.has_next? && new_len > 0
p_e = p.pull
case p_e.event_type
when :start_element
tags.push p_e[0]
results << "<#{tags.last}#{attrs_to_s(p_e[1])}>"
when :end_element
results << "</#{tags.pop}>"
when :text
results << p_e[0][0..new_len]
new_len -= p_e[0].length
else
results << "<!-- #{p_e.inspect} -->"
end
end
if at_end
results << "..."
end
tags.reverse.each do |tag|
results << "</#{tag}>"
end
results
end
private
def attrs_to_s(attrs)
if attrs.empty?
''
else
' ' + attrs.to_a.map { |attr| %{#{attr[0]}="#{attr[1]}"} }.join(' ')
end
end
end
あなたがHTML要素の中央で分割したくない場合は、より複雑なパーサを記述する必要があります。それは、<>ブロックの途中で、そのの間に2つのタグ場合であれば覚えておく必要があります。
あなたがすることをしなかった場合でも、あなたはまだ問題があるでしょう。いくつかは、パーサーcouldntのが見つからないため、終了タグの、どこにでもそれを分割するので、html要素に記事全体を置けば。
それがすべてで可能である場合は、私は記事の中に任意のタグを置くか、何も(なし<div>
など)が含まれているいけないタグにそれを維持しないようにしようとするだろう。あなただけが非常に簡単ですタグの途中であるかどうかを確認する必要がありますそのようにます:
def shorten (string, count = 30)
if string.length >= count
shortened = string[0, count]
splitted = shortened.split(/\s/)
words = splitted.length
if(splitted[words-1].include? "<")
splitted[0,words-2].join(" ") + ' ...'
else
splitted[0, words-1].join(" ") + ' ...'
else
string
end
end
この消毒にHTMLで抽出した最初の刑に服している。と仮定して記モデルに、体属性が含まれるHTML:
# lib/core_ext/string.rb
class String
def first_sentence
self[/(\A[^.|!|?]+)/, 1]
end
end
# app/models/article.rb
def teaser
HTML::FullSanitizer.new.sanitize(body).first_sentence
end
このように変換す"<b>こと</b> が <em>重要</em> 。この条に"と"これは重要な条".
私は
この使用して、以下のソリューションを解決しました宝石をインストールする 'サニタイズ'
gem install sanitize
、次のコードを使用し、ここではのボディのHTMLタグを含むテキストです。
<%= content_tag :div, Sanitize.clean(truncate(body, length: 200, separator: ' ', omission: "... #{ link_to '(continue)', '#' }"), Sanitize::Config::BASIC).html_safe %>
は有効なHTMLで抜粋を与えます。 私はそれが誰かに助けを願っています。
あなたのためにこれの世話をする HTMLTruncator の名前の宝石が用意されました。私はポストの抜粋などを表示するためにそれを使用しました、そして、それは非常に堅牢です。