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.
@@ -0,0 +1,23 @@
1
+ ActionController::Base.class_eval do
2
+
3
+ before_filter do
4
+ append_view_path Dryml::Railtie::PageTagResolver.new(self)
5
+ end
6
+
7
+ attr_accessor :dryml_fallback_tag
8
+
9
+ def dryml_context
10
+ @this
11
+ end
12
+
13
+ def call_dryml_tag(tag, options={})
14
+ # TODO: Figure out what this bit is all about :-)
15
+ if options[:with]
16
+ @this = options[:with] unless options[:field]
17
+ else
18
+ options[:with] = dryml_context
19
+ end
20
+ Dryml.render_tag(view_context, tag, options)
21
+ end
22
+
23
+ end
data/lib/dryml/helper.rb CHANGED
@@ -31,7 +31,7 @@ module Dryml::Helper
31
31
  end
32
32
  res
33
33
  end
34
-
34
+
35
35
  def first_item?
36
36
  if scope.repeat_collection.respond_to? :each_pair
37
37
  this == scope.repeat_collection.first.try.last
@@ -39,8 +39,8 @@ module Dryml::Helper
39
39
  this == scope.repeat_collection.first
40
40
  end
41
41
  end
42
-
43
-
42
+
43
+
44
44
  def last_item?
45
45
  if scope.repeat_collection.respond_to? :each_pair
46
46
  this == scope.repeat_collection.last.try.last
@@ -49,7 +49,7 @@ module Dryml::Helper
49
49
  end
50
50
  end
51
51
 
52
- def param_name_for(path)
52
+ def param_name_for(path)
53
53
  field_path = field_path.to_s.split(".") if field_path.is_one_of?(String, Symbol)
54
54
  attrs = path.rest.map{|part| "[#{part.to_s.sub /\?$/, ''}]"}.join
55
55
  "#{path.first}#{attrs}"
@@ -54,7 +54,7 @@ module Dryml::Parser
54
54
  c = REXML::CData.new( event[1] )
55
55
  @build_context.add( c )
56
56
  when :processing_instruction
57
- @build_context.add( Instruction.new( event[1], event[2] ) )
57
+ @build_context.add( REXML::Instruction.new( event[1], event[2] ) )
58
58
  end
59
59
  end
60
60
  rescue REXML::Validation::ValidationException
@@ -21,8 +21,8 @@
21
21
  "hoboParts['#{dom_id}'] = (#{code});\n"
22
22
  end.join
23
23
  end
24
-
25
-
24
+
25
+
26
26
  def self.pre_marshal(x)
27
27
  if x.is_a?(ActiveRecord::Base) && x.respond_to?(:typed_id)
28
28
  TypedId.new(x.typed_id)
@@ -40,19 +40,19 @@
40
40
  c.form_field_path = environment.form_field_path
41
41
  end
42
42
  end
43
-
44
-
43
+
44
+
45
45
  def self.for_refresh(encoded_context, page_this, session)
46
46
  new do |c|
47
47
  c.unmarshal(encoded_context, page_this, session)
48
48
  end
49
49
  end
50
-
51
-
50
+
51
+
52
52
  def initialize
53
53
  yield self
54
54
  end
55
-
55
+
56
56
  attr_accessor :part_name, :locals, :this, :this_field, :this_id, :form_field_path
57
57
 
58
58
 
@@ -72,26 +72,26 @@
72
72
  raise TamperedWithPartContext unless digest == generate_digest(data, session)
73
73
 
74
74
  context = Marshal.load(Base64.decode64(data))
75
-
75
+
76
76
  part_name, this_id, locals, form_field_path = context
77
77
 
78
78
  if RAILS_DEFAULT_LOGGER
79
79
  RAILS_DEFAULT_LOGGER.info "Call part: #{part_name}. this-id = #{this_id}, locals = #{locals.inspect}"
80
80
  RAILS_DEFAULT_LOGGER.info " : form_field_path = #{form_field_path.inspect}" if form_field_path
81
81
  end
82
-
82
+
83
83
  self.part_name = part_name
84
84
  self.this_id = this_id
85
85
  self.locals = restore_locals(locals)
86
86
  self.form_field_path = form_field_path
87
-
88
- parse_this_id(page_this)
87
+
88
+ parse_this_id(page_this)
89
89
  end
90
90
 
91
91
 
92
92
  # Generate the HMAC keyed message digest. Uses SHA1 by default.
93
93
  def generate_digest(data, session)
94
- secret = self.class.secret || ActionController::Base.session_options[:secret] || ActionController::Base.cached_session_options.first[:secret]
94
+ secret = self.class.secret || Rails.application.config.secret_token
95
95
  key = secret.respond_to?(:call) ? secret.call(session) : secret
96
96
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(self.class.digest), key, data)
97
97
  end
@@ -121,7 +121,7 @@
121
121
  def restore_locals(locals)
122
122
  locals.map do |l|
123
123
  if l.is_a?(TypedId)
124
- Hobo::Model.find_by_typed_id(l)
124
+ Hobo::Model.find_by_typed_id(this_id)
125
125
  else
126
126
  l
127
127
  end
@@ -0,0 +1,23 @@
1
+ module Dryml
2
+ class Railtie
3
+ class PageTagResolver < ActionView::Resolver
4
+
5
+ def initialize(controller)
6
+ @controller = controller
7
+ super()
8
+ end
9
+
10
+ def find_templates(name, prefix, partial, details)
11
+ tag_name = @controller.dryml_fallback_tag || name.dasherize + '-page'
12
+ method_name = tag_name.to_s.gsub('-', '_')
13
+ if Dryml.empty_page_renderer(@controller.view_context).respond_to?(method_name)
14
+ [ActionView::Template.new('', Dryml.page_tag_identifier(@controller.controller_path, tag_name),
15
+ Dryml::Railtie::TemplateHandler, details)]
16
+ else
17
+ []
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ module Dryml
2
+ class Railtie
3
+ class TemplateHandler < ActionView::Template::Handler
4
+
5
+ self.default_format = Mime::HTML
6
+
7
+ def self.call(template)
8
+ "Dryml.call_render(self, local_assigns, '#{template.identifier}')"
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+
15
+
@@ -0,0 +1,26 @@
1
+ module Dryml
2
+ class Railtie < Rails::Railtie
3
+
4
+ ActiveSupport.on_load(:before_initialize) do |app|
5
+ require 'dryml'
6
+ require 'dryml/template'
7
+ require 'dryml/dryml_generator'
8
+ end
9
+
10
+ ActiveSupport.on_load(:action_controller) do
11
+ require 'dryml/extensions/action_controller/dryml_methods'
12
+ end
13
+
14
+ ActiveSupport.on_load(:action_view) do
15
+ ActionView::Template.register_template_handler("dryml", Dryml::Railtie::TemplateHandler)
16
+ end
17
+
18
+ initializer 'dryml' do |app|
19
+ app.config.to_prepare do
20
+ Dryml.clear_cache
21
+ Dryml::Taglib.clear_cache
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -22,7 +22,7 @@
22
22
 
23
23
  undef_method :default
24
24
 
25
- # Question: does this do anything? -Tom
25
+ # Question: does this do anything? -Tom
26
26
  def [](param_name)
27
27
  fetch(param_name, nil)
28
28
  end
data/lib/dryml/taglib.rb CHANGED
@@ -24,29 +24,40 @@
24
24
 
25
25
  private
26
26
 
27
+ # Requirements for hobo-plugin for loading a taglib when the plugin is loaded as a gem:
28
+ # - the plugin must define the <gem_name>.camelize.constantize.root() method
29
+ # - the root() method must return a Pathname object (like Hobo.root, Dryml.root, Rails.root, etc.)
30
+ # - the taglibs must be available in the 'taglibs' dir in the gem root
31
+ # You can include the taglib with <include gem='gem_name'/> if the taglib name has the same gem name.
32
+ # If the plugin defines different taglibs you must also specify the src attribute of the taglib that you want
33
+ # to include: <include gem='gem_name' src='taglib_name'/>'
34
+
27
35
  def taglib_filename(options)
28
- plugin = options[:plugin]
29
- rails_root = Object.const_defined?(:RAILS_ROOT) ? RAILS_ROOT : "."
30
- base = if plugin == "dryml"
31
- "#{DRYML_ROOT}/taglibs"
32
- elsif plugin == "hobo"
33
- "#{HOBO_ROOT}/taglibs"
34
- elsif plugin
35
- "#{rails_root}/vendor/plugins/#{plugin}/taglibs"
36
- elsif options[:src] =~ /\//
37
- "#{rails_root}/app/views"
38
- elsif options[:template_dir] =~ /^#{HOBO_ROOT}/
39
- options[:template_dir]
40
- elsif options[:absolute_template_path]
41
- options[:absolute_template_path]
42
- else
43
- "#{rails_root}/#{options[:template_dir].gsub(/^\//, '')}" # remove leading / if there is one
44
- end
45
-
46
- src = options[:src] || plugin
47
- filename = "#{base}/#{src}.dryml"
48
- raise DrymlException, "No such taglib: #{base} #{options.inspect} #{filename}" unless File.exists?(filename)
49
- filename
36
+ plugin = options[:plugin]
37
+ gem = options[:gem]
38
+ app_root = Object.const_defined?(:Rails) ? Rails.root : Pathname.new(File.expand_path('.'))
39
+ taglibs_path = case
40
+ when plugin == 'dryml'
41
+ Dryml.root.join 'taglibs'
42
+ when plugin == 'hobo', gem == 'hobo'
43
+ Hobo.root.join 'lib/hobo/rapid/taglibs'
44
+ when !plugin.blank?
45
+ app_root.join 'vendor/plugins', plugin, 'taglibs'
46
+ when !gem.blank?
47
+ gem.tr('-','_').camelize.constantize.root.join 'taglibs'
48
+ when options[:src] =~ /\//
49
+ app_root.join 'app/views'
50
+ when options[:template_dir] =~ /^#{Hobo.root}/
51
+ Pathname.new(options[:template_dir])
52
+ when options[:absolute_template_path]
53
+ Pathname.new(options[:absolute_template_path])
54
+ else
55
+ app_root.join options[:template_dir].gsub(/^\//, '') # remove leading / if there is one
56
+ end
57
+ src = options[:src] || gem || plugin
58
+ taglib_file = taglibs_path.join "#{src}.dryml"
59
+ raise DrymlException, "No such taglib: #{src} #{options.inspect} #{taglib_file}" unless taglib_file.exist?
60
+ taglib_file.to_s
50
61
  end
51
62
 
52
63
  end
@@ -38,7 +38,7 @@ module Dryml
38
38
  @src = src
39
39
  @environment = environment # a class or a module
40
40
  @template_path = template_path
41
- @template_path = @template_path.sub(%r(^#{Regexp.escape(RAILS_ROOT)}/), "") if Object.const_defined? :RAILS_ROOT
41
+ @template_path = @template_path.sub(%r(^#{Regexp.escape(Rails.root.to_s)}/), "") if Object.const_defined? :Rails
42
42
 
43
43
  @builder = Template.build_cache[@template_path] || DRYMLBuilder.new(self)
44
44
  @builder.set_environment(environment)
@@ -51,11 +51,11 @@ module Dryml
51
51
  def compile(local_names=[], auto_taglibs=[])
52
52
  now = Time.now
53
53
 
54
- unless @template_path.ends_with?(EMPTY_PAGE)
54
+ unless @template_path.blank?
55
55
  p = Pathname.new template_path
56
- p = Pathname.new(RAILS_ROOT) + p unless p.absolute? || !Object.const_defined?(:RAILS_ROOT)
56
+ p = Pathname.new(Rails.root) + p unless p.absolute? || !Object.const_defined?(:Rails)
57
57
  mtime = p.mtime rescue Time.now
58
-
58
+
59
59
  if !@builder.ready?(mtime)
60
60
  @builder.start
61
61
  parsed = true
@@ -70,7 +70,7 @@ module Dryml
70
70
  Template.build_cache[@template_path] = @builder
71
71
  end
72
72
  end
73
-
73
+
74
74
  # compile the build instructions
75
75
  @builder.build(local_names, auto_taglibs, mtime)
76
76
 
@@ -112,13 +112,13 @@ module Dryml
112
112
 
113
113
  # v important this comes before REXML::Text, as REXML::CData < REXML::Text
114
114
  when REXML::CData
115
- REXML::CData::START + node.to_s + REXML::CData::STOP
115
+ "<% safe_concat %(#{REXML::CData::START + node.to_s + REXML::CData::STOP}) %>"
116
116
 
117
117
  when REXML::Comment
118
- REXML::Comment::START + node.to_s + REXML::Comment::STOP
118
+ "<% safe_concat %(#{REXML::Comment::START + node.to_s + REXML::Comment::STOP}) %>"
119
119
 
120
120
  when REXML::Text
121
- strip_suppressed_whiteaspace(node.to_s)
121
+ text_with_scriplets_to_erb(node.to_s)
122
122
 
123
123
  when REXML::Element
124
124
  element_to_erb(node)
@@ -126,8 +126,19 @@ module Dryml
126
126
  end
127
127
 
128
128
 
129
- def strip_suppressed_whiteaspace(s)
130
- s # s.gsub(/ -(\s*\n\s*)/, '<% \1 %>')
129
+ def text_with_scriplets_to_erb(s)
130
+ scriplet_rex = /(\[!\[DRYML-ERB\d+\s*\]!\])/m
131
+ s.split(scriplet_rex).map do |t|
132
+ case t
133
+ when scriplet_rex
134
+ t
135
+ when /\S+/
136
+ t.gsub!(/(\(|\))/){"\\#{$1}"}
137
+ "<% safe_concat %(#{t}) %>"
138
+ else
139
+ t
140
+ end
141
+ end.join
131
142
  end
132
143
 
133
144
 
@@ -179,7 +190,7 @@ module Dryml
179
190
  require_toplevel(el)
180
191
  require_attribute(el, "as", /^#{DRYML_NAME}$/, true)
181
192
  options = {}
182
- %w(src module plugin as).each do |attr|
193
+ %w(src module plugin gem as).each do |attr|
183
194
  options[attr.to_sym] = el.attributes[attr] if el.attributes[attr]
184
195
  end
185
196
  @builder.add_build_instruction(:include, options)
@@ -234,7 +245,7 @@ module Dryml
234
245
 
235
246
 
236
247
  def define_polymorphic_dispatcher(el, name)
237
- # FIXME: The new erb context ends up being set-up twice
248
+ # FIXME: The new erb context ends up being set-up twice
238
249
  src = %(
239
250
  def #{name}(attributes={}, parameters={})
240
251
  _tag_context(attributes) do
@@ -246,29 +257,31 @@ module Dryml
246
257
  )
247
258
  @builder.add_build_instruction(:eval, :src => src, :line_num => element_line_num(el))
248
259
  end
249
-
250
-
260
+
261
+
251
262
  def extend_element(el)
252
263
  def_element(el, true)
253
264
  end
254
-
255
-
265
+
266
+
256
267
  def type_specific_suffix
257
268
  el = @def_element
258
269
  for_type = el.attributes['for']
259
270
  if for_type
260
271
  type_name = if defined?(HoboFields) && for_type =~ /^[a-z]/
261
272
  # It's a symbolic type name - look up the Ruby type name
262
- klass = HoboFields.to_class(for_type) or
273
+ klass = HoboFields.to_class(for_type) or
263
274
  dryml_exception("No such type in polymorphic tag definition: '#{for_type}'", el)
264
- klass.name
275
+ # ActiveSupport::TimeWithZone.name would return 'Time'
276
+ # so we add an exception to pick the right datetime type
277
+ klass == ActiveSupport::TimeWithZone ? 'datetime' : klass.name
265
278
  else
266
279
  for_type
267
280
  end.underscore.gsub('/', '__')
268
281
  "__for_#{type_name}"
269
282
  end
270
283
  end
271
-
284
+
272
285
 
273
286
  def def_element(el, extend_tag=false)
274
287
  require_toplevel(el)
@@ -285,12 +298,12 @@ module Dryml
285
298
  name += suffix
286
299
  unsafe_name += suffix
287
300
  end
288
-
301
+
289
302
  if el.attributes['polymorphic']
290
303
  %w(for alias-of).each do |attr|
291
304
  dryml_exception("def cannot have both 'polymorphic' and '#{attr}' attributes") if el.attributes[attr]
292
305
  end
293
-
306
+
294
307
  define_polymorphic_dispatcher(el, ruby_name(name))
295
308
  name += "__base"
296
309
  unsafe_name += "__base"
@@ -351,13 +364,13 @@ module Dryml
351
364
  def tag_method(name, el, extend_tag=false)
352
365
  name = ruby_name name
353
366
  param_names = param_names_in_definition(el)
354
-
367
+
355
368
  if extend_tag
356
369
  @extend_key = 'a' + Digest::SHA1.hexdigest(el.to_s)[0..10]
357
370
  alias_statement = "; alias_method_chain_on_include :#{name}, :#{@extend_key}"
358
371
  name = "#{name}_with_#{@extend_key}"
359
372
  end
360
-
373
+
361
374
  src = "<% def #{name}(all_attributes={}, all_parameters={}); " +
362
375
  "parameters = Dryml::TagParameters.new(all_parameters, #{param_names.inspect.underscore}); " +
363
376
  "all_parameters = Dryml::TagParameters.new(all_parameters); " +
@@ -385,17 +398,17 @@ module Dryml
385
398
  "<% output_buffer; end"
386
399
  end
387
400
 
388
-
389
401
  def wrap_source_with_metadata(content, kind, name, *args)
390
402
  if (!include_source_metadata) || name.in?(NO_METADATA_TAGS)
391
403
  content
392
404
  else
393
405
  metadata = [kind, name] + args + [@template_path]
394
- "<!--[DRYML|#{metadata * '|'}[-->" + content + "<!--]DRYML]-->"
406
+ "<% safe_concat(%(<!--[DRYML|#{metadata * '|'}[-->)) %>" +
407
+ content +
408
+ "<% safe_concat(%(<!--]DRYML]-->)) %>"
395
409
  end
396
410
  end
397
411
 
398
-
399
412
  def wrap_tag_method_body_with_metadata(content)
400
413
  name = @def_element.attributes['tag']
401
414
  for_ = @def_element.attributes['for']
@@ -431,7 +444,7 @@ module Dryml
431
444
  el.attributes['for'] || @containing_tag_name
432
445
  end
433
446
  local_name = param_content_local_name(name)
434
- "<%= #{local_name} && #{local_name}.call %>"
447
+ "<%= #{local_name}.call if #{local_name} %>"
435
448
  end
436
449
 
437
450
 
@@ -459,7 +472,7 @@ module Dryml
459
472
 
460
473
  newlines = "\n" * part_src.count("\n")
461
474
  args = [attribute_to_ruby(dom_id), ":#{part_name}", part_locals].compact
462
- "<%= call_part(#{args * ', '}) #{newlines} %>"
475
+ "<%=raw call_part(#{args * ', '}) #{newlines} %>"
463
476
  end
464
477
 
465
478
 
@@ -477,8 +490,8 @@ module Dryml
477
490
  def part_delegate_tag_name(el)
478
491
  "#{@def_name}_#{el.attributes['part']}__part_delegate"
479
492
  end
480
-
481
-
493
+
494
+
482
495
  def current_def_name
483
496
  @def_element && @def_element.attributes['tag']
484
497
  end
@@ -496,8 +509,8 @@ module Dryml
496
509
  nil
497
510
  end
498
511
  end
499
-
500
-
512
+
513
+
501
514
  def inside_def_for_type?
502
515
  @def_element && @def_element.attributes['for']
503
516
  end
@@ -505,7 +518,7 @@ module Dryml
505
518
 
506
519
  def call_name(el)
507
520
  dryml_exception("invalid tag name (remember to use '-' rather than '_')", el) unless el.dryml_name =~ /^#{DRYML_NAME}(\.#{DRYML_NAME})*$/
508
-
521
+
509
522
  name = Dryml.unreserve(ruby_name(el.dryml_name))
510
523
  if call_to_self_from_type_specific_def?(el)
511
524
  "#{name}__base"
@@ -517,8 +530,8 @@ module Dryml
517
530
  name
518
531
  end
519
532
  end
520
-
521
-
533
+
534
+
522
535
  def old_tag_call?(el)
523
536
  @def_element && el.dryml_name == "old-#{current_def_name}"
524
537
  end
@@ -527,7 +540,7 @@ module Dryml
527
540
  def call_to_self_from_type_specific_def?(el)
528
541
  inside_def_for_type? && el.dryml_name == current_def_name &&!el.attributes['for-type']
529
542
  end
530
-
543
+
531
544
 
532
545
  def polymorphic_call_type(el)
533
546
  t = el.attributes['for-type']
@@ -537,7 +550,7 @@ module Dryml
537
550
  'this_type'
538
551
  elsif t =~ /^[A-Z]/
539
552
  t
540
- elsif t =~ /^[a-z]/ && defined? HoboFields.to_class
553
+ elsif t =~ /^[a-z]/ && defined?(HoboFields.to_class)
541
554
  klass = HoboFields.to_class(t)
542
555
  klass.name
543
556
  elsif is_code_attribute?(t)
@@ -607,7 +620,7 @@ module Dryml
607
620
  call_type = nil
608
621
 
609
622
  metadata_name = containing_tag_name || el.expanded_name
610
-
623
+
611
624
  param_items = el.map do |node|
612
625
  case node
613
626
  when REXML::Text
@@ -642,7 +655,7 @@ module Dryml
642
655
  param_items = " :default => #{default_param_proc(el, containing_tag_name)}, "
643
656
  end
644
657
  end
645
-
658
+
646
659
  param_items.concat without_parameters(el)
647
660
 
648
661
  merge_params = el.attributes['merge-params'] || merge_attribute(el)
@@ -660,8 +673,8 @@ module Dryml
660
673
  "{#{param_items}}"
661
674
  end
662
675
  end
663
-
664
-
676
+
677
+
665
678
  def without_parameters(el)
666
679
  without_names = el.attributes.keys.map { |name| name =~ /^without-(.*)/ and $1 }.compact
667
680
  without_names.map { |name| ":#{ruby_name name}_replacement => proc {|__discard__| '' }, " }.join
@@ -738,8 +751,8 @@ module Dryml
738
751
  end
739
752
 
740
753
 
741
- def param_proc(el, metadata_name_prefix)
742
- metadata_name = "#{metadata_name_prefix}><#{el.name}"
754
+ def param_proc(el, metadata_name_suffix)
755
+ metadata_name = "#{el.name} < #{metadata_name_suffix}"
743
756
 
744
757
  nl = tag_newlines(el)
745
758
 
@@ -780,7 +793,10 @@ module Dryml
780
793
  part_name = el.attributes['part']
781
794
  if part_name
782
795
  part_id = el.attributes['id'] || part_name
783
- "<div class='part-wrapper' id='<%= #{attribute_to_ruby part_id} %>'>#{part_element(el, call)}</div>"
796
+
797
+ "<% safe_concat(\"<div class='part-wrapper' id='#{attribute_to_ruby(part_id)[1..-2]}'>\") %>" +
798
+ part_element(el, call) +
799
+ "<% safe_concat(%(</div>)) %>"
784
800
  else
785
801
  call
786
802
  end
@@ -799,7 +815,7 @@ module Dryml
799
815
 
800
816
  next if n.in?(SPECIAL_ATTRIBUTES) || n =~ /^without-/
801
817
  next if el.attributes['part'] && n == 'id' # The id is rendered on the <div class="part-wrapper"> instead
802
-
818
+
803
819
  ":#{ruby_name n} => #{attribute_to_ruby(v)}"
804
820
  end.compact
805
821
 
@@ -817,8 +833,8 @@ module Dryml
817
833
  hash
818
834
  end
819
835
  end
820
-
821
-
836
+
837
+
822
838
  def compile_merge_attrs(el)
823
839
  merge_attrs = el.attributes['merge-attrs']
824
840
  if merge_attrs == "&true"
@@ -830,7 +846,7 @@ module Dryml
830
846
  "(all_attributes & #{merge_attr_names.inspect})"
831
847
  end
832
848
  end
833
-
849
+
834
850
 
835
851
  def static_tag_to_method_call(el)
836
852
  part = el.attributes["part"]
@@ -877,15 +893,11 @@ module Dryml
877
893
  else
878
894
  start_tag_src = el.start_tag_source.gsub(REXML::CData::START, "").gsub(REXML::CData::STOP, "")
879
895
 
880
- # Allow #{...} as an alternate to <%= ... %>
881
- start_tag_src.gsub!(/=\s*('.*?'|".*?")/) do |s|
882
- s.gsub(/#\{(.*?)\}/, '<%= \1 %>')
883
- end
884
-
896
+ sts = "<% safe_concat(%(#{start_tag_src}))%>"
885
897
  if el.has_end_tag?
886
- start_tag_src + children_to_erb(el) + "</#{el.name}>"
898
+ sts + children_to_erb(el) + "<% safe_concat(%(</#{el.name}>)) %>"
887
899
  else
888
- start_tag_src
900
+ sts
889
901
  end
890
902
  end
891
903
  end
@@ -947,7 +959,11 @@ module Dryml
947
959
  "(#{attr[1..-1]})"
948
960
  else
949
961
  if attr !~ /"/
950
- '"' + attr + '"'
962
+ if attr =~ /\#\{/
963
+ '"' + attr + '"'
964
+ else
965
+ '"' + attr + '"'
966
+ end
951
967
  elsif attr !~ /'/
952
968
  "'#{attr}'"
953
969
  else
@@ -1010,9 +1026,7 @@ module Dryml
1010
1026
  end
1011
1027
 
1012
1028
  def include_source_metadata
1013
- # disabled for now -- we're still getting broken rendering with this feature on
1014
- return false
1015
- @include_source_metadata = RAILS_ENV == "development" && !ENV['DRYML_EDITOR'].blank? if @include_source_metadata.nil?
1029
+ @include_source_metadata = Rails.env.development? && !ENV['DRYML_EDITOR'].blank? if @include_source_metadata.nil?
1016
1030
  @include_source_metadata
1017
1031
  end
1018
1032