Add support for the Rouge syntax highlighter

By setting the `highlighter` setting to `rouge` you can now easily
highlight your code with it instead of relying on Pygments. However,
Jekyll doesn't depend on Rouge explicitly, you will need to install it
or add it to your Gemfile.

The documentation has been updated accordingly.
This commit is contained in:
Robin Dupret 2013-12-22 13:53:53 +01:00
parent 92064134d6
commit 0831d2b0f8
12 changed files with 92 additions and 21 deletions

View File

@ -1,12 +1,13 @@
## HEAD ## HEAD
### Major Enhancements ### Major Enhancements
* Rename the `pygments` option to `highlighter`
* Add gem-based plugin whitelist to safe mode (#1657) * Add gem-based plugin whitelist to safe mode (#1657)
* Replace the commander command line parser with a more robust * Replace the commander command line parser with a more robust
solution for our needs called `mercenary` (#1706) solution for our needs called `mercenary` (#1706)
* Remove support for Ruby 1.8.x (#1780) * Remove support for Ruby 1.8.x (#1780)
* Move to jekyll/jekyll from mojombo/jekyll (#1817) * Move to jekyll/jekyll from mojombo/jekyll (#1817)
* Rename the `pygments` option to `highlighter` (#1859)
* Provide support for the Rouge syntax highlighter (#1859)
### Minor Enhancements ### Minor Enhancements
* Move the EntryFilter class into the Jekyll module to avoid polluting the * Move the EntryFilter class into the Jekyll module to avoid polluting the
@ -25,7 +26,7 @@
### Development Fixes ### Development Fixes
* Add a link to the site in the README.md file (#1795) * Add a link to the site in the README.md file (#1795)
* Add in History and site changes from `v1-stable` branch (#1836) * Add in History and site changes from `v1-stable` branch (#1836)
* Fix the `highlight` tag feature * Fix the `highlight` tag feature (#1859)
### Site Enhancements ### Site Enhancements
* Document Kramdown's GFM parser option (#1791) * Document Kramdown's GFM parser option (#1791)

View File

@ -98,6 +98,14 @@ Feature: Site configuration
And I should see "Hello world!" in "_site/index.html" And I should see "Hello world!" in "_site/index.html"
And I should see "class=\"highlight\"" in "_site/index.html" And I should see "class=\"highlight\"" in "_site/index.html"
Scenario: Highlight code with rouge
Given I have an "index.html" page that contains "{% highlight ruby %} puts 'Hello world!' {% endhighlight %}"
And I have a configuration file with "highlighter" set to "rouge"
When I run jekyll
Then the _site directory should exist
And I should see "Hello world!" in "_site/index.html"
And I should see "class=\"highlight\"" in "_site/index.html"
Scenario: Set time and no future dated posts Scenario: Set time and no future dated posts
Given I have a _layouts directory Given I have a _layouts directory
And I have a page layout that contains "Page Layout: {{ site.posts.size }} on {{ site.time | date: "%Y-%m-%d" }}" And I have a page layout that contains "Page Layout: {{ site.posts.size }} on {{ site.time | date: "%Y-%m-%d" }}"

View File

@ -52,6 +52,7 @@ Gem::Specification.new do |s|
s.add_development_dependency('activesupport', '~> 3.2.13') s.add_development_dependency('activesupport', '~> 3.2.13')
s.add_development_dependency('jekyll_test_plugin') s.add_development_dependency('jekyll_test_plugin')
s.add_development_dependency('jekyll_test_plugin_malicious') s.add_development_dependency('jekyll_test_plugin_malicious')
s.add_development_dependency('rouge', '~> 1.0')
# = MANIFEST = # = MANIFEST =
s.files = %w[ s.files = %w[

View File

@ -5,7 +5,7 @@ module Jekyll
module CommonMethods module CommonMethods
def add_code_tags(code, lang) def add_code_tags(code, lang)
code = code.sub(/<pre>/, "<pre><code class=\"#{lang} language-#{lang}\" data-lang=\"#{lang}\">") code = code.sub(/<pre(.*?)>/, "<pre><code class=\"#{lang} language-#{lang}\" data-lang=\"#{lang}\">")
code = code.sub(/<\/pre>/,"</code></pre>") code = code.sub(/<\/pre>/,"</code></pre>")
end end
end end
@ -22,7 +22,7 @@ module Jekyll
end end
end end
module WithoutPygments module WithoutHighlighting
require 'cgi' require 'cgi'
include CommonMethods include CommonMethods
@ -37,6 +37,22 @@ module Jekyll
end end
end end
module WithRouge
include CommonMethods
def block_code(code, lang)
require 'rouge'
lexer = Rouge::Lexer.find_fancy(lang, code) || Rouge::Lexers::PlainText
formatter = Rouge::Formatters::HTML.new
output = "<div class=\"highlight\">"
output << add_code_tags(formatter.render(lexer.lex(code)), lang)
output << "</div>"
end
end
def initialize(config) def initialize(config)
require 'redcarpet' require 'redcarpet'
@config = config @config = config
@ -48,9 +64,13 @@ module Jekyll
Class.new(Redcarpet::Render::HTML) do Class.new(Redcarpet::Render::HTML) do
include WithPygments include WithPygments
end end
when 'rouge'
Class.new(Redcarpet::Render::HTML) do
include WithRouge
end
else else
Class.new(Redcarpet::Render::HTML) do Class.new(Redcarpet::Render::HTML) do
include WithoutPygments include WithoutHighlighting
end end
end end
rescue LoadError rescue LoadError

View File

@ -44,6 +44,8 @@ eos
case context.registers[:site].highlighter case context.registers[:site].highlighter
when 'pygments' when 'pygments'
render_pygments(context, super) render_pygments(context, super)
when 'rouge'
render_rouge(context, super)
else else
render_codehighlighter(context, super) render_codehighlighter(context, super)
end end
@ -65,6 +67,22 @@ eos
return output return output
end end
def render_rouge(context, code)
require 'rouge'
linenos = @options.keys.include?('linenos')
lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
formatter = Rouge::Formatters::HTML.new(line_numbers: linenos)
output = context["highlighter_prefix"] || ""
output << "<div class=\"highlight\">"
output << add_code_tags(formatter.render(lexer.lex(code)), @lang)
output << "</div>"
output << context["highlighter_suffix"] if context["highlighter_suffix"]
return output
end
def render_codehighlighter(context, code) def render_codehighlighter(context, code)
#The div is required because RDiscount blows ass #The div is required because RDiscount blows ass
<<-HTML <<-HTML

View File

@ -1,4 +1,4 @@
pygments: true highlight: pygments
relative_permalinks: false relative_permalinks: false
gauges_id: 503c5af6613f5d0f19000027 gauges_id: 503c5af6613f5d0f19000027
permalink: /news/:year/:month/:day/:title/ permalink: /news/:year/:month/:day/:title/

View File

@ -288,7 +288,7 @@ encoding: nil
future: true future: true
show_drafts: nil show_drafts: nil
limit_posts: 0 limit_posts: 0
pygments: true highlighter: pygments
relative_permalinks: true relative_permalinks: true
@ -362,7 +362,7 @@ Jekyll handles two special Redcarpet extensions:
# ...ruby code # ...ruby code
``` ```
With both fenced code blocks and pygments enabled, this will statically highlight the code; without pygments, it will add a `class="LANGUAGE"` attribute to the `<code>` element, which can be used as a hint by various JavaScript code highlighting libraries. With both fenced code blocks and highlighter enabled, this will statically highlight the code; without any syntax highlighter, it will add a `class="LANGUAGE"` attribute to the `<code>` element, which can be used as a hint by various JavaScript code highlighting libraries.
- `smart` --- This pseudo-extension turns on SmartyPants, which converts straight quotes to curly quotes and runs of hyphens to em (`---`) and en (`--`) dashes. - `smart` --- This pseudo-extension turns on SmartyPants, which converts straight quotes to curly quotes and runs of hyphens to em (`---`) and en (`--`) dashes.
All other extensions retain their usual names from Redcarpet, and no renderer options aside from `smart` can be specified in Jekyll. [A list of available extensions can be found in the Redcarpet README file.][redcarpet_extensions] Make sure you're looking at the README for the right version of Redcarpet: Jekyll currently uses v2.2.x, and extensions like `footnotes` and `highlight` weren't added until after version 3.0.0. The most commonly used extensions are: All other extensions retain their usual names from Redcarpet, and no renderer options aside from `smart` can be specified in Jekyll. [A list of available extensions can be found in the Redcarpet README file.][redcarpet_extensions] Make sure you're looking at the README for the right version of Redcarpet: Jekyll currently uses v2.2.x, and extensions like `footnotes` and `highlight` weren't added until after version 3.0.0. The most commonly used extensions are:

View File

@ -66,9 +66,9 @@ Check out [the extras page](../extras/) for more information.
<h5>ProTip™: Enable Syntax Highlighting</h5> <h5>ProTip™: Enable Syntax Highlighting</h5>
<p> <p>
If youre the kind of person who is using Jekyll, then chances are youll If youre the kind of person who is using Jekyll, then chances are youll
want to enable syntax highlighting using Pygments. You should really want to enable syntax highlighting using Pygments or Rouge. You should
<a href="../templates/#code_snippet_highlighting">check out how to do really <a href="../templates/#code_snippet_highlighting">check out how to
that</a> before you go any further. do that</a> before you go any further.
</p> </p>
</div> </div>

View File

@ -139,8 +139,8 @@ your `excerpt_separator` to `""`.
## Highlighting code snippets ## Highlighting code snippets
Jekyll also has built-in support for syntax highlighting of code snippets using Jekyll also has built-in support for syntax highlighting of code snippets using
Pygments, and including a code snippet in any post is easy. Just use the either Pygments or [Rouge](https://github.com/jayferd/rouge), and including a
dedicated Liquid tag as follows: code snippet in any post is easy. Just use the dedicated Liquid tag as follows:
{% highlight text %} {% highlight text %}
{% raw %}{% highlight ruby %}{% endraw %} {% raw %}{% highlight ruby %}{% endraw %}

View File

@ -232,8 +232,14 @@ These parameters are available via Liquid in the include:
Jekyll has built in support for syntax highlighting of [over 100 Jekyll has built in support for syntax highlighting of [over 100
languages](http://pygments.org/languages/) thanks to languages](http://pygments.org/languages/) thanks to
[Pygments](http://pygments.org/). To use Pygments, you must have Python installed on your [Pygments](http://pygments.org/). To use Pygments, you must have Python installed
system and set `pygments` to `true` in your site's configuration file. on your system and set `highlighter` to `pygments` in your site's configuration
file.
Alternatively, you can use [Rouge](https://github.com/jayferd/rouge) to highlight
your code snippets. It doesn't support as many languages as Pygments does but
it should fit in most cases and it's written in pure Ruby ; you don't need Python
on your system!
To render a code block with syntax highlighting, surround your code as follows: To render a code block with syntax highlighting, surround your code as follows:
@ -249,8 +255,9 @@ end
The argument to the `highlight` tag (`ruby` in the example above) is the The argument to the `highlight` tag (`ruby` in the example above) is the
language identifier. To find the appropriate identifier to use for the language language identifier. To find the appropriate identifier to use for the language
you want to highlight, look for the “short name” on the [Lexers you want to highlight, look for the “short name” on the [Pygments' Lexers
page](http://pygments.org/docs/lexers/). page](http://pygments.org/docs/lexers/) or the [Rouge
wiki](https://github.com/jayferd/rouge/wiki/List-of-supported-languages-and-lexers).
#### Line numbers #### Line numbers

View File

@ -123,8 +123,8 @@ bug](http://aaronqian.com/articles/2009/04/07/redcloth-ate-my-notextile.html)
and will hopefully be fixed for 4.2. You can still use 4.1.9, but the and will hopefully be fixed for 4.2. You can still use 4.1.9, but the
test suite requires that 4.1.0 be installed. If you use a version of test suite requires that 4.1.0 be installed. If you use a version of
RedCloth that does not have the notextile tag, you may notice that RedCloth that does not have the notextile tag, you may notice that
syntax highlighted blocks from Pygments are not formatted correctly, syntax highlighted blocks from Pygments or Rouge are not formatted
among other things. If youre seeing this just install 4.1.0. correctly, among other things. If youre seeing this just install 4.1.0.
### Liquid ### Liquid

View File

@ -42,6 +42,22 @@ puts "Hello world"
end end
end end
context "with rouge enabled" do
setup do
@markdown = Converters::Markdown.new @config.merge({ 'highlighter' => 'rouge' })
end
should "render fenced code blocks with syntax highlighting" do
assert_equal "<div class=\"highlight\"><pre><code class=\"ruby language-ruby\" data-lang=\"ruby\"><span class=\"nb\">puts</span> <span class=\"s2\">\"Hello world\"</span>\n</code></pre></div>", @markdown.convert(
<<-EOS
```ruby
puts "Hello world"
```
EOS
).strip
end
end
context "without any highlighter" do context "without any highlighter" do
setup do setup do
@markdown = Converters::Markdown.new @config.merge({ 'highlighter' => nil }) @markdown = Converters::Markdown.new @config.merge({ 'highlighter' => nil })