分享 Rails 快速实现 markdown 和代码高亮

hisea · 2011年12月14日 · 最后由 yuanchang2018 回复于 2019年07月24日 · 14657 次阅读

还是先做个广告: http://hisea.me

Markdown 是时下很流行的一种标记语言。

可以很简便的生成 html 代码,github 的 README 就是用这种形式显示再代码目录的下面。

Ruby/Rails 借助繁多的 Gem,可以迅速的就做好 markdown 的支持,顺道包含对代码高亮的支持。

Gem 太多,实现方法也太多。

下面就介绍一种比较迅速开发的办法。用了 redcarpet 和 CodeRay 两个 Gem。这也是 hisea.me 用的办法。

首先,安装 GEM

gem 'redcarpet'
gem 'coderay'

接下来,打开 app/helper/application_helper.rb, 添加下列代码。

def markdown(text)
  options = {   
      :autolink => true, 
      :space_after_headers => true,
      :fenced_code_blocks => true,
      :no_intra_emphasis => true,
      :hard_wrap => true,
      :strikethrough =>true
    }
  markdown = Redcarpet::Markdown.new(HTMLwithCodeRay,options)
  markdown.render(h(text)).html_safe
end

class HTMLwithCodeRay < Redcarpet::Render::HTML
  def block_code(code, language)
    CodeRay.scan(code, language).div(:tab_width=>2)
  end
end

解释下上面的代码。 第一步是添加了一个 markdown 方法,配置了一些显示方面的细节,比如 autolink, hard_wrap 之类的。

markdown = Redcarpet::Markdown.new(HTMLwithCodeRay,options)
markdown.render(text).html_safe

这一步用了一个我们自己定义的 HTMLwithCodeRay 的 Render 类来创建一个新的 markdown 对象, 然后用这个自定义类来解析传进来的字符串。

class HTMLwithCodeRay < Redcarpet::Render::HTML
  def block_code(code, language)
    CodeRay.scan(code, language).div(:tab_width=>2)
  end
end

最后就是这个自定义类,里面就重写了一个方法。当我们遇到 block_code 的时候,转交给 CodeRay 来生成高亮。

然后就没了。。。 迅速吧。

html_safe 我感觉是不是误用了,如果 Text 内容是

<script type="text/javascript">alert();</script>

呢?

#1 楼 @Rei 恩,根据需要自己调整。这里就是很简单的把 markdown 生成的 html 显示出来,而且在后台。如需要可以自己先过滤一遍。

#1 楼 @Rei 修改成安全的了。

以前都是用 haml 调 coderay,这次试试用 redcarpet

为什么我生成的效果不太一样呢?

从第二行开始,出现了很多空格。

<script type="text/javascript">
  $(function() {
    alert('hello');
  });
</script>
<strong>hi</strong>

我的问题解决了,应该是 CodeRay 和 Redcarpet 配合的问题,替换到字符串中的"\n"就好了。

Ruby Taiwan 是用 Pygments.rb 實現的: https://github.com/tmm1/pygments.rb

按照教程做的,在模版里调用时传递变量时, <%= markdown(@post.content) %> 会有以下错误 uninitialized constant ApplicationHelper::HTMLwithCodeRay::CodeRay 直接传递字符串可以正常解析。 求解? 谢谢

#9 楼 @lidashuang 你的 application_helper.rb 里面是什么

#10 楼 @hisea

module ApplicationHelper                                                        

    def markdown(text)                                                               
      options = {                                                                    
        :autolink => true,                                                           
        :space_after_headers => true,                                                
        :fenced_code_blocks => true,                                                 
        :no_intra_emphasis => true,                                                  
        :hard_wrap => true,                                                          
        :strikethrough =>true                                                        
      }                                                                              
      markdown = Redcarpet::Markdown.new(HTMLwithCodeRay,options)                    
      markdown.render(h(text)).html_safe                                             
    end                                                                              

    class HTMLwithCodeRay < Redcarpet::Render::HTML                                  
      def block_code(code, language)                                                 
        CodeRay.scan(code, language).div(:tab_width=>2)                              
      end                                                                            
    end                                                                              

  end        

#11 楼 @lidashuang 应该没问题的,你重启服务器了么。另外看上去好像找不到 CodeRay,gem 装了么,开 rails c,打 CodeRay 看看啥反应。

#12 楼 @hisea 应该是 coderay 的问题,我与 coderay 相关的代码去了,就可以。 gem 已经装,在 irb 里也能正常加载 coderay 的类库。我再找找问题 非常感谢

#9 楼 @lidashuang 同样的问题

gem 'redcarpt', '~> 2.0' 

我版本换成这个就 ok 了。

弱弱地问一句: h(text) 有必要吗?直接 text,是不是就有颜色了?

#15 楼 @xiaolai 嗯,h 不是必须的,后面有 html_safe 了,主要是吧文字中不安全因素转化成安全的, 这种的。

http://apidock.com/rails/ERB/Util/h/class

very good!

tanoku/redcarpet on Github 在这个项目不存在了。 现在使用 https://github.com/emiddleton/redcarpet

请问如何高亮呢? 我是这么输入的。 html def person sdf end

ruby def person sdf end

这两种情况都没有亮!

请注意三个 1 前面的那个键我是敲了的,这里没有敲,是因为敲了就变成代码了!

生成的 html 中有

def print puts "" end

可是没有 ruby 这个 css 的 class,怎么高亮嗯?请问这个 class 那里找,还是说我那里搞错了,这个 css 应该是随着 coderay 一起安装的吧。

搞定了

#18 楼 @woaigithub 我还在想说怎么改名了,我明明以前 fork 过 redcarpet 还改过代码、发过 PR …结果一看连我自己的 fork 都变成 from vmg/redcarpet 了…只能猜测是他本人改 ID…

#22 楼 @hisea 客气,大家拾材火焰高

#23 楼 @chitsaou 有可能吧

#23 楼 @chitsaou 看来国外也有人喜欢改点不该该的东西

学习了,感谢 LZ

#7 楼 @daqing 我也遇到这个问题了,请问怎么替换的

匿名 #28 · 2014年05月18日

求问楼主,Rails 4.1.1 是否正常可用?有乱码。

单行代码 \"credentials\"=> { \"token\"=>\"82a663866ad1aa18c476ac26a6cf816f\", \"refresh_token\"=>\"940cc521237e5412d1a75e3919cb11f6\", \"expires_at\"=>1410355745, \"expires\"=>true },

怎么解决 摘要问题呀?? 使用 markdown 语法后,摘要不方便显示了

31楼 已删除
32楼 已删除
33楼 已删除

广告点击进去以后显示:Apache2 Ubuntu Default Page

pengalg 回复

请问你怎么解决摘要问题?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册