locomotive_plugins 1.0.0.beta2 → 1.0.0.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md
CHANGED
@@ -39,6 +39,9 @@ different ID, simply supply the ID in the `register_plugin` call:
|
|
39
39
|
|
40
40
|
LocomotivePlugins::register_plugin(BasicAuth, 'auth')
|
41
41
|
|
42
|
+
See the sections below for usage examples. Also, see the
|
43
|
+
[documentation](http://rubydoc.info/github/colibri-software/locomotive_plugins/).
|
44
|
+
|
42
45
|
### Initialization
|
43
46
|
|
44
47
|
To initialize a plugin object, do not override the `initialize` method because
|
@@ -76,6 +79,12 @@ the Locomotive UI.
|
|
76
79
|
|
77
80
|
### Liquid
|
78
81
|
|
82
|
+
Plugins have the ability to add liquid drops, tags, and filters to
|
83
|
+
LocomotiveCMS. These liquid objects will only be accessible to sites which have
|
84
|
+
enabled the plugin. All liquid objects have access to
|
85
|
+
`@context.registers[:plugin_object]` which supplies the plugin object. This
|
86
|
+
gives access to the config hash and other plugin methods.
|
87
|
+
|
79
88
|
#### Drops
|
80
89
|
|
81
90
|
A plugin can add a liquid drop which can be accessed from page templates in
|
@@ -199,13 +208,31 @@ Here's an example of an HTML config file:
|
|
199
208
|
<p class="inline-hints">My Hint</p>
|
200
209
|
</li>
|
201
210
|
<li>
|
202
|
-
<label name="
|
203
|
-
<select name="
|
211
|
+
<label name="content_type_slug">Content Types</label>
|
212
|
+
<select name="content_type_slug" multiple="multiple">
|
204
213
|
{{#each content_types}}
|
205
214
|
<option value="{{ this.slug }}"> {{ this.name }}</option>
|
206
215
|
{{/each}}
|
207
216
|
</select>
|
208
217
|
</li>
|
218
|
+
<li>
|
219
|
+
<label name="do_awesome_thing">Do the awesome thing?</label>
|
220
|
+
<input type="checkbox" name="do_awesome_thing">
|
221
|
+
</li>
|
222
|
+
|
223
|
+
The values of the input fields in this form will be put into the plugin
|
224
|
+
object's config hash. Any input coming from a checkbox field will be saved as a
|
225
|
+
boolean value, and other input fields will be saved as strings. The keys for
|
226
|
+
the hash are taken from the `name` attribute of each input field. So, if in the
|
227
|
+
previous example, the "My Plugin Config" field is filled with "Config Value", a
|
228
|
+
content type with slug "my\_content\_type" is selected, and the checkbox is
|
229
|
+
checked, the config hash will be as follows:
|
230
|
+
|
231
|
+
{
|
232
|
+
"my_plugin_config" => "Config Value",
|
233
|
+
"content_type_slug" => "my_content_type",
|
234
|
+
"do_awesome_thing" => true
|
235
|
+
}
|
209
236
|
|
210
237
|
### Database Models
|
211
238
|
|
@@ -24,7 +24,7 @@ module Locomotive
|
|
24
24
|
# normally
|
25
25
|
def prefixed_liquid_tags(prefix)
|
26
26
|
self.liquid_tags.inject({}) do |hash, (tag_name, tag_class)|
|
27
|
-
hash["#{prefix}_#{tag_name}"] = tag_subclass(tag_class)
|
27
|
+
hash["#{prefix}_#{tag_name}"] = tag_subclass(prefix, tag_class)
|
28
28
|
hash
|
29
29
|
end
|
30
30
|
end
|
@@ -32,10 +32,14 @@ module Locomotive
|
|
32
32
|
protected
|
33
33
|
|
34
34
|
# Creates a nested subclass to handle rendering this tag
|
35
|
-
def tag_subclass(tag_class)
|
35
|
+
def tag_subclass(prefix, tag_class)
|
36
36
|
tag_class.class_eval <<-CODE
|
37
37
|
class TagSubclass < #{tag_class.to_s}
|
38
38
|
include ::Locomotive::Plugin::TagSubclassMethods
|
39
|
+
|
40
|
+
def self.prefix
|
41
|
+
'#{prefix}'
|
42
|
+
end
|
39
43
|
end
|
40
44
|
CODE
|
41
45
|
tag_class::TagSubclass
|
@@ -46,39 +50,32 @@ module Locomotive
|
|
46
50
|
# Gets the module to include as a filter in liquid. It prefixes the
|
47
51
|
# filter methods with the given string
|
48
52
|
def prefixed_liquid_filter_module(prefix)
|
49
|
-
#
|
50
|
-
|
51
|
-
|
53
|
+
# Create the module to be returned
|
54
|
+
@prefixed_liquid_filter_module = Module.new do
|
55
|
+
include ::Locomotive::Plugin::Liquid::PrefixedFilterModule
|
56
|
+
end
|
52
57
|
|
58
|
+
# Add the prefixed methods to the module
|
53
59
|
raw_filter_modules = [self.class.liquid_filters].flatten.compact
|
54
60
|
raw_filter_modules.each do |mod|
|
55
61
|
mod.public_instance_methods.each do |meth|
|
56
|
-
|
57
|
-
|
58
|
-
self.
|
62
|
+
@prefixed_liquid_filter_module.module_eval do
|
63
|
+
define_method(:"#{prefix}_#{meth}") do |input|
|
64
|
+
self._passthrough_filter_call(prefix, meth, input)
|
59
65
|
end
|
60
|
-
|
66
|
+
end
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
64
|
-
|
70
|
+
# Add a method which returns the modules to include for this prefix
|
71
|
+
@prefixed_liquid_filter_module.module_eval do
|
65
72
|
protected
|
66
73
|
|
67
|
-
|
68
|
-
|
69
|
-
self._build_passthrough_object([#{raw_filter_modules.join(',')}])
|
74
|
+
define_method(:"_modules_for_#{prefix}") do
|
75
|
+
raw_filter_modules
|
70
76
|
end
|
71
|
-
|
72
|
-
def _passthrough_filter_call_for_#{prefix}(meth, input)
|
73
|
-
self._passthrough_object_for_#{prefix}.public_send(meth, input)
|
74
|
-
end
|
75
|
-
CODE
|
76
|
-
|
77
|
-
# Eval the dynamic methods in
|
78
|
-
@prefixed_liquid_filter_module = Module.new do
|
79
|
-
include ::Locomotive::Plugin::Liquid::PrefixedFilterModule
|
80
77
|
end
|
81
|
-
|
78
|
+
|
82
79
|
@prefixed_liquid_filter_module
|
83
80
|
end
|
84
81
|
|
@@ -10,12 +10,51 @@ module Locomotive
|
|
10
10
|
|
11
11
|
protected
|
12
12
|
|
13
|
+
# This method is overridden by LocomotiveCMS to provide custom
|
14
|
+
# functionality when a prefixed method is called
|
15
|
+
def filter_method_called(prefix, meth)
|
16
|
+
end
|
17
|
+
|
13
18
|
def _build_passthrough_object(modules_to_extend)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
19
|
+
obj = ::Liquid::Strainer.new(@context)
|
20
|
+
|
21
|
+
modules_to_extend.each do |mod|
|
22
|
+
obj.extend(mod)
|
23
|
+
end
|
24
|
+
|
25
|
+
obj
|
26
|
+
end
|
27
|
+
|
28
|
+
def _passthrough_object(prefix)
|
29
|
+
@_passthrough_objects ||= {}
|
30
|
+
obj = @_passthrough_objects[prefix]
|
31
|
+
|
32
|
+
# Return it if we have it
|
33
|
+
return obj if obj
|
34
|
+
|
35
|
+
# Otherwise, build it
|
36
|
+
modules_for_prefix_meth = :"_modules_for_#{prefix}"
|
37
|
+
if self.respond_to?(modules_for_prefix_meth)
|
38
|
+
modules = self.__send__(modules_for_prefix_meth)
|
39
|
+
else
|
40
|
+
modules = []
|
41
|
+
end
|
42
|
+
|
43
|
+
@_passthrough_objects[prefix] = self._build_passthrough_object(modules)
|
44
|
+
end
|
45
|
+
|
46
|
+
def _passthrough_filter_call(prefix, meth, input)
|
47
|
+
p = Proc.new do
|
48
|
+
self._passthrough_object(prefix).__send__(meth, input)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Call hook and grab return value if it yields
|
52
|
+
ret = nil
|
53
|
+
self.filter_method_called(prefix, meth) do
|
54
|
+
ret = p.call
|
18
55
|
end
|
56
|
+
|
57
|
+
ret || p.call
|
19
58
|
end
|
20
59
|
|
21
60
|
end
|
@@ -4,18 +4,37 @@ module Locomotive
|
|
4
4
|
module Liquid
|
5
5
|
# @private
|
6
6
|
module TagSubclassMethods
|
7
|
+
|
7
8
|
# Check to see if this tag is enabled in the liquid context and render
|
8
9
|
# accordingly
|
9
10
|
def render(context)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
enabled_tags = context.registers[:enabled_plugin_tags]
|
12
|
+
enabled = enabled_tags && enabled_tags.include?(self.class)
|
13
|
+
|
14
|
+
p = Proc.new do
|
15
|
+
if enabled
|
16
|
+
super
|
17
|
+
elsif self.respond_to?(:render_disabled)
|
18
|
+
self.render_disabled(context)
|
19
|
+
else
|
20
|
+
''
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
ret = nil
|
25
|
+
rendering_tag(self.class.prefix, enabled, context) do
|
26
|
+
ret = p.call
|
17
27
|
end
|
28
|
+
ret || p.call
|
18
29
|
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
# This method is overridden by LocomotiveCMS to provide custom
|
34
|
+
# functionality when the tag is rendering
|
35
|
+
def rendering_tag(prefix, enabled, context)
|
36
|
+
end
|
37
|
+
|
19
38
|
end
|
20
39
|
end
|
21
40
|
end
|
data/lib/version.rb
CHANGED
@@ -7,6 +7,8 @@ module Locomotive
|
|
7
7
|
|
8
8
|
describe '#prefixed_liquid_filter_module' do
|
9
9
|
|
10
|
+
let(:strainer) { ::Liquid::Strainer.new(::Liquid::Context.new) }
|
11
|
+
|
10
12
|
before(:each) do
|
11
13
|
@plugin_with_filter = PluginWithFilter.new({})
|
12
14
|
end
|
@@ -22,10 +24,9 @@ module Locomotive
|
|
22
24
|
end
|
23
25
|
|
24
26
|
it 'the prefixed methods should pass through to the original methods' do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
obj.prefix_add_http('http://google.com').should == 'http://google.com'
|
27
|
+
strainer.extend(@plugin_with_filter.prefixed_liquid_filter_module('prefix'))
|
28
|
+
strainer.prefix_add_http('google.com').should == 'http://google.com'
|
29
|
+
strainer.prefix_add_http('http://google.com').should == 'http://google.com'
|
29
30
|
end
|
30
31
|
|
31
32
|
it 'includes multiple filter modules for one plugin' do
|
@@ -38,13 +39,54 @@ module Locomotive
|
|
38
39
|
it 'works if multiple prefixed modules are mixed into the same object' do
|
39
40
|
@plugin_with_many_filter_modules = PluginWithManyFilterModules.new({})
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
strainer.extend(@plugin_with_filter.prefixed_liquid_filter_module('prefix1'))
|
43
|
+
strainer.extend(@plugin_with_many_filter_modules.prefixed_liquid_filter_module('prefix2'))
|
44
|
+
|
45
|
+
strainer.prefix1_add_http('google.com').should == 'http://google.com'
|
46
|
+
strainer.prefix2_add_newline('google.com').should == "google.com\n"
|
47
|
+
strainer.prefix2_remove_http('http://google.com').should == 'google.com'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should call the filter_method_called hook each time a filter is called' do
|
51
|
+
# Keep track of how many times filter_method_called is called
|
52
|
+
Locomotive::Plugin::Liquid::PrefixedFilterModule.module_eval do
|
53
|
+
attr_reader :count, :prefix, :method
|
54
|
+
|
55
|
+
def filter_method_called(prefix, meth)
|
56
|
+
@count ||= 0
|
57
|
+
@count += 1
|
58
|
+
@prefix = prefix
|
59
|
+
@method = meth
|
60
|
+
yield
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Call filter methods
|
65
|
+
strainer.extend(@plugin_with_filter.prefixed_liquid_filter_module('prefix'))
|
66
|
+
strainer.prefix_add_http('google.com').should == 'http://google.com'
|
67
|
+
strainer.prefix_add_http('http://google.com').should == 'http://google.com'
|
68
|
+
|
69
|
+
# Make sure filter_method_called was called as expected
|
70
|
+
strainer.count.should == 2
|
71
|
+
strainer.prefix.should == 'prefix'
|
72
|
+
strainer.method.should == :add_http
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should give the current liquid context object to the passthrough objects' do
|
76
|
+
Locomotive::Plugin::Liquid::PrefixedFilterModule.module_eval do
|
77
|
+
attr_reader :context
|
78
|
+
def passthrough_objects ; @_passthrough_objects ; end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Extend the module and create the passthrough object
|
82
|
+
strainer.extend(@plugin_with_filter.prefixed_liquid_filter_module('prefix'))
|
83
|
+
strainer.prefix_add_http('google.com').should == 'http://google.com'
|
44
84
|
|
45
|
-
|
46
|
-
obj.
|
47
|
-
obj.
|
85
|
+
# Find the context of the passthrough object
|
86
|
+
obj = strainer.passthrough_objects['prefix']
|
87
|
+
def obj.context ; @context ; end
|
88
|
+
|
89
|
+
obj.context.should == strainer.context
|
48
90
|
end
|
49
91
|
|
50
92
|
end
|
@@ -110,6 +152,37 @@ module Locomotive
|
|
110
152
|
template.render(@context).should == expected_output
|
111
153
|
end
|
112
154
|
|
155
|
+
it 'should call the rendering_tag hook each time a tag is rendered' do
|
156
|
+
TagSubclassMethods.module_eval do
|
157
|
+
def rendering_tag(prefix, enabled, context)
|
158
|
+
context.registers[:rendering_tag][self.class] = {
|
159
|
+
prefix: prefix,
|
160
|
+
enabled: enabled
|
161
|
+
}
|
162
|
+
yield
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
expected_output = <<-TEMPLATE
|
167
|
+
<p>Some Text</p>
|
168
|
+
Some Text
|
169
|
+
TEMPLATE
|
170
|
+
|
171
|
+
@context.registers[:rendering_tag] = {}
|
172
|
+
|
173
|
+
register_tags(@prefixed_tags)
|
174
|
+
@enabled_tags << @prefixed_tags['prefix_paragraph']
|
175
|
+
template = ::Liquid::Template.parse(@raw_template)
|
176
|
+
template.render(@context).should == expected_output
|
177
|
+
|
178
|
+
paragraph_class = ::Locomotive::PluginWithTags::Paragraph::TagSubclass
|
179
|
+
newline_class = ::Locomotive::PluginWithTags::Newline::TagSubclass
|
180
|
+
|
181
|
+
hash = @context.registers[:rendering_tag]
|
182
|
+
hash[paragraph_class].should == { prefix: 'prefix', enabled: true }
|
183
|
+
hash[newline_class].should == { prefix: 'prefix', enabled: false }
|
184
|
+
end
|
185
|
+
|
113
186
|
protected
|
114
187
|
|
115
188
|
def register_tags(tags)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: locomotive_plugins
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta3
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: locomotive_liquid
|