2010-12-01 65 views
37

我在Rails中有一个HTML字符串。我想在包含HTML标记的特定字符数之后截断字符串。另外,如果拆分恰好落在开始和结束标记的中间,我想关闭打开的标记。例如;Rails中是否存在HTML安全截断方法?

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

回答

32

有两种完全不同的解决方案都具有相同的名称:truncate_html

  1. https://github.com/ianwhite/truncate_html:这是一个宝石,并使用HTML解析器(引入nokogiri)
  2. https://github.com/hgmnz/truncate_html:这是你放在一个文件里帮手目录。它使用正则表达式并且没有依赖关系。
+2

工作链接,第二个是:https://github.com/hgmnz/truncate_html – Cristian 2012-12-15 18:06:12

+3

是否有任何新的宝石仍然保持并支持Rails 4? – Alaric 2013-12-20 16:14:58

+0

@RyanClark我会去[hgmnz/truncate_html](https://github.com/hgmnz/truncate_html)。它基于正则表达式,只要Ruby版本兼容,就可以使用任何Rails版本。 – Daniel 2014-04-29 10:15:42

6

您可以使用truncate_html插件。它使用nokogirihtmlentities宝石和确切的插件名称暗示。

2

我们在zendone.com有这个需求。问题是现有解决方案在将较长的HTML文档(MB)截短为较短的文档(KB)时速度很慢。我最终编写了一个名为truncato的基于Nokogiri的库。该库包括some benchmarks比较其性能与其他库。

13

你应该用CSS而不是Ruby来解决这个问题。你正在做一些影响DOM布局的事情,并且没有办法以编程方式设计一个能够一致工作的解决方案。假设你让你的HTML解析器gem正常工作,并且你找到一个大多数时间都能工作的最低公分母字符数。

如果更改字体大小或网站布局会发生什么情况?你将不得不重新计算字符数。

或者让我们说你的html有这样的内容:<p><br /></p><br />这是零字符,但是它会导致大量的空白文本被插入。它甚至可能是一个<blockquote><code>标签,因为过多的填充或边距会使您的布局完全失控。

或者逆,让我们说你有这个3&nbsp;&#8773;&nbsp;&#955;(3   ≅   λ)这是26个字符长,但为了显示它只有5

在于字符数点不能告诉你如何在浏览器中呈现。更不用说事实上,HTML解析器是一段时间不可靠的代码。

这是一些很好的CSS来处理这个问题。在伪类之后,会为最后一行内容添加一个白色淡入淡出。非常好的过渡。

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 
} 

您可以根据需要添加尽可能多的.lines-x类。我用过EM,但PX也一样好。

然后将此到您的元素:<div class="truncate lines-3">....lots of stuff.. </div>

和小提琴:http://jsfiddle.net/ke87h/

+0

这就是我在为我工作的网站上解决问题的方法。当JavaScript可用时,我会截断字符,直到最后符合椭圆。当一行有很多精简或宽字符时,通过多个字符执行截断服务器端会导致锯齿状结果。 – 2013-06-10 18:21:30

+0

这太好了。如果您还需要去除特定元素,则可以在服务器端清理/去除html标签。 – phillyslick 2014-04-11 15:53:53

+0

非常干净!干得好 – Vlad 2017-11-28 10:18:30

2

您可以使用

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

从客户端解决这个问题:

视图

<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; 
} 
67

常规truncate功能工作正常,只是通过:escape => false作为一个选项,以保持完整的HTML。例如:

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

RubyOnRails.org

*编辑我没有仔细阅读问题(或根本TBH),所以这个答案并没有解决这个问题......这是我的答案碰巧找了,所以希望它可以帮助1人或2人:)

3

这将帮助你没有任何额外的努力

raw your_string.truncate(200)