diff --git a/lib/jekyll.rb b/lib/jekyll.rb index a48d346050c..2fb6d10f8a5 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -49,12 +49,14 @@ def require_all(path) require 'jekyll/plugin' require 'jekyll/converter' require 'jekyll/generator' +require 'jekyll/transformer' require 'jekyll/command' require_all 'jekyll/commands' require_all 'jekyll/converters' require_all 'jekyll/converters/markdown' require_all 'jekyll/generators' +require_all 'jekyll/transformers' require_all 'jekyll/tags' SafeYAML::OPTIONS[:suppress_warnings] = true diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 5f4938002f1..b78eb569d30 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -46,7 +46,7 @@ def read_yaml(base, name) # Transform the contents based on the content type. # # Returns nothing. - def transform + def convert self.content = converter.convert(self.content) rescue => e Jekyll.logger.error "Conversion error:", "There was an error converting" + @@ -136,10 +136,12 @@ def do_layout(payload, layouts) payload["pygments_prefix"] = converter.pygments_prefix payload["pygments_suffix"] = converter.pygments_suffix + self.content = self.transform(self.content, info) + self.content = self.render_liquid(self.content, payload, info) - self.transform + self.convert # output keeps track of what will finally be written self.output = self.content @@ -147,6 +149,24 @@ def do_layout(payload, layouts) self.render_all_layouts(layouts, payload, info) end + # Transform the page content with the available plugins. + # + # content - The String of raw content for the page. + # info - The page context object + # + # Returns new content String. + def transform(content, info) + Jekyll::Transformer.subclasses.select do |c| + !self.site.safe || c.safe + end.sort.map do |c| + c.new(info) + end.select do |transformer| + transformer.matches(info[:registers][:page]) + end.inject(content) do |c, t| + t.transform(c) + end + end + # Write the generated page file to the destination directory. # # dest - The String path to the destination dir. diff --git a/lib/jekyll/transformer.rb b/lib/jekyll/transformer.rb new file mode 100644 index 00000000000..7f0bd435efe --- /dev/null +++ b/lib/jekyll/transformer.rb @@ -0,0 +1,4 @@ +module Jekyll + class Transformer < Plugin + end +end diff --git a/site/docs/plugins.md b/site/docs/plugins.md index 4ce17e2f107..3c269f69874 100644 --- a/site/docs/plugins.md +++ b/site/docs/plugins.md @@ -29,11 +29,12 @@ In your site source root, make a `_plugins` directory. Place your plugins here. Any file ending in `*.rb` inside this directory will be loaded before Jekyll generates your site. -In general, plugins you make will fall into one of three categories: +In general, plugins you make will fall into one of four categories: 1. Generators 2. Converters -3. Tags +3. Tranformers +4. Tags ## Generators @@ -190,6 +191,71 @@ In our example, `UpcaseConverter#matches` checks if our filename extension is simply uppercasing the entire content string. Finally, when it saves the page, it will do so with a `.html` extension. +## Transformers + +You can create a transformer when you need Jekyll to alter the content of a file +based on your own rules. For example, a transformer might look like this: + +{% highlight ruby %} +module Jekyll + + class WordFilterTransformer < Transformer + safe true + + def initialize(context) + @context = context + @black_list = %w(death taxes) + end + + def matches(page) + true + end + + def transform(content) + content.gsub(/#{@black_list.join('|')}/i, '****') + end + end + +end +{% endhighlight %} + +In this example, our transformer will find any instance of the words in the +black list, and replace those words with asterisks. + +At minimum, Transformers must implement: + +
+ + + + + + + + + + + + + + + + + +
MethodDescription
+

matches

+

+ Is this a page we want to tranform? Takes one argument: the page + object. Must return true if it matches, + false otherwise. +

+

transform

+

+ Logic to do the content transform. Takes one argument: the raw content + of the file (without YAML front matter). Must return a String. +

+
+ ## Tags If you’d like to include custom liquid tags in your site, you can do so by diff --git a/test/test_post.rb b/test/test_post.rb index 57979c65d85..719e9e62b14 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -256,14 +256,30 @@ def do_render(post) assert_equal "h1. {{ page.title }}\n\nBest *post* ever", @post.content end - should "transform textile" do + should "convert textile" do @post.process(@real_file) @post.read_yaml(@source, @real_file) - @post.transform + @post.convert assert_equal "

{{ page.title }}

\n

Best post ever

", @post.content end + should "run transformers" do + class MyTransformer < Transformer + def initialize(context) + end + def matches(page) + true + end + def transform(content) + content.gsub("test content", "test content success") + end + end + transformed_content = @post.transform("test content", {:registers => { :page => {}}}) + + assert_equal "test content success", transformed_content + end + context "#excerpt" do setup do file = "2013-01-02-post-excerpt.markdown" @@ -296,7 +312,7 @@ def do_render(post) @post.process(file) @post.read_yaml(@source, file) - @post.transform + @post.convert end should "respect given separator" do