pivotal-erector 0.5.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 +81 -0
- data/VERSION.yml +4 -0
- data/bin/erect +7 -0
- data/lib/erector/erect.rb +148 -0
- data/lib/erector/erected.rb +63 -0
- data/lib/erector/extensions/object.rb +18 -0
- data/lib/erector/indenting.rb +36 -0
- data/lib/erector/rails/extensions/action_controller/1.2.5/action_controller.rb +17 -0
- data/lib/erector/rails/extensions/action_controller/2.2.0/action_controller.rb +26 -0
- data/lib/erector/rails/extensions/action_controller.rb +8 -0
- data/lib/erector/rails/extensions/action_view.rb +21 -0
- data/lib/erector/rails/extensions/widget/1.2.5/widget.rb +18 -0
- data/lib/erector/rails/extensions/widget/2.2.0/widget.rb +36 -0
- data/lib/erector/rails/extensions/widget.rb +117 -0
- data/lib/erector/rails/supported_rails_versions.rb +14 -0
- data/lib/erector/rails/template_handlers/1.2.5/action_view_template_handler.rb +32 -0
- data/lib/erector/rails/template_handlers/2.0.0/action_view_template_handler.rb +36 -0
- data/lib/erector/rails/template_handlers/2.1.0/action_view_template_handler.rb +31 -0
- data/lib/erector/rails/template_handlers/2.2.0/action_view_template_handler.rb +46 -0
- data/lib/erector/rails/template_handlers/action_view_template_handler.rb +14 -0
- data/lib/erector/rails.rb +6 -0
- data/lib/erector/raw_string.rb +8 -0
- data/lib/erector/rhtml.treetop +156 -0
- data/lib/erector/unicode.rb +18185 -0
- data/lib/erector/unicode_builder.rb +67 -0
- data/lib/erector/version.rb +10 -0
- data/lib/erector/widget.rb +510 -0
- data/lib/erector/widgets/table.rb +96 -0
- data/lib/erector/widgets.rb +2 -0
- data/lib/erector.rb +16 -0
- data/spec/core_spec_suite.rb +3 -0
- data/spec/erect/erect_spec.rb +145 -0
- data/spec/erect/erected_spec.rb +80 -0
- data/spec/erect/rhtml_parser_spec.rb +318 -0
- data/spec/erector/indentation_spec.rb +136 -0
- data/spec/erector/unicode_builder_spec.rb +75 -0
- data/spec/erector/widget_spec.rb +657 -0
- data/spec/erector/widgets/table_spec.rb +99 -0
- data/spec/rails_spec_suite.rb +3 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/spec_suite.rb +45 -0
- metadata +118 -0
data/README.txt
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
= Erector
|
2
|
+
|
3
|
+
* http://erector.rubyforge.org
|
4
|
+
* mailto:erector-devel@rubyforge.org
|
5
|
+
* http://www.pivotaltracker.com/projects/482
|
6
|
+
|
7
|
+
== DESCRIPTION
|
8
|
+
|
9
|
+
Erector is a Builder-like view framework, inspired by Markaby but overcoming
|
10
|
+
some of its flaws. In Erector all views are objects, not template files,
|
11
|
+
which allows the full power of object-oriented programming (inheritance,
|
12
|
+
modular decomposition, encapsulation) in views. See the rdoc for the
|
13
|
+
Erector::Widget class to learn how to make your own widgets, and visit the
|
14
|
+
project site at http://erector.rubyforge.org for more documentation.
|
15
|
+
|
16
|
+
== SYNOPSIS
|
17
|
+
|
18
|
+
require 'erector'
|
19
|
+
|
20
|
+
class Hello < Erector::Widget
|
21
|
+
def render
|
22
|
+
html do
|
23
|
+
head do
|
24
|
+
title "Hello"
|
25
|
+
end
|
26
|
+
body do
|
27
|
+
text "Hello, "
|
28
|
+
b "world!", :class => 'big'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Hello.new.to_s
|
35
|
+
=> "<html><head><title>Hello</title></head><body>Hello, <b class=\"big\">world!</b></body></html>"
|
36
|
+
|
37
|
+
== REQUIREMENTS
|
38
|
+
|
39
|
+
The gem depends on rake and treetop, although this is just for using the "erect" tool,
|
40
|
+
so deployed applications won't need these. Currently it also requires rails, although
|
41
|
+
we plan to separate the rails-dependent code so you can use Erector cleanly in a non-Rails app.
|
42
|
+
|
43
|
+
== INSTALL
|
44
|
+
|
45
|
+
To install as a gem:
|
46
|
+
|
47
|
+
* sudo gem install erector
|
48
|
+
|
49
|
+
Then add "require 'erector'" to any files which need erector.
|
50
|
+
|
51
|
+
To install as a Rails plugin:
|
52
|
+
|
53
|
+
* Copy the erector source to vendor/plugins/erector in your Rails directory.
|
54
|
+
|
55
|
+
When installing this way, erector is automatically available to your Rails code
|
56
|
+
(no require directive is needed).
|
57
|
+
|
58
|
+
== LICENSE:
|
59
|
+
|
60
|
+
(The MIT License)
|
61
|
+
|
62
|
+
Copyright (c) 2007-8 Pivotal Labs
|
63
|
+
|
64
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
65
|
+
a copy of this software and associated documentation files (the
|
66
|
+
"Software"), to deal in the Software without restriction, including
|
67
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
68
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
69
|
+
permit persons to whom the Software is furnished to do so, subject to
|
70
|
+
the following conditions:
|
71
|
+
|
72
|
+
The above copyright notice and this permission notice shall be
|
73
|
+
included in all copies or substantial portions of the Software.
|
74
|
+
|
75
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
76
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
77
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
78
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
79
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
80
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
81
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/VERSION.yml
ADDED
data/bin/erect
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require "rake"
|
3
|
+
require "erector/erected" # pull this out so we don't recreate the grammar every time
|
4
|
+
|
5
|
+
module Erector
|
6
|
+
class Erect
|
7
|
+
attr_reader :files, :verbose, :mode, :output_dir
|
8
|
+
def initialize(args)
|
9
|
+
@verbose = true
|
10
|
+
@mode = :to_erector
|
11
|
+
@output_dir = nil
|
12
|
+
|
13
|
+
opts = OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: erect [options] [file|dir]*"
|
15
|
+
|
16
|
+
opts.separator "Converts from html/rhtml files to erector widgets, or from erector widgets to html files"
|
17
|
+
opts.separator ""
|
18
|
+
opts.separator "Options:"
|
19
|
+
|
20
|
+
opts.on("-q", "--quiet",
|
21
|
+
"Operate silently except in case of error") do |quiet|
|
22
|
+
@verbose = !quiet
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("--to-erector", "(default) Convert from html/rhtml to erector classes") do
|
26
|
+
@mode = :to_erector
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("--to-html", "Convert from erector to html") do
|
30
|
+
@mode = :to_html
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-o", "--output-dir DIRECTORY", "Output files to DIRECTORY (default: output files go next to input files)") do |dir|
|
34
|
+
@output_dir = dir
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
38
|
+
@mode = :help
|
39
|
+
puts opts
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on_tail("-v", "--version", "Show version") do
|
44
|
+
puts Erector::VERSION
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
opts.parse!(args)
|
50
|
+
@files = args
|
51
|
+
explode_dirs
|
52
|
+
end
|
53
|
+
|
54
|
+
def say(msg)
|
55
|
+
print msg if verbose
|
56
|
+
end
|
57
|
+
|
58
|
+
#todo: unit test
|
59
|
+
def explode_dirs
|
60
|
+
exploded_files = FileList.new
|
61
|
+
files.each do |file|
|
62
|
+
if File.directory?(file)
|
63
|
+
exploded_files.add(explode(file))
|
64
|
+
else
|
65
|
+
exploded_files.add(file)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@files = exploded_files
|
69
|
+
end
|
70
|
+
|
71
|
+
def explode(dir)
|
72
|
+
case mode
|
73
|
+
when :to_erector
|
74
|
+
FileList["#{dir}/**/*.rhtml", "#{dir}/**/*.html", "#{dir}/**/*.html.erb"]
|
75
|
+
when :to_html
|
76
|
+
FileList["#{dir}/**/*.rb"]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def run
|
81
|
+
self.send(mode)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_erector
|
85
|
+
files.each do |file|
|
86
|
+
say "Erecting #{file}... "
|
87
|
+
begin
|
88
|
+
e = Erector::Erected.new(file)
|
89
|
+
e.convert
|
90
|
+
say " --> #{e.filename}\n"
|
91
|
+
rescue => e
|
92
|
+
puts e
|
93
|
+
puts e.backtrace.join("\n\t")
|
94
|
+
puts
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_html
|
100
|
+
files.each do |file|
|
101
|
+
say "Erecting #{file}... "
|
102
|
+
#todo: move this into Erected with better tests for the naming methods
|
103
|
+
begin
|
104
|
+
#todo: fail if file isn't a .rb file
|
105
|
+
require file
|
106
|
+
#todo: understand modulized widgets (e.g. class Foo::Bar::Baz < Erector::Widget in baz.rb)
|
107
|
+
filename = file.split('/').last.gsub(/\.rb$/, '')
|
108
|
+
widget_name = camelize(filename)
|
109
|
+
widget_class = constantize(widget_name)
|
110
|
+
|
111
|
+
if widget_class < Erector::Widget
|
112
|
+
widget = widget_class.new
|
113
|
+
#todo: skip if it's missing a no-arg constructor
|
114
|
+
dir = output_dir || File.dirname(file)
|
115
|
+
FileUtils.mkdir_p(dir)
|
116
|
+
output_file = "#{dir}/#{filename}.html"
|
117
|
+
File.open(output_file, "w") do |f|
|
118
|
+
f.puts widget.to_s
|
119
|
+
end
|
120
|
+
say " --> #{output_file}\n"
|
121
|
+
else
|
122
|
+
say " -- not a widget, skipping\n"
|
123
|
+
end
|
124
|
+
rescue => e
|
125
|
+
puts e
|
126
|
+
puts e.backtrace.join("\n\t")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# stolen from activesuppport/lib/inflector.rb
|
132
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
133
|
+
if first_letter_in_uppercase
|
134
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
135
|
+
else
|
136
|
+
lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
def constantize(camel_cased_word)
|
140
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
141
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
142
|
+
end
|
143
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'treetop'
|
3
|
+
dir = File.dirname(__FILE__)
|
4
|
+
require "#{dir}/indenting"
|
5
|
+
Treetop.load("#{dir}/rhtml.treetop")
|
6
|
+
|
7
|
+
module Erector
|
8
|
+
class Erected
|
9
|
+
def initialize(in_file)
|
10
|
+
@in_file = in_file
|
11
|
+
end
|
12
|
+
|
13
|
+
def filename
|
14
|
+
dir + basename + ".rb"
|
15
|
+
end
|
16
|
+
|
17
|
+
def classname
|
18
|
+
base = classize(basename)
|
19
|
+
parent = File.dirname(@in_file)
|
20
|
+
grandparent = File.dirname(parent)
|
21
|
+
if File.basename(grandparent) == "views"
|
22
|
+
base = "Views::" + classize(File.basename(parent)) + "::" + base
|
23
|
+
end
|
24
|
+
base
|
25
|
+
end
|
26
|
+
|
27
|
+
def text
|
28
|
+
File.read(@in_file)
|
29
|
+
end
|
30
|
+
|
31
|
+
def convert
|
32
|
+
parser = RhtmlParser.new
|
33
|
+
parsed = parser.parse(File.read(@in_file))
|
34
|
+
if parsed.nil?
|
35
|
+
raise "Could not parse #{@in_file}\n" +
|
36
|
+
parser.failure_reason
|
37
|
+
else
|
38
|
+
File.open(filename, "w") do |f|
|
39
|
+
f.puts("class #{classname} < Erector::Widget")
|
40
|
+
f.puts(" def render")
|
41
|
+
f.puts(parsed.set_indent(2).convert)
|
42
|
+
f.puts(" end")
|
43
|
+
f.puts("end")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def basename
|
51
|
+
@in_file.split("/").last.gsub(/\..*$/, '')
|
52
|
+
end
|
53
|
+
|
54
|
+
def dir
|
55
|
+
x = File.dirname(@in_file)
|
56
|
+
return (x == ".") ? "" : "#{x}/"
|
57
|
+
end
|
58
|
+
|
59
|
+
def classize(filename)
|
60
|
+
filename.split("_").map{|part| part.capitalize}.join
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Object
|
2
|
+
def metaclass
|
3
|
+
class << self; self; end
|
4
|
+
end
|
5
|
+
|
6
|
+
def html_escape
|
7
|
+
return CGI.escapeHTML(to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def html_unescape
|
11
|
+
CGI.unescapeHTML(to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
def escape_single_quotes
|
15
|
+
self.gsub(/[']/, '\\\\\'')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'treetop'
|
3
|
+
|
4
|
+
module Erector
|
5
|
+
class Indenting < Treetop::Runtime::SyntaxNode #:nodoc:
|
6
|
+
@@indent = 0
|
7
|
+
|
8
|
+
def set_indent(x)
|
9
|
+
@@indent = x
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def indent
|
14
|
+
[0, @@indent].max
|
15
|
+
end
|
16
|
+
|
17
|
+
def indented(s)
|
18
|
+
" " * indent + s + "\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
def line(s)
|
22
|
+
indented(s)
|
23
|
+
end
|
24
|
+
|
25
|
+
def line_in(s)
|
26
|
+
s = indented(s)
|
27
|
+
@@indent += 1
|
28
|
+
s
|
29
|
+
end
|
30
|
+
|
31
|
+
def line_out(s)
|
32
|
+
@@indent -= 1
|
33
|
+
indented(s)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
ActionController::Base.class_eval do
|
2
|
+
def render_widget(widget_class, assigns=@assigns)
|
3
|
+
@__widget_class = widget_class
|
4
|
+
@__widget_assigns = assigns
|
5
|
+
add_variables_to_assigns
|
6
|
+
render :inline => "<% @__widget_class.new(self, @__widget_assigns, _erbout).render %>"
|
7
|
+
end
|
8
|
+
|
9
|
+
def render_with_erector_widget(*options, &block)
|
10
|
+
if options.first.is_a?(Hash) && widget = options.first.delete(:widget)
|
11
|
+
render_widget widget, @assigns, &block
|
12
|
+
else
|
13
|
+
render_without_erector_widget *options, &block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
alias_method_chain :render, :erector_widget
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
ActionController::Base.class_eval do
|
2
|
+
def render_widget(widget_class, assigns=nil)
|
3
|
+
@__widget_class = widget_class
|
4
|
+
if assigns
|
5
|
+
@__widget_assigns = assigns
|
6
|
+
else
|
7
|
+
@__widget_assigns = {}
|
8
|
+
variables = instance_variable_names
|
9
|
+
variables -= protected_instance_variables
|
10
|
+
variables.each do |name|
|
11
|
+
@__widget_assigns[name.sub('@', "")] = instance_variable_get(name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
response.template.send(:_evaluate_assigns_and_ivars)
|
15
|
+
render :inline => "<% @__widget_class.new(self, @__widget_assigns, output_buffer).render %>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_with_erector_widget(*options, &block)
|
19
|
+
if options.first.is_a?(Hash) && widget = options.first.delete(:widget)
|
20
|
+
render_widget widget, @assigns, &block
|
21
|
+
else
|
22
|
+
render_without_erector_widget *options, &block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
alias_method_chain :render, :erector_widget
|
26
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
if (
|
3
|
+
ActionController::Base.instance_methods + ActionController::Base.private_instance_methods).
|
4
|
+
include?("add_variables_to_assigns")
|
5
|
+
require File.expand_path("#{dir}/action_controller/1.2.5/action_controller")
|
6
|
+
else
|
7
|
+
require File.expand_path("#{dir}/action_controller/2.2.0/action_controller")
|
8
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
unless ActionView.const_defined?(:Template)
|
2
|
+
ActionView::Base.class_eval do
|
3
|
+
attr_reader :template_file_path
|
4
|
+
def render_template_with_saving_file_path(template_extension, template, file_path = nil, local_assigns = {})
|
5
|
+
@template_file_path = file_path
|
6
|
+
render_template_without_saving_file_path(template_extension, template, file_path, local_assigns)
|
7
|
+
end
|
8
|
+
alias_method_chain :render_template, :saving_file_path
|
9
|
+
|
10
|
+
def render_partial_with_notification(*args, &blk)
|
11
|
+
@is_partial_template = true
|
12
|
+
render_partial_without_notification(*args, &blk)
|
13
|
+
end
|
14
|
+
alias_method_chain :render_partial, :notification
|
15
|
+
|
16
|
+
def is_partial_template?
|
17
|
+
@is_partial_template || false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Erector
|
2
|
+
Widget.class_eval do
|
3
|
+
attr_reader :_erbout
|
4
|
+
|
5
|
+
after_initialize do
|
6
|
+
@_erbout = output
|
7
|
+
end
|
8
|
+
|
9
|
+
def define_javascript_functions(*args)
|
10
|
+
begin
|
11
|
+
text raw(helpers.define_javascript_functions(*args))
|
12
|
+
rescue => e
|
13
|
+
puts e.backtrace.join("\n\t")
|
14
|
+
raise e
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Erector
|
2
|
+
Widget.class_eval do
|
3
|
+
def output
|
4
|
+
process_output_buffer || @output
|
5
|
+
end
|
6
|
+
|
7
|
+
def capture_with_helpers(&block)
|
8
|
+
helpers ? helpers.capture(&block) : capture_without_helpers(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
alias_method_chain :capture, :helpers
|
12
|
+
|
13
|
+
# This is here to force #helpers.capture to return the output
|
14
|
+
def __in_erb_template; end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def process_output_buffer
|
19
|
+
if helpers.respond_to?(:output_buffer)
|
20
|
+
buffer = helpers.output_buffer
|
21
|
+
buffer.is_a?(String) ? buffer : handle_rjs_buffer
|
22
|
+
else
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def handle_rjs_buffer
|
28
|
+
returning buffer = helpers.output_buffer.dup.to_s do
|
29
|
+
helpers.output_buffer.clear
|
30
|
+
helpers.with_output_buffer(buffer) do
|
31
|
+
buffer << helpers.output_buffer.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Erector
|
2
|
+
Widget.class_eval do
|
3
|
+
include ActionController::UrlWriter
|
4
|
+
|
5
|
+
# helpers returning raw text
|
6
|
+
[
|
7
|
+
:image_tag,
|
8
|
+
:javascript_include_tag,
|
9
|
+
:stylesheet_link_tag,
|
10
|
+
:sortable_element,
|
11
|
+
:sortable_element_js,
|
12
|
+
:text_field_with_auto_complete,
|
13
|
+
].each do |helper_name|
|
14
|
+
define_method helper_name do |*args|
|
15
|
+
begin
|
16
|
+
text raw(helpers.send(helper_name, *args))
|
17
|
+
rescue => e
|
18
|
+
puts e.backtrace.join("\n\t")
|
19
|
+
raise e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# helpers returning raw text whose first parameter is HTML escaped
|
25
|
+
[
|
26
|
+
:link_to,
|
27
|
+
:link_to_remote,
|
28
|
+
:mail_to,
|
29
|
+
:button_to,
|
30
|
+
:submit_tag,
|
31
|
+
].each do |helper_name|
|
32
|
+
|
33
|
+
method_def =<<-METHOD_DEF
|
34
|
+
def #{helper_name}(link_text, *args, &block)
|
35
|
+
text raw(helpers.#{helper_name}(h(link_text), *args, &block))
|
36
|
+
end
|
37
|
+
METHOD_DEF
|
38
|
+
eval(method_def)
|
39
|
+
end
|
40
|
+
|
41
|
+
def error_messages_for(*args)
|
42
|
+
text raw(helpers.error_messages_for(*args))
|
43
|
+
end
|
44
|
+
|
45
|
+
# return text, take block
|
46
|
+
[
|
47
|
+
:link_to_function,
|
48
|
+
:text_field_tag,
|
49
|
+
:password_field_tag,
|
50
|
+
:check_box_tag
|
51
|
+
].each do |method_to_proxy_with_block|
|
52
|
+
method_def =<<-METHOD_DEF
|
53
|
+
def #{method_to_proxy_with_block}(*args, &block)
|
54
|
+
text raw(helpers.#{method_to_proxy_with_block}(*args, &block))
|
55
|
+
end
|
56
|
+
METHOD_DEF
|
57
|
+
eval(method_def)
|
58
|
+
end
|
59
|
+
|
60
|
+
# render text, take block
|
61
|
+
[
|
62
|
+
:error_messages_for,
|
63
|
+
:form_tag,
|
64
|
+
:form_for,
|
65
|
+
].each do |method_to_proxy_with_block|
|
66
|
+
method_def =<<-METHOD_DEF
|
67
|
+
def #{method_to_proxy_with_block}(*args, &block)
|
68
|
+
helpers.#{method_to_proxy_with_block}(*args, &block)
|
69
|
+
end
|
70
|
+
METHOD_DEF
|
71
|
+
eval(method_def)
|
72
|
+
end
|
73
|
+
|
74
|
+
def javascript_include_merged(key)
|
75
|
+
helpers.javascript_include_merged(key)
|
76
|
+
end
|
77
|
+
|
78
|
+
def stylesheet_link_merged(key)
|
79
|
+
helpers.stylesheet_link_merged(key)
|
80
|
+
end
|
81
|
+
|
82
|
+
def flash
|
83
|
+
helpers.controller.send(:flash)
|
84
|
+
end
|
85
|
+
|
86
|
+
def session
|
87
|
+
helpers.controller.session
|
88
|
+
end
|
89
|
+
|
90
|
+
def controller
|
91
|
+
helpers.controller
|
92
|
+
end
|
93
|
+
|
94
|
+
def cycle(*args)
|
95
|
+
helpers.cycle(*args)
|
96
|
+
end
|
97
|
+
|
98
|
+
def simple_format(string)
|
99
|
+
p raw(string.to_s.html_escape.gsub(/\r\n?/, "\n").gsub(/\n/, "<br/>\n"))
|
100
|
+
end
|
101
|
+
|
102
|
+
def time_ago_in_words(*args)
|
103
|
+
helpers.time_ago_in_words(*args)
|
104
|
+
end
|
105
|
+
|
106
|
+
def pluralize(*args)
|
107
|
+
helpers.pluralize(*args)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
dir = File.dirname(__FILE__)
|
113
|
+
if ActionView::Base.instance_methods.include?("output_buffer")
|
114
|
+
require "#{dir}/widget/2.2.0/widget"
|
115
|
+
else
|
116
|
+
require "#{dir}/widget/1.2.5/widget"
|
117
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Erector
|
2
|
+
module Rails
|
3
|
+
SUPPORTED_RAILS_VERSIONS = {
|
4
|
+
# "1.2.5" => {'version' => '1.2.5', 'git_tag' => 'v1.2.5'},
|
5
|
+
"1.99.0" => {'version' => '1.99.0', 'git_tag' => 'v2.0.0_RC1'},
|
6
|
+
"2.0.2" => {'version' => '2.0.2', 'git_tag' => 'v2.0.2'},
|
7
|
+
"2.1.0" => {'version' => '2.1.0', 'git_tag' => 'v2.1.0'},
|
8
|
+
"2.2.0" => {'version' => '2.2.0', 'git_tag' => 'v2.2.0'},
|
9
|
+
"2.2.2" => {'version' => '2.2.2', 'git_tag' => 'v2.2.2'},
|
10
|
+
"2.3.2" => {'version' => '2.3.2', 'git_tag' => 'v2.3.2'},
|
11
|
+
# "edge" => {'version' => 'edge', 'git_tag' => 'master'}, #TODO: Readd edge support
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActionView #:nodoc:
|
2
|
+
module TemplateHandlers #:nodoc:
|
3
|
+
class Erector
|
4
|
+
def self.line_offset
|
5
|
+
2
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :view
|
9
|
+
def initialize(view)
|
10
|
+
@view = view
|
11
|
+
end
|
12
|
+
|
13
|
+
def compilable?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
ActionView::Base.register_template_handler :rb, ActionView::TemplateHandlers::Erector
|
18
|
+
|
19
|
+
def render(template, local_assigns)
|
20
|
+
relative_path_parts = view.first_render.split('/')
|
21
|
+
require_dependency view.template_file_path
|
22
|
+
|
23
|
+
dot_rb = /\.rb$/
|
24
|
+
widget_class = relative_path_parts.inject(Views) do |mod, node|
|
25
|
+
mod.const_get(node.gsub(dot_rb, '').gsub(".html", "").camelize)
|
26
|
+
end
|
27
|
+
render_method = view.is_partial_template? ? 'render_partial' : 'render'
|
28
|
+
widget_class.new(view, view.assigns).to_s(render_method)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|