glue 0.31.0 → 0.40.0
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/doc/AUTHORS +1 -1
- data/doc/LICENSE +2 -3
- data/doc/RELEASES +0 -4
- data/lib/glue.rb +3 -3
- data/lib/glue/attribute.rb +114 -0
- data/lib/glue/attributeutils.rb +117 -0
- data/lib/glue/autoreload.rb +0 -4
- data/lib/glue/builder.rb +0 -2
- data/lib/glue/builder/xml.rb +0 -2
- data/lib/glue/cache.rb +3 -5
- data/lib/glue/cache/drb.rb +0 -2
- data/lib/glue/cache/memory.rb +0 -2
- data/lib/glue/cache/og.rb +11 -6
- data/lib/glue/configuration.rb +60 -15
- data/lib/glue/fixture.rb +3 -5
- data/lib/glue/localization.rb +0 -2
- data/lib/glue/logger.rb +1 -2
- data/lib/glue/mail.rb +0 -2
- data/lib/glue/mailer.rb +4 -2
- data/lib/glue/mailer/incoming.rb +0 -2
- data/lib/glue/mailer/outgoing.rb +3 -5
- data/lib/glue/settings.rb +0 -2
- data/lib/glue/uri.rb +0 -2
- data/lib/glue/validation.rb +6 -8
- data/test/glue/builder/tc_xml.rb +3 -2
- data/test/glue/tc_attribute.rb +112 -0
- data/test/glue/{tc_property_mixins.rb → tc_attribute_mixins.rb} +9 -11
- data/test/glue/tc_configuration.rb +1 -1
- data/test/glue/tc_fixture.rb +4 -3
- data/test/glue/tc_logger.rb +2 -2
- data/test/glue/tc_mail.rb +22 -21
- data/test/glue/tc_stores.rb +0 -2
- data/test/glue/tc_uri.rb +12 -12
- data/test/glue/tc_validation.rb +13 -13
- metadata +52 -64
- data/INSTALL +0 -56
- data/ProjectInfo +0 -49
- data/README +0 -21
- data/lib/glue/markup.rb +0 -123
- data/lib/glue/property.rb +0 -290
- data/lib/glue/sanitize.rb +0 -48
- data/lib/glue/template.rb +0 -219
- data/setup.rb +0 -1585
- data/test/glue/tc_property.rb +0 -112
- data/test/glue/tc_property_type_checking.rb +0 -41
- data/test/glue/tc_template.rb +0 -35
data/lib/glue/property.rb
DELETED
@@ -1,290 +0,0 @@
|
|
1
|
-
require 'facet/annotation'
|
2
|
-
require 'facet/inheritor'
|
3
|
-
require 'facet/dictionary'
|
4
|
-
require 'facets/core/module/on_included'
|
5
|
-
require 'facets/more/aspects'
|
6
|
-
|
7
|
-
require 'glue/validation'
|
8
|
-
require 'og/entity'
|
9
|
-
require 'og/relation/all'
|
10
|
-
|
11
|
-
# A convienience structure that holds property
|
12
|
-
# metadata. A property is a special type of class annotation.
|
13
|
-
# Typically used in Og managed classes (ie Entities), but it
|
14
|
-
# is *not* Og specific.
|
15
|
-
#--
|
16
|
-
# TODO: reimplement type checking.
|
17
|
-
# TODO: try to clean this up.
|
18
|
-
#++
|
19
|
-
|
20
|
-
class Property
|
21
|
-
|
22
|
-
# The hash used to store the property options.
|
23
|
-
|
24
|
-
attr_accessor :hash
|
25
|
-
|
26
|
-
def initialize(hash)
|
27
|
-
@hash = hash
|
28
|
-
@hash = @hash.to_h unless @hash.is_a?(Hash)
|
29
|
-
end
|
30
|
-
|
31
|
-
def [](key)
|
32
|
-
@hash[key]
|
33
|
-
end
|
34
|
-
alias_method :method_missing, :[]
|
35
|
-
|
36
|
-
def []=(key, val)
|
37
|
-
@hash[key] = val
|
38
|
-
end
|
39
|
-
|
40
|
-
def <=>(other)
|
41
|
-
@hash[:symbol] <=> other.hash[:symbol]
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_s
|
45
|
-
@hash[:symbol].to_s
|
46
|
-
end
|
47
|
-
alias_method :name, :to_s
|
48
|
-
|
49
|
-
# :section: Property related utils and helpers.
|
50
|
-
|
51
|
-
class << self
|
52
|
-
|
53
|
-
# Populate an object from a hash of values.
|
54
|
-
# This is a truly dangerous method.
|
55
|
-
#
|
56
|
-
# === Options:
|
57
|
-
# * name
|
58
|
-
# * force_boolean
|
59
|
-
|
60
|
-
def populate_object(obj, values, options = {})
|
61
|
-
# If a class is passed create an instance.
|
62
|
-
obj = obj.new if obj.is_a?(Class)
|
63
|
-
|
64
|
-
for prop in obj.class.properties.values
|
65
|
-
|
66
|
-
unless options[:all]
|
67
|
-
next if prop.symbol == obj.class.primary_key.symbol or prop.control == :none or prop.disable_control
|
68
|
-
end
|
69
|
-
|
70
|
-
prop_name = prop.symbol.to_s
|
71
|
-
|
72
|
-
# See if there is an incoming request param for this prop.
|
73
|
-
|
74
|
-
if values.has_key?(prop_name)
|
75
|
-
|
76
|
-
prop_value = values[prop_name]
|
77
|
-
|
78
|
-
# to_s must be called on the prop_value incase the
|
79
|
-
# request is IOString.
|
80
|
-
|
81
|
-
prop_value = prop_value.to_s unless prop_value.is_a?(Hash) or prop_value.is_a?(Array)
|
82
|
-
|
83
|
-
# If property is a Blob dont overwrite current
|
84
|
-
# property's data if "".
|
85
|
-
|
86
|
-
break if prop.klass == Og::Blob and prop_value.empty?
|
87
|
-
|
88
|
-
# If custom preprocessing is active then try and
|
89
|
-
# preprocess.
|
90
|
-
|
91
|
-
prop_value = preprocess_value(obj, prop, prop_value) if options[:preprocess]
|
92
|
-
|
93
|
-
# assign using __force_ methods.
|
94
|
-
obj.send("__force_#{prop_name}", prop_value)
|
95
|
-
|
96
|
-
# Set a boolean property to false if it is not in the request.
|
97
|
-
# requires force_boolean == true.
|
98
|
-
|
99
|
-
elsif options[:force_boolean] and (prop.klass == TrueClass or prop.klass == FalseClass)
|
100
|
-
obj.send("__force_#{prop_name}", 0)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
if options[:assign_relations]
|
105
|
-
for rel in obj.class.relations
|
106
|
-
|
107
|
-
unless options[:all]
|
108
|
-
next if rel.options[:control] == :none or rel.options[:disable_control]
|
109
|
-
end
|
110
|
-
|
111
|
-
rel_name = rel.name.to_s
|
112
|
-
|
113
|
-
# Renew the relations from values
|
114
|
-
|
115
|
-
if rel.kind_of?(Og::RefersTo)
|
116
|
-
if foreign_oid = values[rel_name]
|
117
|
-
foreign_oid = foreign_oid.to_s unless foreign_oid.is_a?(Hash) or foreign_oid.is_a?(Array)
|
118
|
-
foreign_oid = nil if foreign_oid == 'nil' or foreign_oid == 'none'
|
119
|
-
# if custom preprocessing is active then try and preprocess
|
120
|
-
foreign_oid = preprocess_value(obj, rel, foreign_oid) if options[:preprocess]
|
121
|
-
end
|
122
|
-
obj.send("__force_#{rel.foreign_key}", foreign_oid)
|
123
|
-
elsif rel.kind_of?(Og::JoinsMany) || rel.kind_of?(Og::HasMany)
|
124
|
-
collection = obj.send(rel_name)
|
125
|
-
collection.remove_all
|
126
|
-
if values.has_key?(rel_name)
|
127
|
-
primary_keys = values[rel_name]
|
128
|
-
|
129
|
-
# if custom preprocessing is active then try and preprocess
|
130
|
-
primary_keys = preprocess_value(obj, rel, primary_keys) if options[:preprocess]
|
131
|
-
|
132
|
-
primary_keys.each do |v|
|
133
|
-
next if v.to_s == "nil" or v.to_s == "none"
|
134
|
-
collection << rel.target_class[v.to_s.to_i]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
#--
|
142
|
-
# gmosx, FIXME: this is a hack, will be replaced with proper
|
143
|
-
# code soon.
|
144
|
-
#++
|
145
|
-
|
146
|
-
for callback in obj.class.assign_callbacks
|
147
|
-
callback.call(obj, values, options)
|
148
|
-
end if obj.class.respond_to?(:assign_callbacks)
|
149
|
-
|
150
|
-
return obj
|
151
|
-
end
|
152
|
-
|
153
|
-
# This method will attempt to process [value] through the
|
154
|
-
# any on_populate preprocessors available.
|
155
|
-
#
|
156
|
-
# first looks if a method was specified on the property
|
157
|
-
#
|
158
|
-
# ie. property :this, String, :on_populate => :change_value
|
159
|
-
# ==> would mean #change_value(val) would get called
|
160
|
-
# TODO: set :on_populate to false to exclude it from any preprocessing
|
161
|
-
#
|
162
|
-
# next an #on_populate method will be looked for on any
|
163
|
-
# associated Nitro::Control (if controls is running)
|
164
|
-
#
|
165
|
-
# otherwise [value] is left untouched
|
166
|
-
|
167
|
-
def preprocess_value(obj, prop_or_rel, value)
|
168
|
-
if prop_or_rel.on_populate && obj.respond_to?(prop_or_rel.on_populate.to_sym)
|
169
|
-
return obj.send(prop_or_rel.on_populate.to_sym, value)
|
170
|
-
elsif Object.const_defined? :Nitro
|
171
|
-
if control = Nitro::Form::Control.fetch(obj, prop_or_rel, :default => nil) and control.respond_to?(:on_populate)
|
172
|
-
return control.on_populate(value)
|
173
|
-
end
|
174
|
-
else
|
175
|
-
return value
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
def eval_helpers(writer, m, sym, klass)
|
180
|
-
return unless writer
|
181
|
-
|
182
|
-
code = %{
|
183
|
-
def __force_#{sym}(val)
|
184
|
-
if respond_to?(:force_#{sym})
|
185
|
-
self.#{sym} = force_#{sym}(val)
|
186
|
-
else
|
187
|
-
self.#{sym}=(} << case klass.name
|
188
|
-
when Fixnum.name: 'val.to_s.empty? ? nil : val.to_i'
|
189
|
-
when String.name: 'val.to_s'
|
190
|
-
when Float.name: 'val.to_f'
|
191
|
-
when Time.name: 'val.is_a?(Hash) ? Time.local(val["year"],val["month"],val["day"],val["hour"],val["min"]) : Time.parse(val.to_s)'
|
192
|
-
when Date.name: 'val.is_a?(Hash) ? Time.local(val["year"],val["month"],val["day"]).to_date : Time.parse(val.to_s).to_date'
|
193
|
-
when TrueClass.name, FalseClass.name: 'val == "on" or val == "true" ? true: val.to_i > 0'
|
194
|
-
else 'val'
|
195
|
-
end + %{)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
}
|
199
|
-
|
200
|
-
m.module_eval(code)
|
201
|
-
end
|
202
|
-
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
#--
|
207
|
-
# Extend the default Module.
|
208
|
-
#
|
209
|
-
# The properties hash, keeps the property metadata as a hash to avoid
|
210
|
-
# the null issue.
|
211
|
-
#++
|
212
|
-
|
213
|
-
class Module
|
214
|
-
[ nil, :_reader, :_writer, :_accessor].each do |m|
|
215
|
-
writer = (m != :reader)
|
216
|
-
code = %{
|
217
|
-
def prop#{m} (*args)
|
218
|
-
inheritor(:properties, Dictionary.new, :merge) unless @properties
|
219
|
-
|
220
|
-
args = args.flatten
|
221
|
-
harg = {}
|
222
|
-
while args.last.is_a?(Hash)
|
223
|
-
harg.update(args.pop)
|
224
|
-
end
|
225
|
-
|
226
|
-
harg[:klass] = args.pop if args.last.is_a?(Class)
|
227
|
-
klass = harg[:klass] ||= String
|
228
|
-
|
229
|
-
raise if args.empty? and harg.empty?
|
230
|
-
|
231
|
-
# If the class defines the include_as_property callback
|
232
|
-
# call to modify the base with custom code.
|
233
|
-
|
234
|
-
skip = false
|
235
|
-
|
236
|
-
if klass.respond_to? :included_as_property
|
237
|
-
skip = klass.included_as_property(self, args, harg)
|
238
|
-
end
|
239
|
-
|
240
|
-
unless skip
|
241
|
-
if !args.empty?
|
242
|
-
undef_keys = args.select{ |a| !method_defined?(a) }
|
243
|
-
unless undef_keys.empty?
|
244
|
-
attr#{m} *undef_keys
|
245
|
-
end
|
246
|
-
args.each { |a|
|
247
|
-
a = a.to_sym
|
248
|
-
an = define_annotation(a, harg)
|
249
|
-
ah = an.to_h.merge(:symbol => a)
|
250
|
-
# gmosx: allow for duplicate declarations.
|
251
|
-
properties![a] = Property.new(ah)
|
252
|
-
Property.eval_helpers(#{writer}, self, a, harg[:klass])
|
253
|
-
}
|
254
|
-
else
|
255
|
-
undef_keys = harg.keys.select{ |a| !method_defined?(a) }
|
256
|
-
attribute#{m} *undef_keys
|
257
|
-
harg.each { |a,h|
|
258
|
-
a = a.to_sym
|
259
|
-
an = define_annotation(a, h)
|
260
|
-
ah = an.to_h.merge(:symbol => a)
|
261
|
-
# gmosx: allow for property redefinitions.
|
262
|
-
properties![a] = Property.new(ah)
|
263
|
-
Property.eval_helpers(#{writer}, self, a, harg[:klass])
|
264
|
-
}
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
Module.__add_prop_hook__(self)
|
269
|
-
end
|
270
|
-
}
|
271
|
-
|
272
|
-
module_eval(code)
|
273
|
-
end
|
274
|
-
alias :property :prop_accessor
|
275
|
-
|
276
|
-
# NITRO specific!! leave blank in facets.
|
277
|
-
# TODO: factor in eval_helpers into the hook!
|
278
|
-
|
279
|
-
def self.__add_prop_hook__(m)
|
280
|
-
m.send(:include, Og::EntityMixin) unless m.ancestors.include?(Og::EntityMixin)
|
281
|
-
m.send(:include, Glue::Validation) unless m.ancestors.include?(Glue::Validation)
|
282
|
-
m.send(:include, ::Aspects) unless m.ancestors.include?(::Aspects)
|
283
|
-
end
|
284
|
-
|
285
|
-
end
|
286
|
-
|
287
|
-
# * George Moschovitis <gm@navel.gr>
|
288
|
-
# * Tom Sawyer <transfire@gmail.com>
|
289
|
-
# * Chris Farmiloe <chris.farmiloe@farmiloe.com>
|
290
|
-
# * Bryan Soto <bryan.a.soto@gmail.com>
|
data/lib/glue/sanitize.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# Code from rubyonrails project (http://www.rubyonrails.com)
|
2
|
-
# Temporarily here.
|
3
|
-
|
4
|
-
require 'html/tokenizer'
|
5
|
-
require 'html/node'
|
6
|
-
|
7
|
-
VERBOTEN_TAGS = %w(form script) unless defined?(VERBOTEN_TAGS)
|
8
|
-
VERBOTEN_ATTRS = /^on/i unless defined?(VERBOTEN_ATTRS)
|
9
|
-
|
10
|
-
class String
|
11
|
-
# Sanitizes the given HTML by making form and script tags into regular
|
12
|
-
# text, and removing all "onxxx" attributes (so that arbitrary Javascript
|
13
|
-
# cannot be executed). Also removes href attributes that start with
|
14
|
-
# "javascript:".
|
15
|
-
#
|
16
|
-
# Returns the sanitized text.
|
17
|
-
def self.sanitize(html)
|
18
|
-
# only do this if absolutely necessary
|
19
|
-
if html.index("<")
|
20
|
-
tokenizer = HTML::Tokenizer.new(html)
|
21
|
-
new_text = ""
|
22
|
-
|
23
|
-
while token = tokenizer.next
|
24
|
-
node = HTML::Node.parse(nil, 0, 0, token, false)
|
25
|
-
new_text << case node
|
26
|
-
when HTML::Tag
|
27
|
-
if VERBOTEN_TAGS.include?(node.name)
|
28
|
-
node.to_s.gsub(/</, "<")
|
29
|
-
else
|
30
|
-
if node.closing != :close
|
31
|
-
node.attributes.delete_if { |attr,v| attr =~ VERBOTEN_ATTRS }
|
32
|
-
if node.attributes["href"] =~ /^javascript:/i
|
33
|
-
node.attributes.delete "href"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
node.to_s
|
37
|
-
end
|
38
|
-
else
|
39
|
-
node.to_s.gsub(/</, "<")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
html = new_text
|
44
|
-
end
|
45
|
-
|
46
|
-
html
|
47
|
-
end
|
48
|
-
end
|
data/lib/glue/template.rb
DELETED
@@ -1,219 +0,0 @@
|
|
1
|
-
require 'facets/more/openobject'
|
2
|
-
require 'glue/configuration'
|
3
|
-
|
4
|
-
module Glue
|
5
|
-
|
6
|
-
# A template is a text file with embeded Ruby code. The template
|
7
|
-
# processor converts the original text file to ruby code and
|
8
|
-
# then evaluates this code to produce the result of the
|
9
|
-
# template transformation.
|
10
|
-
|
11
|
-
module TemplateMixin
|
12
|
-
|
13
|
-
# Convert a template to actual Ruby code, ready to be
|
14
|
-
# evaluated.
|
15
|
-
#
|
16
|
-
# [+template+]
|
17
|
-
# The template as a String.
|
18
|
-
#
|
19
|
-
# [+buffer+]
|
20
|
-
# The variable to act as a buffer where the ruby code
|
21
|
-
# for this template will be generated. Passed as a
|
22
|
-
# String.
|
23
|
-
#
|
24
|
-
# [+base_dir+]
|
25
|
-
# The base directory where the templates reside.
|
26
|
-
|
27
|
-
def compile_template(template, buffer = '@out', base_dir = Dir.pwd)
|
28
|
-
text = template.dup
|
29
|
-
|
30
|
-
# Strip the xml header! (interracts with the following gsub!)
|
31
|
-
text.gsub!(/<\?xml.*\?>/, "")
|
32
|
-
|
33
|
-
# Statically include sub-template files.
|
34
|
-
# The target file is included at compile time.
|
35
|
-
#
|
36
|
-
# gmosx: must be xformed before the <?r pi.
|
37
|
-
#
|
38
|
-
# Example:
|
39
|
-
# <?include href="root/myfile.sx" ?>
|
40
|
-
|
41
|
-
text.gsub!(/<\?include href=["|'](.*?)["|'](.*)\?>/) do |match|
|
42
|
-
itext = File.read("#{base_dir}/#$1")
|
43
|
-
itext.gsub!(/<\?xml.*\?>/, '')
|
44
|
-
itext.gsub!(/<\/?root(.*?)>/m, ' ');
|
45
|
-
itext
|
46
|
-
end
|
47
|
-
|
48
|
-
# Transform include instructions <include href="xxx" />
|
49
|
-
# must be transformed before the processinc instructions.
|
50
|
-
# Useful to include fragments cached on disk
|
51
|
-
#
|
52
|
-
# gmosx, FIXME: NOT TESTED! test and add caching.
|
53
|
-
# add load_statically_included fixes.
|
54
|
-
|
55
|
-
text.gsub!(/<include href=["|'](.*?)["|'](.*)(.?)\/>/) do |match|
|
56
|
-
"<?r File.read( '\#{@dispatcher.root}/#$1' ?>"
|
57
|
-
end
|
58
|
-
|
59
|
-
# xform render/inject instructions <render href="xxx" />
|
60
|
-
# must be transformed before the processinc instructions.
|
61
|
-
|
62
|
-
text.gsub!(/<(render|inject) href=["|'](.*?)["|'](.*)(.?)\/>/) do |match|
|
63
|
-
"<?r render '#$2' ?>"
|
64
|
-
end
|
65
|
-
|
66
|
-
# Remove <root> elements. typically removed by xslt but lets
|
67
|
-
# play it safe. The <root> element is typically added to
|
68
|
-
# template files to make them XHTML valid.
|
69
|
-
|
70
|
-
text.gsub!(/<(\/)?root>/, '')
|
71
|
-
|
72
|
-
# Transform the processing instructions, use <?r as
|
73
|
-
# a marker.
|
74
|
-
|
75
|
-
text.gsub!(/\?>/, "; #{buffer} << %^")
|
76
|
-
text.gsub!(/<\?r(\s?)/, "^; ")
|
77
|
-
|
78
|
-
# Transform alternative code tags.
|
79
|
-
# (very useful in xsl stylesheets)
|
80
|
-
|
81
|
-
text.gsub!(/<\/ruby>/, "; #{buffer} << %^")
|
82
|
-
text.gsub!(/<ruby>/, "^; ")
|
83
|
-
|
84
|
-
# Also handle erb/asp/jsp style tags. Those tags
|
85
|
-
# *cannot* be used with an xslt stylesheet.
|
86
|
-
|
87
|
-
text.gsub!(/%>/, "; #{buffer} << %^")
|
88
|
-
text.gsub!(/<%/, "^; ")
|
89
|
-
|
90
|
-
# Alterative versions of interpolation.
|
91
|
-
# (very useful in xsl stylesheets)
|
92
|
-
# Example: #\my_val\
|
93
|
-
|
94
|
-
text.gsub!(/\#\\(.*?)\\/, '#{\1}')
|
95
|
-
|
96
|
-
# Alternative for entities.
|
97
|
-
# (useful in xsl stylesheets)
|
98
|
-
# Examples: %nbsp;, %rquo;
|
99
|
-
|
100
|
-
text.gsub!(/%(#\d+|\w+);/, '&\1;')
|
101
|
-
|
102
|
-
# Compile time ruby code. This code is evaluated when
|
103
|
-
# compiling the template and the result injected directly
|
104
|
-
# into the result. Usefull for example to prevaluate
|
105
|
-
# localization. Just use the #[] marker instead of #{}.
|
106
|
-
|
107
|
-
text.gsub!(/\#\[(.*?)\]/) do |match|
|
108
|
-
eval($1)
|
109
|
-
end
|
110
|
-
|
111
|
-
text = "#{buffer} << %^" + text + "^"
|
112
|
-
|
113
|
-
return text
|
114
|
-
end
|
115
|
-
|
116
|
-
# Evaluate the template.
|
117
|
-
#
|
118
|
-
# [+ruby+]
|
119
|
-
# A String containing the compiled template
|
120
|
-
# code.
|
121
|
-
#
|
122
|
-
# [+binding+]
|
123
|
-
# The evaluation binding for the rendering.
|
124
|
-
|
125
|
-
def evaluate_template(ruby, the_binding = nil)
|
126
|
-
eval(ruby, the_binding)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Compile and render the template.
|
130
|
-
|
131
|
-
def process_template(template, buffer = '@out', the_binding = nil)
|
132
|
-
evaluate_template(compile_template(template, buffer), the_binding)
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
# A helper class that provides access to the Template methods
|
138
|
-
# as singleton methods.
|
139
|
-
|
140
|
-
class Template
|
141
|
-
|
142
|
-
# The default root directory where template files reside.
|
143
|
-
|
144
|
-
if File.exist?('template')
|
145
|
-
default_root = 'template'
|
146
|
-
elsif File.exist?('src/template')
|
147
|
-
default_root = 'src/template'
|
148
|
-
else
|
149
|
-
default_root = 'public'
|
150
|
-
end
|
151
|
-
|
152
|
-
setting :root, :default => default_root, :doc => 'The default root directory where template files reside'
|
153
|
-
|
154
|
-
# The default template name.
|
155
|
-
|
156
|
-
setting :default, :default => 'index', :doc => 'The default template name'
|
157
|
-
|
158
|
-
# The default template file extension.
|
159
|
-
|
160
|
-
setting :extension, :default => 'xhtml', :doc => 'The default template file extension'
|
161
|
-
|
162
|
-
# Strip xml comments from templates?
|
163
|
-
|
164
|
-
setting :strip_xml_comments, :default => false, :doc => 'Strip xml comments from templates?'
|
165
|
-
|
166
|
-
class << self
|
167
|
-
include TemplateMixin
|
168
|
-
alias_method :compile, :compile_template
|
169
|
-
alias_method :transform, :compile_template
|
170
|
-
alias_method :evaluate, :evaluate_template
|
171
|
-
alias_method :process, :process_template
|
172
|
-
end
|
173
|
-
|
174
|
-
include TemplateMixin
|
175
|
-
|
176
|
-
# Helper.
|
177
|
-
|
178
|
-
def render(template)
|
179
|
-
str = ''
|
180
|
-
process_template(template, 'str', binding)
|
181
|
-
return str
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# A Template that reads from files and also
|
186
|
-
# provides a simple but effective caching scheme.
|
187
|
-
# An intuitive binding mechanism provides the
|
188
|
-
# expansion environment.
|
189
|
-
|
190
|
-
class FileTemplate < OpenObject
|
191
|
-
include TemplateMixin
|
192
|
-
|
193
|
-
@@compiled_template_cache = {}
|
194
|
-
|
195
|
-
attr_accessor :template_filename
|
196
|
-
|
197
|
-
def initialize(filename = nil)
|
198
|
-
super
|
199
|
-
@template_filename = filename
|
200
|
-
end
|
201
|
-
|
202
|
-
def process
|
203
|
-
__out__ = ''
|
204
|
-
|
205
|
-
unless compiled = @@compiled_template_cache[@template_filename]
|
206
|
-
template = File.read(@template_filename)
|
207
|
-
compiled = compile_template(template, '__out__')
|
208
|
-
@@compiled_template_cache[@template_filename] = compiled
|
209
|
-
end
|
210
|
-
|
211
|
-
evaluate_template(compiled, binding)
|
212
|
-
|
213
|
-
return __out__
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
end
|
218
|
-
|
219
|
-
# * George Moschovitis <gm@navel.gr>
|