Merge pull request #1872 from jekyll/gjtorikian-steal-envygeeks-custom-markdown-processors

This commit is contained in:
Parker Moore 2013-12-25 22:05:31 -08:00
commit 5c4831af49
3 changed files with 112 additions and 15 deletions

View File

@ -8,19 +8,21 @@ module Jekyll
def setup def setup
return if @setup return if @setup
@parser = case @config['markdown'] @parser =
when 'redcarpet' case @config['markdown'].downcase
RedcarpetParser.new @config when 'redcarpet' then RedcarpetParser.new(@config)
when 'kramdown' when 'kramdown' then KramdownParser.new(@config)
KramdownParser.new @config when 'rdiscount' then RDiscountParser.new(@config)
when 'rdiscount' when 'maruku' then MarukuParser.new(@config)
RDiscountParser.new @config
when 'maruku'
MarukuParser.new @config
else else
STDERR.puts "Invalid Markdown processor: #{@config['markdown']}" # So they can't try some tricky bullshit or go down the ancestor chain, I hope.
STDERR.puts " Valid options are [ maruku | rdiscount | kramdown | redcarpet ]" if allowed_custom_class?(@config['markdown'])
raise FatalException.new("Invalid Markdown process: #{@config['markdown']}") self.class.const_get(@config['markdown']).new(@config)
else
Jekyll.logger.error "Invalid Markdown Processor:", "#{@config['markdown']}"
Jekyll.logger.error "", "Valid options are [ maruku | rdiscount | kramdown | redcarpet ]"
raise FatalException, "Invalid Markdown Processor: #{@config['markdown']}"
end
end end
@setup = true @setup = true
end end
@ -38,6 +40,19 @@ module Jekyll
setup setup
@parser.convert(content) @parser.convert(content)
end end
private
# Private: Determine whether a class name is an allowed custom markdown
# class name
#
# parser_name - the name of the parser class
#
# Returns true if the parser name contains only alphanumeric characters
# and is defined within Jekyll::Converters::Markdown
def allowed_custom_class?(parser_name)
parser_name !~ /[^A-Za-z0-9]/ && self.class.constants.include?(parser_name.to_sym)
end
end end
end end
end end

View File

@ -16,7 +16,12 @@ Maruku comes with optional support for LaTeX to PNG rendering via blahtex
Maruku to not assume a fixed location for `dvips`, check out [Remis Maruku Maruku to not assume a fixed location for `dvips`, check out [Remis Maruku
fork](http://github.com/remi/maruku). fork](http://github.com/remi/maruku).
## RDiscount ## Alternative Markdown Processors
While Jekyll defaults to using Maruku for Markdown conversion, you may use one
of the other three pre-defined markdown parsers or define your own.
### RDiscount
If you prefer to use [RDiscount](http://github.com/rtomayko/rdiscount) instead If you prefer to use [RDiscount](http://github.com/rtomayko/rdiscount) instead
of [Maruku](http://github.com/bhollis/maruku) for Markdown, just make sure you have of [Maruku](http://github.com/bhollis/maruku) for Markdown, just make sure you have
@ -34,7 +39,7 @@ have Jekyll run with that option.
markdown: rdiscount markdown: rdiscount
{% endhighlight %} {% endhighlight %}
## Kramdown ### Kramdown
You can also use [Kramdown](http://kramdown.rubyforge.org/) instead of Maruku You can also use [Kramdown](http://kramdown.rubyforge.org/) instead of Maruku
for Markdown. Make sure that Kramdown is installed: for Markdown. Make sure that Kramdown is installed:
@ -54,3 +59,34 @@ Kramdown has various options for customizing the HTML output. The
[Configuration](/docs/configuration/) page lists the default options used by [Configuration](/docs/configuration/) page lists the default options used by
Jekyll. A complete list of options is also available on the [Kramdown Jekyll. A complete list of options is also available on the [Kramdown
website](http://kramdown.rubyforge.org/options.html). website](http://kramdown.rubyforge.org/options.html).
### User-Defined
So, you're totally at odds with our four built-in markdown parsers, eh? No
sweat. You can define one as a plugin:
{% highlight ruby %}
require 'jekyll'
require 'some_renderer'
class Jekyll::Converters::Markdown::MyCustomParser
def initialize(config)
@site_config = config
end
def convert(content)
# (this _must_ return the resulting String after the rendering)
SomeRenderer.new(@site_config).to_html(content)
end
end
{% endhighlight %}
Once you've got that setup, ask Jekyll to use your custom markdown parser in
your `_config.yml` file:
{% highlight yaml %}
markdown: MyCustomParser
{% endhighlight %}
(Note that this **is case-sensitive**, and is only the piece after
`Jekyll::Converters::Markdown`.) And there you are!

View File

@ -262,6 +262,52 @@ class TestSite < Test::Unit::TestCase
end end
end end
context 'using a non-default markdown processor in the configuration' do
should 'use the non-default markdown processor' do
class Jekyll::Converters::Markdown::CustomMarkdown
def initialize(*args)
@args = args
end
def convert(*args)
""
end
end
custom_processor = "CustomMarkdown"
s = Site.new(Jekyll.configuration.merge({ 'markdown' => custom_processor }))
assert_nothing_raised do
s.process
end
# Do some cleanup, we don't like straggling stuff's.
Jekyll::Converters::Markdown.send(:remove_const, :CustomMarkdown)
end
should 'ignore, if there are any bad characters in the class name' do
module Jekyll::Converters::Markdown::Custom
class Markdown
def initialize(*args)
@args = args
end
def convert(*args)
""
end
end
end
bad_processor = "Custom::Markdown"
s = Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
assert_raise Jekyll::FatalException do
s.process
end
# Do some cleanup, we don't like straggling stuff's.
Jekyll::Converters::Markdown.send(:remove_const, :Custom)
end
end
context 'with an invalid markdown processor in the configuration' do context 'with an invalid markdown processor in the configuration' do
should 'not throw an error at initialization time' do should 'not throw an error at initialization time' do
bad_processor = 'not a processor name' bad_processor = 'not a processor name'