dryml 1.1.0 → 1.3.0.RC
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/Rakefile +7 -32
- data/VERSION +1 -0
- data/dryml.gemspec +21 -65
- data/lib/dryml/dryml_builder.rb +7 -9
- data/lib/dryml/dryml_doc.rb +39 -39
- data/lib/dryml/dryml_generator.rb +71 -94
- data/lib/dryml/extensions/action_controller/dryml_methods.rb +23 -0
- data/lib/dryml/helper.rb +4 -4
- data/lib/dryml/parser/tree_parser.rb +1 -1
- data/lib/dryml/part_context.rb +13 -13
- data/lib/dryml/railtie/page_tag_resolver.rb +23 -0
- data/lib/dryml/railtie/template_handler.rb +15 -0
- data/lib/dryml/railtie.rb +26 -0
- data/lib/dryml/tag_parameters.rb +1 -1
- data/lib/dryml/taglib.rb +33 -22
- data/lib/dryml/template.rb +73 -59
- data/lib/dryml/template_environment.rb +42 -56
- data/lib/dryml.rb +188 -250
- data/taglibs/core.dryml +37 -27
- data/test/dryml.rdoctest +5 -6
- metadata +32 -47
- data/lib/dryml/dryml_support_controller.rb +0 -13
- data/lib/dryml/template_handler.rb +0 -187
@@ -1,7 +1,7 @@
|
|
1
1
|
module Dryml
|
2
2
|
|
3
3
|
class TemplateEnvironment
|
4
|
-
|
4
|
+
|
5
5
|
class << self
|
6
6
|
def inherited(subclass)
|
7
7
|
subclass.compiled_local_names = []
|
@@ -26,10 +26,9 @@ module Dryml
|
|
26
26
|
include ActionView::Helpers
|
27
27
|
include Helper ## FIXME remove
|
28
28
|
|
29
|
-
def initialize(
|
30
|
-
unless
|
29
|
+
def initialize(view=nil)
|
30
|
+
unless view.nil?
|
31
31
|
@view = view
|
32
|
-
@_view_name = view_name
|
33
32
|
@_erb_binding = binding
|
34
33
|
@_part_contexts = {}
|
35
34
|
@_scoped_variables = ScopedVariables.new
|
@@ -49,14 +48,14 @@ module Dryml
|
|
49
48
|
end
|
50
49
|
end
|
51
50
|
|
52
|
-
for attr in [:erb_binding, :part_contexts,
|
51
|
+
for attr in [:erb_binding, :part_contexts,
|
53
52
|
:this, :this_parent, :this_field, :this_key,
|
54
53
|
:form_this, :form_field_path, :form_field_names]
|
55
54
|
class_eval "def #{attr}; @_#{attr}; end"
|
56
55
|
end
|
57
|
-
|
56
|
+
|
58
57
|
def path_for_form_field
|
59
|
-
@_form_field_path.nil? and raise Dryml::DrymlException,
|
58
|
+
@_form_field_path.nil? and raise Dryml::DrymlException,
|
60
59
|
"DRYML cannot provide the correct form-field name here (this_field = #{this_field.inspect}, this = #{this.inspect})"
|
61
60
|
@_form_field_path
|
62
61
|
end
|
@@ -142,10 +141,10 @@ module Dryml
|
|
142
141
|
object = this
|
143
142
|
end
|
144
143
|
end
|
145
|
-
|
144
|
+
|
146
145
|
id = if (typed_id = object.try.typed_id)
|
147
146
|
typed_id
|
148
|
-
elsif object ==
|
147
|
+
elsif object == this
|
149
148
|
"this"
|
150
149
|
end
|
151
150
|
attribute ? "#{id}:#{attribute}" : id
|
@@ -160,26 +159,26 @@ module Dryml
|
|
160
159
|
end
|
161
160
|
res
|
162
161
|
end
|
163
|
-
|
164
|
-
|
162
|
+
|
163
|
+
|
165
164
|
def refresh_part(encoded_context, session, dom_id)
|
166
|
-
context = Dryml::PartContext.for_refresh(encoded_context,
|
167
|
-
|
165
|
+
context = Dryml::PartContext.for_refresh(encoded_context, this, session)
|
166
|
+
|
168
167
|
with_part_context(context) do
|
169
168
|
send("#{context.part_name}_part", *context.locals)
|
170
169
|
end
|
171
170
|
end
|
172
171
|
|
173
|
-
|
172
|
+
|
174
173
|
def with_part_context(context, &block)
|
175
174
|
this, this_field = context.this, context.this_field
|
176
|
-
|
175
|
+
|
177
176
|
b = if context.form_field_path
|
178
177
|
proc { with_form_context(:unknown, context.form_field_path, &block) }
|
179
178
|
else
|
180
179
|
block
|
181
180
|
end
|
182
|
-
|
181
|
+
|
183
182
|
if this && this_field
|
184
183
|
new_object_context(this) { new_field_context(this_field, &b) }
|
185
184
|
elsif this
|
@@ -206,11 +205,13 @@ module Dryml
|
|
206
205
|
|
207
206
|
def find_polymorphic_tag(name, call_type=nil)
|
208
207
|
call_type ||= (this.respond_to?(:member_class) && this.member_class) || this_type
|
209
|
-
|
210
208
|
begin
|
211
209
|
found = nil
|
212
210
|
while true
|
213
|
-
|
211
|
+
# ActiveSupport::TimeWithZone.name would return 'Time'
|
212
|
+
# so we add an exception to pick the right datetime type
|
213
|
+
type_name = ( call_type == ActiveSupport::TimeWithZone ? 'datetime' : call_type.name.to_s).underscore.gsub('/', '__')
|
214
|
+
if respond_to?(poly_name = "#{name}__for_#{type_name}")
|
214
215
|
found = poly_name
|
215
216
|
break
|
216
217
|
else
|
@@ -236,7 +237,7 @@ module Dryml
|
|
236
237
|
else
|
237
238
|
res = context_map(string_or_array) { yield }
|
238
239
|
end
|
239
|
-
res.
|
240
|
+
res.safe_join
|
240
241
|
end
|
241
242
|
|
242
243
|
|
@@ -283,17 +284,17 @@ module Dryml
|
|
283
284
|
parent, field, obj = Dryml.get_field_path(this, path)
|
284
285
|
@_this, @_this_parent, @_this_field = obj, parent, field
|
285
286
|
end
|
286
|
-
|
287
|
+
|
287
288
|
if @_form_field_path
|
288
|
-
@_form_field_path += path
|
289
|
+
@_form_field_path += path
|
289
290
|
@_form_field_paths_by_object[@_this] = @_form_field_path
|
290
291
|
end
|
291
|
-
|
292
|
+
|
292
293
|
yield
|
293
294
|
end
|
294
295
|
end
|
295
|
-
|
296
|
-
|
296
|
+
|
297
|
+
|
297
298
|
def find_form_field_path(object)
|
298
299
|
back = []
|
299
300
|
while object
|
@@ -310,8 +311,8 @@ module Dryml
|
|
310
311
|
end
|
311
312
|
end
|
312
313
|
end
|
313
|
-
|
314
|
-
|
314
|
+
|
315
|
+
|
315
316
|
|
316
317
|
|
317
318
|
def _tag_context(attributes)
|
@@ -331,13 +332,14 @@ module Dryml
|
|
331
332
|
|
332
333
|
|
333
334
|
def with_form_context(form_this=this, form_field_path=[form_this.class.name.underscore])
|
335
|
+
ctx = [@_form_this, @_form_field_path, @_form_field_paths_by_object]
|
334
336
|
@_form_this = form_this
|
335
337
|
@_form_field_path = form_field_path
|
336
338
|
@_form_field_paths_by_object = { form_this => form_field_path }
|
337
339
|
res = scope.new_scope :in_form => true, :form_field_names => [] do
|
338
340
|
yield
|
339
341
|
end
|
340
|
-
@_form_this
|
342
|
+
@_form_this, @_form_field_path, @_form_field_paths_by_object = ctx
|
341
343
|
res
|
342
344
|
end
|
343
345
|
|
@@ -348,7 +350,7 @@ module Dryml
|
|
348
350
|
|
349
351
|
|
350
352
|
def _tag_locals(attributes, locals)
|
351
|
-
attributes.symbolize_keys
|
353
|
+
attributes = attributes.symbolize_keys
|
352
354
|
#ensure with and field are not in attributes
|
353
355
|
attributes.delete(:with)
|
354
356
|
attributes.delete(:field)
|
@@ -386,13 +388,13 @@ module Dryml
|
|
386
388
|
def call_tag_parameter(the_tag, attributes, parameters, caller_parameters, param_name)
|
387
389
|
overriding_proc = caller_parameters[param_name]
|
388
390
|
replacing_proc = caller_parameters[:"#{param_name}_replacement"]
|
389
|
-
|
391
|
+
|
390
392
|
unless param_name == the_tag || param_name == :default
|
391
393
|
classes = attributes[:class]
|
392
394
|
param_class = param_name.to_s.gsub('_', '-')
|
393
395
|
attributes[:class] = if classes
|
394
396
|
classes =~ /\b#{param_class}\b/ ? classes : "#{classes} #{param_class}"
|
395
|
-
else
|
397
|
+
else
|
396
398
|
param_class
|
397
399
|
end
|
398
400
|
end
|
@@ -456,7 +458,7 @@ module Dryml
|
|
456
458
|
else
|
457
459
|
proc { |default| default_content.call(default) if default_content }
|
458
460
|
end
|
459
|
-
parameters = parameters.merge(:default => d)
|
461
|
+
parameters = parameters.merge(:default => d)
|
460
462
|
end
|
461
463
|
|
462
464
|
if the_tag.is_one_of?(String, Symbol)
|
@@ -511,25 +513,17 @@ module Dryml
|
|
511
513
|
end
|
512
514
|
end
|
513
515
|
end
|
514
|
-
|
515
|
-
|
516
|
+
|
517
|
+
|
516
518
|
def merge_parameter_hashes(given_parameters, overriding_parameters)
|
517
519
|
to_merge = given_parameters.keys & overriding_parameters.keys
|
518
520
|
no_merge = overriding_parameters.keys - to_merge
|
519
521
|
result = given_parameters.dup
|
520
|
-
|
522
|
+
|
521
523
|
no_merge.each { |k| result[k] = overriding_parameters[k] }
|
522
524
|
to_merge.each { |k| result[k] = merge_tag_parameter(given_parameters[k], overriding_parameters[k])}
|
523
|
-
|
524
|
-
result
|
525
|
-
end
|
526
|
-
|
527
|
-
|
528
525
|
|
529
|
-
|
530
|
-
def part_contexts_javascripts
|
531
|
-
storage = part_contexts_storage
|
532
|
-
storage.blank? ? "" : "<script type=\"text/javascript\">\n#{storage}</script>\n"
|
526
|
+
result
|
533
527
|
end
|
534
528
|
|
535
529
|
|
@@ -541,14 +535,7 @@ module Dryml
|
|
541
535
|
def render_tag(tag_name, attributes)
|
542
536
|
method_name = tag_name.to_s.gsub('-', '_')
|
543
537
|
if respond_to?(method_name)
|
544
|
-
|
545
|
-
|
546
|
-
# TODO: Temporary hack to get the dryml metadata comments in the right place
|
547
|
-
if false && RAILS_ENV == "development"
|
548
|
-
res.gsub(/^(.*?)(<!DOCTYPE.*?>).*?(<html.*?>)/m, "\\2\\3\\1")
|
549
|
-
else
|
550
|
-
res
|
551
|
-
end
|
538
|
+
send(method_name, attributes).strip
|
552
539
|
else
|
553
540
|
false
|
554
541
|
end
|
@@ -580,14 +567,13 @@ module Dryml
|
|
580
567
|
end
|
581
568
|
attr_string = " #{attrs.sort * ' '}" unless attrs.empty?
|
582
569
|
end
|
583
|
-
|
584
|
-
content = new_context { yield } if block_given?
|
570
|
+
content = capture { new_context &block } if block_given?
|
585
571
|
res = if empty
|
586
|
-
"<#{name}#{attr_string}#{scope.xmldoctype ? ' /' : ''}>"
|
572
|
+
"<#{name}#{attr_string}#{scope.xmldoctype ? ' /' : ''}>".html_safe
|
587
573
|
else
|
588
|
-
"<#{name}#{attr_string}
|
574
|
+
"<#{name}#{attr_string}>".html_safe + content + "</#{name}>".html_safe
|
589
575
|
end
|
590
|
-
if
|
576
|
+
if content.is_a? ActionView::NonConcattingString
|
591
577
|
concat res
|
592
578
|
else
|
593
579
|
res
|
data/lib/dryml.rb
CHANGED
@@ -4,294 +4,232 @@
|
|
4
4
|
# Copyright:: Copyright (c) 2008
|
5
5
|
# License:: Distributes under the same terms as Ruby
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
# gem dependencies
|
10
|
-
require 'hobosupport'
|
7
|
+
require 'hobo_support'
|
11
8
|
require 'action_pack'
|
12
|
-
require 'active_record' if ActionPack::VERSION::MAJOR==2 && ActionPack::VERSION::MINOR==2
|
13
|
-
|
14
|
-
if ActiveSupport.const_defined? :Dependencies
|
15
|
-
if ActiveSupport::Dependencies.respond_to?(:autoload_paths)
|
16
|
-
ActiveSupport::Dependencies.autoload_paths |= [ File.dirname(__FILE__)]
|
17
|
-
else
|
18
|
-
ActiveSupport::Dependencies.load_paths |= [ File.dirname(__FILE__)]
|
19
|
-
end
|
20
|
-
end
|
21
9
|
|
22
|
-
|
23
|
-
::DRYML_ROOT = File.expand_path(File.dirname(__FILE__) + "/..")
|
10
|
+
ActiveSupport::Dependencies.autoload_paths |= [File.dirname(__FILE__)]
|
24
11
|
|
25
12
|
# The Don't Repeat Yourself Markup Language
|
26
13
|
module Dryml
|
27
14
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
class DrymlException < Exception
|
33
|
-
def initialize(message, path=nil, line_num=nil)
|
34
|
-
if path && line_num
|
35
|
-
super(message + " -- at #{path}:#{line_num}")
|
36
|
-
else
|
37
|
-
super(message)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
TagDef = Struct.new "TagDef", :name, :attrs, :proc
|
15
|
+
VERSION = File.read(File.expand_path('../../VERSION', __FILE__)).strip
|
16
|
+
@@root = Pathname.new File.expand_path('../..', __FILE__)
|
17
|
+
def self.root; @@root; end
|
43
18
|
|
44
|
-
|
19
|
+
class DrymlSyntaxError < RuntimeError; end
|
45
20
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@renderer_classes = {}
|
54
|
-
@tag_page_renderer_classes = {}
|
55
|
-
|
56
|
-
extend self
|
57
|
-
|
58
|
-
attr_accessor :last_if
|
59
|
-
|
60
|
-
def enable(generator_directories=[], output_directory=".")
|
61
|
-
ActionView::Template.register_template_handler("dryml", Dryml::TemplateHandler)
|
62
|
-
if ActionView::Template.respond_to? :exempt_from_layout
|
63
|
-
ActionView::Template.exempt_from_layout('dryml')
|
64
|
-
elsif
|
65
|
-
ActionView::Base.exempt_from_layout('dryml')
|
66
|
-
end
|
67
|
-
DrymlGenerator.enable(generator_directories, output_directory)
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
def precompile_taglibs
|
72
|
-
Dir.chdir(RAILS_ROOT) do
|
73
|
-
taglibs = Dir["vendor/plugins/**/taglibs/**/*.dryml"] + Dir["app/views/taglibs/**/*.dryml"]
|
74
|
-
taglibs.each do |f|
|
75
|
-
Dryml::Taglib.get(:template_dir => File.dirname(f), :src => File.basename(f).remove(".dryml"))
|
76
|
-
end
|
21
|
+
class DrymlException < Exception
|
22
|
+
def initialize(message, path=nil, line_num=nil)
|
23
|
+
if path && line_num
|
24
|
+
super(message + " -- at #{path}:#{line_num}")
|
25
|
+
else
|
26
|
+
super(message)
|
77
27
|
end
|
78
28
|
end
|
79
|
-
|
80
|
-
|
81
|
-
def clear_cache
|
82
|
-
@renderer_classes = {}
|
83
|
-
@tag_page_renderer_classes = {}
|
84
|
-
end
|
85
|
-
|
86
|
-
def render_tag(view, tag, options={})
|
87
|
-
renderer = empty_page_renderer(view)
|
88
|
-
renderer.render_tag(tag, options)
|
89
|
-
end
|
90
|
-
|
91
|
-
|
92
|
-
def empty_page_renderer(view)
|
93
|
-
controller_name = view.controller.class.name.underscore.sub(/_controller$/, "")
|
94
|
-
page_renderer(view, [], "#{controller_name}/#{EMPTY_PAGE}")
|
95
|
-
end
|
96
|
-
|
97
|
-
|
98
|
-
def page_renderer_for_template(view, local_names, template)
|
99
|
-
page_renderer(view, local_names, template.path_without_extension, template.filename)
|
100
|
-
end
|
101
|
-
|
102
|
-
|
103
|
-
def page_renderer(view, local_names=[], page=nil, filename=nil)
|
104
|
-
if RAILS_ENV == "development"
|
105
|
-
clear_cache
|
106
|
-
Taglib.clear_cache
|
107
|
-
end
|
108
|
-
|
109
|
-
prepare_view!(view)
|
110
|
-
included_taglibs = ([APPLICATION_TAGLIB, subsite_taglib(page)] + controller_taglibs(view.controller.class)).compact
|
111
|
-
|
112
|
-
if page.ends_with?(EMPTY_PAGE)
|
113
|
-
# DELETE ME: controller_class = controller_class_for(page)
|
114
|
-
controller_class = view.controller.class
|
115
|
-
@tag_page_renderer_classes[controller_class.name] ||=
|
116
|
-
make_renderer_class("", page, local_names, DEFAULT_IMPORTS, included_taglibs)
|
117
|
-
@tag_page_renderer_classes[controller_class.name].new(page, view)
|
118
|
-
else
|
119
|
-
filename ||= if view.view_paths.respond_to? :find_template
|
120
|
-
# Rails 2.3
|
121
|
-
view.view_paths.find_template(page + ".dryml").filename
|
122
|
-
else
|
123
|
-
# Rails 2.2
|
124
|
-
view._pick_template(page + ".dryml").filename
|
125
|
-
end
|
126
|
-
mtime = File.mtime(filename)
|
127
|
-
renderer_class = @renderer_classes[page]
|
29
|
+
end
|
128
30
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
31
|
+
TagDef = Struct.new "TagDef", :name, :attrs, :proc
|
32
|
+
RESERVED_WORDS = %w{if for while do class else elsif unless case when module in}
|
33
|
+
ID_SEPARATOR = '; dryml-tag: '
|
34
|
+
APPLICATION_TAGLIB = { :src => "taglibs/application" }
|
35
|
+
CORE_TAGLIB = { :src => "core", :plugin => "dryml" }
|
36
|
+
DEFAULT_IMPORTS = defined?(ApplicationHelper) ? [ApplicationHelper] : []
|
37
|
+
@cache = {}
|
38
|
+
extend self
|
39
|
+
attr_accessor :last_if
|
40
|
+
|
41
|
+
def precompile_taglibs
|
42
|
+
Dir.chdir(Rails.root) do
|
43
|
+
Dir["app/views/taglibs/**/*.dryml"].each do |f|
|
44
|
+
Taglib.get(:template_dir => File.dirname(f), :src => File.basename(f).remove(".dryml"))
|
139
45
|
end
|
140
46
|
end
|
47
|
+
end
|
141
48
|
|
49
|
+
def clear_cache
|
50
|
+
@cache = {}
|
51
|
+
end
|
142
52
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
|
53
|
+
def render_tag(view, tag, options={})
|
54
|
+
renderer = empty_page_renderer(view)
|
55
|
+
renderer.render_tag(tag, options)
|
56
|
+
end
|
149
57
|
|
150
|
-
|
151
|
-
|
152
|
-
|
58
|
+
def empty_page_renderer(view)
|
59
|
+
page_renderer(view, page_tag_identifier(view.controller.controller_path))
|
60
|
+
end
|
153
61
|
|
62
|
+
def page_tag_identifier(controller_path, tag_name='')
|
63
|
+
"controller: #{controller_path}#{ID_SEPARATOR}#{tag_name}"
|
64
|
+
end
|
154
65
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
66
|
+
def call_render(view, local_assigns, identifier)
|
67
|
+
renderer = page_renderer(view, identifier, local_assigns.keys)
|
68
|
+
this = view.controller.send(:dryml_context) || local_assigns[:this]
|
69
|
+
view.instance_variable_set("@this", this)
|
70
|
+
if identifier =~ /#{ID_SEPARATOR}/
|
71
|
+
tag_name = identifier.split(ID_SEPARATOR).last
|
72
|
+
renderer.render_tag(tag_name, {:with => this} )
|
73
|
+
else
|
74
|
+
renderer.render_page(this, local_assigns).strip
|
160
75
|
end
|
76
|
+
end
|
161
77
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
78
|
+
def page_renderer(view, identifier, local_names=[], controller_path=nil)
|
79
|
+
controller_path ||= view.controller.controller_path
|
80
|
+
if identifier =~ /#{ID_SEPARATOR}/
|
81
|
+
identifier = identifier.split(ID_SEPARATOR).first
|
82
|
+
@cache[identifier] ||= make_renderer_class("", "", local_names, taglibs_for(controller_path))
|
83
|
+
@cache[identifier].new(view)
|
84
|
+
else
|
85
|
+
mtime = File.mtime(identifier)
|
86
|
+
renderer_class = @cache[identifier]
|
87
|
+
# do we need to recompile?
|
88
|
+
if (!renderer_class || # nothing cached?
|
89
|
+
(local_names - renderer_class.compiled_local_names).any? || # any new local names?
|
90
|
+
renderer_class.load_time < mtime) # cache out of date?
|
91
|
+
renderer_class = make_renderer_class(File.read(identifier), identifier,
|
92
|
+
local_names, taglibs_for(controller_path))
|
93
|
+
renderer_class.load_time = mtime
|
94
|
+
@cache[identifier] = renderer_class
|
173
95
|
end
|
96
|
+
renderer_class.new(view)
|
174
97
|
end
|
98
|
+
end
|
175
99
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
return nil if object.nil?
|
187
|
-
parent = object
|
188
|
-
object = get_field(parent, field)
|
189
|
-
end
|
190
|
-
[parent, path.last, object]
|
191
|
-
end
|
192
|
-
|
193
|
-
|
194
|
-
def prepare_view!(view)
|
195
|
-
# Not sure why this isn't done for me...
|
196
|
-
# There's probably a button to press round here somewhere
|
197
|
-
for var in %w(@flash @cookies @action_name @_session @_request @request_origin
|
198
|
-
@template @request @ignore_missing_templates @_headers @variables_added
|
199
|
-
@_flash @response @template_class
|
200
|
-
@_cookies @before_filter_chain_aborted @url
|
201
|
-
@_response @template_root @headers @_params @params @session)
|
202
|
-
unless @view.instance_variables.include?(var)
|
203
|
-
view.instance_variable_set(var, view.controller.instance_variable_get(var))
|
204
|
-
end
|
205
|
-
end
|
100
|
+
def get_field(object, field)
|
101
|
+
return nil if object.nil?
|
102
|
+
field_str = field.to_s
|
103
|
+
case
|
104
|
+
when object.respond_to?(field_str)
|
105
|
+
object.send(field_str)
|
106
|
+
when field_str =~ /^\d+$/
|
107
|
+
object[field.to_i]
|
108
|
+
else
|
109
|
+
object[field]
|
206
110
|
end
|
111
|
+
end
|
207
112
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
# uses [Hobo::HoboHelper, Hobo::Translations,
|
216
|
-
# ApplicationHelper]
|
217
|
-
# included_taglibs:: A list of Taglibs to include. { :src =>
|
218
|
-
# "core", :plugin => "dryml" } is automatically
|
219
|
-
# added to this list.
|
220
|
-
#
|
221
|
-
def make_renderer_class(template_src, template_path, locals=[], imports=[], included_taglibs=[])
|
222
|
-
renderer_class = Class.new(TemplateEnvironment)
|
223
|
-
compile_renderer_class(renderer_class, template_src, template_path, locals, imports, included_taglibs)
|
224
|
-
renderer_class
|
113
|
+
def get_field_path(object, path)
|
114
|
+
return nil if object.nil?
|
115
|
+
path = path.is_a?(String) ? path.split('.') : Array(path)
|
116
|
+
parent = nil
|
117
|
+
path.each do |field|
|
118
|
+
parent = object
|
119
|
+
object = get_field(parent, field)
|
225
120
|
end
|
121
|
+
[parent, path.last, object]
|
122
|
+
end
|
226
123
|
|
124
|
+
def unreserve(word)
|
125
|
+
word = word.to_s
|
126
|
+
word += '_' if RESERVED_WORDS.include?(word)
|
127
|
+
word
|
128
|
+
end
|
227
129
|
|
228
|
-
|
229
|
-
|
230
|
-
|
130
|
+
def static_tags
|
131
|
+
@static_tags ||= begin
|
132
|
+
path = if Object.const_defined?(:Rails) && FileTest.exists?("#{Rails.root}/config/dryml_static_tags.txt")
|
133
|
+
"#{Rails.root}/config/dryml_static_tags.txt"
|
134
|
+
else
|
135
|
+
File.join(File.dirname(__FILE__), "dryml/static_tags")
|
136
|
+
end
|
137
|
+
File.readlines(path).*.chop
|
138
|
+
end
|
139
|
+
end
|
231
140
|
|
232
|
-
|
141
|
+
attr_writer :static_tags
|
142
|
+
|
143
|
+
# FIXME: This helper seems to be useless, since it does need Rails,
|
144
|
+
# and with Rails it is useless since Dryml does not need Hobo
|
145
|
+
#
|
146
|
+
# Helper function for use outside Hobo/Rails
|
147
|
+
#
|
148
|
+
# Pass the template context in locals[:this]
|
149
|
+
#
|
150
|
+
# This function caches. If the mtime of template_path is older
|
151
|
+
# than the last compilation time, the cached version will be
|
152
|
+
# used. If no template_path is given, template_src is used as the
|
153
|
+
# key to the cache.
|
154
|
+
#
|
155
|
+
# If a local variable is not present when the template is
|
156
|
+
# compiled, it will be ignored when the template is used. In
|
157
|
+
# other words, the variable values may change, but the names may
|
158
|
+
# not.
|
159
|
+
#
|
160
|
+
# included_taglibs is only used during template compilation.
|
161
|
+
#
|
162
|
+
# @param [String] template_src the DRYML source
|
163
|
+
# @param [Hash] locals local variables.
|
164
|
+
# @param [String, nil] template_path the filename of the source.
|
165
|
+
# @param [Array] included_taglibs A list of Taglibs to include. { :src =>
|
166
|
+
# "core", :plugin => "dryml" } is automatically
|
167
|
+
# added to this list.
|
168
|
+
# @param [ActionView::Base] view an ActionView instance
|
169
|
+
def render(template_src, locals={}, template_path=nil, included_taglibs=[], view=nil)
|
170
|
+
template_path ||= template_src
|
171
|
+
view ||= ActionView::Base.new(ActionController::Base.view_paths, {})
|
172
|
+
this = locals.delete(:this) || nil
|
173
|
+
|
174
|
+
renderer_class = Dryml::Template.build_cache[template_path]._?.environment ||
|
175
|
+
make_renderer_class(template_src, template_path, locals.keys)
|
176
|
+
renderer_class.new(view).render_page(this, locals)
|
177
|
+
end
|
233
178
|
|
234
|
-
|
235
|
-
all_local_names = renderer_class.compiled_local_names | locals
|
179
|
+
private
|
236
180
|
|
237
|
-
|
238
|
-
|
181
|
+
def taglibs_for(controller_path)
|
182
|
+
( taglibs_in_dir('application').unshift(APPLICATION_TAGLIB) +
|
183
|
+
subsite_taglibs(controller_path) +
|
184
|
+
(controller_path.camelize+"Controller").constantize.try.included_taglibs||[]
|
185
|
+
).compact
|
186
|
+
end
|
239
187
|
|
188
|
+
def subsite_taglibs(controller_path)
|
189
|
+
parts = controller_path.split("/")
|
190
|
+
subsite = parts.length >= 2 ? parts[0..-2].join('_') : "front"
|
191
|
+
src = "taglibs/#{subsite}_site"
|
192
|
+
Object.const_defined?(:Rails) && File.exists?("#{Rails.root}/app/views/#{src}.dryml") ?
|
193
|
+
taglibs_in_dir("#{subsite}_site").unshift({ :src => src }) : []
|
194
|
+
end
|
240
195
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
else
|
246
|
-
word
|
196
|
+
def taglibs_in_dir(dir_name)
|
197
|
+
Dir.chdir(Rails.root) do
|
198
|
+
Dir["app/views/taglibs/#{dir_name}/**/*.dryml"].map{|f| File.basename f, '.dryml'}.map do |n|
|
199
|
+
{ :src => "taglibs/#{dir_name}/#{n}" }
|
247
200
|
end
|
248
201
|
end
|
202
|
+
end
|
249
203
|
|
204
|
+
# create and compile a renderer class (AKA Dryml::Template::Environment)
|
205
|
+
#
|
206
|
+
# template_src:: the DRYML source
|
207
|
+
# template_path:: the filename of the source. This is used for
|
208
|
+
# caching
|
209
|
+
# locals:: local variables.
|
210
|
+
# imports:: A list of helper modules to import. For example, Hobo
|
211
|
+
# uses [Hobo::Helper, Hobo::Helper::Translations,
|
212
|
+
# ApplicationHelper]
|
213
|
+
# included_taglibs:: A list of Taglibs to include. { :src =>
|
214
|
+
# "core", :plugin => "dryml" } is automatically
|
215
|
+
# added to this list.
|
216
|
+
#
|
217
|
+
def make_renderer_class(template_src, template_path, locals=[], taglibs=[])
|
218
|
+
renderer_class = Class.new(TemplateEnvironment)
|
219
|
+
compile_renderer_class(renderer_class, template_src, template_path, locals, taglibs)
|
220
|
+
renderer_class
|
221
|
+
end
|
250
222
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
"#{RAILS_ROOT}/config/dryml_static_tags.txt"
|
255
|
-
else
|
256
|
-
File.join(File.dirname(__FILE__), "dryml/static_tags")
|
257
|
-
end
|
258
|
-
File.readlines(path).*.chop
|
259
|
-
end
|
260
|
-
end
|
223
|
+
def compile_renderer_class(renderer_class, template_src, template_path, locals, taglibs=[])
|
224
|
+
template = Dryml::Template.new(template_src, renderer_class, template_path)
|
225
|
+
DEFAULT_IMPORTS.each {|m| template.import_module(m)}
|
261
226
|
|
262
|
-
|
227
|
+
# the sum of all the names we've seen so far - eventually we'll be ready for all of 'em
|
228
|
+
all_local_names = renderer_class.compiled_local_names | locals
|
263
229
|
|
264
|
-
|
265
|
-
|
266
|
-
# Pass the template context in locals[:this]
|
267
|
-
#
|
268
|
-
# This function caches. If the mtime of template_path is older
|
269
|
-
# than the last compilation time, the cached version will be
|
270
|
-
# used. If no template_path is given, template_src is used as the
|
271
|
-
# key to the cache.
|
272
|
-
#
|
273
|
-
# If a local variable is not present when the template is
|
274
|
-
# compiled, it will be ignored when the template is used. In
|
275
|
-
# other words, the variable values may change, but the names may
|
276
|
-
# not.
|
277
|
-
#
|
278
|
-
# included_taglibs is only used during template compilation.
|
279
|
-
#
|
280
|
-
# @param [String] template_src the DRYML source
|
281
|
-
# @param [Hash] locals local variables.
|
282
|
-
# @param [String, nil] template_path the filename of the source.
|
283
|
-
# @param [Array] included_taglibs A list of Taglibs to include. { :src =>
|
284
|
-
# "core", :plugin => "dryml" } is automatically
|
285
|
-
# added to this list.
|
286
|
-
# @param [ActionView::Base] view an ActionView instance
|
287
|
-
def render(template_src, locals={}, template_path=nil, included_taglibs=[], view=nil)
|
288
|
-
template_path ||= template_src
|
289
|
-
view ||= ActionView::Base.new(ActionController::Base.view_paths, {})
|
290
|
-
this = locals.delete(:this) || nil
|
230
|
+
template.compile(all_local_names, [CORE_TAGLIB]+taglibs)
|
231
|
+
end
|
291
232
|
|
292
|
-
renderer_class = Dryml::Template.build_cache[template_path]._?.environment ||
|
293
|
-
Dryml.make_renderer_class(template_src, template_path, locals.keys, [], included_taglibs)
|
294
|
-
renderer_class.new(template_path, view).render_page(this, locals)
|
295
|
-
end
|
296
|
-
|
297
233
|
end
|
234
|
+
|
235
|
+
require 'dryml/railtie' if Object.const_defined?(:Rails)
|