Truncate Markdown?
j'ai un site de Rails, où le contenu est écrit en markdown. Je souhaite afficher un extrait de chacune, avec un "Lire la suite.." lien.
Comment puis-je aller à ce sujet? Simple tronquer le texte brut ne fonctionnera pas, par exemple..
>> "This is an [example](http://example.com)"[0..25]
=> "This is an [example](http:"
Idéalement, je veux permettre à l'auteur (éventuellement) insérer un marqueur de préciser ce qu'il faut utiliser le "snippet", si non il faudrait 250 mots, et append "..."par exemple)..
This article is an example of something or other.
This segment will be used as the snippet on the index page.
^^^^^^^^^^^^^^^
This text will be visible once clicking the "Read more.." link
on pourrait penser au marqueur comme un marqueur EOF (qui peut être ignoré lors de l'affichage du document complet)
j'utilise maruku pour les Démarques de traitement (RedCloth est très biaisé en faveur de Textile, BlueCloth est extrêmement buggé, et je voulais un natif Ruby analyseur qui exclu peg-markdown et RDiscount)
alternativement (puisque le Markdown est traduit en HTML de toute façon) tronquer le HTML correctement serait une option-bien qu'il serait préférable de ne pas markdown()
l'ensemble de la le document, juste pour obtenir les premières lignes.
donc, les options auxquelles je peux penser sont (par ordre de préférence)..
- ajouter une option "tronquer" à l'analyseur maruku, qui n'analysera que les premiers mots x, ou jusqu'au marqueur "extrait".
- Ecrire/trouver un analyseur-agnostique Markdown tronquer r
- Ecrire/trouver un intelligent HTML tronquer la fonction
7 réponses
- Ecrire/trouver un intelligent HTML tronquer la fonction
The following from http://mikeburnscoder.wordpress.com/2006/11/11/truncating-html-in-ruby/, avec quelques modifications va correctement tronquer HTML, et permettre facilement l'ajout d'une chaîne de caractères avant les balises de fermeture.
>> puts "<p><b><a href=\"hi\">Something</a></p>".truncate_html(5, at_end = "...")
=> <p><b><a href="hi">Someth...</a></b></p>
Le code modifié:
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
Voici une solution qui fonctionne pour moi avec le Textile.
- Convertir en HTML
- la tronquer.
supprimez toutes les balises HTML qui ont été coupées en deux avec
html_string.gsub(/<[^>]*$/, "")
puis, utilise Hpricot pour nettoyer et fermer les étiquettes non fermées
html_string = Hpricot( html_string ).to_s
je le fais dans un helper, et avec la mise en cache il n'y a pas de problème de performance.
Vous pouvez utiliser une expression régulière pour trouver une ligne constituée de rien, mais "^" caractères:
markdown_string = <<-eos
This article is an example of something or other.
This segment will be used as the snippet on the index page.
^^^^^^^^^^^^^^^
This text will be visible once clicking the "Read more.." link
eos
preview = markdown_string[0...(markdown_string =~ /^\^+$/)]
puts preview
Plutôt que d'essayer de tronquer le texte, pourquoi ne pas avoir 2 zones de saisie, l'un pour le "argumentaire d'ouverture" et l'un des principaux "tripes". De cette façon, vos auteurs sauront exactement ce qui est affiché sans avoir à se fier à une sorte de marqueur funkly EOF.
je devrai être d'accord avec l'approche" deux entrées", et l'auteur de contenu n'aura pas besoin de s'inquiéter, puisque vous pouvez modifier la logique de fond pour mélanger les deux entrées en une lors de la présentation du contenu complet.
full_content = input1 + input2 // perhaps with some complementary html, for a better formatting
Je ne suis pas sûr que cela s'applique à ce cas, mais en ajoutant la solution ci-dessous par souci d'exhaustivité. Vous pouvez utiliser la méthode strip_tags si vous tronquez les contenus rendus Markdown:
truncate(strip_tags(markdown(article.contents)), length: 50)
provenant de: http://devblog.boonecommunitynetwork.com/rails-and-markdown/
Une option plus simple qui fonctionne bien:
truncate(markdown(item.description), length: 100, escape: false)