Merge pull request #1859 from robin850/rouge
This commit is contained in:
commit
012387396a
|
@ -7,6 +7,7 @@
|
|||
* Remove support for Ruby 1.8.x (#1780)
|
||||
* Move to jekyll/jekyll from mojombo/jekyll (#1817)
|
||||
* Allow custom markdown processors (#1872)
|
||||
* Provide support for the Rouge syntax highlighter (#1859)
|
||||
|
||||
### Minor Enhancements
|
||||
* Move the EntryFilter class into the Jekyll module to avoid polluting the
|
||||
|
@ -37,6 +38,7 @@
|
|||
* Add in History and site changes from `v1-stable` branch (#1836)
|
||||
* Testing additions on the Excerpt class (#1893)
|
||||
* Update Kramdown to `~> 1.3` (#1894)
|
||||
* Fix the `highlight` tag feature (#1859)
|
||||
|
||||
### Site Enhancements
|
||||
* Document Kramdown's GFM parser option (#1791)
|
||||
|
|
|
@ -91,11 +91,19 @@ Feature: Site configuration
|
|||
And I should see "<a href=\"http://google.com\">Google</a>" in "_site/index.html"
|
||||
|
||||
Scenario: Highlight code with pygments
|
||||
Given I have an "index.html" file that contains "{% highlight ruby %} puts 'Hello world!' {% endhighlight %}"
|
||||
And I have a configuration file with "pygments" set to "true"
|
||||
Given I have an "index.html" page that contains "{% highlight ruby %} puts 'Hello world!' {% endhighlight %}"
|
||||
When I run jekyll
|
||||
Then the _site directory should exist
|
||||
And I should see "puts '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"
|
||||
|
||||
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
|
||||
Given I have a _layouts directory
|
||||
|
|
|
@ -52,6 +52,7 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency('activesupport', '~> 3.2.13')
|
||||
s.add_development_dependency('jekyll_test_plugin')
|
||||
s.add_development_dependency('jekyll_test_plugin_malicious')
|
||||
s.add_development_dependency('rouge', '~> 1.3')
|
||||
|
||||
# = MANIFEST =
|
||||
s.files = %w[
|
||||
|
|
|
@ -24,12 +24,12 @@ module Jekyll
|
|||
'limit_posts' => 0,
|
||||
'lsi' => false,
|
||||
'future' => true, # remove and make true just default
|
||||
'pygments' => true,
|
||||
|
||||
'relative_permalinks' => true, # backwards-compatibility with < 1.0
|
||||
# will be set to false once 2.0 hits
|
||||
|
||||
'markdown' => 'maruku',
|
||||
'highlighter' => 'pygments',
|
||||
'permalink' => 'date',
|
||||
'baseurl' => '/',
|
||||
'include' => ['.htaccess'],
|
||||
|
@ -210,6 +210,16 @@ module Jekyll
|
|||
config.delete('server_port')
|
||||
end
|
||||
|
||||
if config.has_key? 'pygments'
|
||||
Jekyll.logger.warn "Deprecation:", "The 'pygments' configuration option" +
|
||||
" has been renamed to 'highlighter'. Please update your" +
|
||||
" config file accordingly. The allowed values are 'rouge', " +
|
||||
"'pygments' or null."
|
||||
|
||||
config['highlighter'] = 'pygments' if config['pygments']
|
||||
config.delete('pygments')
|
||||
end
|
||||
|
||||
%w[include exclude].each do |option|
|
||||
if config.fetch(option, []).is_a?(String)
|
||||
Jekyll.logger.warn "Deprecation:", "The '#{option}' configuration option" +
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
module Jekyll
|
||||
class Converter < Plugin
|
||||
# Public: Get or set the pygments prefix. When an argument is specified,
|
||||
# Public: Get or set the highlighter prefix. When an argument is specified,
|
||||
# the prefix will be set. If no argument is specified, the current prefix
|
||||
# will be returned.
|
||||
#
|
||||
# pygments_prefix - The String prefix (default: nil).
|
||||
# highlighter_prefix - The String prefix (default: nil).
|
||||
#
|
||||
# Returns the String prefix.
|
||||
def self.pygments_prefix(pygments_prefix = nil)
|
||||
@pygments_prefix = pygments_prefix if pygments_prefix
|
||||
@pygments_prefix
|
||||
def self.highlighter_prefix(highlighter_prefix = nil)
|
||||
@highlighter_prefix = highlighter_prefix if highlighter_prefix
|
||||
@highlighter_prefix
|
||||
end
|
||||
|
||||
# Public: Get or set the pygments suffix. When an argument is specified,
|
||||
# Public: Get or set the highlighter suffix. When an argument is specified,
|
||||
# the suffix will be set. If no argument is specified, the current suffix
|
||||
# will be returned.
|
||||
#
|
||||
# pygments_suffix - The String suffix (default: nil).
|
||||
# highlighter_suffix - The String suffix (default: nil).
|
||||
#
|
||||
# Returns the String suffix.
|
||||
def self.pygments_suffix(pygments_suffix = nil)
|
||||
@pygments_suffix = pygments_suffix if pygments_suffix
|
||||
@pygments_suffix
|
||||
def self.highlighter_suffix(highlighter_suffix = nil)
|
||||
@highlighter_suffix = highlighter_suffix if highlighter_suffix
|
||||
@highlighter_suffix
|
||||
end
|
||||
|
||||
# Initialize the converter.
|
||||
|
@ -31,18 +31,18 @@ module Jekyll
|
|||
@config = config
|
||||
end
|
||||
|
||||
# Get the pygments prefix.
|
||||
# Get the highlighter prefix.
|
||||
#
|
||||
# Returns the String prefix.
|
||||
def pygments_prefix
|
||||
self.class.pygments_prefix
|
||||
def highlighter_prefix
|
||||
self.class.highlighter_prefix
|
||||
end
|
||||
|
||||
# Get the pygments suffix.
|
||||
# Get the highlighter suffix.
|
||||
#
|
||||
# Returns the String suffix.
|
||||
def pygments_suffix
|
||||
self.class.pygments_suffix
|
||||
def highlighter_suffix
|
||||
self.class.highlighter_suffix
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,8 +3,8 @@ module Jekyll
|
|||
class Markdown < Converter
|
||||
safe true
|
||||
|
||||
pygments_prefix "\n"
|
||||
pygments_suffix "\n"
|
||||
highlighter_prefix "\n"
|
||||
highlighter_suffix "\n"
|
||||
|
||||
def setup
|
||||
return if @setup
|
||||
|
|
|
@ -22,7 +22,7 @@ module Jekyll
|
|||
end
|
||||
end
|
||||
|
||||
module WithoutPygments
|
||||
module WithoutHighlighting
|
||||
require 'cgi'
|
||||
|
||||
include CommonMethods
|
||||
|
@ -37,19 +37,50 @@ module Jekyll
|
|||
end
|
||||
end
|
||||
|
||||
module WithRouge
|
||||
require 'rouge'
|
||||
require 'rouge/plugins/redcarpet'
|
||||
|
||||
if Rouge.version < '1.3.0'
|
||||
abort "Please install Rouge 1.3.0 or greater and try running Jekyll again."
|
||||
end
|
||||
|
||||
include Rouge::Plugins::Redcarpet
|
||||
include CommonMethods
|
||||
|
||||
def block_code(code, lang)
|
||||
code = "<pre>#{super}</pre>"
|
||||
|
||||
output = "<div class=\"highlight\">"
|
||||
output << add_code_tags(code, lang)
|
||||
output << "</div>"
|
||||
end
|
||||
|
||||
protected
|
||||
def rouge_formatter(opts = {})
|
||||
Rouge::Formatters::HTML.new(opts.merge(wrap: false))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize(config)
|
||||
require 'redcarpet'
|
||||
@config = config
|
||||
@redcarpet_extensions = {}
|
||||
@config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true }
|
||||
|
||||
@renderer ||= if @config['pygments']
|
||||
@renderer ||= case @config['highlighter']
|
||||
when 'pygments'
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithPygments
|
||||
end
|
||||
when 'rouge'
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithRouge
|
||||
end
|
||||
else
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithoutPygments
|
||||
include WithoutHighlighting
|
||||
end
|
||||
end
|
||||
rescue LoadError
|
||||
|
|
|
@ -3,8 +3,8 @@ module Jekyll
|
|||
class Textile < Converter
|
||||
safe true
|
||||
|
||||
pygments_prefix '<notextile>'
|
||||
pygments_suffix '</notextile>'
|
||||
highlighter_prefix '<notextile>'
|
||||
highlighter_suffix '</notextile>'
|
||||
|
||||
def setup
|
||||
return if @setup
|
||||
|
|
|
@ -145,8 +145,8 @@ module Jekyll
|
|||
info = { :filters => [Jekyll::Filters], :registers => { :site => self.site, :page => payload['page'] } }
|
||||
|
||||
# render and transform content (this becomes the final content of the object)
|
||||
payload["pygments_prefix"] = converter.pygments_prefix
|
||||
payload["pygments_suffix"] = converter.pygments_suffix
|
||||
payload["highlighter_prefix"] = converter.highlighter_prefix
|
||||
payload["highlighter_suffix"] = converter.highlighter_suffix
|
||||
|
||||
self.content = self.render_liquid(self.content,
|
||||
payload,
|
||||
|
|
|
@ -9,8 +9,8 @@ module Jekyll
|
|||
arg_is_present? args, "--auto", "The switch '--auto' has been replaced with '--watch'."
|
||||
arg_is_present? args, "--no-auto", "To disable auto-replication, simply leave off \
|
||||
the '--watch' switch."
|
||||
arg_is_present? args, "--pygments", "The 'pygments' setting can only be set in \
|
||||
your config files."
|
||||
arg_is_present? args, "--pygments", "The 'pygments'settings has been removed in \
|
||||
favour of 'highlighter'."
|
||||
arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in your \
|
||||
config files."
|
||||
arg_is_present? args, "--url", "The 'url' setting can only be set in your config files."
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Jekyll
|
||||
class Site
|
||||
attr_accessor :config, :layouts, :posts, :pages, :static_files,
|
||||
:categories, :exclude, :include, :source, :dest, :lsi, :pygments,
|
||||
:categories, :exclude, :include, :source, :dest, :lsi, :highlighter,
|
||||
:permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts,
|
||||
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts, :gems
|
||||
|
||||
|
@ -13,7 +13,7 @@ module Jekyll
|
|||
def initialize(config)
|
||||
self.config = config.clone
|
||||
|
||||
%w[safe lsi pygments baseurl exclude include future show_drafts limit_posts keep_files gems].each do |opt|
|
||||
%w[safe lsi highlighter baseurl exclude include future show_drafts limit_posts keep_files gems].each do |opt|
|
||||
self.send("#{opt}=", config[opt])
|
||||
end
|
||||
|
||||
|
|
|
@ -41,8 +41,11 @@ eos
|
|||
end
|
||||
|
||||
def render(context)
|
||||
if context.registers[:site].pygments
|
||||
case context.registers[:site].highlighter
|
||||
when 'pygments'
|
||||
render_pygments(context, super)
|
||||
when 'rouge'
|
||||
render_rouge(context, super)
|
||||
else
|
||||
render_codehighlighter(context, super)
|
||||
end
|
||||
|
@ -58,9 +61,28 @@ eos
|
|||
@lang
|
||||
)
|
||||
|
||||
output = context["pygments_prefix"] + output if context["pygments_prefix"]
|
||||
output = output + context["pygments_suffix"] if context["pygments_suffix"]
|
||||
output
|
||||
output = context["highlighter_prefix"] + output if context["highlighter_prefix"]
|
||||
output << context["highlighter_suffix"] if context["highlighter_suffix"]
|
||||
|
||||
return output
|
||||
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, wrap: false)
|
||||
|
||||
pre = "<pre>#{formatter.format(lexer.lex(code))}</pre>"
|
||||
|
||||
output = context["highlighter_prefix"] || ""
|
||||
output << "<div class=\"highlight\">"
|
||||
output << add_code_tags(pre, @lang)
|
||||
output << "</div>"
|
||||
output << context["highlighter_suffix"] if context["highlighter_suffix"]
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
def render_codehighlighter(context, code)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
name: Your New Jekyll Site
|
||||
markdown: redcarpet
|
||||
pygments: true
|
||||
highlighter: pygments
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pygments: true
|
||||
highlight: pygments
|
||||
relative_permalinks: false
|
||||
gauges_id: 503c5af6613f5d0f19000027
|
||||
permalink: /news/:year/:month/:day/:title/
|
||||
|
|
|
@ -288,7 +288,7 @@ encoding: nil
|
|||
future: true
|
||||
show_drafts: nil
|
||||
limit_posts: 0
|
||||
pygments: true
|
||||
highlighter: pygments
|
||||
|
||||
relative_permalinks: true
|
||||
|
||||
|
@ -363,7 +363,7 @@ Jekyll handles two special Redcarpet extensions:
|
|||
# ...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.
|
||||
|
||||
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:
|
||||
|
|
|
@ -66,9 +66,10 @@ Check out [the extras page](../extras/) for more information.
|
|||
<h5>ProTip™: Enable Syntax Highlighting</h5>
|
||||
<p>
|
||||
If you’re the kind of person who is using Jekyll, then chances are you’ll
|
||||
want to enable syntax highlighting using Pygments. You should really
|
||||
<a href="../templates/#code_snippet_highlighting">check out how to do
|
||||
that</a> before you go any further.
|
||||
want to enable syntax highlighting using <a href="http://pygments.org/">Pygments</a>
|
||||
or <a href="https://github.com/jayferd/rouge">Rouge</a>. You should really
|
||||
<a href="../templates/#code_snippet_highlighting">check out how to
|
||||
do that</a> before you go any farther.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -139,8 +139,8 @@ your `excerpt_separator` to `""`.
|
|||
## Highlighting code snippets
|
||||
|
||||
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
|
||||
dedicated Liquid tag as follows:
|
||||
either Pygments or Rouge, and including a code snippet in any post is easy. Just
|
||||
use the dedicated Liquid tag as follows:
|
||||
|
||||
{% highlight text %}
|
||||
{% raw %}{% highlight ruby %}{% endraw %}
|
||||
|
|
|
@ -230,8 +230,14 @@ These parameters are available via Liquid in the include:
|
|||
|
||||
Jekyll has built in support for syntax highlighting of [over 100
|
||||
languages](http://pygments.org/languages/) thanks to
|
||||
[Pygments](http://pygments.org/). To use Pygments, you must have Python installed on your
|
||||
system and set `pygments` to `true` in your site's configuration file.
|
||||
[Pygments](http://pygments.org/). To use Pygments, you must have Python installed
|
||||
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:
|
||||
|
||||
|
@ -247,8 +253,9 @@ end
|
|||
|
||||
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
|
||||
you want to highlight, look for the “short name” on the [Lexers
|
||||
page](http://pygments.org/docs/lexers/).
|
||||
you want to highlight, look for the “short name” on the [Pygments' 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
|
||||
|
||||
|
|
|
@ -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
|
||||
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
|
||||
syntax highlighted blocks from Pygments are not formatted correctly,
|
||||
among other things. If you’re seeing this just install 4.1.0.
|
||||
syntax highlighted blocks from Pygments or Rouge are not formatted
|
||||
correctly, among other things. If you’re seeing this just install 4.1.0.
|
||||
|
||||
### Liquid
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ class TestConfiguration < Test::Unit::TestCase
|
|||
"watch" => true,
|
||||
"server" => true,
|
||||
"exclude" => "READ-ME.md, Gemfile,CONTRIBUTING.hello.markdown",
|
||||
"include" => "STOP_THE_PRESSES.txt,.heloses, .git"
|
||||
"include" => "STOP_THE_PRESSES.txt,.heloses, .git",
|
||||
"pygments" => true,
|
||||
}]
|
||||
end
|
||||
should "unset 'auto' and 'watch'" do
|
||||
|
@ -78,6 +79,11 @@ class TestConfiguration < Test::Unit::TestCase
|
|||
assert @config.backwards_compatibilize.has_key?("include")
|
||||
assert_equal @config.backwards_compatibilize["include"], %w[STOP_THE_PRESSES.txt .heloses .git]
|
||||
end
|
||||
should "set highlighter to pygments" do
|
||||
assert @config.has_key?("pygments")
|
||||
assert !@config.backwards_compatibilize.has_key?("pygments")
|
||||
assert_equal @config.backwards_compatibilize["highlighter"], "pygments"
|
||||
end
|
||||
end
|
||||
context "#fix_common_issues" do
|
||||
setup do
|
||||
|
|
|
@ -28,7 +28,7 @@ class TestRedcarpet < Test::Unit::TestCase
|
|||
|
||||
context "with pygments enabled" do
|
||||
setup do
|
||||
@markdown = Converters::Markdown.new @config.merge({ 'pygments' => true })
|
||||
@markdown = Converters::Markdown.new @config.merge({ 'highlighter' => 'pygments' })
|
||||
end
|
||||
|
||||
should "render fenced code blocks with syntax highlighting" do
|
||||
|
@ -42,9 +42,25 @@ puts "Hello world"
|
|||
end
|
||||
end
|
||||
|
||||
context "with pygments disabled" do
|
||||
context "with rouge enabled" do
|
||||
setup do
|
||||
@markdown = Converters::Markdown.new @config.merge({ 'pygments' => false })
|
||||
@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
|
||||
setup do
|
||||
@markdown = Converters::Markdown.new @config.merge({ 'highlighter' => nil })
|
||||
end
|
||||
|
||||
should "render fenced code blocks without syntax highlighting" do
|
||||
|
|
|
@ -6,7 +6,7 @@ class TestTags < Test::Unit::TestCase
|
|||
|
||||
def create_post(content, override = {}, converter_class = Jekyll::Converters::Markdown)
|
||||
stub(Jekyll).configuration do
|
||||
Jekyll::Configuration::DEFAULTS.deep_merge({'pygments' => true}).deep_merge(override)
|
||||
Jekyll::Configuration::DEFAULTS.deep_merge({'highlighter' => 'pygments'}).deep_merge(override)
|
||||
end
|
||||
site = Site.new(Jekyll.configuration)
|
||||
|
||||
|
@ -16,8 +16,8 @@ class TestTags < Test::Unit::TestCase
|
|||
|
||||
info = { :filters => [Jekyll::Filters], :registers => { :site => site } }
|
||||
@converter = site.converters.find { |c| c.class == converter_class }
|
||||
payload = { "pygments_prefix" => @converter.pygments_prefix,
|
||||
"pygments_suffix" => @converter.pygments_suffix }
|
||||
payload = { "highlighter_prefix" => @converter.highlighter_prefix,
|
||||
"highlighter_suffix" => @converter.highlighter_suffix }
|
||||
|
||||
@result = Liquid::Template.parse(content).render!(payload, info)
|
||||
@result = @converter.convert(@result)
|
||||
|
|
Loading…
Reference in New Issue