merb_comatose 0.0.2
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/LICENSE +20 -0
- data/README +4 -0
- data/Rakefile +52 -0
- data/TODO +5 -0
- data/lib/class_options.rb +36 -0
- data/lib/comatose/comatose_drop.rb +64 -0
- data/lib/comatose/configuration.rb +69 -0
- data/lib/comatose/page_wrapper.rb +119 -0
- data/lib/comatose/processing_context.rb +69 -0
- data/lib/comatose/version.rb +4 -0
- data/lib/liquid/block.rb +96 -0
- data/lib/liquid/context.rb +190 -0
- data/lib/liquid/document.rb +17 -0
- data/lib/liquid/drop.rb +48 -0
- data/lib/liquid/errors.rb +7 -0
- data/lib/liquid/extensions.rb +53 -0
- data/lib/liquid/file_system.rb +62 -0
- data/lib/liquid/htmltags.rb +64 -0
- data/lib/liquid/standardfilters.rb +111 -0
- data/lib/liquid/standardtags.rb +399 -0
- data/lib/liquid/strainer.rb +42 -0
- data/lib/liquid/tag.rb +25 -0
- data/lib/liquid/template.rb +88 -0
- data/lib/liquid/variable.rb +39 -0
- data/lib/liquid.rb +52 -0
- data/lib/merb_comatose/merbtasks.rb +6 -0
- data/lib/merb_comatose.rb +30 -0
- data/lib/redcloth.rb +1129 -0
- data/lib/support/class_options.rb +36 -0
- data/lib/text_filters/markdown.rb +14 -0
- data/lib/text_filters/markdown_smartypants.rb +15 -0
- data/lib/text_filters/none.rb +8 -0
- data/lib/text_filters/rdoc.rb +13 -0
- data/lib/text_filters/simple.rb +8 -0
- data/lib/text_filters/textile.rb +15 -0
- data/lib/text_filters.rb +138 -0
- data/spec/merb_comatose_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +97 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 YOUR NAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
require 'merb-core'
|
5
|
+
require 'merb-core/tasks/merb'
|
6
|
+
|
7
|
+
GEM_NAME = "merb_comatose"
|
8
|
+
GEM_VERSION = "0.0.2"
|
9
|
+
AUTHOR = "Jacques Crocker"
|
10
|
+
EMAIL = "merbjedi@gmail.com"
|
11
|
+
HOMEPAGE = "http://merbjedi.com/"
|
12
|
+
SUMMARY = "Partial Port of Comatose with focus on rendering from Comatose Pages (no admin yet)"
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.rubyforge_project = 'merb'
|
16
|
+
s.name = GEM_NAME
|
17
|
+
s.version = GEM_VERSION
|
18
|
+
s.platform = Gem::Platform::RUBY
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
21
|
+
s.summary = SUMMARY
|
22
|
+
s.description = s.summary
|
23
|
+
s.author = AUTHOR
|
24
|
+
s.email = EMAIL
|
25
|
+
s.homepage = HOMEPAGE
|
26
|
+
|
27
|
+
# s.add_dependency('merb', '>= 1.0')
|
28
|
+
|
29
|
+
s.require_path = 'lib'
|
30
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
|
31
|
+
end
|
32
|
+
|
33
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
34
|
+
pkg.gem_spec = spec
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "install the plugin as a gem"
|
38
|
+
task :install do
|
39
|
+
Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Uninstall the gem"
|
43
|
+
task :uninstall do
|
44
|
+
Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Create a gemspec file"
|
48
|
+
task :gemspec do
|
49
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
50
|
+
file.puts spec.to_ruby
|
51
|
+
end
|
52
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
class Class
|
2
|
+
def define_option(name, default=nil)
|
3
|
+
sym = name.to_sym
|
4
|
+
cattr_reader(sym)
|
5
|
+
cattr_writer(sym)
|
6
|
+
send("#{name.to_s}=", default)
|
7
|
+
end
|
8
|
+
|
9
|
+
def blockable_attr_accessor(sym)
|
10
|
+
module_eval(<<-EVAL, __FILE__, __LINE__)
|
11
|
+
def #{sym}(&block)
|
12
|
+
if block_given?
|
13
|
+
@#{sym} = block
|
14
|
+
else
|
15
|
+
@#{sym}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def #{sym}=(value)
|
19
|
+
@#{sym} = value
|
20
|
+
end
|
21
|
+
EVAL
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Module
|
26
|
+
def attr_accessor_with_default(sym, default = nil, &block)
|
27
|
+
raise 'Default value or block required' unless !default.nil? || block
|
28
|
+
define_method(sym, block_given? ? block : Proc.new { default })
|
29
|
+
module_eval(<<-EVAL, __FILE__, __LINE__)
|
30
|
+
def #{sym}=(value)
|
31
|
+
class << self; attr_reader :#{sym} end
|
32
|
+
@#{sym} = value
|
33
|
+
end
|
34
|
+
EVAL
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Comatose
|
2
|
+
|
3
|
+
class ComatoseDrop < ::Liquid::Drop
|
4
|
+
|
5
|
+
private :initialize
|
6
|
+
|
7
|
+
def before_method(method)
|
8
|
+
self.send(method.to_sym)
|
9
|
+
rescue
|
10
|
+
ComatoseController.logger.debug "Error calling #{method}: #{$!}"
|
11
|
+
raise $!
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# Define a new ComatoseDrop by name
|
16
|
+
def define( name, &block )
|
17
|
+
d = ComatoseDrop.new
|
18
|
+
d.instance_eval(&block)
|
19
|
+
Comatose.registered_drops[name] = d
|
20
|
+
rescue
|
21
|
+
ComatoseController.logger.debug "Drop '#{name}' was not included: #{$!}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
|
28
|
+
# Returns/initializes a hash for storing ComatoseDrops
|
29
|
+
def registered_drops
|
30
|
+
@registered_drops ||= {}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Simple wrapper around the ProcessingContext.define method
|
34
|
+
# I think Comatose.define_drop is probably simpler to remember too
|
35
|
+
def define_drop(name, &block)
|
36
|
+
ComatoseDrop.define(name, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Registers a 'filter' for Liquid use
|
40
|
+
def register_filter(module_name)
|
41
|
+
Liquid::Template.register_filter(module_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
#
|
49
|
+
# Some Default Filters/Drops
|
50
|
+
#
|
51
|
+
|
52
|
+
module IncludeFilter
|
53
|
+
def include(input)
|
54
|
+
page = ComatosePage.find_by_path(input)
|
55
|
+
params = @context['params']
|
56
|
+
# TODO: Add more of the context into the included page's context...
|
57
|
+
page.to_html( { 'params' => params } )
|
58
|
+
rescue
|
59
|
+
"Page at <tt>#{input}</tt> could not be found. <pre>#{$!}</pre>"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Comatose.register_filter IncludeFilter
|
64
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Comatose
|
2
|
+
|
3
|
+
def self.config
|
4
|
+
@@config ||= Configuration.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.configure(&block)
|
8
|
+
raise "#configure must be sent a block" unless block_given?
|
9
|
+
yield config
|
10
|
+
config.validate!
|
11
|
+
end
|
12
|
+
|
13
|
+
# All of the 'mount' points for Comatose
|
14
|
+
def self.mount_points
|
15
|
+
@@mount_points ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
# Adds a 'mount' point to the list of known roots...
|
19
|
+
def self.add_mount_point(path, info={:index=>''})
|
20
|
+
path = "/#{path}" unless path.starts_with? '/'
|
21
|
+
info[:root]=path
|
22
|
+
mount_points << info
|
23
|
+
end
|
24
|
+
|
25
|
+
class Configuration
|
26
|
+
|
27
|
+
attr_accessor_with_default :admin_title, 'Comatose'
|
28
|
+
attr_accessor_with_default :admin_includes, []
|
29
|
+
attr_accessor_with_default :admin_helpers, []
|
30
|
+
attr_accessor_with_default :admin_sub_title, 'The Micro CMS'
|
31
|
+
attr_accessor_with_default :content_type, 'utf-8'
|
32
|
+
attr_accessor_with_default :default_filter, '[No Filter]'
|
33
|
+
attr_accessor_with_default :default_processor, :liquid
|
34
|
+
attr_accessor_with_default :default_tree_level, 2
|
35
|
+
attr_accessor_with_default :disable_caching, false
|
36
|
+
attr_accessor_with_default :hidden_meta_fields, []
|
37
|
+
attr_accessor_with_default :helpers, []
|
38
|
+
attr_accessor_with_default :includes, []
|
39
|
+
attr_accessor_with_default :allow_import_export, true
|
40
|
+
|
41
|
+
# 'Blockable' setters
|
42
|
+
blockable_attr_accessor :authorization
|
43
|
+
blockable_attr_accessor :admin_authorization
|
44
|
+
blockable_attr_accessor :admin_get_author
|
45
|
+
blockable_attr_accessor :admin_get_root_page
|
46
|
+
blockable_attr_accessor :after_setup
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
# Default procs for blockable attrs....
|
50
|
+
@authorization = Proc.new { true }
|
51
|
+
@admin_authorization = Proc.new { true }
|
52
|
+
@admin_get_author = Proc.new { request.env['REMOTE_ADDR'] }
|
53
|
+
@admin_get_root_page = Proc.new { ComatosePage.root }
|
54
|
+
@after_setup = Proc.new { true }
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate!
|
58
|
+
# Rips through the config and validates it's, er, valid
|
59
|
+
raise ConfigurationError.new( "admin_get_author must be a Proc or Symbol" ) unless @admin_get_author.is_a? Proc or @admin_get_author.is_a? Symbol
|
60
|
+
raise ConfigurationError.new( "admin_authorization must be a Proc or Symbol" ) unless @admin_authorization.is_a? Proc or @admin_authorization.is_a? Symbol
|
61
|
+
raise ConfigurationError.new( "authorization must be a Proc or Symbol" ) unless @authorization.is_a? Proc or @authorization.is_a? Symbol
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
class ConfigurationError < StandardError; end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Giving direct access to the AR model is disconcerting, so this wraps the AR
|
2
|
+
# Model to prevent access to certain, destructive behavior
|
3
|
+
class Comatose::PageWrapper
|
4
|
+
|
5
|
+
@@allowed_methods = %w(id full_path uri slug keywords title to_html filter_type author updated_on created_on)
|
6
|
+
@@custom_methods = %w(link content parent next previous children rchildren first_child last_child has_keyword)
|
7
|
+
|
8
|
+
attr_accessor :page
|
9
|
+
private :page
|
10
|
+
|
11
|
+
def initialize( page, locals={} )
|
12
|
+
@page = page
|
13
|
+
@keyword_lst = []
|
14
|
+
@keyword_hsh = {}
|
15
|
+
unless page.nil?
|
16
|
+
@keyword_lst = (page.keywords || '').downcase.split(',').map {|k| k.strip }
|
17
|
+
@keyword_lst.each {|kw| @keyword_hsh[kw] = true}
|
18
|
+
end
|
19
|
+
@locals = locals
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_keyword?(keyword)
|
23
|
+
@page.has_keyword?(keyword)
|
24
|
+
end
|
25
|
+
|
26
|
+
def has_keyword
|
27
|
+
@keyword_hsh
|
28
|
+
end
|
29
|
+
|
30
|
+
def next
|
31
|
+
@next_page ||= begin
|
32
|
+
if @page.lower_item.nil?
|
33
|
+
nil
|
34
|
+
else
|
35
|
+
Comatose::PageWrapper.new( @page.lower_item )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def previous
|
41
|
+
@prev_page ||= begin
|
42
|
+
if @page.higher_item.nil?
|
43
|
+
nil
|
44
|
+
else
|
45
|
+
Comatose::PageWrapper.new( @page.higher_item )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def first_child
|
51
|
+
children.first
|
52
|
+
end
|
53
|
+
|
54
|
+
def def last_child
|
55
|
+
children.last
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generates a link to this page... You can pass in the link text,
|
59
|
+
# otherwise it will default to the page title.
|
60
|
+
def link( title=nil )
|
61
|
+
title = @page.title if title.nil?
|
62
|
+
TextFilters[@page.filter_type].create_link(title, @page.uri)
|
63
|
+
end
|
64
|
+
|
65
|
+
def content
|
66
|
+
@page.to_html( @locals )
|
67
|
+
end
|
68
|
+
|
69
|
+
def parent
|
70
|
+
@parent ||= begin
|
71
|
+
if @page.parent.nil?
|
72
|
+
nil
|
73
|
+
else
|
74
|
+
Comatose::PageWrapper.new( @page.parent )
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def children
|
80
|
+
# Cache the results so that you can have multiple calls to #children without a penalty
|
81
|
+
@children ||= @page.children.to_a.collect {|child| Comatose::PageWrapper.new( child, @locals )}
|
82
|
+
end
|
83
|
+
|
84
|
+
# Children, in reverse order
|
85
|
+
def rchildren
|
86
|
+
children.reverse
|
87
|
+
end
|
88
|
+
|
89
|
+
def [](key)
|
90
|
+
if @@allowed_methods.include? key.to_s #or page.attributes.has_key? key.to_s
|
91
|
+
page.send( key )
|
92
|
+
elsif @@custom_methods.include? key
|
93
|
+
self.send(key.to_sym)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def has_key?(key)
|
98
|
+
@@allowed_methods.include? key or @@custom_methods.include? key
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
@page.title
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_liquid
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
def method_missing(method_id, *args)
|
110
|
+
#STDERR.puts "Looking for method: #{method_id} (#{method_id.class.to_s}) in [#{@@allowed_methods.join(', ')}] or [#{page.attributes.keys.join(', ')}]"
|
111
|
+
if @@allowed_methods.include? method_id.to_s or page.attributes.has_key? method_id.to_s
|
112
|
+
page.send( method_id, *args)
|
113
|
+
else
|
114
|
+
# Access nazi says: NO ACCESS FOR YOU!!
|
115
|
+
# but he says it silently...
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# This is the rendering context object you have access to in text processing...
|
2
|
+
class Comatose::ProcessingContext
|
3
|
+
@@supported_methods = %w(page include)
|
4
|
+
|
5
|
+
def initialize( page, locals={} )
|
6
|
+
@locals = locals.stringify_keys if locals.respond_to? :stringify_keys
|
7
|
+
@page = Comatose::PageWrapper.new(page, @locals)
|
8
|
+
end
|
9
|
+
|
10
|
+
def page
|
11
|
+
@page
|
12
|
+
end
|
13
|
+
|
14
|
+
def include(path, locals={})
|
15
|
+
begin
|
16
|
+
page = ComatosePage.find_by_path(path)
|
17
|
+
page.to_html( @locals.merge(locals) )
|
18
|
+
rescue
|
19
|
+
"<p>Page at <tt>#{path}</tt> could not be found.</p>"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_by_path(path)
|
24
|
+
begin
|
25
|
+
page = ComatosePage.find_by_path(path)
|
26
|
+
Comatose::PageWrapper.new(page, @locals)
|
27
|
+
rescue
|
28
|
+
"<p>Page at <tt>#{path}</tt> could not be found.</p>"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
if key.to_s.downcase == 'page'
|
34
|
+
@page
|
35
|
+
elsif @locals.has_key? key
|
36
|
+
@locals[key]
|
37
|
+
elsif Comatose.registered_drops.has_key? key
|
38
|
+
Comatose.registered_drops[key]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_key?(key)
|
43
|
+
@@supported_methods.include?(key) or @locals.has_key?(key) or Comatose.registered_drops.has_key?(key)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_liquid
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_binding
|
51
|
+
binding
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing(method_id, *args)
|
55
|
+
method_name = method_id.to_s
|
56
|
+
if @locals.has_key? method_name
|
57
|
+
@locals[method_name]
|
58
|
+
elsif Comatose.registered_drops.has_key? method_name
|
59
|
+
Comatose.registered_drops[method_name].context = self
|
60
|
+
Comatose.registered_drops[method_name]
|
61
|
+
else
|
62
|
+
"<!-- ProcessingContext: Couldn't find #{method_id} -->"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
|
data/lib/liquid/block.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Liquid
|
2
|
+
|
3
|
+
class Block < Tag
|
4
|
+
def parse(tokens)
|
5
|
+
@nodelist ||= []
|
6
|
+
@nodelist.clear
|
7
|
+
|
8
|
+
while token = tokens.shift
|
9
|
+
|
10
|
+
case token
|
11
|
+
when /^#{TagStart}/
|
12
|
+
if token =~ /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/
|
13
|
+
|
14
|
+
# if we found the proper block delimitor just end parsing here and let the outer block
|
15
|
+
# proceed
|
16
|
+
if block_delimiter == $1
|
17
|
+
end_tag
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
# fetch the tag from registered blocks
|
22
|
+
if tag = Template.tags[$1]
|
23
|
+
@nodelist << tag.new($2, tokens)
|
24
|
+
else
|
25
|
+
# this tag is not registered with the system
|
26
|
+
# pass it to the current block for special handling or error reporting
|
27
|
+
unknown_tag($1, $2, tokens)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} "
|
31
|
+
end
|
32
|
+
when /^#{VariableStart}/
|
33
|
+
@nodelist << create_variable(token)
|
34
|
+
when ''
|
35
|
+
# pass
|
36
|
+
else
|
37
|
+
@nodelist << token
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Make sure that its ok to end parsing in the current block.
|
42
|
+
# Effectively this method will throw and exception unless the current block is
|
43
|
+
# of type Document
|
44
|
+
assert_missing_delimitation!
|
45
|
+
end
|
46
|
+
|
47
|
+
def end_tag
|
48
|
+
end
|
49
|
+
|
50
|
+
def unknown_tag(tag, params, tokens)
|
51
|
+
case tag
|
52
|
+
when 'else'
|
53
|
+
raise SyntaxError, "#{block_name} tag does not expect else tag"
|
54
|
+
when 'end'
|
55
|
+
raise SyntaxError, "'end' is not a valid delimiter for #{block_name} tags. use #{block_delimiter}"
|
56
|
+
else
|
57
|
+
raise SyntaxError, "Unknown tag '#{tag}'"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def block_delimiter
|
62
|
+
"end#{block_name}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def block_name
|
66
|
+
self.class.name.scan(/\w+$/).first.downcase
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_variable(token)
|
70
|
+
token.scan(/^#{VariableStart}(.*)#{VariableEnd}$/) do |content|
|
71
|
+
return Variable.new(content.first)
|
72
|
+
end
|
73
|
+
raise SyntaxError.new("Variable '#{token}' was not properly terminated with regexp: #{VariableEnd.inspect} ")
|
74
|
+
end
|
75
|
+
|
76
|
+
def render(context)
|
77
|
+
render_all(@nodelist, context)
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
|
82
|
+
def assert_missing_delimitation!
|
83
|
+
raise SyntaxError.new("#{block_name} tag was never closed")
|
84
|
+
end
|
85
|
+
|
86
|
+
def render_all(list, context)
|
87
|
+
list.collect do |token|
|
88
|
+
if token.respond_to?(:render)
|
89
|
+
token.render(context)
|
90
|
+
else
|
91
|
+
token.to_s
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|