Tronquer Markdown?
-
29-08-2019 - |
Question
J'ai un site Rails où le contenu est écrit en Markdown. Je souhaite afficher un extrait de chacun, avec un lien « En savoir plus .. ».
Comment puis-je cela? Simple tronquant 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 (le cas échéant) insérer un marqueur pour indiquer ce à utiliser comme « extrait », sinon il faudrait 250 mots, et d'ajouter « ... » - 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
Le marqueur peut être considéré comme un marqueur EOF (qui peut être ignoré lors de l'affichage du document)
J'utilise Maruku pour le traitement de Markdown (RedCloth est très biaisé en faveur du textile, BlueCloth est extrêmement bogué, et je voulais un analyseur-Ruby natif qui exclut peg-démarquage et RDiscount)
Vous pouvez également (depuis le Markdown est traduit en HTML de toute façon) tronquer correctement le HTML serait une option -. Bien qu'il serait préférable de ne pas markdown()
le document entier, juste pour obtenir les premières lignes
Alors, les options que je peux penser sont (par ordre de préférence) ..
- Ajouter une option « tronquer » à l'analyseur de Maruku, qui n'analyser les premiers mots de x, ou jusqu'à ce que le marqueur « extrait ».
- Ecrire / trouver un analyseur agnostique Markdown truncate'r
- Ecrire / trouver une fonction tronquer HTML intelligente
La solution
- Ecrire / trouver une fonction tronquer HTML intelligente
Ce qui suit de http: //mikeburnscoder.wordpress. com / 2006/11/11 / html tronquer-en-ruby / , avec quelques modifications seront correctement tronquer HTML, et permettent facilement annexant une chaîne avant que 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
Autres conseils
Voici une solution qui fonctionne pour moi avec textile.
- Convertir en HTML
- tronquer.
-
Supprimer toutes les balises HTML qui a été coupé en deux avec
html_string.gsub(/<[^>]*$/, "")
-
Ensuite, utilise hpricot pour le nettoyer et à proximité des balises non fermées
html_string = Hpricot( html_string ).to_s
Je le fais dans une aide, 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 composée de rien « ^ » 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 boîtes d'entrée, un pour l ' « ouverture texte de présentation » et un pour les principaux « tripes ». De cette façon, vos auteurs savent exactement ce qui est spectacle quand sans avoir à compter sur une sorte de marqueur funkly EOF.
Je suis d'accord avec l'approche « deux entrées », et l'auteur de contenu, il conviendrait de ne pas inquiéter, puisque vous pouvez modifier la logique de fond pour mélanger les deux entrées dans un en montrant le contenu complet.
full_content = input1 + input2 // perhaps with some complementary html, for a better formatting
Je ne sais pas si elle applique à ce cas, mais en ajoutant la solution ci-dessous pour un souci d'exhaustivité. Vous pouvez utiliser strip_tags méthode si vous tronquer le contenu rendu Markdown-:
truncate(strip_tags(markdown(article.contents)), length: 50)
Provenant: http://devblog.boonecommunitynetwork.com/rails-and-markdown/
Une option plus simple qui fonctionne:
truncate(markdown(item.description), length: 100, escape: false)