该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-08-22
但是在开发JavaEye3.0的时候,却发现auto_link有bug,一旦帖子当中的URL后面紧跟中文的话,auto_link就会把URL后面所有的中文当做URL的一部分进行格式化,直到碰到空格为止,例如: 引用 http://www.iteye.com网站很不错
就会被格式化为: 引用 <a href="http://www.iteye.com网站很不错">http://www.iteye.com网站很不错</a>
看来得到rails的源代码里找答案了。 打开netbeans,敲快捷键Ctrl+O,在弹出窗口输入:texthelper,回车,netbeans已经帮我打开了text_helper.rb源代码,通过Navigator窗口,很方便的定位到auto_link方法,仔细看一下,原来主要是这个正则表达式在起作用: AUTO_LINK_RE = %r{ ( # leading text <\w+.*?>| # leading HTML tag, or [^=!:'"/]| # leading punctuation, or ^ # beginning of line ) ( (?:https?://)| # protocol spec, or (?:www\.) # www.* ) ( [-\w]+ # subdomain or domain (?:\.[-\w]+)* # remaining subdomains or domain (?::\d+)? # port (?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path (?:\?[\w\+%&=.;-]+)? # query string (?:\#[\w\-]*)? # trailing anchor ) ([[:punct:]]|\s|<|$) # trailing text }x unless const_defined?(:AUTO_LINK_RE) 但这个正则表达式上看下看,左看右看都没有啥问题阿。于是把这个正则表达式拷贝出来,放在一个ruby文件里面test.rb,一点点单独调试,但怎么调试都正常,即使把上面那个URL放进去,也可以正常截断中文。 难道是因为rails做了手脚?为了验证这一点,在test.rb前面加上如下内容: ENV["RAILS_ENV"] = "development" require File.expand_path(File.dirname(__FILE__) + "/../config/environment") 再运行test.rb,果然!中文又被包括进去了,看来就是rails做了手脚。 再回过头仔细看这个正则表达式,只有[\w]和字符串处理有关系,为了验证这一点,我们做如下试验: 创建一个char.rb文件,内容如下: def name return "范凯" end 请注意!该文件保存格式请必须使用UTF-8!! 然后打开irb,进行如下交互: 引用 irb(main):001:0> load "char.rb"
=> true irb(main):002:0> name => "\350\214\203\345\207\257" irb(main):003:0> name.match /[A-Za-z0-9_]+/ => nil irb(main):004:0> name.match /\w+/ => nil 请注意标记为红色的行,在ruby的内存中,中文字符串的编码使用的是unicode格式,中文字符串不能够匹配到/[\w]+/上面去,而/[A-Za-z0-9_]+/与/\w+/是同义词。 好了,现在启动rails的环境: 引用 $ ./script/console
Loading development environment. >> load "char.rb" => [] >> name => "鑼冨嚡" >> name.match /[A-Za-z0-9_]+/ => nil >> name.match /\w+/ => #<MatchData:0x474693c> 哈哈,水落石出了!!由于rails的ActiveSupport的引入,在ruby的内存当中,字符串被转换为UTF-8格式了(显示乱码是因为我的Windows操作系统是GBK编码),而中文字符串居然可以匹配/\w+/了! 我们可以看到,由于rails在内存当中以UTF-8格式操作中文字符串,而不是ruby默认的unicode格式,这就导致了正则表达式的歧义:/[A-Za-z0-9_]+/不能匹配中文,但是/\w+/可以匹配中文,但实际上在ruby当中,这两个正则表达式本应该是同义词。 明白了问题的根源,就清楚了如何去解决auto_link的bug,修改正则表达式和相关方法,将\w替换为A-Za-z0-9,并将其放入你的rails项目的application_helper.rb当中,这样就可以在项目启动以后覆盖rails系统类库的定义: AUTO_LINK_RE = %r{ ( # leading text <\w+.*?>| # leading HTML tag, or [^=!:'"/]| # leading punctuation, or ^ # beginning of line ) ( (?:https?://)| # protocol spec, or (?:www\.) # www.* ) ( [-0-9A-Za-z_]+ # subdomain or domain (?:\.[-0-9A-Za-z_]+)* # remaining subdomains or domain (?::\d+)? # port (?:/(?:(?:[~0-9A-Za-z_\+%-]|(?:[,.;:][^\s$]))+)?)* # path (?:\?[0-9A-Za-z_\+%&=.;-]+)? # query string (?:\#[0-9A-Za-z_\-]*)? # trailing anchor ) }x unless const_defined?(:AUTO_LINK_RE) def auto_link_urls(text, href_options = {}) extra_options = tag_options(href_options.stringify_keys) || "" text.gsub(AUTO_LINK_RE) do all, a, b, c = $&, $1, $2, $3 if a =~ /<a\s/i # don't replace URL's that are already linked all else text = b + c text = yield(text) if block_given? %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>) end end end OK,搞定了,这下auto_link可以正确截断中文了。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-08-22
我也遇到过类似问题,看了代码没未果。还是robbin找到了问题的答案
|
|
返回顶楼 | |
发表时间:2007-08-22
虽然用不到这条技巧,这个挖的过程还是很精彩的。
|
|
返回顶楼 | |
发表时间:2007-08-24
robbin
你的这篇文章,csdn怎么都没属你的名字呀? http://news.csdn.net/n/20070706/106176.html |
|
返回顶楼 | |
发表时间:2007-08-27
有的URL里带中文参数的会怎么样
比如:http://www.iteye.com?keyword=网站很不错 我以前就这样传过参数 |
|
返回顶楼 | |
发表时间:2007-08-30
老大是否用restful来架构javaeye3.0?强烈关注中
|
|
返回顶楼 | |
发表时间:2007-08-30
若是用restful来架构javaeye3.0,很期待此版本早点出来,url的设计好借鉴借鉴。。
|
|
返回顶楼 | |
发表时间:2007-11-09
请问一下如图的Rich Editor是怎么实现的.怎么用,在哪可以下载到.
|
|
返回顶楼 | |
发表时间:2007-11-09
FCKeditor 不支持safari
|
|
返回顶楼 | |
发表时间:2007-11-19
庄严 写道 有的URL里带中文参数的会怎么样
比如:http://www.iteye.com?keyword=网站很不错 我以前就这样传过参数 应该是转成编码形式吧? http://www.iteye.com/?keyword=%CD%F8%D5%BE%BA%DC%B2%BB%B4%ED |
|
返回顶楼 | |