Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transformer Plugin #1520

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/jekyll.rb
Expand Up @@ -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
Expand Down
24 changes: 22 additions & 2 deletions lib/jekyll/convertible.rb
Expand Up @@ -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" +
Expand Down Expand Up @@ -136,17 +136,37 @@ 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

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.
Expand Down
4 changes: 4 additions & 0 deletions lib/jekyll/transformer.rb
@@ -0,0 +1,4 @@
module Jekyll
class Transformer < Plugin
end
end
70 changes: 68 additions & 2 deletions site/docs/plugins.md
Expand Up @@ -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

Expand Down Expand Up @@ -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:

<div class="mobile-side-scroller">
<table>
<thead>
<tr>
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p><code>matches</code></p>
</td>
<td><p>
Is this a page we want to tranform? Takes one argument: the page
object. Must return <code>true</code> if it matches,
<code>false</code> otherwise.
</p></td>
</tr>
<tr>
<td>
<p><code>transform</code></p>
</td>
<td><p>
Logic to do the content transform. Takes one argument: the raw content
of the file (without YAML front matter). Must return a String.
</p></td>
</tr>
</tbody>
</table>
</div>

## Tags

If you’d like to include custom liquid tags in your site, you can do so by
Expand Down
22 changes: 19 additions & 3 deletions test/test_post.rb
Expand Up @@ -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 "<h1>{{ page.title }}</h1>\n<p>Best <strong>post</strong> ever</p>", @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"
Expand Down Expand Up @@ -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
Expand Down