erector 0.7.0 → 0.7.1

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.txt CHANGED
@@ -13,6 +13,8 @@ modular decomposition, encapsulation) in views. See the rdoc for the
13
13
  Erector::Widget class to learn how to make your own widgets, and visit the
14
14
  project site at http://erector.rubyforge.org for more documentation.
15
15
 
16
+ No, seriously, we've got hella docs at http://erector.rubyforge.org
17
+
16
18
  == SYNOPSIS
17
19
 
18
20
  require 'erector'
@@ -25,7 +27,7 @@ project site at http://erector.rubyforge.org for more documentation.
25
27
  end
26
28
  body do
27
29
  text "Hello, "
28
- b target, :class => 'big'
30
+ b @target, :class => 'big'
29
31
  text "!"
30
32
  end
31
33
  end
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 7
4
- :patch: 0
4
+ :patch: 1
@@ -6,6 +6,7 @@ require "active_support/inflector"
6
6
  require "active_support/inflections"
7
7
  require "#{dir}/erector/extensions/object"
8
8
  require "#{dir}/erector/raw_string"
9
+ require "#{dir}/erector/externals"
9
10
  require "#{dir}/erector/widget"
10
11
  require "#{dir}/erector/inline"
11
12
  require "#{dir}/erector/unicode"
@@ -0,0 +1,29 @@
1
+ module Erector
2
+ module Externals
3
+ def externals(type, klass = nil)
4
+ type = type.to_sym
5
+ assure_externals_declared(type, klass)
6
+ x = @@externals[type].dup
7
+ if klass
8
+ x.select{|value| @@externals[klass].include?(value)}
9
+ else
10
+ x
11
+ end
12
+ end
13
+
14
+ def assure_externals_declared(type, klass)
15
+ @@externals ||= {}
16
+ @@externals[type] ||= []
17
+ @@externals[klass] ||= [] if klass
18
+ end
19
+
20
+ def external(type, value)
21
+ type = type.to_sym
22
+ klass = self # since it's a class method, self should be the class itself
23
+ assure_externals_declared(type, klass)
24
+ @@externals[type] << value unless @@externals[type].include?(value)
25
+ @@externals[klass] << value unless @@externals[klass].include?(value)
26
+ end
27
+ end
28
+
29
+ end
@@ -1,7 +1,10 @@
1
1
  dir = File.dirname(__FILE__)
2
2
  require "action_controller"
3
3
  require "#{dir}/rails/rails_version"
4
+ require "#{dir}/rails/rails_form_builder"
4
5
  require "#{dir}/rails/extensions/rails_widget"
5
6
  require "#{dir}/rails/extensions/action_controller"
6
7
  require "#{dir}/rails/extensions/action_view"
7
- require "#{dir}/rails/template_handlers/action_view_template_handler"
8
+ require "#{dir}/rails/extensions/rails_widget/rails_helpers"
9
+ require "#{dir}/rails/template_handlers/rb_handler"
10
+ require "#{dir}/rails/template_handlers/ert_handler"
@@ -12,7 +12,7 @@ ActionController::Base.class_eval do
12
12
  end
13
13
  end
14
14
  response.template.send(:_evaluate_assigns_and_ivars)
15
- render :inline => "<% @__widget_class.new(@__widget_assigns).to_s(:output => output_buffer, :helpers => self) %>"
15
+ render :inline => "<% @__widget_class.new(@__widget_assigns.merge(:parent => self)).to_s %>"
16
16
  end
17
17
 
18
18
  def render_with_erector_widget(*options, &block)
@@ -8,40 +8,37 @@ module Erector
8
8
  process_output_buffer || @output
9
9
  end
10
10
 
11
- def capture_with_helpers(&block)
12
- helpers ? helpers.capture(&block) : capture_without_helpers(&block)
11
+ def capture_with_parent(&block)
12
+ parent ? parent.capture(&block) : capture_without_parent(&block)
13
13
  end
14
14
 
15
- alias_method_chain :capture, :helpers
15
+ alias_method_chain :capture, :parent
16
16
 
17
- # This is here to force #helpers.capture to return the output
17
+ # This is here to force #parent.capture to return the output
18
18
  def __in_erb_template; end
19
19
 
20
20
  private
21
21
 
22
22
  def process_output_buffer
23
- if helpers.respond_to?(:output_buffer)
24
- buffer = helpers.output_buffer
25
- buffer.is_a?(String) ? buffer : handle_rjs_buffer
23
+ if parent.respond_to?(:output_buffer)
24
+ parent.output_buffer.is_a?(String) ? parent.output_buffer : handle_rjs_buffer
26
25
  else
27
26
  nil
28
27
  end
29
28
  end
30
29
 
31
30
  def handle_rjs_buffer
32
- returning buffer = helpers.output_buffer.dup.to_s do
33
- helpers.output_buffer.clear
34
- helpers.with_output_buffer(buffer) do
35
- buffer << helpers.output_buffer.to_s
31
+ returning buffer = parent.output_buffer.dup.to_s do
32
+ parent.output_buffer.clear
33
+ parent.with_output_buffer(buffer) do
34
+ buffer << parent.output_buffer.to_s
36
35
  end
37
36
  end
38
37
  end
39
38
  end
40
-
39
+
41
40
  class InlineRailsWidget < RailsWidget
42
41
  include Inline
43
42
  end
44
-
45
- end
46
43
 
47
- require "#{File.dirname(__FILE__)}/rails_widget/helpers"
44
+ end
@@ -0,0 +1,136 @@
1
+ module Erector
2
+ class RailsWidget < Widget
3
+ module RailsHelpers
4
+ include ActionController::UrlWriter
5
+
6
+ # parent returning raw text whose first parameter is HTML escaped
7
+ ESCAPED_HELPERS = [
8
+ :link_to,
9
+ :link_to_remote,
10
+ :mail_to,
11
+ :button_to,
12
+ :submit_tag,
13
+ ]
14
+ ESCAPED_HELPERS.each do |method_name|
15
+ start_line = __LINE__ + 2
16
+ method_def =<<-METHOD_DEF
17
+ def #{method_name}(link_text, *args, &block)
18
+ rawtext(parent.#{method_name}(h(link_text), *args, &block))
19
+ end
20
+ METHOD_DEF
21
+ eval(method_def, binding, __FILE__, start_line)
22
+ end
23
+
24
+ # return text, take block
25
+ RAW_HELPERS = [
26
+ :link_to_function,
27
+ :text_field_tag,
28
+ :password_field_tag,
29
+ :check_box_tag,
30
+ :error_messages_for,
31
+ :submit_tag,
32
+ :file_field,
33
+ :image_tag,
34
+ :javascript_include_tag,
35
+ :stylesheet_link_tag,
36
+ :sortable_element,
37
+ :sortable_element_js,
38
+ :text_field_with_auto_complete
39
+ ]
40
+ RAW_HELPERS.each do |method_name|
41
+ start_line = __LINE__ + 2
42
+ method_def =<<-METHOD_DEF
43
+ def #{method_name}(*args, &block)
44
+ rawtext parent.#{method_name}(*args, &block)
45
+ end
46
+ METHOD_DEF
47
+ eval(method_def, binding, __FILE__, start_line)
48
+ end
49
+
50
+ CAPTURED_HELPERS_WITHOUT_CONCAT = [
51
+ :render
52
+ ]
53
+ CAPTURED_HELPERS_WITHOUT_CONCAT.each do |method_name|
54
+ start_line = __LINE__ + 2
55
+ method_def =<<-METHOD_DEF
56
+ def #{method_name}(*args, &block)
57
+ captured = parent.capture do
58
+ parent.concat(parent.#{method_name}(*args, &block))
59
+ parent.output_buffer.to_s
60
+ end
61
+ rawtext(captured)
62
+ end
63
+ METHOD_DEF
64
+ eval(method_def, binding, __FILE__, start_line)
65
+ end
66
+
67
+ CAPTURED_HELPERS_WITH_CONCAT = [
68
+ :form_tag
69
+ ]
70
+ CAPTURED_HELPERS_WITH_CONCAT.each do |method_name|
71
+ start_line = __LINE__ + 2
72
+ method_def =<<-METHOD_DEF
73
+ def #{method_name}(*args, &block)
74
+ captured = parent.capture do
75
+ parent.#{method_name}(*args, &block)
76
+ parent.output_buffer.to_s
77
+ end
78
+ rawtext(captured)
79
+ end
80
+ METHOD_DEF
81
+ eval(method_def, binding, __FILE__, start_line)
82
+ end
83
+
84
+ def form_for(record_or_name_or_array, *args, &proc)
85
+ options = args.extract_options!
86
+ options[:builder] ||= ::Erector::RailsFormBuilder
87
+ args.push(options)
88
+ parent.form_for(record_or_name_or_array, *args, &proc)
89
+ end
90
+
91
+ def fields_for(record_or_name_or_array, *args, &proc)
92
+ options = args.extract_options!
93
+ options[:builder] ||= ::Erector::RailsFormBuilder
94
+ args.push(options)
95
+ parent.fields_for(record_or_name_or_array, *args, &proc)
96
+ end
97
+
98
+ def javascript_include_merged(key)
99
+ parent.javascript_include_merged(key)
100
+ end
101
+
102
+ def stylesheet_link_merged(key)
103
+ parent.stylesheet_link_merged(key)
104
+ end
105
+
106
+ def flash
107
+ parent.controller.send(:flash)
108
+ end
109
+
110
+ def session
111
+ parent.controller.session
112
+ end
113
+
114
+ def controller
115
+ parent.controller
116
+ end
117
+
118
+ def cycle(*args)
119
+ parent.cycle(*args)
120
+ end
121
+
122
+ def simple_format(string)
123
+ p raw(string.to_s.html_escape.gsub(/\r\n?/, "\n").gsub(/\n/, "<br/>\n"))
124
+ end
125
+
126
+ def time_ago_in_words(*args)
127
+ parent.time_ago_in_words(*args)
128
+ end
129
+
130
+ def pluralize(*args)
131
+ parent.pluralize(*args)
132
+ end
133
+ end
134
+ include RailsHelpers
135
+ end
136
+ end
@@ -0,0 +1,20 @@
1
+ module Erector
2
+ class RailsFormBuilder
3
+ attr_reader :parent, :template
4
+
5
+ def initialize(object_name, object, template, options, proc)
6
+ @template = template
7
+ @parent = ActionView::Helpers::FormBuilder.new(object_name, object, template, options, proc)
8
+ end
9
+
10
+ def method_missing(method_name, *args, &block)
11
+ if parent.respond_to?(method_name)
12
+ return_value = parent.send(method_name, *args, &block)
13
+ template.concat(return_value) if return_value.is_a?(String)
14
+ return_value
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,6 +1,6 @@
1
1
  module Erector
2
2
  module Rails
3
- RAILS_VERSION = "2.3.2"
4
- RAILS_VERSION_TAG = "v2.3.2"
3
+ RAILS_VERSION = "2.3.4"
4
+ RAILS_VERSION_TAG = "v2.3.4"
5
5
  end
6
6
  end
@@ -0,0 +1,32 @@
1
+ module ActionView #:nodoc:
2
+ module TemplateHandlers #:nodoc:
3
+ class ErtTemplate < TemplateHandler
4
+ include Compilable
5
+ def self.line_offset
6
+ 2
7
+ end
8
+
9
+ ActionView::Template.instance_eval do
10
+ register_template_handler :ert, ActionView::TemplateHandlers::ErtTemplate
11
+ end
12
+
13
+ def compile(template)
14
+ [
15
+ "extend ::Erector::Mixin",
16
+ "@output_buffer = ''",
17
+ "memoized_instance_variables = instance_variables.inject({}) do |all, instance_variable|",
18
+ " all[instance_variable] = instance_variable_get(instance_variable)",
19
+ " all",
20
+ "end",
21
+ "r =::Erector::RailsWidget.inline do",
22
+ " memoized_instance_variables.each do |instance_variable, value|",
23
+ " instance_variable_set(instance_variable, value)",
24
+ " end",
25
+ template.source,
26
+ "end",
27
+ "r.to_s",
28
+ ].join("; ")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,13 +1,13 @@
1
1
  module ActionView #:nodoc:
2
2
  module TemplateHandlers #:nodoc:
3
- class Erector < TemplateHandler
3
+ class RbHandler < TemplateHandler
4
4
  include Compilable
5
5
  def self.line_offset
6
6
  2
7
7
  end
8
8
 
9
9
  ActionView::Template.instance_eval do
10
- register_template_handler :rb, ActionView::TemplateHandlers::Erector
10
+ register_template_handler :rb, ActionView::TemplateHandlers::RbHandler
11
11
  end
12
12
 
13
13
  def compile(template)
@@ -33,6 +33,8 @@ module Erector
33
33
  # like a normal method and leaves it up to the caller to emit that string if
34
34
  # it wants.
35
35
  class Widget
36
+ extend Erector::Externals # 'extend'ing since they're class methods, not instance methods
37
+
36
38
  class << self
37
39
  def all_tags
38
40
  Erector::Widget.full_tags + Erector::Widget.empty_tags
@@ -84,6 +86,7 @@ module Erector
84
86
  def after_initialize_parts
85
87
  @after_initialize_parts ||= []
86
88
  end
89
+
87
90
  end
88
91
 
89
92
  # Class method by which widget classes can declare that they need certain
@@ -153,21 +156,20 @@ module Erector
153
156
 
154
157
  SPACES_PER_INDENT = 2
155
158
 
156
- RESERVED_INSTANCE_VARS = [:helpers, :assigns, :block, :parent, :output, :prettyprint, :indentation, :at_start_of_line]
159
+ RESERVED_INSTANCE_VARS = [:helpers, :assigns, :block, :output, :prettyprint, :indentation, :at_start_of_line]
157
160
 
158
161
  attr_reader *RESERVED_INSTANCE_VARS
162
+ attr_reader :parent
159
163
 
160
164
  def initialize(assigns={}, &block)
161
165
  unless assigns.is_a? Hash
162
166
  raise "Erector's API has changed. Now you should pass only an options hash into Widget.new; the rest come in via to_s, or by using #widget."
163
167
  end
164
- if (respond_to? :render) &&
165
- !self.method(:render).to_s.include?("(RailsWidget)")
166
- raise "Erector's API has changed. You should rename #{self.class}#render to #content."
167
- end
168
168
  @assigns = assigns
169
- assign_locals(assigns)
170
- @parent = block ? eval("self", block.binding) : nil
169
+ assign_instance_variables(assigns)
170
+ unless @parent
171
+ @parent = block ? eval("self", block.binding) : nil
172
+ end
171
173
  @block = block
172
174
  self.class.after_initialize self
173
175
  end
@@ -197,14 +199,14 @@ module Erector
197
199
  end
198
200
 
199
201
  public
200
- def assign_locals(local_assigns)
202
+ def assign_instance_variables (instance_variables)
201
203
  needed = self.class.get_needs.map{|need| need.is_a?(Hash) ? need.keys : need}.flatten
202
204
  assigned = []
203
- local_assigns.each do |name, value|
205
+ instance_variables.each do |name, value|
204
206
  unless needed.empty? || needed.include?(name)
205
207
  raise "Unknown parameter '#{name}'. #{self.class.name} only accepts #{needed.join(', ')}"
206
208
  end
207
- assign_local(name, value)
209
+ assign_instance_variable(name, value)
208
210
  assigned << name
209
211
  end
210
212
 
@@ -212,7 +214,7 @@ module Erector
212
214
  self.class.get_needs.select{|var| var.is_a? Hash}.each do |hash|
213
215
  hash.each_pair do |name, value|
214
216
  unless assigned.include?(name)
215
- assign_local(name, value)
217
+ assign_instance_variable(name, value)
216
218
  assigned << name
217
219
  end
218
220
  end
@@ -224,9 +226,11 @@ module Erector
224
226
  end
225
227
  end
226
228
 
227
- def assign_local(name, value)
229
+ def assign_instance_variable (name, value)
228
230
  raise ArgumentError, "Sorry, #{name} is a reserved variable name for Erector. Please choose a different name." if RESERVED_INSTANCE_VARS.include?(name)
229
- instance_variable_set("@#{name}", value)
231
+ name = name.to_s
232
+ ivar_name = (name[0..0] == '@' ? name : "@#{name}")
233
+ instance_variable_set(ivar_name, value)
230
234
  end
231
235
 
232
236
  # Render (like to_s) but adding newlines and indentation.
@@ -279,14 +283,12 @@ module Erector
279
283
  end
280
284
  end
281
285
 
282
- alias_method :inspect, :to_s
283
-
284
286
  # Template method which must be overridden by all widget subclasses.
285
287
  # Inside this method you call the magic #element methods which emit HTML
286
288
  # and text to the output string. If you call "super" (or don't override
287
289
  # +content+) then your widget will render any block that was passed into
288
290
  # its constructor. If you want this block to have access to Erector methods
289
- # then see Erector::Inline#content.
291
+ # then see Erector::Inline#content or Erector#inline.
290
292
  def content
291
293
  if @block
292
294
  @block.call
@@ -465,6 +467,15 @@ module Erector
465
467
  output << "<?xml#{format_sorted(sort_for_xml_declaration(attributes))}?>"
466
468
  end
467
469
 
470
+ # Emits an HTML comment, which looks like this: &lt;!--foo--&gt;
471
+ # see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
472
+ # Since "Authors should avoid putting two or more adjacent hyphens inside comments,"
473
+ # we emit a warning if you do that.
474
+ def comment(text)
475
+ puts "Warning: Authors should avoid putting two or more adjacent hyphens inside comments." if text =~ /--/
476
+ output << "<!--#{text}-->"
477
+ end
478
+
468
479
  # Creates a whole new output string, executes the block, then converts the
469
480
  # output string to a string and emits it as raw text. If at all possible
470
481
  # you should avoid this method since it hurts performance, and use
@@ -562,6 +573,21 @@ module Erector
562
573
  false
563
574
  end
564
575
  end
576
+
577
+ # emits a jQuery script that is to be run on document ready
578
+ def jquery(txt)
579
+ javascript do
580
+ jquery_ready txt
581
+ end
582
+ end
583
+
584
+ protected
585
+ def jquery_ready(txt)
586
+ rawtext "\n"
587
+ rawtext "$(document).ready(function(){\n"
588
+ rawtext txt
589
+ rawtext "\n});"
590
+ end
565
591
 
566
592
  ### internal utility methods
567
593