jekyll_ext 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.textile +16 -0
  2. data/Rakefile +5 -0
  3. data/bin/ejekyll +34 -0
  4. data/lib/aop.rb +107 -0
  5. metadata +83 -0
data/README.textile ADDED
@@ -0,0 +1,16 @@
1
+ h1. jekyll_ext
2
+
3
+ <em>jekyll_ext</em> allows you to extend the Jekyll static blog generator without forking and modifying it's codebase.
4
+ With this code, not only do your extensions live in your blog directory, but they can also be shared and reutilized.
5
+
6
+ More information can be found here: "Jekyll Extensions -= Pain":http://rfelix.com/2010/01/19/jekyll-extensions-minus-equal-pain/
7
+
8
+ h2. Installation
9
+
10
+ <code>gem install jekyll_ext</code>
11
+
12
+ Now you just need to create the directory <em>_extensions</em> in your blog where all your extensions will live. Any <em>.rb</em> file in that directory or subdirectory will automatically be loaded by <em>jekyll_ext</em>.
13
+
14
+ IMPORTANT: Instead of using the <code>jekyll</code> command, you should now use <code>ejekyll</code> instead (which is just a jekyll wrapper that loads your extensions).
15
+
16
+ To get you started, take a look at my own <em>_extensions</em> directory: "my_jekyll_extensions":http://github.com/rfelix/my_jekyll_extensions
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "rake"
2
+ require "rake/clean"
3
+ require "mg"
4
+
5
+ MG.new("jekyll_ext.gemspec")
data/bin/ejekyll ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Code based on gist supplied by Alban Peignier (http://gist.github.com/379361)
4
+
5
+ require 'rubygems'
6
+ require 'jekyll'
7
+
8
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'aop.rb')
9
+
10
+ module Jekyll
11
+
12
+ class << self
13
+ alias_method :configuration_without_extensions, :configuration
14
+ def configuration_with_extensions(options)
15
+ options = configuration_without_extensions(options)
16
+ Dir["_extensions/*.rb", "_extensions/*/*.rb"].each do |f|
17
+ puts "Loading Extension: #{File.basename(f)}"
18
+ load f
19
+ end
20
+ options
21
+ end
22
+ alias_method :configuration, :configuration_with_extensions
23
+
24
+ alias_method :original_version, :version
25
+ def version
26
+ original_version + " (Extended)"
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ original_jekyll = ENV['PATH'].split(':').collect { |d| "#{d}/jekyll" }.find{ |p| File.exists?(p) }
34
+ load original_jekyll
data/lib/aop.rb ADDED
@@ -0,0 +1,107 @@
1
+ if RUBY_VERSION >= "1.9"
2
+ require 'continuation'
3
+ end
4
+
5
+ module AOP
6
+ extend self
7
+
8
+ # Intercept the +meth_name+ method of +klass+ and execute +block+ before the
9
+ # original method.
10
+ # +klass+ Class that method to be intercepted belongs to
11
+ # +meth_name+ Name of method to be intercepted
12
+ # +block+ Code to executed before method, and can receive as parameters:
13
+ # 1. the instance that has been intercepted
14
+ # 2. the arguments passed to the original method
15
+ #
16
+ def before(klass, meth_name, &block)
17
+ intercept(klass, meth_name, :before, &block)
18
+ end
19
+
20
+ # Intercept the +meth_name+ method of +klass+ and execute +block+ after the
21
+ # original method
22
+ # +klass+ Class that method to be intercepted belongs to
23
+ # +meth_name+ Name of method to be intercepted
24
+ # +block+ Code to executed before method, and can receive as parameters:
25
+ # 1. the instance that has been intercepted
26
+ # 2. the arguments passed to the original method
27
+ #
28
+ def after(klass, meth_name, &block)
29
+ intercept(klass, meth_name, :after, &block)
30
+ end
31
+
32
+ # Intercept the +meth_name+ method of +klass+ and execute +block+ before and
33
+ # after the original method, but needs explicit calling of a Ruby proc/lambda.
34
+ # +klass+ Class that method to be intercepted belongs to
35
+ # +meth_name+ Name of method to be intercepted
36
+ # +block+ Code to executed before method, and can receive as parameters:
37
+ # 1. the instance that has been intercepted
38
+ # 2. the arguments passed to the original method
39
+ # 3. the proc that, if called, will proceed with the execution of the method
40
+ # 4. the proc that, if called, will abort the execution of the method returning
41
+ # whatever was passed as arguments to the block
42
+ #
43
+ def around(klass, meth_name, &block)
44
+ intercept(klass, meth_name, :around, &block)
45
+ end
46
+
47
+ private
48
+
49
+ # Use Ruby metaprogramming capabilities to intercept the method only once, making
50
+ # it execute the blocks defined for before, after, and around at the correct
51
+ # time before, after, or around the calling of the original method.
52
+ # +klass+ Class that method to be intercepted belongs to
53
+ # +meth_name+ Name of method to be intercepted
54
+ # +type+ Type of interception to be made (before, after, or around)
55
+ # +block+ Code to executed before/after/around method
56
+ #
57
+ def intercept(klass, meth_name, type, &block)
58
+ orig_name = "aop_orig_#{meth_name}".to_sym
59
+ meth_name = meth_name.to_sym
60
+ @intercepted_methods ||= Hash.new do |h,k|
61
+ # h[class_name] = hash
62
+ h[k] = Hash.new do |h,k|
63
+ # h[class_name][method_name] = hash
64
+ h[k] = Hash.new do |h,k|
65
+ # h[class_name][method_name][interception_type] = array
66
+ h[k] = []
67
+ end
68
+ end
69
+ end
70
+
71
+ make_interception = !@intercepted_methods[klass].has_key?(meth_name)
72
+ @intercepted_methods[klass][meth_name][type] << block
73
+ method_chain = @intercepted_methods[klass][meth_name]
74
+
75
+ if make_interception
76
+ klass.class_eval do
77
+ alias_method orig_name, meth_name
78
+ define_method(meth_name) do |*args|
79
+ method_chain[:before].each { |m| m.call(self, args) }
80
+ # The result of the callcc block will either be the last line in the actual
81
+ # ruby block, or it will be whatever is passed as arguments when calling the
82
+ # +abort_continuation+ proc
83
+ callcc do |abort_continuation|
84
+ # First lambda in chain is the call to the original method
85
+ call_lambda = lambda { send(orig_name, *args) }
86
+ method_chain[:around].each do |m|
87
+ # Make a chain of lambdas that calls the previouly defined
88
+ # lambda, thus creating a chain of around blocks that will
89
+ # all finally reach the original method block
90
+ prev_call_lambda = call_lambda
91
+ call_lambda = lambda {
92
+ # If +prev_call_lambda+ is called, the next around block in
93
+ # chain until the last one which corresponds to the original method call
94
+ # if +abort_continuation+ is called, then this loop is aborted and the
95
+ # callcc block returns whatever was passed as an argument to the proc call
96
+ m.call(self, args, prev_call_lambda, abort_continuation)
97
+ }
98
+ end
99
+ result = call_lambda.call
100
+ method_chain[:after].each { |m| m.call(self, result, args) }
101
+ result
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll_ext
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Raoul Felix
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-21 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mg
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: " jekyll_ext allows you to extend the Jekyll static blog generator without forking\n and modifying it's codebase. With this code, not only do your extensions live in\n your blog directory, but they can also be shared and reutilized.\n"
36
+ email: gems@rfelix.com
37
+ executables:
38
+ - ejekyll
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/aop.rb
45
+ - bin/ejekyll
46
+ - Rakefile
47
+ - README.textile
48
+ has_rdoc: true
49
+ homepage: http://rfelix.com/2010/01/19/jekyll-extensions-minus-equal-pain/
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.7
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Create Jekyll extensions that are local to your blog and that can be shared with others
82
+ test_files: []
83
+