Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Transformer Plugin #1520

Closed
wants to merge 5 commits into from

3 participants

@PeteMichaud

In reference to issue #1509, I wrote an implementation of the Transformer plugins as described in that issue and implemented in https://github.com/PeteMichaud/jekyllpedia/blob/master/_plugins/jekyllpedia.rb (Note: the jekyllpedia thing is only meant as an API reference, the implementation is broken in like 6 ways that I can see off the top of my head, don't use it until I actually write it correctly).

I opted to Transform prior to the liquid conversion (see https://github.com/PeteMichaud/jekyll/compare/transformer#L1R139), because I thought that was probably more powerful than the other way around. Now Transformers can potentially inject or alter the liquid code before that code is rendered to a final page.

@PeteMichaud

Do I need to change things for it to be accepted? Are we waiting until next release cycle to merge this since it's a new feature, or what's the deal? I'd like to stay using the main line of jekyll, but I really need this functionality, so if I could get an idea of if and when this might be accepted and make it into rubygems that would be awesome.

Anything I can do to make this better or to help in any way, let me know.

@mattr-
Owner
@PeteMichaud

I understand @mattr- thanks for the update 8)

@parkr parkr closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 8, 2013
  1. @PeteMichaud
  2. @PeteMichaud

    run transformer plugins during do_layout. Also changed name of transf…

    PeteMichaud authored
    …orm method to convert since that method runs converters, and the new one runs transformers
  3. @PeteMichaud
  4. @PeteMichaud

    transformer tests

    PeteMichaud authored
  5. @PeteMichaud
This page is out of date. Refresh to see the latest.
View
2  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
View
24 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.
View
4 lib/jekyll/transformer.rb
@@ -0,0 +1,4 @@
+module Jekyll
+ class Transformer < Plugin
+ end
+end
View
70 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:
+
+<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
View
22 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 "<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"
@@ -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
Something went wrong with that request. Please try again.