В Ruby on Rails, как сделать подсветку синтаксиса с помощью Markdown (RDiscount/BlueCloth) с CodeRay?

Я знаю, что существуют Railscast и ASCIIcast для использования Textile (RedCloth) с CodeRay, и это делается помощником:

module ApplicationHelper    
  def coderay(text)  
    text.gsub(/\<code( lang="(.+?)")?\>(.+?)\<\/code\>/m) do  
      CodeRay.scan($3, $2).div(:css => :class)  
    end  
  end  
end  

а также

<%= textilize(coderay(@article.content)) %>

поэтому предполагается, что @article.content уже имеет <code> и </code> (чтобы CodeRay мог работать)...

но что, если это Markdown, то «отступ в 4 пробела», как в StackOverflow, сначала нужно будет преобразовать в формат <code> и </code>.

Итак, в этом случае, похоже, мы можем использовать

<%= coderay(Markdown.new(@article.content).to_html).html_safe  #html_safe for Rails 3 %>  

поэтому он сначала получает формат <code> и </code> для использования CodeRay, а затем просто заменяет /<code>.*?</code>/m результатами CodeRay.

Это правильный способ сделать это? Но если у нас на самом деле есть <code> и </code> в коде с отступом в 4 пробела, то это на самом деле задушит эту обработку, потому что теперь есть вложенные <code>, поэтому первое <code> будет сопоставлено, а второе <code> будет пропущено как просто контент для CodeRay. , а затем сопоставьте первый </code> и оставьте второй </code> необработанным. Как это можно сделать - может быть, у CodeRay есть какие-то опции Markdown?


person nonopolarity    schedule 13.03.2011    source источник


Ответы (1)


В этом помогает небольшой драгоценный камень под названием lesstile. Однако мне не хотелось использовать драгоценный камень, поэтому я извлек основную функциональность, которая сводится к следующему:

options = {
    :code_formatter => lambda {|code, lang|
        CodeRay.scan(CGI::unescapeHTML(code), lang).html.div
    }
}

text += "\n" unless (text.rindex("\n") == text.size - 1)
text.gsub!(/\r\n/, "\n")
output = ""

while match = text.match(/---\s*?([\w\s\._+()-]*?)\s*?\n(.*?)---\n/m)
    captures = match.captures
    code = captures[1]
    lang = captures[0].blank? ? nil : captures[0].downcase.strip.intern

    output += 
    options[:text_formatter][match.pre_match] +
    options[:code_formatter][code, lang]

    text = match.post_match
end

output += options[:text_formatter][text.chomp]

Вы можете обозначить код в вашем текстиле/уценке, используя «---», чтобы заключить его и при желании добавить язык, например «---ruby», например:

---ruby
def hi
  print "hi"
end
---

Отлично работает с Markdown.

person fx_    schedule 14.03.2011