I have a string of HTML in Rails. I'd like to truncate the string after a certain number of characters not including the HTML markup. Also, if the split happens to fall in the middle of an opening and closing tag, I'd like to close the open tag/s. Fo开发者_JAVA百科r example;
html = "123<a href='#'>456</a>7890"
truncate_markup(html, :length => 5) --> "123<a href='#'>45</a>"
the regular truncate
function works fine, just pass :escape => false
as an option to keep the HTML intact. eg:
truncate(@html_text, :length => 230, :omission => "" , :escape => false)
RubyOnRails.org
*Edit I didn't read the question very carefully (or at all TBH), so this answer does not solve this question... It IS the answer I happened to be looking for though, so hopefully it helps 1 or 2 people :)
There are two completely different solutions both with the same name: truncate_html
- https://github.com/ianwhite/truncate_html : This is a gem and uses an html parser (nokogiri)
- https://github.com/hgmnz/truncate_html : This is a file you put in your helpers directory. It uses regular expressions and has no dependencies.
You should solve this problem with CSS rather than Ruby. You are doing something that affects the DOM layout, and there is no way to programmatically devise a solution that will work consistently.
Let's say you get your HTML parser gem working, and you find a lowest common denominator character count that will work most of the time.
What happens if you change font sizes, or your site layout? You'll have to recalculate the character count again.
Or let's say your html has something like this in it: <p><br /></p><br />
That is zero characters, however it would cause a big chunk of blank text to be inserted. It could even be a <blockquote>
or <code>
tag with too much padding or margin to throw your layout totally out of whack.
Or the inverse, let's say you have this 3 ≅ λ
(3 ≅ λ) That is 26 characters long, but for display purposes it is only 5.
The point being that character count tells you nothing about how something will render in the browser. Not to mention the fact HTML parsers are hefty pieces of code that can at times be unreliable.
Here is some good CSS to deal with this. The :after pseudo class will add a white fade to the last line of content. Very nice transition.
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
}
You can add as many .lines-x
classes as you see fit. I used em but px is just as good.
Then apply this to your element: <div class="truncate lines-3">....lots of stuff.. </div>
and the fiddle: http://jsfiddle.net/ke87h/
You could use the truncate_html plugin for this. It uses nokogiri and htmlentities gems and does exactly what the plugin name suggests.
We had this need in zendone.com. The problem was that the existing solutions were very slow when truncating long HTML documents (MBs) into shorter ones (KBs). I ended up coding a library based in Nokogiri called truncato. The library includes some benchmarks comparing its performance with other libs.
This will help you without any extra effort
raw your_string.truncate(200)
your_tagged_string.truncate(60).html_safe
You can use
truncate(html.gsub(/(<[^>]+>)/, ''), 5)
We can do that with the help of simple_format http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-simple_format
html = "123<a href='#'>456</a>7890"
simle_format(truncate_markup(html, :length => 5))
=> "123 456 7890"
You can use the truncate
method in combination with sanitize
.
truncate(sanitize(html_content), length: 100, separator: '</p>', escape: false)
This will truncate your HTML using the separator but it can produce HTML without closing tags. To fix this we can use the sanitize method again, which will clean the HTML and add the missing tags.
sanitize(truncate(sanitize(html_content), length: 100, separator: '</p>', escape: false))
Solving this problem from the client side:
view:
<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;
}
精彩评论