erector-rails4 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +5 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +143 -0
  10. data/README.md +4 -0
  11. data/Rakefile +24 -0
  12. data/erector-rails4.gemspec +36 -0
  13. data/erector-rails4.sublimeproject +20 -0
  14. data/lib/erector/abstract_widget.rb +231 -0
  15. data/lib/erector/after_initialize.rb +29 -0
  16. data/lib/erector/attributes.rb +29 -0
  17. data/lib/erector/cache.rb +37 -0
  18. data/lib/erector/caching.rb +65 -0
  19. data/lib/erector/convenience.rb +98 -0
  20. data/lib/erector/dependencies.rb +24 -0
  21. data/lib/erector/dependency.rb +31 -0
  22. data/lib/erector/element.rb +113 -0
  23. data/lib/erector/externals.rb +104 -0
  24. data/lib/erector/html.rb +12 -0
  25. data/lib/erector/html_widget.rb +220 -0
  26. data/lib/erector/inline.rb +37 -0
  27. data/lib/erector/jquery.rb +28 -0
  28. data/lib/erector/mixin.rb +12 -0
  29. data/lib/erector/needs.rb +95 -0
  30. data/lib/erector/output.rb +144 -0
  31. data/lib/erector/promise.rb +141 -0
  32. data/lib/erector/rails/form_builder.rb +44 -0
  33. data/lib/erector/rails/railtie.rb +13 -0
  34. data/lib/erector/rails/template_handler.rb +16 -0
  35. data/lib/erector/rails/widget_renderer.rb +6 -0
  36. data/lib/erector/rails.rb +221 -0
  37. data/lib/erector/raw_string.rb +12 -0
  38. data/lib/erector/sass.rb +32 -0
  39. data/lib/erector/tag.rb +66 -0
  40. data/lib/erector/text.rb +123 -0
  41. data/lib/erector/unicode.rb +18185 -0
  42. data/lib/erector/unicode_builder.rb +67 -0
  43. data/lib/erector/version.rb +5 -0
  44. data/lib/erector/widget.rb +94 -0
  45. data/lib/erector/widgets.rb +5 -0
  46. data/lib/erector/xml_widget.rb +131 -0
  47. data/lib/erector.rb +28 -0
  48. data/spec/dummy/Rakefile +7 -0
  49. data/spec/dummy/app/controllers/application.rb +6 -0
  50. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  51. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  52. data/spec/dummy/app/views/layouts/erb_as_layout.html.erb +2 -0
  53. data/spec/dummy/app/views/layouts/widget_as_layout.rb +8 -0
  54. data/spec/dummy/app/views/test/_erb.erb +1 -0
  55. data/spec/dummy/app/views/test/_erector.rb +5 -0
  56. data/spec/dummy/app/views/test/_partial_with_locals.rb +7 -0
  57. data/spec/dummy/app/views/test/bare.rb +5 -0
  58. data/spec/dummy/app/views/test/erb_from_erector.html.rb +5 -0
  59. data/spec/dummy/app/views/test/erector_from_erb.html.erb +1 -0
  60. data/spec/dummy/app/views/test/erector_with_locals_from_erb.html.erb +6 -0
  61. data/spec/dummy/app/views/test/implicit_assigns.html.rb +5 -0
  62. data/spec/dummy/app/views/test/needs.html.rb +7 -0
  63. data/spec/dummy/app/views/test/needs_subclass.html.rb +5 -0
  64. data/spec/dummy/app/views/test/protected_instance_variable.html.rb +5 -0
  65. data/spec/dummy/app/views/test/render_default.html.rb +5 -0
  66. data/spec/dummy/app/views/test/render_default_erb_with_layout.html.erb +1 -0
  67. data/spec/dummy/app/views/test/render_default_widget_with_layout.html.rb +5 -0
  68. data/spec/dummy/app/views/test/render_partial.html.rb +5 -0
  69. data/spec/dummy/app/views/test/render_with_widget_as_layout.rb +5 -0
  70. data/spec/dummy/app/views/test/render_with_widget_as_layout_using_content_for.rb +8 -0
  71. data/spec/dummy/config/application.rb +44 -0
  72. data/spec/dummy/config/boot.rb +10 -0
  73. data/spec/dummy/config/database.yml +22 -0
  74. data/spec/dummy/config/environment.rb +5 -0
  75. data/spec/dummy/config/environments/development.rb +22 -0
  76. data/spec/dummy/config/environments/production.rb +49 -0
  77. data/spec/dummy/config/environments/test.rb +36 -0
  78. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  79. data/spec/dummy/config/initializers/inflections.rb +10 -0
  80. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  81. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  82. data/spec/dummy/config/initializers/session_store.rb +8 -0
  83. data/spec/dummy/config/locales/en.yml +5 -0
  84. data/spec/dummy/config/routes.rb +3 -0
  85. data/spec/dummy/config.ru +4 -0
  86. data/spec/dummy/db/seeds.rb +7 -0
  87. data/spec/dummy/script/rails +6 -0
  88. data/spec/dummy/spec/form_builder_spec.rb +21 -0
  89. data/spec/dummy/spec/rails_helpers_spec.rb +236 -0
  90. data/spec/dummy/spec/rails_spec_helper.rb +10 -0
  91. data/spec/dummy/spec/rails_widget_spec.rb +83 -0
  92. data/spec/dummy/spec/render_spec.rb +369 -0
  93. data/spec/erector/after_initialize_spec.rb +45 -0
  94. data/spec/erector/cache_spec.rb +133 -0
  95. data/spec/erector/caching_spec.rb +184 -0
  96. data/spec/erector/convenience_spec.rb +250 -0
  97. data/spec/erector/dependency_spec.rb +67 -0
  98. data/spec/erector/hello_from_readme.rb +18 -0
  99. data/spec/erector/hello_from_readme_spec.rb +11 -0
  100. data/spec/erector/html_spec.rb +585 -0
  101. data/spec/erector/indentation_spec.rb +211 -0
  102. data/spec/erector/inline_spec.rb +94 -0
  103. data/spec/erector/jquery_spec.rb +35 -0
  104. data/spec/erector/mixin_spec.rb +65 -0
  105. data/spec/erector/needs_spec.rb +141 -0
  106. data/spec/erector/output_spec.rb +293 -0
  107. data/spec/erector/promise_spec.rb +173 -0
  108. data/spec/erector/sample-file.txt +1 -0
  109. data/spec/erector/sass_spec.rb +57 -0
  110. data/spec/erector/tag_spec.rb +67 -0
  111. data/spec/erector/unicode_builder_spec.rb +75 -0
  112. data/spec/erector/widget_spec.rb +310 -0
  113. data/spec/erector/xml_widget_spec.rb +73 -0
  114. data/spec/spec_helper.rb +31 -0
  115. metadata +368 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8d7ab718f35dd1c6ddbc0f0a94c9a5970a640409
4
+ data.tar.gz: f5845d25690158ac26bb5a93b15dfe26f8ae89c4
5
+ SHA512:
6
+ metadata.gz: 14a5c297ce93d70031a2fd4256b4b59bf24cbe96062dffe710696e6ac2052b9608572394d70039af2f8b366d92b51fde1eb6ac1ac551593ca44a6fa6e370b51e
7
+ data.tar.gz: 9acefa6d9f2baf9dec0f2a1629b0084f4d37d15f39b9fa28a674f9c57be3c3f9991c0a3d25c9d3a52f25d83aefff7bca3136103c17619ada35d19ac6378d07de
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+ repo_token: J1XUNT8uCGW7viYD01wooJ6PSlVc3Iyt2
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/config/database.yml
5
+ spec/dummy/log/*.log
6
+ spec/dummy/tmp/
7
+ spec/dummy/.sass-cache
8
+ spec/dummy/public/uploads/*
9
+ tmp/*
10
+ coverage/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ erector
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+ rvm:
5
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in dobt_auth.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,143 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ erector-rails4 (0.0.1)
5
+ rails (>= 4.0)
6
+ treetop (>= 1.2.3)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (4.0.0)
12
+ actionpack (= 4.0.0)
13
+ mail (~> 2.5.3)
14
+ actionpack (4.0.0)
15
+ activesupport (= 4.0.0)
16
+ builder (~> 3.1.0)
17
+ erubis (~> 2.7.0)
18
+ rack (~> 1.5.2)
19
+ rack-test (~> 0.6.2)
20
+ activemodel (4.0.0)
21
+ activesupport (= 4.0.0)
22
+ builder (~> 3.1.0)
23
+ activerecord (4.0.0)
24
+ activemodel (= 4.0.0)
25
+ activerecord-deprecated_finders (~> 1.0.2)
26
+ activesupport (= 4.0.0)
27
+ arel (~> 4.0.0)
28
+ activerecord-deprecated_finders (1.0.3)
29
+ activesupport (4.0.0)
30
+ i18n (~> 0.6, >= 0.6.4)
31
+ minitest (~> 4.2)
32
+ multi_json (~> 1.3)
33
+ thread_safe (~> 0.1)
34
+ tzinfo (~> 0.3.37)
35
+ arel (4.0.1)
36
+ atomic (1.1.14)
37
+ builder (3.1.4)
38
+ coveralls (0.7.0)
39
+ multi_json (~> 1.3)
40
+ rest-client
41
+ simplecov (>= 0.7)
42
+ term-ansicolor
43
+ thor
44
+ diff-lcs (1.1.3)
45
+ erubis (2.7.0)
46
+ haml (4.0.3)
47
+ tilt
48
+ hike (1.2.3)
49
+ i18n (0.6.5)
50
+ mail (2.5.4)
51
+ mime-types (~> 1.16)
52
+ treetop (~> 1.4.8)
53
+ mime-types (1.25)
54
+ mini_portile (0.5.2)
55
+ minitest (4.7.5)
56
+ multi_json (1.8.2)
57
+ nokogiri (1.6.0)
58
+ mini_portile (~> 0.5.0)
59
+ polyglot (0.3.3)
60
+ predicated (0.2.6)
61
+ rack (1.5.2)
62
+ rack-test (0.6.2)
63
+ rack (>= 1.0)
64
+ rails (4.0.0)
65
+ actionmailer (= 4.0.0)
66
+ actionpack (= 4.0.0)
67
+ activerecord (= 4.0.0)
68
+ activesupport (= 4.0.0)
69
+ bundler (>= 1.3.0, < 2.0)
70
+ railties (= 4.0.0)
71
+ sprockets-rails (~> 2.0.0)
72
+ railties (4.0.0)
73
+ actionpack (= 4.0.0)
74
+ activesupport (= 4.0.0)
75
+ rake (>= 0.8.7)
76
+ thor (>= 0.18.1, < 2.0)
77
+ rake (10.1.0)
78
+ rest-client (1.6.7)
79
+ mime-types (>= 1.16)
80
+ rr (1.1.2)
81
+ rspec-core (2.12.2)
82
+ rspec-expectations (2.12.1)
83
+ diff-lcs (~> 1.1.3)
84
+ rspec-mocks (2.12.2)
85
+ rspec-rails (2.12.2)
86
+ actionpack (>= 3.0)
87
+ activesupport (>= 3.0)
88
+ railties (>= 3.0)
89
+ rspec-core (~> 2.12.0)
90
+ rspec-expectations (~> 2.12.0)
91
+ rspec-mocks (~> 2.12.0)
92
+ ruby2ruby (2.0.6)
93
+ ruby_parser (~> 3.1)
94
+ sexp_processor (~> 4.0)
95
+ ruby_parser (3.2.2)
96
+ sexp_processor (~> 4.1)
97
+ sass (3.2.12)
98
+ sexp_processor (4.4.0)
99
+ simplecov (0.7.1)
100
+ multi_json (~> 1.0)
101
+ simplecov-html (~> 0.7.1)
102
+ simplecov-html (0.7.1)
103
+ sprockets (2.10.1)
104
+ hike (~> 1.2)
105
+ multi_json (~> 1.0)
106
+ rack (~> 1.0)
107
+ tilt (~> 1.1, != 1.3.0)
108
+ sprockets-rails (2.0.1)
109
+ actionpack (>= 3.0)
110
+ activesupport (>= 3.0)
111
+ sprockets (~> 2.8)
112
+ sqlite3 (1.3.8)
113
+ term-ansicolor (1.2.2)
114
+ tins (~> 0.8)
115
+ thor (0.18.1)
116
+ thread_safe (0.1.3)
117
+ atomic
118
+ tilt (1.4.1)
119
+ tins (0.12.0)
120
+ treetop (1.4.15)
121
+ polyglot
122
+ polyglot (>= 0.3.1)
123
+ tzinfo (0.3.38)
124
+ wrong (0.7.0)
125
+ diff-lcs (~> 1.1.2)
126
+ predicated (~> 0.2.6)
127
+ ruby2ruby (>= 2.0.1)
128
+ ruby_parser (>= 3.0.1)
129
+ sexp_processor (>= 4.0)
130
+
131
+ PLATFORMS
132
+ ruby
133
+
134
+ DEPENDENCIES
135
+ coveralls
136
+ erector-rails4!
137
+ haml
138
+ nokogiri
139
+ rr
140
+ rspec-rails (= 2.12.2)
141
+ sass
142
+ sqlite3
143
+ wrong (>= 0.5.4)
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ Erector for Rails 4 [![Build Status](https://travis-ci.org/adamjacobbecker/erector-rails4.png?branch=master)](https://travis-ci.org/adamjacobbecker/erector-rails4) [![Coverage Status](https://coveralls.io/repos/adamjacobbecker/erector-rails4/badge.png)](https://coveralls.io/r/adamjacobbecker/erector-rails4)
2
+ =====
3
+
4
+ This is a fork of [Erector](https://github.com/erector/erector) with a lotta old crap removed. Currently under active development, but in regular use at [DOBT](https://www.github.com/dobtco).
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Erector'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
@@ -0,0 +1,36 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "erector/version"
5
+
6
+ Gem::Specification.new do |s|
7
+
8
+ s.name = "erector-rails4"
9
+ s.version = Erector::VERSION
10
+
11
+ s.required_ruby_version = Gem::Requirement.new('>= 2.0.0')
12
+ s.authors = ["Alex Chaffee", "Brian Takita", "Jeff Dean", "Jim Kingdon", "John Firebaugh", "Adam Becker"]
13
+ s.summary = "Erector, for Rails 4"
14
+ s.description = "This is a fork of Erector, updated for Rails 4."
15
+ s.email = "adam@dobt.co"
16
+ s.license = "MIT"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {features,spec}/*`.split("\n")
20
+
21
+ s.homepage = "http://github.com/adamjacobbecker/erector-rails4"
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency 'rails', '>= 4.0'
25
+ s.add_dependency 'treetop', '>= 1.2.3'
26
+
27
+ s.add_development_dependency 'coveralls'
28
+ s.add_development_dependency 'haml'
29
+ s.add_development_dependency 'nokogiri'
30
+ s.add_development_dependency 'rr'
31
+ s.add_development_dependency 'rspec-rails', '2.12.2'
32
+ s.add_development_dependency 'sass'
33
+ s.add_development_dependency 'sqlite3'
34
+ s.add_development_dependency 'wrong', ">=0.5.4"
35
+
36
+ end
@@ -0,0 +1,20 @@
1
+ {
2
+ "folders":
3
+ [
4
+ {
5
+ "path": ".",
6
+ "folder_exclude_patterns": ["coverage", "log", "tmp"],
7
+ "file_exclude_patterns": ["*.sublime-workspace", "*.sql"]
8
+ }
9
+ ],
10
+
11
+ "settings":
12
+ {
13
+ // indentation
14
+ "tab_size": 2,
15
+ "translate_tabs_to_spaces": true,
16
+ "trim_trailing_white_space_on_save": true,
17
+ // ensure line endings is linux style (even when on Windows)
18
+ "default_line_ending": "LF"
19
+ }
20
+ }
@@ -0,0 +1,231 @@
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
+
8
+ module Erector
9
+
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.
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
+
23
+ @@prettyprint_default = false
24
+ def prettyprint_default
25
+ @@prettyprint_default
26
+ end
27
+
28
+ def self.prettyprint_default
29
+ @@prettyprint_default
30
+ end
31
+
32
+ def self.prettyprint_default=(enabled)
33
+ @@prettyprint_default = enabled
34
+ end
35
+
36
+ @@hyphenize_underscores = false
37
+
38
+ def self.hyphenize_underscores
39
+ @@hyphenize_underscores
40
+ end
41
+
42
+ def self.hyphenize_underscores=(enabled)
43
+ @@hyphenize_underscores = enabled
44
+ end
45
+
46
+ def self.inline(*args, &block)
47
+ Class.new(self) do
48
+ include Erector::Inline
49
+ end.new(*args, &block)
50
+ end
51
+
52
+ [:helpers, :assigns, :output, :parent, :block].each do |attr|
53
+ class_eval(<<-SRC, __FILE__, __LINE__ + 1)
54
+ def #{attr}
55
+ @_#{attr}
56
+ end
57
+ SRC
58
+ end
59
+
60
+ def initialize(assigns = {}, &block)
61
+ unless assigns.is_a? Hash
62
+ raise ArgumentError, "Erector widgets are initialized with only a parameter hash, but you passed #{assigns.class}:#{assigns.inspect}. (Other parameters are passed to to_html, or the #widget method.)"
63
+ end
64
+
65
+ @_assigns = assigns
66
+
67
+ assigns.each do |name, value|
68
+ instance_variable_set(name.to_s[0..0] == '@' ? name : "@#{name}", value)
69
+ end
70
+
71
+ @_parent = eval("self", block.binding) if block
72
+ @_block = block
73
+
74
+ self.class.after_initialize(self)
75
+ end
76
+
77
+ # Entry point for rendering a widget (and all its children). This method
78
+ # creates a new output string (if necessary), calls this widget's #content
79
+ # method and returns the string.
80
+ #
81
+ # Options:
82
+ # output:: the string (or array, or Erector::Output) to output to.
83
+ # Default: a new empty string
84
+ # prettyprint:: whether Erector should add newlines and indentation.
85
+ # Default: the value of prettyprint_default (which, in turn,
86
+ # is false by default).
87
+ # indentation:: the amount of spaces to indent. Ignored unless prettyprint
88
+ # is true.
89
+ # max_length:: preferred maximum length of a line. Line wraps will only
90
+ # occur at space characters, so a long word may end up
91
+ # creating a line longer than this. If nil (default), then
92
+ # there is no arbitrary limit to line lengths, and only
93
+ # internal newline characters and prettyprinting will
94
+ # determine newlines in the output.
95
+ # helpers:: a helpers object containing utility methods. Usually this is a
96
+ # Rails view object.
97
+ # content_method_name:: in case you want to call a method other than
98
+ # #content, pass its name in here.
99
+ #
100
+ def emit(options = {})
101
+ _emit(options).to_s
102
+ end
103
+
104
+ # alias for #emit
105
+ # @deprecated Please use {#emit} instead
106
+ def to_s(*args)
107
+ unless defined? @@already_warned_to_s
108
+ $stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
109
+ @@already_warned_to_s = true
110
+ end
111
+ to_html(*args)
112
+ end
113
+
114
+ # Entry point for rendering a widget (and all its children). Same as
115
+ # #render / #to_html only it returns an array, for theoretical performance
116
+ # improvements when using a Rack server (like Sinatra or Rails Metal).
117
+ #
118
+ # # Options: see #emit
119
+ def to_a(options = {})
120
+ _emit(options).to_a
121
+ end
122
+
123
+ # Template method which must be overridden by all widget subclasses.
124
+ # Inside this method you call the magic #element methods which emit HTML
125
+ # and text to the output string.
126
+ #
127
+ # If you call "super" (or don't override
128
+ # +content+, or explicitly call "call_block") then your widget will
129
+ # execute the block that was passed into its constructor. The semantics of
130
+ # this block are confusing; make sure to read the rdoc for
131
+ # Erector#call_block
132
+ def content
133
+ call_block
134
+ end
135
+
136
+ # When this method is executed, the default block that was passed in to
137
+ # the widget's constructor will be executed. The semantics of this
138
+ # block -- that is, what "self" is, and whether it has access to
139
+ # Erector methods like "div" and "text", and the widget's instance
140
+ # variables -- can be quite confusing. The rule is, most of the time the
141
+ # block is evaluated using "call" or "yield", which means that its scope
142
+ # is that of the caller. So if that caller is not an Erector widget, it
143
+ # will *not* have access to the Erector methods, but it *will* have access
144
+ # to instance variables and methods of the calling object.
145
+ #
146
+ # If you want this block to have access to Erector methods then use
147
+ # Erector::Inline#content or Erector#inline.
148
+ def call_block
149
+ @_block.call(self) if @_block
150
+ end
151
+
152
+ # Emits a (nested) widget onto the current widget's output stream. Accepts
153
+ # either a class or an instance. If the first argument is a class, then
154
+ # the second argument is a hash used to populate its instance variables.
155
+ # If the first argument is an instance then the hash must be unspecified
156
+ # (or empty). If a block is passed to this method, then it gets set as the
157
+ # emited widget's block, and will be executed when that widget calls
158
+ # +call_block+ or calls +super+ from inside its +content+ method.
159
+ #
160
+ # This is the preferred way to call one widget from inside another. This
161
+ # method assures that the same output string is used, which gives better
162
+ # performance than using +capture+ or +to_html+.
163
+ def widget(target, assigns = {}, options = {}, &block)
164
+ if target.is_a? Class
165
+ target.new(assigns, &block)._emit_via(self, options)
166
+ else
167
+ unless assigns.empty?
168
+ raise "Unexpected second parameter. Did you mean to pass in assigns when you instantiated the #{target.class.to_s}?"
169
+ end
170
+ target._emit_via(self, options, &block)
171
+ end
172
+ end
173
+
174
+ # Creates a whole new output string, executes the block, then converts the
175
+ # output string to a string and returns it as raw text. If at all possible
176
+ # you should avoid this method since it hurts performance, and use
177
+ # +widget+ instead.
178
+ def capture_content
179
+ original, @_output = output, Output.new
180
+ yield
181
+ original.widgets.concat(output.widgets) # todo: test!!!
182
+ output.to_s
183
+ ensure
184
+ @_output = original
185
+ end
186
+ alias_method :capture, :capture_content
187
+
188
+ protected
189
+ # executes this widget's #content method, which emits stuff onto the
190
+ # output stream
191
+ def _emit(options = {}, &block)
192
+ @_block = block if block
193
+ @_parent = options[:parent] || parent
194
+ @_helpers = options[:helpers] || parent
195
+ if options[:output]
196
+ # todo: document that either :buffer or :output can be used to specify an output buffer, and deprecate :output
197
+ if options[:output].is_a? Output
198
+ @_output = options[:output]
199
+ else
200
+ @_output = Output.new({:buffer => options[:output]}.merge(options))
201
+ end
202
+ else
203
+ @_output = Output.new(options)
204
+ end
205
+
206
+ output.widgets << self.class
207
+ send(options[:content_method_name] || :content)
208
+ output
209
+ end
210
+
211
+ # same as _emit, but using a parent widget's output stream and helpers
212
+ def _emit_via(parent, options = {}, &block)
213
+ _emit(options.merge(:parent => parent,
214
+ :output => parent.output,
215
+ :helpers => parent.helpers), &block)
216
+ end
217
+
218
+ protected
219
+
220
+ def sort_for_xml_declaration(attributes)
221
+ # correct order is "version, encoding, standalone" (XML 1.0 section 2.8).
222
+ # But we only try to put version before encoding for now.
223
+ stringized = []
224
+ attributes.each do |key, value|
225
+ stringized << [key.to_s, value]
226
+ end
227
+ stringized.sort{|a, b| b <=> a}
228
+ end
229
+
230
+ end
231
+ end