2010-12-01 10 views
37

Ich habe eine Zeichenfolge von HTML in Rails. Ich möchte die Zeichenfolge nach einer bestimmten Anzahl von Zeichen, die das HTML-Markup nicht enthalten, abschneiden. Wenn die Aufteilung zufällig in die Mitte eines öffnenden und schließenden Tags fällt, möchte ich die offenen Tags schließen. Beispielsweise;Gibt es eine sichere HTML-Methode in Rails?

html = "123<a href='#'>456</a>7890" 
truncate_markup(html, :length => 5) --> "123<a href='#'>45</a>" 

Antwort

32

Es gibt zwei völlig unterschiedliche Lösungen, die sowohl mit dem gleichen Namen: truncate_html

  1. https://github.com/ianwhite/truncate_html: Dies ist ein Juwel und verwendet einen HTML-Parser (nokogiri)
  2. https://github.com/hgmnz/truncate_html: Dies ist eine Datei, die Sie in setzen Sie Ihre Helferverzeichnis. Es verwendet reguläre Ausdrücke und hat keine Abhängigkeiten.
+2

Die Arbeits Link für das zweite ist: https://github.com/hgmnz/truncate_html – Cristian

+3

Gibt es irgendwelche neueren Edelsteine, die noch gepflegt werden und Schienen 4 stützen? – Alaric

+0

@RyanClark Ich würde mit [hgmnz/truncate_html] (https://github.com/hgmnz/truncate_html) gehen. Es basiert auf regulären Ausdrücken und sollte mit jeder Rails-Version funktionieren, solange die Ruby-Versionen kompatibel sind. – Daniel

6

Sie könnten dafür das truncate_html Plugin verwenden. Es verwendet nokogiri und htmlentities Edelsteine ​​und tut genau, was der Name des Plugins vorschlägt.

2

Wir hatten dieses Bedürfnis in zendone.com. Das Problem bestand darin, dass die vorhandenen Lösungen sehr langsam waren, wenn lange HTML-Dokumente (MBs) in kürzere (KBs) gekürzt wurden. Ich schrieb eine Bibliothek mit dem Namen truncato in Nokogiri. Die Bibliothek enthält some benchmarks, die ihre Leistung mit anderen Bibliotheken vergleicht.

13

Sie sollten dieses Problem mit CSS anstatt Ruby lösen. Sie tun etwas, das sich auf das DOM-Layout auswirkt, und es gibt keine Möglichkeit, programmatisch eine Lösung zu entwickeln, die konsistent funktioniert.

Angenommen, Ihr HTML-Parser-Juwel funktioniert, und Sie finden einen kleinsten gemeinsamen Nenner, der die meiste Zeit funktioniert.

Was passiert, wenn Sie die Schriftgröße oder das Layout Ihrer Website ändern? Sie müssen die Zeichenanzahl erneut neu berechnen.

Oder lassen Sie uns sagen, Ihr HTML hat so etwas in diesem: <p><br /></p><br /> Das ist null Zeichen, aber es würde dazu führen, dass ein großer Brocken leerer Text eingefügt wird. Es könnte sogar ein <blockquote> oder <code> Tag mit zu viel Polsterung oder Rand sein, um Ihr Layout völlig aus dem Gleichgewicht zu bringen.

Oder das Gegenteil, sagen wir, Sie haben diese 3&nbsp;&#8773;&nbsp;&#955; (3   ≅   λ) Das 26 Zeichen lang ist, aber für die Anzeige ist es nur 5.

Der Punkt, dass Zeichenzahl ist sagt nichts über wie etwas im Browser rendern wird. Ganz zu schweigen von der Tatsache, dass HTML-Parser große Teile von Code sind, die manchmal unzuverlässig sein können.

Hier ist ein paar gute CSS, um damit umzugehen. Nach der Pseudoklasse wird eine weiße Einblendung zur letzten Zeile des Inhalts hinzugefügt. Sehr schöner Übergang.

body { font-size: 16px;} 
p {font-size: 1em; line-height: 1.2em} 
/* Maximum height math is: 
    line-height * #oflines - 0.4 
    the 0.4 offset is to make the cutoff look nicer */ 
.lines-3{height: 3.2em;} 
.lines-6{height: 6.8em;} 
.truncate {overflow: hidden; position:relative} 
.truncate:after{ 
    content:""; 
    height: 1em; 
    display: block; 
    width: 100%; 
    position:absolute; 
    background-color:white; 
    opacity: 0.8; 
    bottom: -0.3em 
} 

Sie können so viele .lines-x Klassen hinzufügen, wie Sie für richtig halten. Ich habe em verwendet, aber px ist genauso gut.

Dann bewerben Sie diese zu Ihrem Element: <div class="truncate lines-3">....lots of stuff.. </div>

und die Geige: http://jsfiddle.net/ke87h/

+0

So habe ich das Problem auf der Seite angesprochen, für die ich arbeite. Wenn JavaScript verfügbar ist, trenne ich die Zeichen vom Ende ab, bis sie mit Ellipsen am Ende übereinstimmen. Das Abschneiden der Server-Seite um eine Anzahl von Zeichen kann zu zackigen Ergebnissen führen, wenn eine Zeile viele dünne oder breite Zeichen enthält. –

+0

Das ist großartig. Sie können HTML-Tags auf der Serverseite bereinigen/entfernen, wenn Sie auch bestimmte Elemente entfernen müssen. – phillyslick

+0

So viel sauberer! Gute Arbeit – Vlad

2

können Sie verwenden

truncate(html.gsub(/(<[^>]+>)/, ''), 5) 
+1

Dies würde alle HTML ausziehen, nicht wahr? – Arcolye

+0

Fügen Sie 'separator' param hinzu, um das Wort crop zu verhindern: truncate (html.gsub (/ (<[^>) +>) /, ''), length: 5, separator: '') –

+1

Kann auch Rails '' strip_tags''Helfer benutzen um dies zu tun. – alexpls

0

Die Lösung dieses Problems aus der Client-Seite:

Ansicht :

<script> 
    $(function() { 
    $('.post-preview').each(function() { 
     var tmp_height = $(this).innerHeight(); 
     if ((tmp_height > 100) && (tmp_height < 200)) { 
     $(this).addClass("preview-small"); 
     } 
     else if (tmp_height >= 200) { 
     $(this).addClass("preview-large") 
     } 
     else { 
     //do nothing 
     } 
    }); 
    }); 
</script> 

css

.preview-small { 
    height: 100px; 
    overflow: hidden; 
} 

.preview-large { 
    height: 200px; 
    overflow: hidden; 
} 
+0

Diese Frage ist für Rails, überprüfen Titel: "Gibt es eine sichere HTML-Methode in Rails truncate?" –

67

die regelmäßige truncate Funktion einwandfrei funktioniert, geben Sie einfach :escape => false als Option die HTML intakt zu halten. zB:

truncate(@html_text, :length => 230, :omission => "" , :escape => false) 

RubyOnRails.org

* Edit ich die Frage nicht sehr sorgfältig lesen (oder überhaupt TBH), so dass diese Antwort auf diese Frage nicht lösen ... Es ist die Antwort, die ich geschah zu suchen, obwohl, so hoffentlich hilft es 1 oder 2 Personen :)

+2

Google brachte mich hierher und es war, was ich suchte. Vielen Dank. – penner

+1

Danke! Genau das habe ich gesucht. –

+1

Du hast mir geholfen. Zitate wurden durch ihren Code wie “ angezeigt, aber indem Sie die Escape-Option auf false setzen, funktioniert es wie ich will. Vielen Dank. –

3

Dies wird Ihnen ohne zusätzlichen Aufwand helfen

raw your_string.truncate(200) 
+0

"..ohne den HTML-Markup ", dieser Code funktioniert mit HTML –

+2

schön, ich benutzte so ' '' sanitize ("mein Text mit html", Tags: ['h1']). truncate (150)) '' ' die erste sanitize wird das fehlende Markup abschließen, die innere Sanitize wird meine unerwünschten Tags entfernen und am Ende abgeschnitten wird wie ein html_safe abgeschnitten, danke – Alexis

Verwandte Themen