Schienen: einen Teaser / Auszug für einen Artikel erhalten
-
22-08-2019 - |
Frage
Ich habe eine Seite, die News-Artikel auflistet. So schneiden nach unten auf die Länge der Seite, ich will nur einen Teaser angezeigt werden (die ersten 200 Wörter / 600 Buchstaben des Artikels) und zeigt dann eine „mehr ...“ -Link, dass, wenn sie angeklickt, wird der Rest des erweitern Artikel in einer jQuery / Javascript Art und Weise. Nun habe ich alles, was herausgefunden und auch die folgende Hilfsmethode auf etwas Paste Seite gefunden, die sicherstellen werden, dass der News-Artikel (string) nicht direkt in der Mitte eines Wortes zerhackt:
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
Das Problem, das ich habe, ist, dass die News-Artikel Stellen, die ich von der DB erhalten werden formatiert HTML. Also, wenn ich unglücklich bin, wird der oben Helfer dort meinen Artikel String direkt in der Mitte eines HTML-Tags und legen Sie die „mehr ...“ string zerhacken (zB zwischen „“), denen korrupte meine HTML-Datei auf der Seite .
Gibt es eine Möglichkeit, um dieses oder ist es ein Plugin gibt, die ich Auszüge / Teasern aus einer HTML-Zeichenfolge zu erzeugen, verwenden kann?
Lösung 3
Vielen Dank für Ihre Antworten! Doch in der Zwischenzeit stieß ich auf dem jQuery HTML Truncator Plugin , die meine Zwecke perfekt passt und verschiebt die Verkürzung auf der Client-Seite. Es ist nicht einfacher: -)
Andere Tipps
Sie können eine Kombination von verwenden Sanitize und kürzen .
truncate("And they found that many people were sleeping better.",
:omission => "... (continued)", :length => 15)
# => And they found... (continued)
Ich mache eine ähnliche Aufgabe, wo ich Blog-Posts haben und ich möchte nur einen kurzen Ausschnitt zeigen. Also meiner Meinung nach muss ich einfach:
sanitize(truncate(blog_post.body, length: 150))
Das entfernt die HTML-Tags aus, gibt mir die ersten 150 Zeichen und in der Ansicht behandelt, so dass es MVC freundlich ist.
Viel Glück!
Meine Antwort hier sollte Arbeit tun. Die ursprüngliche Frage (err, von mir gefragt) etwa Abschlag Kürzen, aber ich beenden den Abschlag Umwandlung bis HTML dann, dass Kürzen, so sollte es funktionieren.
Natürlich, wenn Ihre Website viel Verkehr wird, sollten Sie den Auszug Cache (vielleicht, wenn die Post erstellt / aktualisiert, können Sie den Ausschnitt in der Datenbank speichern können?), Würde dies auch bedeuten, könnten Sie dem Benutzer erlauben, zu ändern oder geben Sie ihre eigenen Auszug
Verbrauch:
>> puts "<p><b><a href=\"hi\">Something</a></p>".truncate_html(5, at_end = "...")
=> <p><b><a href="hi">Someth...</a></b></p>
.. und der Code (von der anderen Antwort kopiert):
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
Möchten Sie einen komplexeren Parser schreiben, wenn Sie nicht wollen, in der Mitte von HTML-Elementen spalten. es hätte sich daran zu erinnern, wenn sie in der Mitte eines <> Block und wenn ihr zwischen zwei Markierungen ist.
auch wenn man das täte, würden Sie immer noch Probleme haben. wenn einige setzen den ganzen Artikel in ein HTML-Element, da der Parser könne nicht es überall geteilt, wegen des fehlenden schließenden Tages.
, wenn es möglich ist, überhaupt würde ich versuche keine Tags in den Artikeln zu setzen oder es um Schlagworte zu halten, die (nicht <div>
usw.) enthalten nicht nichts. auf diese Weise würden Sie müssen nur überprüfen, ob Sie in der Mitte eines Tags sind, die ziemlich einfach:
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
ich hätte die HTML hygienisiert und extrahiert den ersten Satz. Vorausgesetzt, dass Sie einen Artikel Modell, mit einem ‚Körper‘ Attribut, das den HTML enthält:
# 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
Dies würde konvertieren " Das ist ein wichtig Artikel! Und hier ist der Rest des Artikels." in „Dies ist ein wichtiger Beitrag“.
Ich löste dies mit folgenden Lösung
Installieren gem 'sanieren'
gem install sanitize
und verwendeten Code folgen, hier Körper wird Text HTML-Tags enthalten.
<%= content_tag :div, Sanitize.clean(truncate(body, length: 200, separator: ' ', omission: "... #{ link_to '(continue)', '#' }"), Sanitize::Config::BASIC).html_safe %>
Gibt Auszug mit gültigen html. Ich hoffe, es hilft jemand.
Es gibt jetzt ein Juwel namens HTMLTruncator , die für Sie kümmern sich um das dauert. Ich habe es Post Ausschnitte und dergleichen angezeigt werden, und es ist sehr robust.