ruby on rails - official - Truncate Markdown?
inspinia v5 (7)
Tengo un sitio de Rails, donde el contenido está escrito en rebajas. Deseo mostrar un fragmento de cada uno, con un enlace "Leer más ...".
¿Cómo hago esto? El truncado simple del texto sin formato no funcionará, por ejemplo ...
>> "This is an [example](http://example.com)"[0..25]
=> "This is an [example](http:"
Idealmente, quiero permitir que el autor (opcionalmente) inserte un marcador para especificar qué usar como "fragmento", si no, tomaría 250 palabras y anexaría "...", por ejemplo ...
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
El marcador podría considerarse como un marcador EOF (que puede ignorarse al mostrar el documento completo)
Estoy usando maruku para el procesamiento de reducción (RedCloth es muy parcial hacia Textile, BlueCloth es extremadamente defectuoso, y yo quería un analizador nativo de Ruby que descartaba el peg-markdown y RDiscount)
Alternativamente (dado que Markdown se traduce a HTML de todos modos) truncar el HTML correctamente sería una opción, aunque sería preferible no markdown()
todo el documento, solo para obtener las primeras líneas.
Entonces, las opciones que puedo pensar son (en orden de preferencia) ...
- Agregue una opción "truncar" al analizador de maruku, que solo analizará las primeras x palabras, o hasta el marcador "fragmento".
- Escribir / encontrar un analizador sintáctico de trásicos Truncate''r
- Escribir / encontrar una función de truncado HTML inteligente
- Escribir / encontrar una función de truncado HTML inteligente
Lo siguiente de http://mikeburnscoder.wordpress.com/2006/11/11/truncating-html-in-ruby/ , con algunas modificaciones, truncará correctamente HTML y permitirá agregar fácilmente una cadena antes de las etiquetas de cierre.
>> puts "<p><b><a href=/"hi/">Something</a></p>".truncate_html(5, at_end = "...")
=> <p><b><a href="hi">Someth...</a></b></p>
El código modificado:
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
Aquí hay una solución que funciona para mí con Textile.
- Convertirlo a HTML
- Truncarlo.
Elimine las etiquetas HTML que se cortaron por la mitad con
html_string.gsub(/<[^>]*$/, "")
Luego, usa Hpricot para limpiarlo y cerrar las etiquetas sin cerrar
html_string = Hpricot( html_string ).to_s
Hago esto en una ayuda, y con el almacenamiento en caché no hay problema de rendimiento.
En lugar de intentar truncar el texto, ¿por qué no tener 2 cuadros de entrada, uno para el "anuncio de apertura" y otro para las "agallas" principales? De esa forma, sus autores sabrán exactamente qué se muestra cuando no tengan que depender de algún tipo de marcador EOF funky.
Puede usar una expresión regular para encontrar una línea que consta de nada más que "^" caracteres:
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
Tendré que estar de acuerdo con el enfoque de "dos entradas", y el escritor de contenido no tendrá que preocuparse, ya que puede modificar la lógica de fondo para mezclar las dos entradas en una al mostrar todo el contenido.
full_content = input1 + input2 // perhaps with some complementary html, for a better formatting
No estoy seguro de si se aplica a este caso, pero agregando la solución a continuación para completar. Puede usar el método strip_tags si está truncando los contenidos renderizados de Markdown:
truncate(strip_tags(markdown(article.contents)), length: 50)
Procedencia de: http://devblog.boonecommunitynetwork.com/rails-and-markdown/
Una opción más simple que simplemente funciona:
truncate(markdown(item.description), length: 100, escape: false)