jekyll_ext 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +16 -0
- data/Rakefile +5 -0
- data/bin/ejekyll +34 -0
- data/lib/aop.rb +107 -0
- 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
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
|
+
|