erector 0.8.3 → 0.9.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +21 -0
- data/Rakefile +171 -0
- data/VERSION.yml +3 -2
- data/lib/erector.rb +3 -5
- data/lib/erector/abstract_widget.rb +76 -31
- data/lib/erector/attributes.rb +34 -0
- data/lib/erector/caching.rb +1 -0
- data/lib/erector/convenience.rb +12 -4
- data/lib/erector/dependency.rb +2 -1
- data/lib/erector/element.rb +113 -0
- data/lib/erector/erect/erect.rb +10 -7
- data/lib/erector/externals.rb +2 -1
- data/lib/erector/html.rb +6 -340
- data/lib/erector/html_widget.rb +300 -0
- data/lib/erector/inline.rb +1 -1
- data/lib/erector/output.rb +39 -12
- data/lib/erector/promise.rb +137 -0
- data/lib/erector/rails2/extensions/rails_widget.rb +1 -1
- data/lib/erector/rails3.rb +1 -1
- data/lib/erector/sass.rb +14 -19
- data/lib/erector/tag.rb +65 -0
- data/lib/erector/text.rb +123 -0
- data/lib/erector/version.rb +1 -1
- data/lib/erector/widget.rb +52 -12
- data/lib/erector/widgets/page.rb +12 -10
- data/lib/erector/xml_widget.rb +131 -0
- data/spec/erector/caching_spec.rb +1 -0
- data/spec/erector/externals_spec.rb +0 -1
- data/spec/erector/html_spec.rb +9 -25
- data/spec/erector/output_spec.rb +102 -9
- data/spec/erector/promise_spec.rb +173 -0
- data/spec/erector/sass_spec.rb +1 -1
- data/spec/erector/tag_spec.rb +67 -0
- data/spec/erector/widget_spec.rb +53 -2
- data/spec/erector/xml_widget_spec.rb +74 -0
- data/spec/rails2/rails_app/Gemfile +1 -0
- data/spec/rails2/rails_app/spec/rails_spec_helper.rb +2 -0
- data/spec/rails_root/Gemfile +11 -0
- data/spec/rails_root/README +256 -0
- data/spec/rails_root/Rakefile +7 -0
- data/spec/rails_root/app/controllers/application.rb +6 -0
- data/spec/rails_root/app/controllers/application_controller.rb +3 -0
- data/spec/rails_root/app/helpers/application_helper.rb +2 -0
- data/spec/rails_root/app/views/layouts/application.html.erb +14 -0
- data/spec/rails_root/app/views/test/_erb.erb +1 -0
- data/spec/rails_root/app/views/test/_erector.rb +5 -0
- data/spec/rails_root/app/views/test/_partial_with_locals.rb +7 -0
- data/spec/rails_root/app/views/test/bare.rb +5 -0
- data/spec/rails_root/app/views/test/erb_from_erector.html.rb +5 -0
- data/spec/rails_root/app/views/test/erector_from_erb.html.erb +1 -0
- data/spec/rails_root/app/views/test/erector_with_locals_from_erb.html.erb +6 -0
- data/spec/rails_root/app/views/test/implicit_assigns.html.rb +5 -0
- data/spec/rails_root/app/views/test/needs.html.rb +7 -0
- data/spec/rails_root/app/views/test/needs_subclass.html.rb +5 -0
- data/spec/rails_root/app/views/test/protected_instance_variable.html.rb +5 -0
- data/spec/rails_root/app/views/test/render_default.html.rb +5 -0
- data/spec/rails_root/app/views/test/render_partial.html.rb +5 -0
- data/spec/rails_root/config.ru +4 -0
- data/spec/rails_root/config/application.rb +42 -0
- data/spec/rails_root/config/boot.rb +13 -0
- data/spec/rails_root/config/database.yml +22 -0
- data/spec/rails_root/config/environment.rb +5 -0
- data/spec/rails_root/config/environments/development.rb +22 -0
- data/spec/rails_root/config/environments/production.rb +49 -0
- data/spec/rails_root/config/environments/test.rb +35 -0
- data/spec/rails_root/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_root/config/initializers/inflections.rb +10 -0
- data/spec/rails_root/config/initializers/mime_types.rb +5 -0
- data/spec/rails_root/config/initializers/secret_token.rb +7 -0
- data/spec/rails_root/config/initializers/session_store.rb +8 -0
- data/spec/rails_root/config/locales/en.yml +5 -0
- data/spec/rails_root/config/routes.rb +58 -0
- data/spec/rails_root/db/seeds.rb +7 -0
- data/spec/rails_root/doc/README_FOR_APP +2 -0
- data/spec/rails_root/log/development.log +17 -0
- data/spec/rails_root/log/test.log +3750 -0
- data/spec/rails_root/public/404.html +26 -0
- data/spec/rails_root/public/422.html +26 -0
- data/spec/rails_root/public/500.html +26 -0
- data/spec/rails_root/public/dispatch.cgi +10 -0
- data/spec/rails_root/public/dispatch.fcgi +24 -0
- data/spec/rails_root/public/dispatch.rb +10 -0
- data/spec/rails_root/public/favicon.ico +0 -0
- data/spec/rails_root/public/images/rails.png +0 -0
- data/spec/rails_root/public/index.html +262 -0
- data/spec/rails_root/public/javascripts/application.js +2 -0
- data/spec/rails_root/public/javascripts/controls.js +965 -0
- data/spec/rails_root/public/javascripts/dragdrop.js +974 -0
- data/spec/rails_root/public/javascripts/effects.js +1123 -0
- data/spec/rails_root/public/javascripts/prototype.js +6001 -0
- data/spec/rails_root/public/javascripts/rails.js +175 -0
- data/spec/rails_root/public/robots.txt +5 -0
- data/spec/rails_root/script/about +3 -0
- data/spec/rails_root/script/console +3 -0
- data/spec/rails_root/script/destroy +3 -0
- data/spec/rails_root/script/generate +3 -0
- data/spec/rails_root/script/performance/benchmarker +3 -0
- data/spec/rails_root/script/performance/profiler +3 -0
- data/spec/rails_root/script/performance/request +3 -0
- data/spec/rails_root/script/plugin +3 -0
- data/spec/rails_root/script/process/inspector +3 -0
- data/spec/rails_root/script/process/reaper +3 -0
- data/spec/rails_root/script/process/spawner +3 -0
- data/spec/rails_root/script/rails +6 -0
- data/spec/rails_root/script/runner +3 -0
- data/spec/rails_root/script/server +3 -0
- data/spec/rails_root/spec/form_builder_spec.rb +21 -0
- data/spec/rails_root/spec/rails_helpers_spec.rb +220 -0
- data/spec/rails_root/spec/rails_spec_helper.rb +10 -0
- data/spec/rails_root/spec/rails_widget_spec.rb +83 -0
- data/spec/rails_root/spec/render_spec.rb +298 -0
- data/spec/rails_root/test/performance/browsing_test.rb +9 -0
- data/spec/rails_root/test/test_helper.rb +13 -0
- data/spec/spec_helper.rb +3 -1
- metadata +202 -66
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "treetop", ">= 1.2.3"
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem "activesupport", "~>3"
|
7
|
+
gem "rspec", "~>2"
|
8
|
+
gem "rubyforge"
|
9
|
+
gem "rr"
|
10
|
+
gem "nokogiri"
|
11
|
+
gem "jeweler"
|
12
|
+
gem "haml"
|
13
|
+
gem "sass"
|
14
|
+
gem "erubis"
|
15
|
+
gem "rdoc", "~>2.3"
|
16
|
+
gem "wrong", ">=0.5.4"
|
17
|
+
end
|
18
|
+
|
19
|
+
group :rails do
|
20
|
+
gem "rails", "~> 3.0.0"
|
21
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
puts "RUBY_VERSION=#{RUBY_VERSION}"
|
2
|
+
|
3
|
+
begin
|
4
|
+
# fix http://stackoverflow.com/questions/4932881/gemcutter-rake-build-now-throws-undefined-method-write-for-syckemitter
|
5
|
+
require 'psych' unless RUBY_VERSION =~ /^1\.8/
|
6
|
+
rescue LoadError
|
7
|
+
warn "Couldn't find psych; continuing."
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake'
|
11
|
+
require 'rake/testtask'
|
12
|
+
|
13
|
+
require "rspec/core/rake_task"
|
14
|
+
|
15
|
+
require 'rdoc'
|
16
|
+
here = File.expand_path(File.dirname(__FILE__))
|
17
|
+
$LOAD_PATH.unshift("#{here}/lib")
|
18
|
+
|
19
|
+
require "erector/version"
|
20
|
+
|
21
|
+
begin
|
22
|
+
require 'jeweler'
|
23
|
+
Jeweler::Tasks.new do |gemspec|
|
24
|
+
gemspec.version = Erector::VERSION
|
25
|
+
gemspec.name = "erector"
|
26
|
+
gemspec.summary = "HTML/XML Builder library"
|
27
|
+
gemspec.email = "erector@googlegroups.com"
|
28
|
+
gemspec.description = "Erector is a Builder-like view framework, inspired by Markaby but overcoming some of its flaws. In Erector all views are objects, not template files, which allows the full power of object-oriented programming (inheritance, modular decomposition, encapsulation) in views."
|
29
|
+
gemspec.files = FileList[
|
30
|
+
"README.txt",
|
31
|
+
"VERSION.yml",
|
32
|
+
"lib/**/*",
|
33
|
+
"bin/erector",
|
34
|
+
]
|
35
|
+
gemspec.executables = ["erector"]
|
36
|
+
specs = Dir.glob("spec/**/*") #.reject { |file| file =~ %r{spec/rails2/} }
|
37
|
+
gemspec.test_files = ([
|
38
|
+
"Rakefile",
|
39
|
+
"Gemfile",
|
40
|
+
] + specs).flatten
|
41
|
+
gemspec.homepage = "http://erector.rubyforge.org/"
|
42
|
+
gemspec.authors = [
|
43
|
+
"Alex Chaffee",
|
44
|
+
"Brian Takita",
|
45
|
+
"Jeff Dean",
|
46
|
+
"Jim Kingdon",
|
47
|
+
"John Firebaugh",
|
48
|
+
]
|
49
|
+
# gemspec.add_dependency 'treetop', ">= 1.2.3" # Jeweler now reads Gemfile, I think
|
50
|
+
end
|
51
|
+
|
52
|
+
Jeweler::RubyforgeTasks.new do |rubyforge|
|
53
|
+
rubyforge.doc_task = "rdoc"
|
54
|
+
rubyforge.remote_doc_path = "rdoc"
|
55
|
+
end
|
56
|
+
|
57
|
+
rescue LoadError
|
58
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Default: run most tests"
|
62
|
+
task :default => :spec
|
63
|
+
task :cruise => [:install_gems, :print_environment, :test]
|
64
|
+
task :test => :spec
|
65
|
+
|
66
|
+
task :install_gems do
|
67
|
+
sh "bundle check"
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Build the web site from the .rb files in web/"
|
71
|
+
task :web do
|
72
|
+
files = Dir["web/*.rb"] - ["web/page.rb", "web/sidebar.rb", "web/clickable_li.rb"]
|
73
|
+
require 'erector'
|
74
|
+
require 'erector/erect/erect'
|
75
|
+
$: << "."
|
76
|
+
Erector::Widget.prettyprint_default = true
|
77
|
+
Erector::Erect.new(["--to-html", * files]).run
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "Generate rdoc"
|
81
|
+
task :docs => :rdoc
|
82
|
+
|
83
|
+
task :rdoc => :clean_rdoc
|
84
|
+
task :clean_rdoc do
|
85
|
+
FileUtils.rm_rf("rdoc")
|
86
|
+
end
|
87
|
+
|
88
|
+
# push the docs to Rubyforge
|
89
|
+
task :publish_docs => :"rubyforge:release:docs"
|
90
|
+
|
91
|
+
desc "Publish web site to RubyForge"
|
92
|
+
task :publish_web do
|
93
|
+
config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
94
|
+
host = "#{config["username"]}@rubyforge.org"
|
95
|
+
rubyforge_name = "erector"
|
96
|
+
remote_dir = "/var/www/gforge-projects/#{rubyforge_name}"
|
97
|
+
local_dir = "web"
|
98
|
+
rdoc_dir = "rdoc"
|
99
|
+
rsync_args = '--archive --verbose --delete'
|
100
|
+
|
101
|
+
sh %{rsync #{rsync_args} --exclude=#{rdoc_dir} #{local_dir}/ #{host}:#{remote_dir}}
|
102
|
+
end
|
103
|
+
|
104
|
+
require 'rdoc/task'
|
105
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
106
|
+
rdoc.rdoc_dir = 'rdoc'
|
107
|
+
rdoc.title = "Erector #{Erector::VERSION}"
|
108
|
+
rdoc.options << '--inline-source' << "--promiscuous"
|
109
|
+
rdoc.options << "--main=README.txt"
|
110
|
+
# rdoc.options << '--diagram' if RUBY_PLATFORM !~ /win32/ and `which dot` =~ /\/dot/ and not ENV['NODOT']
|
111
|
+
rdoc.rdoc_files.include('README.txt')
|
112
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
113
|
+
rdoc.rdoc_files.include('bin/**/*')
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "Regenerate unicode.rb from UnicodeData.txt from unicode.org. Only needs to be run when there is a new version of the Unicode specification"
|
117
|
+
task(:build_unicode) do
|
118
|
+
require 'lib/erector/unicode_builder'
|
119
|
+
builder = Erector::UnicodeBuilder.new(
|
120
|
+
File.open("/usr/lib/perl5/5.8.8/unicore/UnicodeData.txt"),
|
121
|
+
File.open("lib/erector/unicode.rb", "w")
|
122
|
+
)
|
123
|
+
builder.generate
|
124
|
+
end
|
125
|
+
|
126
|
+
task :print_environment do
|
127
|
+
puts <<-ENVIRONMENT
|
128
|
+
Build environment:
|
129
|
+
#{`uname -a`.chomp}
|
130
|
+
#{`ruby -v`.chomp}
|
131
|
+
SQLite3: #{`sqlite3 -version`}
|
132
|
+
#{`gem env`}
|
133
|
+
Local gems:
|
134
|
+
#{`gem list`.gsub(/^/, ' ')}
|
135
|
+
ENVIRONMENT
|
136
|
+
end
|
137
|
+
|
138
|
+
namespace :spec do
|
139
|
+
desc "Run core specs."
|
140
|
+
RSpec::Core::RakeTask.new(:core) do |spec|
|
141
|
+
spec.pattern = 'spec/erector/*_spec.rb'
|
142
|
+
end
|
143
|
+
|
144
|
+
desc "Run specs for the 'erector' command line tool."
|
145
|
+
RSpec::Core::RakeTask.new(:erect) do |spec|
|
146
|
+
spec.pattern = 'spec/erect/*_spec.rb'
|
147
|
+
end
|
148
|
+
|
149
|
+
desc "Run specs for erector's Rails integration."
|
150
|
+
RSpec::Core::RakeTask.new(:rails) do |spec|
|
151
|
+
spec.pattern = 'spec/rails_root/spec/*_spec.rb'
|
152
|
+
end
|
153
|
+
|
154
|
+
desc "Run specs for erector's Rails integration under Rails 2."
|
155
|
+
task :rails2 do
|
156
|
+
Dir.chdir("spec/rails2/rails_app") do
|
157
|
+
# Bundler.with_clean_env do
|
158
|
+
sh "BUNDLE_GEMFILE='./Gemfile' bundle exec rake rails2"
|
159
|
+
# end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
desc "Run all specs under Rails 3.1 - prepare with 'bundle install --gemfile Gemfile-rails31'"
|
164
|
+
task :rails31 do
|
165
|
+
gemfile = "#{here}/Gemfile-rails31"
|
166
|
+
sh "BUNDLE_GEMFILE='#{gemfile}' bundle exec rake spec:core spec:erect spec:rails"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
desc "Run most specs"
|
171
|
+
task :spec => ['spec:core', 'spec:erect', 'spec:rails', 'spec:rails2']
|
data/VERSION.yml
CHANGED
data/lib/erector.rb
CHANGED
@@ -3,11 +3,6 @@ end
|
|
3
3
|
|
4
4
|
require "cgi"
|
5
5
|
require "yaml"
|
6
|
-
begin
|
7
|
-
require "sass"
|
8
|
-
rescue LoadError => e
|
9
|
-
# oh well, no Sass
|
10
|
-
end
|
11
6
|
|
12
7
|
require "erector/raw_string"
|
13
8
|
require "erector/dependencies"
|
@@ -21,7 +16,10 @@ require "erector/html"
|
|
21
16
|
require "erector/convenience"
|
22
17
|
require "erector/jquery"
|
23
18
|
require "erector/sass"
|
19
|
+
|
24
20
|
require "erector/abstract_widget"
|
21
|
+
require "erector/xml_widget"
|
22
|
+
require "erector/html_widget"
|
25
23
|
require "erector/widget"
|
26
24
|
|
27
25
|
require "erector/inline"
|
@@ -1,8 +1,25 @@
|
|
1
|
+
require 'erector/element'
|
2
|
+
require 'erector/attributes'
|
3
|
+
require 'erector/text'
|
4
|
+
require 'erector/convenience'
|
5
|
+
require 'erector/after_initialize'
|
6
|
+
require 'erector/output'
|
7
|
+
|
1
8
|
module Erector
|
2
9
|
|
3
|
-
# Abstract base class for Widget. This pattern allows Widget to include lots
|
4
|
-
# have proper semantics for "super" in
|
10
|
+
# Abstract base class for Widget. This pattern allows Widget to include lots
|
11
|
+
# of nicely organized modules and still have proper semantics for "super" in
|
12
|
+
# subclasses. See the rdoc for Widget for the list of all the included
|
13
|
+
# modules.
|
5
14
|
class AbstractWidget
|
15
|
+
|
16
|
+
include Erector::Element
|
17
|
+
include Erector::Attributes
|
18
|
+
include Erector::Text
|
19
|
+
include Erector::AfterInitialize
|
20
|
+
|
21
|
+
include Erector::Convenience
|
22
|
+
|
6
23
|
@@prettyprint_default = false
|
7
24
|
def prettyprint_default
|
8
25
|
@@prettyprint_default
|
@@ -50,30 +67,30 @@ module Erector
|
|
50
67
|
# method and returns the string.
|
51
68
|
#
|
52
69
|
# Options:
|
53
|
-
# output:: the string to output to.
|
70
|
+
# output:: the string (or array, or Erector::Output) to output to.
|
71
|
+
# Default: a new empty string
|
54
72
|
# prettyprint:: whether Erector should add newlines and indentation.
|
55
|
-
# Default: the value of prettyprint_default (which
|
56
|
-
# by default).
|
73
|
+
# Default: the value of prettyprint_default (which, in turn,
|
74
|
+
# is false by default).
|
57
75
|
# indentation:: the amount of spaces to indent. Ignored unless prettyprint
|
58
76
|
# is true.
|
59
77
|
# max_length:: preferred maximum length of a line. Line wraps will only
|
60
|
-
# occur at space characters, so a long word may end up
|
61
|
-
# a line longer than this. If nil (default), then
|
62
|
-
# arbitrary limit to line lengths, and only
|
63
|
-
# characters and prettyprinting will
|
64
|
-
# output.
|
78
|
+
# occur at space characters, so a long word may end up
|
79
|
+
# creating a line longer than this. If nil (default), then
|
80
|
+
# there is no arbitrary limit to line lengths, and only
|
81
|
+
# internal newline characters and prettyprinting will
|
82
|
+
# determine newlines in the output.
|
65
83
|
# helpers:: a helpers object containing utility methods. Usually this is a
|
66
84
|
# Rails view object.
|
67
85
|
# content_method_name:: in case you want to call a method other than
|
68
86
|
# #content, pass its name in here.
|
69
87
|
#
|
70
|
-
def
|
71
|
-
raise "Erector::Widget#to_html takes an options hash, not a symbol. Try calling \"to_html(:content_method_name=> :#{options})\"" if options.is_a? Symbol
|
88
|
+
def render(options = {})
|
72
89
|
_render(options).to_s
|
73
90
|
end
|
74
91
|
|
75
|
-
# alias for #
|
76
|
-
# @deprecated Please use {#
|
92
|
+
# alias for #render
|
93
|
+
# @deprecated Please use {#render} instead
|
77
94
|
def to_s(*args)
|
78
95
|
unless defined? @@already_warned_to_s
|
79
96
|
$stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
|
@@ -82,36 +99,39 @@ module Erector
|
|
82
99
|
to_html(*args)
|
83
100
|
end
|
84
101
|
|
85
|
-
# Entry point for rendering a widget (and all its children). Same as
|
86
|
-
# only it returns an array, for theoretical performance
|
87
|
-
# Rack server (like Sinatra or Rails Metal).
|
102
|
+
# Entry point for rendering a widget (and all its children). Same as
|
103
|
+
# #render / #to_html only it returns an array, for theoretical performance
|
104
|
+
# improvements when using a Rack server (like Sinatra or Rails Metal).
|
88
105
|
#
|
89
|
-
# # Options: see #
|
106
|
+
# # Options: see #render
|
90
107
|
def to_a(options = {})
|
91
108
|
_render(options).to_a
|
92
109
|
end
|
93
110
|
|
94
111
|
# Template method which must be overridden by all widget subclasses.
|
95
112
|
# Inside this method you call the magic #element methods which emit HTML
|
96
|
-
# and text to the output string.
|
113
|
+
# and text to the output string.
|
114
|
+
#
|
115
|
+
# If you call "super" (or don't override
|
97
116
|
# +content+, or explicitly call "call_block") then your widget will
|
98
117
|
# execute the block that was passed into its constructor. The semantics of
|
99
|
-
# this block are confusing; make sure to read the rdoc for
|
118
|
+
# this block are confusing; make sure to read the rdoc for
|
119
|
+
# Erector#call_block
|
100
120
|
def content
|
101
121
|
call_block
|
102
122
|
end
|
103
|
-
|
104
|
-
# When this method is executed, the default block that was passed in to
|
105
|
-
# the widget's constructor will be executed. The semantics of this
|
123
|
+
|
124
|
+
# When this method is executed, the default block that was passed in to
|
125
|
+
# the widget's constructor will be executed. The semantics of this
|
106
126
|
# block -- that is, what "self" is, and whether it has access to
|
107
127
|
# Erector methods like "div" and "text", and the widget's instance
|
108
128
|
# variables -- can be quite confusing. The rule is, most of the time the
|
109
129
|
# block is evaluated using "call" or "yield", which means that its scope
|
110
130
|
# is that of the caller. So if that caller is not an Erector widget, it
|
111
|
-
# will *not* have access to the Erector methods, but it *will* have access
|
131
|
+
# will *not* have access to the Erector methods, but it *will* have access
|
112
132
|
# to instance variables and methods of the calling object.
|
113
|
-
#
|
114
|
-
# If you want this block to have access to Erector methods then use
|
133
|
+
#
|
134
|
+
# If you want this block to have access to Erector methods then use
|
115
135
|
# Erector::Inline#content or Erector#inline.
|
116
136
|
def call_block
|
117
137
|
@_block.call(self) if @_block
|
@@ -122,7 +142,8 @@ module Erector
|
|
122
142
|
# the second argument is a hash used to populate its instance variables.
|
123
143
|
# If the first argument is an instance then the hash must be unspecified
|
124
144
|
# (or empty). If a block is passed to this method, then it gets set as the
|
125
|
-
# rendered widget's block
|
145
|
+
# rendered widget's block, and will be executed when that widget calls
|
146
|
+
# +call_block+ or calls +super+ from inside its +content+ method.
|
126
147
|
#
|
127
148
|
# This is the preferred way to call one widget from inside another. This
|
128
149
|
# method assures that the same output string is used, which gives better
|
@@ -140,8 +161,8 @@ module Erector
|
|
140
161
|
|
141
162
|
# Creates a whole new output string, executes the block, then converts the
|
142
163
|
# output string to a string and returns it as raw text. If at all possible
|
143
|
-
# you should avoid this method since it hurts performance, and use
|
144
|
-
# instead.
|
164
|
+
# you should avoid this method since it hurts performance, and use
|
165
|
+
# +widget+ instead.
|
145
166
|
def capture
|
146
167
|
original, @_output = output, Output.new
|
147
168
|
yield
|
@@ -152,22 +173,46 @@ module Erector
|
|
152
173
|
end
|
153
174
|
|
154
175
|
protected
|
176
|
+
# executes this widget's #content method, which emits stuff onto the
|
177
|
+
# output stream
|
155
178
|
def _render(options = {}, &block)
|
156
179
|
@_block = block if block
|
157
180
|
@_parent = options[:parent] || parent
|
158
181
|
@_helpers = options[:helpers] || parent
|
159
|
-
|
160
|
-
|
182
|
+
if options[:output]
|
183
|
+
# todo: document that either :buffer or :output can be used to specify an output buffer, and deprecate :output
|
184
|
+
if options[:output].is_a? Output
|
185
|
+
@_output = options[:output]
|
186
|
+
else
|
187
|
+
@_output = Output.new({:buffer => options[:output]}.merge(options))
|
188
|
+
end
|
189
|
+
else
|
190
|
+
@_output = Output.new(options)
|
191
|
+
end
|
161
192
|
|
162
193
|
output.widgets << self.class
|
163
194
|
send(options[:content_method_name] || :content)
|
164
195
|
output
|
165
196
|
end
|
166
197
|
|
198
|
+
# same as _render, but using a parent widget's output stream and helpers
|
167
199
|
def _render_via(parent, options = {}, &block)
|
168
200
|
_render(options.merge(:parent => parent,
|
169
201
|
:output => parent.output,
|
170
202
|
:helpers => parent.helpers), &block)
|
171
203
|
end
|
204
|
+
|
205
|
+
protected
|
206
|
+
|
207
|
+
def sort_for_xml_declaration(attributes)
|
208
|
+
# correct order is "version, encoding, standalone" (XML 1.0 section 2.8).
|
209
|
+
# But we only try to put version before encoding for now.
|
210
|
+
stringized = []
|
211
|
+
attributes.each do |key, value|
|
212
|
+
stringized << [key.to_s, value]
|
213
|
+
end
|
214
|
+
stringized.sort{|a, b| b <=> a}
|
215
|
+
end
|
216
|
+
|
172
217
|
end
|
173
218
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Erector
|
2
|
+
module Attributes
|
3
|
+
def format_attributes(attributes)
|
4
|
+
if !attributes || attributes.empty?
|
5
|
+
""
|
6
|
+
else
|
7
|
+
format_sorted(sort_attributes(attributes))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_sorted(sorted)
|
12
|
+
results = ['']
|
13
|
+
sorted.each do |key, value|
|
14
|
+
if value
|
15
|
+
if value.is_a?(Array)
|
16
|
+
value = value.flatten
|
17
|
+
next if value.empty?
|
18
|
+
value = value.join(' ')
|
19
|
+
end
|
20
|
+
results << "#{key}=\"#{h(value)}\""
|
21
|
+
end
|
22
|
+
end
|
23
|
+
results.join(' ')
|
24
|
+
end
|
25
|
+
|
26
|
+
def sort_attributes(attributes)
|
27
|
+
stringized = []
|
28
|
+
attributes.each do |key, value|
|
29
|
+
stringized << [key.to_s, value]
|
30
|
+
end
|
31
|
+
stringized.sort
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|