haml 4.0.6 → 5.2.0

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.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +19 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +72 -0
  5. data/.yardopts +2 -3
  6. data/CHANGELOG.md +138 -4
  7. data/FAQ.md +4 -14
  8. data/Gemfile +16 -0
  9. data/MIT-LICENSE +2 -2
  10. data/README.md +79 -42
  11. data/REFERENCE.md +142 -67
  12. data/Rakefile +44 -63
  13. data/TODO +24 -0
  14. data/benchmark.rb +70 -0
  15. data/haml.gemspec +45 -0
  16. data/lib/haml.rb +2 -0
  17. data/lib/haml/.gitattributes +1 -0
  18. data/lib/haml/attribute_builder.rb +164 -0
  19. data/lib/haml/attribute_compiler.rb +235 -0
  20. data/lib/haml/attribute_parser.rb +150 -0
  21. data/lib/haml/buffer.rb +29 -136
  22. data/lib/haml/compiler.rb +110 -320
  23. data/lib/haml/engine.rb +34 -41
  24. data/lib/haml/error.rb +28 -24
  25. data/lib/haml/escapable.rb +77 -0
  26. data/lib/haml/exec.rb +38 -20
  27. data/lib/haml/filters.rb +22 -27
  28. data/lib/haml/generator.rb +42 -0
  29. data/lib/haml/helpers.rb +134 -89
  30. data/lib/haml/helpers/action_view_extensions.rb +4 -2
  31. data/lib/haml/helpers/action_view_mods.rb +45 -60
  32. data/lib/haml/helpers/action_view_xss_mods.rb +2 -0
  33. data/lib/haml/helpers/safe_erubi_template.rb +20 -0
  34. data/lib/haml/helpers/safe_erubis_template.rb +5 -1
  35. data/lib/haml/helpers/xss_mods.rb +23 -13
  36. data/lib/haml/options.rb +63 -69
  37. data/lib/haml/parser.rb +292 -228
  38. data/lib/haml/plugin.rb +37 -0
  39. data/lib/haml/railtie.rb +38 -12
  40. data/lib/haml/sass_rails_filter.rb +18 -4
  41. data/lib/haml/template.rb +13 -6
  42. data/lib/haml/template/options.rb +13 -2
  43. data/lib/haml/temple_engine.rb +123 -0
  44. data/lib/haml/temple_line_counter.rb +30 -0
  45. data/lib/haml/util.rb +83 -202
  46. data/lib/haml/version.rb +3 -1
  47. data/yard/default/.gitignore +1 -0
  48. data/yard/default/fulldoc/html/css/common.sass +15 -0
  49. data/yard/default/layout/html/footer.erb +12 -0
  50. metadata +73 -108
  51. data/lib/haml/template/plugin.rb +0 -41
  52. data/test/engine_test.rb +0 -2013
  53. data/test/erb/_av_partial_1.erb +0 -12
  54. data/test/erb/_av_partial_2.erb +0 -8
  55. data/test/erb/action_view.erb +0 -62
  56. data/test/erb/standard.erb +0 -55
  57. data/test/filters_test.rb +0 -254
  58. data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
  59. data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
  60. data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
  61. data/test/gemfiles/Gemfile.rails-4.0.x +0 -5
  62. data/test/helper_test.rb +0 -583
  63. data/test/markaby/standard.mab +0 -52
  64. data/test/mocks/article.rb +0 -6
  65. data/test/parser_test.rb +0 -105
  66. data/test/results/content_for_layout.xhtml +0 -12
  67. data/test/results/eval_suppressed.xhtml +0 -9
  68. data/test/results/helpers.xhtml +0 -70
  69. data/test/results/helpful.xhtml +0 -10
  70. data/test/results/just_stuff.xhtml +0 -70
  71. data/test/results/list.xhtml +0 -12
  72. data/test/results/nuke_inner_whitespace.xhtml +0 -40
  73. data/test/results/nuke_outer_whitespace.xhtml +0 -148
  74. data/test/results/original_engine.xhtml +0 -20
  75. data/test/results/partial_layout.xhtml +0 -5
  76. data/test/results/partial_layout_erb.xhtml +0 -5
  77. data/test/results/partials.xhtml +0 -21
  78. data/test/results/render_layout.xhtml +0 -3
  79. data/test/results/silent_script.xhtml +0 -74
  80. data/test/results/standard.xhtml +0 -162
  81. data/test/results/tag_parsing.xhtml +0 -23
  82. data/test/results/very_basic.xhtml +0 -5
  83. data/test/results/whitespace_handling.xhtml +0 -90
  84. data/test/template_test.rb +0 -354
  85. data/test/templates/_av_partial_1.haml +0 -9
  86. data/test/templates/_av_partial_1_ugly.haml +0 -9
  87. data/test/templates/_av_partial_2.haml +0 -5
  88. data/test/templates/_av_partial_2_ugly.haml +0 -5
  89. data/test/templates/_layout.erb +0 -3
  90. data/test/templates/_layout_for_partial.haml +0 -3
  91. data/test/templates/_partial.haml +0 -8
  92. data/test/templates/_text_area.haml +0 -3
  93. data/test/templates/_text_area_helper.html.haml +0 -4
  94. data/test/templates/action_view.haml +0 -47
  95. data/test/templates/action_view_ugly.haml +0 -47
  96. data/test/templates/breakage.haml +0 -8
  97. data/test/templates/content_for_layout.haml +0 -8
  98. data/test/templates/eval_suppressed.haml +0 -11
  99. data/test/templates/helpers.haml +0 -55
  100. data/test/templates/helpful.haml +0 -11
  101. data/test/templates/just_stuff.haml +0 -85
  102. data/test/templates/list.haml +0 -12
  103. data/test/templates/nuke_inner_whitespace.haml +0 -32
  104. data/test/templates/nuke_outer_whitespace.haml +0 -144
  105. data/test/templates/original_engine.haml +0 -17
  106. data/test/templates/partial_layout.haml +0 -3
  107. data/test/templates/partial_layout_erb.erb +0 -4
  108. data/test/templates/partialize.haml +0 -1
  109. data/test/templates/partials.haml +0 -12
  110. data/test/templates/render_layout.haml +0 -2
  111. data/test/templates/silent_script.haml +0 -45
  112. data/test/templates/standard.haml +0 -43
  113. data/test/templates/standard_ugly.haml +0 -43
  114. data/test/templates/tag_parsing.haml +0 -21
  115. data/test/templates/very_basic.haml +0 -4
  116. data/test/templates/whitespace_handling.haml +0 -87
  117. data/test/test_helper.rb +0 -81
  118. data/test/util_test.rb +0 -63
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Haml
2
- VERSION = "4.0.6"
4
+ VERSION = "5.2.0"
3
5
  end
@@ -0,0 +1 @@
1
+ *.css
@@ -0,0 +1,15 @@
1
+ #filecontents
2
+ *:target, dt:target + dd
3
+ background-color: #ccf
4
+ border: 1px solid #88b
5
+ dt
6
+ font-weight: bold
7
+ dd
8
+ margin:
9
+ left: 0
10
+ bottom: 0.7em
11
+ padding-left: 3em
12
+ dt:target
13
+ border-bottom-style: none
14
+ & + dd
15
+ border-top-style: none
@@ -0,0 +1,12 @@
1
+ <%= superb :footer %>
2
+ <% if ENV["ANALYTICS"] %>
3
+ <script type="text/javascript">
4
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
5
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
6
+ </script>
7
+ <script type="text/javascript">
8
+ try {
9
+ var pageTracker = _gat._getTracker("<%= ENV["ANALYTICS"] %>");
10
+ pageTracker._trackPageview();
11
+ } catch(err) {}</script>
12
+ <% end %>
metadata CHANGED
@@ -1,17 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.6
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Nathan Weizenbaum
7
+ - Natalie Weizenbaum
8
8
  - Hampton Catlin
9
9
  - Norman Clarke
10
- autorequire:
10
+ - Akira Matsuda
11
+ autorequire:
11
12
  bindir: bin
12
13
  cert_chain: []
13
- date: 2014-12-01 00:00:00.000000000 Z
14
+ date: 2020-09-28 00:00:00.000000000 Z
14
15
  dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: temple
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.8.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.0
15
30
  - !ruby/object:Gem::Dependency
16
31
  name: tilt
17
32
  requirement: !ruby/object:Gem::Requirement
@@ -32,14 +47,14 @@ dependencies:
32
47
  requirements:
33
48
  - - ">="
34
49
  - !ruby/object:Gem::Version
35
- version: 3.0.0
50
+ version: 4.0.0
36
51
  type: :development
37
52
  prerelease: false
38
53
  version_requirements: !ruby/object:Gem::Requirement
39
54
  requirements:
40
55
  - - ">="
41
56
  - !ruby/object:Gem::Version
42
- version: 3.0.0
57
+ version: 4.0.0
43
58
  - !ruby/object:Gem::Dependency
44
59
  name: rbench
45
60
  requirement: !ruby/object:Gem::Requirement
@@ -56,6 +71,20 @@ dependencies:
56
71
  version: '0'
57
72
  - !ruby/object:Gem::Dependency
58
73
  name: minitest
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '4.0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '4.0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: nokogiri
59
88
  requirement: !ruby/object:Gem::Requirement
60
89
  requirements:
61
90
  - - ">="
@@ -69,19 +98,19 @@ dependencies:
69
98
  - !ruby/object:Gem::Version
70
99
  version: '0'
71
100
  - !ruby/object:Gem::Dependency
72
- name: nokogiri
101
+ name: simplecov
73
102
  requirement: !ruby/object:Gem::Requirement
74
103
  requirements:
75
- - - "~>"
104
+ - - '='
76
105
  - !ruby/object:Gem::Version
77
- version: 1.5.10
106
+ version: 0.17.1
78
107
  type: :development
79
108
  prerelease: false
80
109
  version_requirements: !ruby/object:Gem::Requirement
81
110
  requirements:
82
- - - "~>"
111
+ - - '='
83
112
  - !ruby/object:Gem::Version
84
- version: 1.5.10
113
+ version: 0.17.1
85
114
  description: |
86
115
  Haml (HTML Abstraction Markup Language) is a layer on top of HTML or XML that's
87
116
  designed to express the structure of documents in a non-repetitive, elegant, and
@@ -90,129 +119,72 @@ description: |
90
119
  but it can function as a stand-alone templating engine.
91
120
  email:
92
121
  - haml@googlegroups.com
93
- - norman@njclarke.com
122
+ - ronnie@dio.jp
94
123
  executables:
95
124
  - haml
96
125
  extensions: []
97
126
  extra_rdoc_files: []
98
127
  files:
128
+ - ".gitignore"
129
+ - ".gitmodules"
130
+ - ".travis.yml"
99
131
  - ".yardopts"
100
132
  - CHANGELOG.md
101
133
  - FAQ.md
134
+ - Gemfile
102
135
  - MIT-LICENSE
103
136
  - README.md
104
137
  - REFERENCE.md
105
138
  - Rakefile
139
+ - TODO
140
+ - benchmark.rb
106
141
  - bin/haml
142
+ - haml.gemspec
107
143
  - lib/haml.rb
144
+ - lib/haml/.gitattributes
145
+ - lib/haml/attribute_builder.rb
146
+ - lib/haml/attribute_compiler.rb
147
+ - lib/haml/attribute_parser.rb
108
148
  - lib/haml/buffer.rb
109
149
  - lib/haml/compiler.rb
110
150
  - lib/haml/engine.rb
111
151
  - lib/haml/error.rb
152
+ - lib/haml/escapable.rb
112
153
  - lib/haml/exec.rb
113
154
  - lib/haml/filters.rb
155
+ - lib/haml/generator.rb
114
156
  - lib/haml/helpers.rb
115
157
  - lib/haml/helpers/action_view_extensions.rb
116
158
  - lib/haml/helpers/action_view_mods.rb
117
159
  - lib/haml/helpers/action_view_xss_mods.rb
160
+ - lib/haml/helpers/safe_erubi_template.rb
118
161
  - lib/haml/helpers/safe_erubis_template.rb
119
162
  - lib/haml/helpers/xss_mods.rb
120
163
  - lib/haml/options.rb
121
164
  - lib/haml/parser.rb
165
+ - lib/haml/plugin.rb
122
166
  - lib/haml/railtie.rb
123
167
  - lib/haml/sass_rails_filter.rb
124
168
  - lib/haml/template.rb
125
169
  - lib/haml/template/options.rb
126
- - lib/haml/template/plugin.rb
170
+ - lib/haml/temple_engine.rb
171
+ - lib/haml/temple_line_counter.rb
127
172
  - lib/haml/util.rb
128
173
  - lib/haml/version.rb
129
- - test/engine_test.rb
130
- - test/erb/_av_partial_1.erb
131
- - test/erb/_av_partial_2.erb
132
- - test/erb/action_view.erb
133
- - test/erb/standard.erb
134
- - test/filters_test.rb
135
- - test/gemfiles/Gemfile.rails-3.0.x
136
- - test/gemfiles/Gemfile.rails-3.1.x
137
- - test/gemfiles/Gemfile.rails-3.2.x
138
- - test/gemfiles/Gemfile.rails-4.0.x
139
- - test/helper_test.rb
140
- - test/markaby/standard.mab
141
- - test/mocks/article.rb
142
- - test/parser_test.rb
143
- - test/results/content_for_layout.xhtml
144
- - test/results/eval_suppressed.xhtml
145
- - test/results/helpers.xhtml
146
- - test/results/helpful.xhtml
147
- - test/results/just_stuff.xhtml
148
- - test/results/list.xhtml
149
- - test/results/nuke_inner_whitespace.xhtml
150
- - test/results/nuke_outer_whitespace.xhtml
151
- - test/results/original_engine.xhtml
152
- - test/results/partial_layout.xhtml
153
- - test/results/partial_layout_erb.xhtml
154
- - test/results/partials.xhtml
155
- - test/results/render_layout.xhtml
156
- - test/results/silent_script.xhtml
157
- - test/results/standard.xhtml
158
- - test/results/tag_parsing.xhtml
159
- - test/results/very_basic.xhtml
160
- - test/results/whitespace_handling.xhtml
161
- - test/template_test.rb
162
- - test/templates/_av_partial_1.haml
163
- - test/templates/_av_partial_1_ugly.haml
164
- - test/templates/_av_partial_2.haml
165
- - test/templates/_av_partial_2_ugly.haml
166
- - test/templates/_layout.erb
167
- - test/templates/_layout_for_partial.haml
168
- - test/templates/_partial.haml
169
- - test/templates/_text_area.haml
170
- - test/templates/_text_area_helper.html.haml
171
- - test/templates/action_view.haml
172
- - test/templates/action_view_ugly.haml
173
- - test/templates/breakage.haml
174
- - test/templates/content_for_layout.haml
175
- - test/templates/eval_suppressed.haml
176
- - test/templates/helpers.haml
177
- - test/templates/helpful.haml
178
- - test/templates/just_stuff.haml
179
- - test/templates/list.haml
180
- - test/templates/nuke_inner_whitespace.haml
181
- - test/templates/nuke_outer_whitespace.haml
182
- - test/templates/original_engine.haml
183
- - test/templates/partial_layout.haml
184
- - test/templates/partial_layout_erb.erb
185
- - test/templates/partialize.haml
186
- - test/templates/partials.haml
187
- - test/templates/render_layout.haml
188
- - test/templates/silent_script.haml
189
- - test/templates/standard.haml
190
- - test/templates/standard_ugly.haml
191
- - test/templates/tag_parsing.haml
192
- - test/templates/very_basic.haml
193
- - test/templates/whitespace_handling.haml
194
- - test/test_helper.rb
195
- - test/util_test.rb
174
+ - yard/default/.gitignore
175
+ - yard/default/fulldoc/html/css/common.sass
176
+ - yard/default/layout/html/footer.erb
196
177
  homepage: http://haml.info/
197
178
  licenses:
198
179
  - MIT
199
- metadata: {}
200
- post_install_message: |2+
201
-
202
- HEADS UP! Haml 4.0 has many improvements, but also has changes that may break
203
- your application:
204
-
205
- * Support for Ruby 1.8.6 dropped
206
- * Support for Rails 2 dropped
207
- * Sass filter now always outputs <style> tags
208
- * Data attributes are now hyphenated, not underscored
209
- * html2haml utility moved to the html2haml gem
210
- * Textile and Maruku filters moved to the haml-contrib gem
211
-
212
- For more info see:
213
-
214
- http://rubydoc.info/github/haml/haml/file/CHANGELOG.md
215
-
180
+ metadata:
181
+ bug_tracker_uri: https://github.com/haml/haml/issues
182
+ changelog_uri: https://github.com/haml/haml/blob/main/CHANGELOG.md
183
+ documentation_uri: http://haml.info/docs.html
184
+ homepage_uri: http://haml.info
185
+ mailing_list_uri: https://groups.google.com/forum/?fromgroups#!forum/haml
186
+ source_code_uri: https://github.com/haml/haml
187
+ post_install_message:
216
188
  rdoc_options: []
217
189
  require_paths:
218
190
  - lib
@@ -220,22 +192,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
220
192
  requirements:
221
193
  - - ">="
222
194
  - !ruby/object:Gem::Version
223
- version: '0'
195
+ version: 2.0.0
224
196
  required_rubygems_version: !ruby/object:Gem::Requirement
225
197
  requirements:
226
198
  - - ">="
227
199
  - !ruby/object:Gem::Version
228
200
  version: '0'
229
201
  requirements: []
230
- rubyforge_project:
231
- rubygems_version: 2.4.4
232
- signing_key:
202
+ rubygems_version: 3.1.4
203
+ signing_key:
233
204
  specification_version: 4
234
205
  summary: An elegant, structured (X)HTML/XML templating engine.
235
- test_files:
236
- - test/engine_test.rb
237
- - test/filters_test.rb
238
- - test/helper_test.rb
239
- - test/parser_test.rb
240
- - test/template_test.rb
241
- - test/util_test.rb
206
+ test_files: []
@@ -1,41 +0,0 @@
1
- module Haml
2
-
3
- # This module makes Haml work with Rails using the template handler API.
4
- class Plugin < ActionView::Template::Handlers::ERB.superclass
5
-
6
- # Rails 3.1+, template handlers don't inherit from anything. In <= 3.0, they
7
- # do. To avoid messy logic figuring this out, we just inherit from whatever
8
- # the ERB handler does.
9
-
10
- # In Rails 3.1+, we don't need to include Compilable.
11
- if (ActionPack::VERSION::MAJOR == 3) && (ActionPack::VERSION::MINOR < 1)
12
- include ActionView::Template::Handlers::Compilable
13
- end
14
-
15
- def handles_encoding?; true; end
16
-
17
- def compile(template)
18
- options = Haml::Template.options.dup
19
- if (ActionPack::VERSION::MAJOR >= 4) && template.respond_to?(:type)
20
- options[:mime_type] = template.type
21
- elsif template.respond_to? :mime_type
22
- options[:mime_type] = template.mime_type
23
- end
24
- options[:filename] = template.identifier
25
- Haml::Engine.new(template.source, options).compiler.precompiled_with_ambles([])
26
- end
27
-
28
- # In Rails 3.1+, #call takes the place of #compile
29
- def self.call(template)
30
- new.compile(template)
31
- end
32
-
33
- def cache_fragment(block, name = {}, options = nil)
34
- @view.fragment_for(block, name, options) do
35
- eval("_hamlout.buffer", block.binding)
36
- end
37
- end
38
- end
39
- end
40
-
41
- ActionView::Template.register_template_handler(:haml, Haml::Plugin)
@@ -1,2013 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'test_helper'
3
-
4
- class EngineTest < MiniTest::Unit::TestCase
5
- # A map of erroneous Haml documents to the error messages they should produce.
6
- # The error messages may be arrays;
7
- # if so, the second element should be the line number that should be reported for the error.
8
- # If this isn't provided, the tests will assume the line number should be the last line of the document.
9
- EXCEPTION_MAP = {
10
- "!!!\n a" => error(:illegal_nesting_header),
11
- "a\n b" => error(:illegal_nesting_plain),
12
- "/ a\n b" => error(:illegal_nesting_content),
13
- "% a" => error(:invalid_tag, '% a'),
14
- "%p a\n b" => error(:illegal_nesting_line, 'p'),
15
- "%p=" => error(:no_ruby_code, '='),
16
- "%p~" => error(:no_ruby_code, '~'),
17
- "~" => error(:no_ruby_code, '~'),
18
- "=" => error(:no_ruby_code, '='),
19
- "%p/\n a" => error(:illegal_nesting_self_closing),
20
- ":a\n b" => [error(:filter_not_defined, 'a'), 1],
21
- ":a= b" => error(:invalid_filter_name, 'a= b'),
22
- "." => error(:illegal_element),
23
- ".#" => error(:illegal_element),
24
- ".{} a" => error(:illegal_element),
25
- ".() a" => error(:illegal_element),
26
- ".= a" => error(:illegal_element),
27
- "%p..a" => error(:illegal_element),
28
- "%a/ b" => error(:self_closing_content),
29
- " %p foo" => error(:indenting_at_start),
30
- " %p foo" => error(:indenting_at_start),
31
- "- end" => error(:no_end),
32
- "%p{:a => 'b',\n:c => 'd'}/ e" => [error(:self_closing_content), 2],
33
- "%p{:a => 'b',\n:c => 'd'}=" => [error(:no_ruby_code, '='), 2],
34
- "%p.{:a => 'b',\n:c => 'd'} e" => [error(:illegal_element), 1],
35
- "%p{:a => 'b',\n:c => 'd',\n:e => 'f'}\n%p/ a" => [error(:self_closing_content), 4],
36
- "%p{:a => 'b',\n:c => 'd',\n:e => 'f'}\n- raise 'foo'" => ["foo", 4],
37
- "%p{:a => 'b',\n:c => raise('foo'),\n:e => 'f'}" => ["foo", 2],
38
- "%p{:a => 'b',\n:c => 'd',\n:e => raise('foo')}" => ["foo", 3],
39
- " \n\t\n %p foo" => [error(:indenting_at_start), 3],
40
- "\n\n %p foo" => [error(:indenting_at_start), 3],
41
- "%p\n foo\n foo" => [error(:inconsistent_indentation, "1 space", "2 spaces"), 3],
42
- "%p\n foo\n%p\n foo" => [error(:inconsistent_indentation, "1 space", "2 spaces"), 4],
43
- "%p\n\t\tfoo\n\tfoo" => [error(:inconsistent_indentation, "1 tab", "2 tabs"), 3],
44
- "%p\n foo\n foo" => [error(:inconsistent_indentation, "3 spaces", "2 spaces"), 3],
45
- "%p\n foo\n %p\n bar" => [error(:inconsistent_indentation, "3 spaces", "2 spaces"), 4],
46
- "%p\n :plain\n bar\n \t baz" => [error(:inconsistent_indentation, '" \t "', "2 spaces"), 4],
47
- "%p\n foo\n%p\n bar" => [error(:deeper_indenting, 2), 4],
48
- "%p\n foo\n %p\n bar" => [error(:deeper_indenting, 3), 4],
49
- "%p\n \tfoo" => [error(:cant_use_tabs_and_spaces), 2],
50
- "%p(" => error(:invalid_attribute_list, '"("'),
51
- "%p(foo=)" => error(:invalid_attribute_list, '"(foo=)"'),
52
- "%p(foo 'bar')" => error(:invalid_attribute_list, '"(foo \'bar\')"'),
53
- "%p(foo=\nbar)" => [error(:invalid_attribute_list, '"(foo="'), 1],
54
- "%p(foo 'bar'\nbaz='bang')" => [error(:invalid_attribute_list, '"(foo \'bar\'"'), 1],
55
- "%p(foo='bar'\nbaz 'bang'\nbip='bop')" => [error(:invalid_attribute_list, '"(foo=\'bar\' baz \'bang\'"'), 2],
56
- "%p{'foo' => 'bar' 'bar' => 'baz'}" => :compile,
57
- "%p{:foo => }" => :compile,
58
- "%p{=> 'bar'}" => :compile,
59
- "%p{'foo => 'bar'}" => :compile,
60
- "%p{:foo => 'bar}" => :compile,
61
- "%p{:foo => 'bar\"}" => :compile,
62
- # Regression tests
63
- "foo\n\n\n bar" => [error(:illegal_nesting_plain), 4],
64
- "%p/\n\n bar" => [error(:illegal_nesting_self_closing), 3],
65
- "%p foo\n\n bar" => [error(:illegal_nesting_line, 'p'), 3],
66
- "/ foo\n\n bar" => [error(:illegal_nesting_content), 3],
67
- "!!!\n\n bar" => [error(:illegal_nesting_header), 3],
68
- "- raise 'foo'\n\n\n\nbar" => ["foo", 1],
69
- "= 'foo'\n-raise 'foo'" => ["foo", 2],
70
- "\n\n\n- raise 'foo'" => ["foo", 4],
71
- "%p foo |\n bar |\n baz |\nbop\n- raise 'foo'" => ["foo", 5],
72
- "foo\n:ruby\n 1\n 2\n 3\n- raise 'foo'" => ["foo", 6],
73
- "foo\n:erb\n 1\n 2\n 3\n- raise 'foo'" => ["foo", 6],
74
- "foo\n:plain\n 1\n 2\n 3\n- raise 'foo'" => ["foo", 6],
75
- "foo\n:plain\n 1\n 2\n 3\n4\n- raise 'foo'" => ["foo", 7],
76
- "foo\n:plain\n 1\n 2\n 3\#{''}\n- raise 'foo'" => ["foo", 6],
77
- "foo\n:plain\n 1\n 2\n 3\#{''}\n4\n- raise 'foo'" => ["foo", 7],
78
- "foo\n:plain\n 1\n 2\n \#{raise 'foo'}" => ["foo", 5],
79
- "= raise 'foo'\nfoo\nbar\nbaz\nbang" => ["foo", 1],
80
- "- case 1\n\n- when 1\n - raise 'foo'" => ["foo", 4],
81
- }
82
-
83
- User = Struct.new('User', :id)
84
- class CustomHamlClass < Struct.new(:id)
85
- def haml_object_ref
86
- "my_thing"
87
- end
88
- end
89
- CpkRecord = Struct.new('CpkRecord', :id) do
90
- def to_key
91
- [*self.id] unless id.nil?
92
- end
93
- end
94
-
95
- def use_test_tracing(options)
96
- unless options[:filename]
97
- # use caller method name as fake filename. useful for debugging
98
- i = -1
99
- caller[i+=1] =~ /`(.+?)'/ until $1 and $1.index('test_') == 0
100
- options[:filename] = "(#{$1})"
101
- end
102
- options
103
- end
104
-
105
- def render(text, options = {}, &block)
106
- options = use_test_tracing(options)
107
- super
108
- end
109
-
110
- def engine(text, options = {})
111
- options = use_test_tracing(options)
112
- Haml::Engine.new(text, options)
113
- end
114
-
115
- def setup
116
- return if RUBY_VERSION < "1.9"
117
- @old_default_internal = Encoding.default_internal
118
- silence_warnings{Encoding.default_internal = nil}
119
- end
120
-
121
- def teardown
122
- return if RUBY_VERSION < "1.9"
123
- silence_warnings{Encoding.default_internal = @old_default_internal}
124
- end
125
-
126
- def test_empty_render
127
- assert_equal "", render("")
128
- end
129
-
130
- def test_flexible_tabulation
131
- assert_equal("<p>\n foo\n</p>\n<q>\n bar\n <a>\n baz\n </a>\n</q>\n",
132
- render("%p\n foo\n%q\n bar\n %a\n baz"))
133
- assert_equal("<p>\n foo\n</p>\n<q>\n bar\n <a>\n baz\n </a>\n</q>\n",
134
- render("%p\n\tfoo\n%q\n\tbar\n\t%a\n\t\tbaz"))
135
- assert_equal("<p>\n \t \t bar\n baz\n</p>\n",
136
- render("%p\n :plain\n \t \t bar\n baz"))
137
- end
138
-
139
- def test_empty_render_should_remain_empty
140
- assert_equal('', render(''))
141
- end
142
-
143
- def test_attributes_should_render_correctly
144
- assert_equal("<div class='atlantis' style='ugly'></div>", render(".atlantis{:style => 'ugly'}").chomp)
145
- end
146
-
147
- def test_css_id_as_attribute_should_be_appended_with_underscore
148
- assert_equal("<div id='my_id_1'></div>", render("#my_id{:id => '1'}").chomp)
149
- assert_equal("<div id='my_id_1'></div>", render("#my_id{:id => 1}").chomp)
150
- end
151
-
152
- def test_ruby_code_should_work_inside_attributes
153
- assert_equal("<p class='3'>foo</p>", render("%p{:class => 1+2} foo").chomp)
154
- end
155
-
156
- def test_class_attr_with_array
157
- assert_equal("<p class='a b'>foo</p>\n", render("%p{:class => %w[a b]} foo")) # basic
158
- assert_equal("<p class='a b css'>foo</p>\n", render("%p.css{:class => %w[a b]} foo")) # merge with css
159
- assert_equal("<p class='b css'>foo</p>\n", render("%p.css{:class => %w[css b]} foo")) # merge uniquely
160
- assert_equal("<p class='a b c d'>foo</p>\n", render("%p{:class => [%w[a b], %w[c d]]} foo")) # flatten
161
- assert_equal("<p class='a b'>foo</p>\n", render("%p{:class => [:a, :b] } foo")) # stringify
162
- assert_equal("<p>foo</p>\n", render("%p{:class => [nil, false] } foo")) # strip falsey
163
- assert_equal("<p class='a'>foo</p>\n", render("%p{:class => :a} foo")) # single stringify
164
- assert_equal("<p>foo</p>\n", render("%p{:class => false} foo")) # single falsey
165
- assert_equal("<p class='a b html'>foo</p>\n", render("%p(class='html'){:class => %w[a b]} foo")) # html attrs
166
- end
167
-
168
- def test_id_attr_with_array
169
- assert_equal("<p id='a_b'>foo</p>\n", render("%p{:id => %w[a b]} foo")) # basic
170
- assert_equal("<p id='css_a_b'>foo</p>\n", render("%p#css{:id => %w[a b]} foo")) # merge with css
171
- assert_equal("<p id='a_b_c_d'>foo</p>\n", render("%p{:id => [%w[a b], %w[c d]]} foo")) # flatten
172
- assert_equal("<p id='a_b'>foo</p>\n", render("%p{:id => [:a, :b] } foo")) # stringify
173
- assert_equal("<p>foo</p>\n", render("%p{:id => [nil, false] } foo")) # strip falsey
174
- assert_equal("<p id='a'>foo</p>\n", render("%p{:id => :a} foo")) # single stringify
175
- assert_equal("<p>foo</p>\n", render("%p{:id => false} foo")) # single falsey
176
- assert_equal("<p id='html_a_b'>foo</p>\n", render("%p(id='html'){:id => %w[a b]} foo")) # html attrs
177
- end
178
-
179
- def test_colon_in_class_attr
180
- assert_equal("<p class='foo:bar'>\n", render("%p.foo:bar/"))
181
- end
182
-
183
- def test_colon_in_id_attr
184
- assert_equal("<p id='foo:bar'>\n", render("%p#foo:bar/"))
185
- end
186
-
187
- def test_dynamic_attributes_with_no_content
188
- assert_equal(<<HTML, render(<<HAML))
189
- <p>
190
- <a href='http://haml.info'></a>
191
- </p>
192
- HTML
193
- %p
194
- %a{:href => "http://" + "haml.info"}
195
- HAML
196
- end
197
-
198
- def test_attributes_with_to_s
199
- assert_equal(<<HTML, render(<<HAML))
200
- <p id='foo_2'></p>
201
- <p class='2 foo'></p>
202
- <p blaz='2'></p>
203
- <p 2='2'></p>
204
- HTML
205
- %p#foo{:id => 1+1}
206
- %p.foo{:class => 1+1}
207
- %p{:blaz => 1+1}
208
- %p{(1+1) => 1+1}
209
- HAML
210
- end
211
-
212
- def test_nil_should_render_empty_tag
213
- assert_equal("<div class='no_attributes'></div>",
214
- render(".no_attributes{:nil => nil}").chomp)
215
- end
216
-
217
- def test_strings_should_get_stripped_inside_tags
218
- assert_equal("<div class='stripped'>This should have no spaces in front of it</div>",
219
- render(".stripped This should have no spaces in front of it").chomp)
220
- end
221
-
222
- def test_one_liner_should_be_one_line
223
- assert_equal("<p>Hello</p>", render('%p Hello').chomp)
224
- end
225
-
226
- def test_one_liner_with_newline_shouldnt_be_one_line
227
- assert_equal("<p>\n foo\n bar\n</p>", render('%p= "foo\nbar"').chomp)
228
- end
229
-
230
- def test_multi_render
231
- engine = engine("%strong Hi there!")
232
- assert_equal("<strong>Hi there!</strong>\n", engine.to_html)
233
- assert_equal("<strong>Hi there!</strong>\n", engine.to_html)
234
- assert_equal("<strong>Hi there!</strong>\n", engine.to_html)
235
- end
236
-
237
- def test_interpolation
238
- assert_equal("<p>Hello World</p>\n", render('%p Hello #{who}', :locals => {:who => 'World'}))
239
- assert_equal("<p>\n Hello World\n</p>\n", render("%p\n Hello \#{who}", :locals => {:who => 'World'}))
240
- end
241
-
242
- def test_interpolation_in_the_middle_of_a_string
243
- assert_equal("\"title 'Title'. \"\n",
244
- render("\"title '\#{\"Title\"}'. \""))
245
- end
246
-
247
- def test_interpolation_at_the_beginning_of_a_line
248
- assert_equal("<p>2</p>\n", render('%p #{1 + 1}'))
249
- assert_equal("<p>\n 2\n</p>\n", render("%p\n \#{1 + 1}"))
250
- end
251
-
252
- def test_escaped_interpolation
253
- assert_equal("<p>Foo &amp; Bar & Baz</p>\n", render('%p& Foo #{"&"} Bar & Baz'))
254
- end
255
-
256
- def test_nil_tag_value_should_render_as_empty
257
- assert_equal("<p></p>\n", render("%p= nil"))
258
- end
259
-
260
- def test_tag_with_failed_if_should_render_as_empty
261
- assert_equal("<p></p>\n", render("%p= 'Hello' if false"))
262
- end
263
-
264
- def test_static_attributes_with_empty_attr
265
- assert_equal("<img alt='' src='/foo.png'>\n", render("%img{:src => '/foo.png', :alt => ''}"))
266
- end
267
-
268
- def test_dynamic_attributes_with_empty_attr
269
- assert_equal("<img alt='' src='/foo.png'>\n", render("%img{:width => nil, :src => '/foo.png', :alt => String.new}"))
270
- end
271
-
272
- def test_attribute_hash_with_newlines
273
- assert_equal("<p a='b' c='d'>foop</p>\n", render("%p{:a => 'b',\n :c => 'd'} foop"))
274
- assert_equal("<p a='b' c='d'>\n foop\n</p>\n", render("%p{:a => 'b',\n :c => 'd'}\n foop"))
275
- assert_equal("<p a='b' c='d'>\n", render("%p{:a => 'b',\n :c => 'd'}/"))
276
- assert_equal("<p a='b' c='d' e='f'></p>\n", render("%p{:a => 'b',\n :c => 'd',\n :e => 'f'}"))
277
- end
278
-
279
- def test_attr_hashes_not_modified
280
- hash = {:color => 'red'}
281
- assert_equal(<<HTML, render(<<HAML, :locals => {:hash => hash}))
282
- <div color='red'></div>
283
- <div class='special' color='red'></div>
284
- <div color='red'></div>
285
- HTML
286
- %div{hash}
287
- .special{hash}
288
- %div{hash}
289
- HAML
290
- assert_equal(hash, {:color => 'red'})
291
- end
292
-
293
- def test_ugly_semi_prerendered_tags
294
- assert_equal(<<HTML, render(<<HAML, :ugly => true))
295
- <p a='2'></p>
296
- <p a='2'>foo</p>
297
- <p a='2'>
298
- <p a='2'>foo</p>
299
- <p a='2'>foo
300
- bar</p>
301
- <p a='2'>foo
302
- bar</p>
303
- <p a='2'>
304
- foo
305
- </p>
306
- HTML
307
- %p{:a => 1 + 1}
308
- %p{:a => 1 + 1} foo
309
- %p{:a => 1 + 1}/
310
- %p{:a => 1 + 1}= "foo"
311
- %p{:a => 1 + 1}= "foo\\nbar"
312
- %p{:a => 1 + 1}~ "foo\\nbar"
313
- %p{:a => 1 + 1}
314
- foo
315
- HAML
316
- end
317
-
318
- def test_end_of_file_multiline
319
- assert_equal("<p>0</p>\n<p>1</p>\n<p>2</p>\n", render("- for i in (0...3)\n %p= |\n i |"))
320
- end
321
-
322
- def test_cr_newline
323
- assert_equal("<p>foo</p>\n<p>bar</p>\n<p>baz</p>\n<p>boom</p>\n", render("%p foo\r%p bar\r\n%p baz\n\r%p boom"))
324
- end
325
-
326
- def test_textareas
327
- assert_equal("<textarea>Foo&#x000A; bar&#x000A; baz</textarea>\n",
328
- render('%textarea= "Foo\n bar\n baz"'))
329
-
330
- assert_equal("<pre>Foo&#x000A; bar&#x000A; baz</pre>\n",
331
- render('%pre= "Foo\n bar\n baz"'))
332
-
333
- assert_equal("<textarea>#{'a' * 100}</textarea>\n",
334
- render("%textarea #{'a' * 100}"))
335
-
336
- assert_equal("<p>\n <textarea>Foo\n Bar\n Baz</textarea>\n</p>\n", render(<<SOURCE))
337
- %p
338
- %textarea
339
- Foo
340
- Bar
341
- Baz
342
- SOURCE
343
- end
344
-
345
- def test_pre_code
346
- assert_equal(<<HTML, render(<<HAML))
347
- <pre><code>Foo&#x000A; bar&#x000A; baz</code></pre>
348
- HTML
349
- %pre
350
- %code
351
- :preserve
352
- Foo
353
- bar
354
- baz
355
- HAML
356
- end
357
-
358
- def test_boolean_attributes
359
- assert_equal("<p bar baz='true' foo='bar'></p>\n",
360
- render("%p{:foo => 'bar', :bar => true, :baz => 'true'}", :format => :html4))
361
- assert_equal("<p bar='bar' baz='true' foo='bar'></p>\n",
362
- render("%p{:foo => 'bar', :bar => true, :baz => 'true'}", :format => :xhtml))
363
-
364
- assert_equal("<p baz='false' foo='bar'></p>\n",
365
- render("%p{:foo => 'bar', :bar => false, :baz => 'false'}", :format => :html4))
366
- assert_equal("<p baz='false' foo='bar'></p>\n",
367
- render("%p{:foo => 'bar', :bar => false, :baz => 'false'}", :format => :xhtml))
368
- end
369
-
370
- def test_nuke_inner_whitespace_in_loops
371
- assert_equal(<<HTML, render(<<HAML))
372
- <ul>foobarbaz</ul>
373
- HTML
374
- %ul<
375
- - for str in %w[foo bar baz]
376
- = str
377
- HAML
378
- end
379
-
380
- def test_both_whitespace_nukes_work_together
381
- assert_equal(<<RESULT, render(<<SOURCE))
382
- <p><q>Foo
383
- Bar</q></p>
384
- RESULT
385
- %p
386
- %q><= "Foo\\nBar"
387
- SOURCE
388
- end
389
-
390
- def test_nil_option
391
- assert_equal("<p foo='bar'></p>\n", render('%p{:foo => "bar"}', :attr_wrapper => nil))
392
- end
393
-
394
- def test_comment_with_crazy_nesting
395
- assert_equal(<<HTML, render(<<HAML))
396
- foo
397
- bar
398
- HTML
399
- foo
400
- -#
401
- ul
402
- %li{
403
- foo
404
- bar
405
- HAML
406
- end
407
-
408
- # Regression tests
409
-
410
- unless RUBY_VERSION < "1.9"
411
- def test_indentation_after_dynamic_attr_hash
412
- assert_equal(<<HTML, render(<<HAML))
413
- <html>
414
- <body>
415
- <img src='test'>
416
- foo
417
- bar
418
- </body>
419
- </html>
420
- HTML
421
- %html
422
- %body
423
- %img{:src => 'te'+'st'}
424
- = "foo\\nbar"
425
- HAML
426
- end
427
- end
428
-
429
- def test_whitespace_nuke_with_both_newlines
430
- assert_equal("<p>foo</p>\n", render('%p<= "\nfoo\n"'))
431
- assert_equal(<<HTML, render(<<HAML))
432
- <p>
433
- <p>foo</p>
434
- </p>
435
- HTML
436
- %p
437
- %p<= "\\nfoo\\n"
438
- HAML
439
- end
440
-
441
- def test_whitespace_nuke_with_tags_and_else
442
- assert_equal(<<HTML, render(<<HAML))
443
- <a>
444
- <b>foo</b>
445
- </a>
446
- HTML
447
- %a
448
- %b<
449
- - if false
450
- = "foo"
451
- - else
452
- foo
453
- HAML
454
-
455
- assert_equal(<<HTML, render(<<HAML))
456
- <a>
457
- <b>
458
- foo
459
- </b>
460
- </a>
461
- HTML
462
- %a
463
- %b
464
- - if false
465
- = "foo"
466
- - else
467
- foo
468
- HAML
469
- end
470
-
471
- def test_outer_whitespace_nuke_with_empty_script
472
- assert_equal(<<HTML, render(<<HAML))
473
- <p>
474
- foo<a></a></p>
475
- HTML
476
- %p
477
- foo
478
- = " "
479
- %a>
480
- HAML
481
- end
482
-
483
- def test_both_case_indentation_work_with_deeply_nested_code
484
- result = <<RESULT
485
- <h2>
486
- other
487
- </h2>
488
- RESULT
489
- assert_equal(result, render(<<HAML))
490
- - case 'other'
491
- - when 'test'
492
- %h2
493
- hi
494
- - when 'other'
495
- %h2
496
- other
497
- HAML
498
- assert_equal(result, render(<<HAML))
499
- - case 'other'
500
- - when 'test'
501
- %h2
502
- hi
503
- - when 'other'
504
- %h2
505
- other
506
- HAML
507
- end
508
-
509
- def test_equals_block_with_ugly
510
- assert_equal("foo\n", render(<<HAML, :ugly => true))
511
- = capture_haml do
512
- foo
513
- HAML
514
- end
515
-
516
- def test_plain_equals_with_ugly
517
- assert_equal("foo\nbar\n", render(<<HAML, :ugly => true))
518
- = "foo"
519
- bar
520
- HAML
521
- end
522
-
523
- def test_inline_if
524
- assert_equal(<<HTML, render(<<HAML))
525
- <p>One</p>
526
- <p></p>
527
- <p>Three</p>
528
- HTML
529
- - for name in ["One", "Two", "Three"]
530
- %p= name unless name == "Two"
531
- HAML
532
- end
533
-
534
- def test_end_with_method_call
535
- assert_equal(<<HTML, render(<<HAML))
536
- 2|3|4
537
- b-a-r
538
- HTML
539
- = [1, 2, 3].map do |i|
540
- - i + 1
541
- - end.join("|")
542
- = "bar".gsub(/./) do |s|
543
- - s + "-"
544
- - end.gsub(/-$/) do |s|
545
- - ''
546
- HAML
547
- end
548
-
549
- def test_nested_end_with_method_call
550
- assert_equal(<<HTML, render(<<HAML))
551
- <p>
552
- 2|3|4
553
- b-a-r
554
- </p>
555
- HTML
556
- %p
557
- = [1, 2, 3].map do |i|
558
- - i + 1
559
- - end.join("|")
560
- = "bar".gsub(/./) do |s|
561
- - s + "-"
562
- - end.gsub(/-$/) do |s|
563
- - ''
564
- HAML
565
- end
566
-
567
- def test_silent_end_with_stuff
568
- assert_equal(<<HTML, render(<<HAML))
569
- e
570
- d
571
- c
572
- b
573
- a
574
- HTML
575
- - str = "abcde"
576
- - if true
577
- = str.slice!(-1).chr
578
- - end until str.empty?
579
- HAML
580
-
581
- assert_equal(<<HTML, render(<<HAML))
582
- <p>hi!</p>
583
- HTML
584
- - if true
585
- %p hi!
586
- - end if "foo".gsub(/f/) do
587
- - "z"
588
- - end + "bar"
589
- HAML
590
- end
591
-
592
- def test_multiline_with_colon_after_filter
593
- assert_equal(<<HTML, render(<<HAML))
594
- Foo
595
- Bar
596
- HTML
597
- :plain
598
- Foo
599
- = { :a => "Bar", |
600
- :b => "Baz" }[:a] |
601
- HAML
602
- assert_equal(<<HTML, render(<<HAML))
603
-
604
- Bar
605
- HTML
606
- :plain
607
- = { :a => "Bar", |
608
- :b => "Baz" }[:a] |
609
- HAML
610
- end
611
-
612
- def test_multiline_in_filter
613
- assert_equal(<<HTML, render(<<HAML))
614
- Foo |
615
- Bar |
616
- Baz
617
- HTML
618
- :plain
619
- Foo |
620
- Bar |
621
- Baz
622
- HAML
623
- end
624
-
625
- def test_curly_brace
626
- assert_equal(<<HTML, render(<<HAML))
627
- Foo { Bar
628
- HTML
629
- == Foo { Bar
630
- HAML
631
- end
632
-
633
- def test_escape_attrs_false
634
- assert_equal(<<HTML, render(<<HAML, :escape_attrs => false))
635
- <div class='<?php echo "&quot;" ?>' id='foo'>
636
- bar
637
- </div>
638
- HTML
639
- #foo{:class => '<?php echo "&quot;" ?>'}
640
- bar
641
- HAML
642
- end
643
-
644
- def test_escape_attrs_always
645
- assert_equal(<<HTML, render(<<HAML, :escape_attrs => :always))
646
- <div class='"&amp;lt;&amp;gt;&amp;amp;"' id='foo'>
647
- bar
648
- </div>
649
- HTML
650
- #foo{:class => '"&lt;&gt;&amp;"'}
651
- bar
652
- HAML
653
- end
654
-
655
- def test_escape_html
656
- html = <<HTML
657
- &amp;
658
- &
659
- &amp;
660
- HTML
661
-
662
- assert_equal(html, render(<<HAML, :escape_html => true))
663
- &= "&"
664
- != "&"
665
- = "&"
666
- HAML
667
-
668
- assert_equal(html, render(<<HAML, :escape_html => true))
669
- &~ "&"
670
- !~ "&"
671
- ~ "&"
672
- HAML
673
-
674
- assert_equal(html, render(<<HAML, :escape_html => true))
675
- & \#{"&"}
676
- ! \#{"&"}
677
- \#{"&"}
678
- HAML
679
-
680
- assert_equal(html, render(<<HAML, :escape_html => true))
681
- &== \#{"&"}
682
- !== \#{"&"}
683
- == \#{"&"}
684
- HAML
685
-
686
- tag_html = <<HTML
687
- <p>&amp;</p>
688
- <p>&</p>
689
- <p>&amp;</p>
690
- HTML
691
-
692
- assert_equal(tag_html, render(<<HAML, :escape_html => true))
693
- %p&= "&"
694
- %p!= "&"
695
- %p= "&"
696
- HAML
697
-
698
- assert_equal(tag_html, render(<<HAML, :escape_html => true))
699
- %p&~ "&"
700
- %p!~ "&"
701
- %p~ "&"
702
- HAML
703
-
704
- assert_equal(tag_html, render(<<HAML, :escape_html => true))
705
- %p& \#{"&"}
706
- %p! \#{"&"}
707
- %p \#{"&"}
708
- HAML
709
-
710
- assert_equal(tag_html, render(<<HAML, :escape_html => true))
711
- %p&== \#{"&"}
712
- %p!== \#{"&"}
713
- %p== \#{"&"}
714
- HAML
715
- end
716
-
717
- def test_new_attrs_with_hash
718
- assert_equal("<a href='#'></a>\n", render('%a(href="#")'))
719
- end
720
-
721
- def test_silent_script_with_hyphen_case
722
- assert_equal("", render("- a = 'foo-case-bar-case'"))
723
- end
724
-
725
- def test_silent_script_with_hyphen_end
726
- assert_equal("", render("- a = 'foo-end-bar-end'"))
727
- end
728
-
729
- def test_silent_script_with_hyphen_end_and_block
730
- silence_warnings do
731
- assert_equal(<<HTML, render(<<HAML))
732
- <p>foo-end</p>
733
- <p>bar-end</p>
734
- HTML
735
- - ("foo-end-bar-end".gsub(/\\w+-end/) do |s|
736
- %p= s
737
- - end; nil)
738
- HAML
739
- end
740
- end
741
-
742
- def test_if_without_content_and_else
743
- assert_equal(<<HTML, render(<<HAML))
744
- foo
745
- HTML
746
- - if false
747
- - else
748
- foo
749
- HAML
750
-
751
- assert_equal(<<HTML, render(<<HAML))
752
- foo
753
- HTML
754
- - if true
755
- - if false
756
- - else
757
- foo
758
- HAML
759
- end
760
-
761
- def test_html_attributes_with_hash
762
- assert_equal("<a href='#' rel='top'>Foo</a>\n",
763
- render('%a(href="#" rel="top") Foo'))
764
- assert_equal("<a href='#'>Foo</a>\n",
765
- render('%a(href="#") #{"Foo"}'))
766
-
767
- assert_equal("<a href='#\"'></a>\n", render('%a(href="#\\"")'))
768
- end
769
-
770
- def test_case_assigned_to_var
771
- assert_equal(<<HTML, render(<<HAML))
772
- bar
773
- HTML
774
- - var = case 12
775
- - when 1; "foo"
776
- - when 12; "bar"
777
- = var
778
- HAML
779
-
780
- assert_equal(<<HTML, render(<<HAML))
781
- bar
782
- HTML
783
- - var = case 12
784
- - when 1
785
- - "foo"
786
- - when 12
787
- - "bar"
788
- = var
789
- HAML
790
-
791
- assert_equal(<<HTML, render(<<HAML))
792
- bar
793
- HTML
794
- - var = case 12
795
- - when 1
796
- - "foo"
797
- - when 12
798
- - "bar"
799
- = var
800
- HAML
801
- end
802
-
803
- def test_nested_case_assigned_to_var
804
- assert_equal(<<HTML, render(<<HAML))
805
- bar
806
- HTML
807
- - if true
808
- - var = case 12
809
- - when 1; "foo"
810
- - when 12; "bar"
811
- = var
812
- HAML
813
- end
814
-
815
- def test_case_assigned_to_multiple_vars
816
- assert_equal(<<HTML, render(<<HAML))
817
- bar
818
- bip
819
- HTML
820
- - var, vip = case 12
821
- - when 1; ["foo", "baz"]
822
- - when 12; ["bar", "bip"]
823
- = var
824
- = vip
825
- HAML
826
- end
827
-
828
- def test_if_assigned_to_var
829
- assert_equal(<<HTML, render(<<HAML))
830
- foo
831
- HTML
832
- - var = if false
833
- - else
834
- - "foo"
835
- = var
836
- HAML
837
-
838
- assert_equal(<<HTML, render(<<HAML))
839
- foo
840
- HTML
841
- - var = if false
842
- - elsif 12 == 12
843
- - "foo"
844
- - elsif 14 == 14; "bar"
845
- - else
846
- - "baz"
847
- = var
848
- HAML
849
-
850
- assert_equal(<<HTML, render(<<HAML))
851
- foo
852
- HTML
853
- - var = if false
854
- - "bar"
855
- - else
856
- - "foo"
857
- = var
858
- HAML
859
- end
860
-
861
- def test_case_with_newline_after_case
862
- assert_equal(<<HTML, render(<<HAML))
863
- foo
864
- HTML
865
- - case 1
866
-
867
- - when 1
868
- foo
869
- - when 2
870
- bar
871
- HAML
872
-
873
- assert_equal(<<HTML, render(<<HAML))
874
- bar
875
- HTML
876
- - case 2
877
-
878
- - when 1
879
- foo
880
- - when 2
881
- bar
882
- HAML
883
- end
884
-
885
- def test_escape_html_with_interpolated_if_statement
886
- assert_equal(<<HTML, render(<<HAML, :escape_html => true))
887
- foo,
888
- HTML
889
- foo\#{"," if true}
890
- HAML
891
- end
892
-
893
- # HTML escaping tests
894
-
895
- def test_ampersand_equals_should_escape
896
- assert_equal("<p>\n foo &amp; bar\n</p>\n", render("%p\n &= 'foo & bar'", :escape_html => false))
897
- end
898
-
899
- def test_ampersand_equals_inline_should_escape
900
- assert_equal("<p>foo &amp; bar</p>\n", render("%p&= 'foo & bar'", :escape_html => false))
901
- end
902
-
903
- def test_ampersand_equals_should_escape_before_preserve
904
- assert_equal("<textarea>foo&#x000A;bar</textarea>\n", render('%textarea&= "foo\nbar"', :escape_html => false))
905
- end
906
-
907
- def test_bang_equals_should_not_escape
908
- assert_equal("<p>\n foo & bar\n</p>\n", render("%p\n != 'foo & bar'", :escape_html => true))
909
- end
910
-
911
- def test_bang_equals_inline_should_not_escape
912
- assert_equal("<p>foo & bar</p>\n", render("%p!= 'foo & bar'", :escape_html => true))
913
- end
914
-
915
- def test_static_attributes_should_be_escaped
916
- assert_equal("<img class='atlantis' style='ugly&amp;stupid'>\n",
917
- render("%img.atlantis{:style => 'ugly&stupid'}"))
918
- assert_equal("<div class='atlantis' style='ugly&amp;stupid'>foo</div>\n",
919
- render(".atlantis{:style => 'ugly&stupid'} foo"))
920
- assert_equal("<p class='atlantis' style='ugly&amp;stupid'>foo</p>\n",
921
- render("%p.atlantis{:style => 'ugly&stupid'}= 'foo'"))
922
- assert_equal("<p class='atlantis' style='ugly&#x000A;stupid'></p>\n",
923
- render("%p.atlantis{:style => \"ugly\\nstupid\"}"))
924
- end
925
-
926
- def test_dynamic_attributes_should_be_escaped
927
- assert_equal("<img alt='' src='&amp;foo.png'>\n",
928
- render("%img{:width => nil, :src => '&foo.png', :alt => String.new}"))
929
- assert_equal("<p alt='' src='&amp;foo.png'>foo</p>\n",
930
- render("%p{:width => nil, :src => '&foo.png', :alt => String.new} foo"))
931
- assert_equal("<div alt='' src='&amp;foo.png'>foo</div>\n",
932
- render("%div{:width => nil, :src => '&foo.png', :alt => String.new}= 'foo'"))
933
- assert_equal("<img alt='' src='foo&#x000A;.png'>\n",
934
- render("%img{:width => nil, :src => \"foo\\n.png\", :alt => String.new}"))
935
- end
936
-
937
- def test_string_double_equals_should_be_esaped
938
- assert_equal("<p>4&&lt;</p>\n", render("%p== \#{2+2}&\#{'<'}", :escape_html => true))
939
- assert_equal("<p>4&<</p>\n", render("%p== \#{2+2}&\#{'<'}", :escape_html => false))
940
- end
941
-
942
- def test_escaped_inline_string_double_equals
943
- assert_equal("<p>4&&lt;</p>\n", render("%p&== \#{2+2}&\#{'<'}", :escape_html => true))
944
- assert_equal("<p>4&&lt;</p>\n", render("%p&== \#{2+2}&\#{'<'}", :escape_html => false))
945
- end
946
-
947
- def test_unescaped_inline_string_double_equals
948
- assert_equal("<p>4&<</p>\n", render("%p!== \#{2+2}&\#{'<'}", :escape_html => true))
949
- assert_equal("<p>4&<</p>\n", render("%p!== \#{2+2}&\#{'<'}", :escape_html => false))
950
- end
951
-
952
- def test_escaped_string_double_equals
953
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => true))
954
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => false))
955
- end
956
-
957
- def test_unescaped_string_double_equals
958
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n !== \#{2+2}&\#{'<'}", :escape_html => true))
959
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n !== \#{2+2}&\#{'<'}", :escape_html => false))
960
- end
961
-
962
- def test_string_interpolation_should_be_esaped
963
- assert_equal("<p>4&&lt;</p>\n", render("%p \#{2+2}&\#{'<'}", :escape_html => true))
964
- assert_equal("<p>4&<</p>\n", render("%p \#{2+2}&\#{'<'}", :escape_html => false))
965
- end
966
-
967
- def test_escaped_inline_string_interpolation
968
- assert_equal("<p>4&&lt;</p>\n", render("%p& \#{2+2}&\#{'<'}", :escape_html => true))
969
- assert_equal("<p>4&&lt;</p>\n", render("%p& \#{2+2}&\#{'<'}", :escape_html => false))
970
- end
971
-
972
- def test_unescaped_inline_string_interpolation
973
- assert_equal("<p>4&<</p>\n", render("%p! \#{2+2}&\#{'<'}", :escape_html => true))
974
- assert_equal("<p>4&<</p>\n", render("%p! \#{2+2}&\#{'<'}", :escape_html => false))
975
- end
976
-
977
- def test_escaped_string_interpolation
978
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => true))
979
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => false))
980
- end
981
-
982
- def test_unescaped_string_interpolation
983
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n ! \#{2+2}&\#{'<'}", :escape_html => true))
984
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n ! \#{2+2}&\#{'<'}", :escape_html => false))
985
- end
986
-
987
- def test_scripts_should_respect_escape_html_option
988
- assert_equal("<p>\n foo &amp; bar\n</p>\n", render("%p\n = 'foo & bar'", :escape_html => true))
989
- assert_equal("<p>\n foo & bar\n</p>\n", render("%p\n = 'foo & bar'", :escape_html => false))
990
- end
991
-
992
- def test_inline_scripts_should_respect_escape_html_option
993
- assert_equal("<p>foo &amp; bar</p>\n", render("%p= 'foo & bar'", :escape_html => true))
994
- assert_equal("<p>foo & bar</p>\n", render("%p= 'foo & bar'", :escape_html => false))
995
- end
996
-
997
- def test_script_ending_in_comment_should_render_when_html_is_escaped
998
- assert_equal("foo&amp;bar\n", render("= 'foo&bar' #comment", :escape_html => true))
999
- end
1000
-
1001
- def test_script_with_if_shouldnt_output
1002
- assert_equal(<<HTML, render(<<HAML))
1003
- <p>foo</p>
1004
- <p></p>
1005
- HTML
1006
- %p= "foo"
1007
- %p= "bar" if false
1008
- HAML
1009
- end
1010
-
1011
- # Options tests
1012
-
1013
- def test_filename_and_line
1014
- begin
1015
- render("\n\n = abc", :filename => 'test', :line => 2)
1016
- rescue Exception => e
1017
- assert_kind_of Haml::SyntaxError, e
1018
- assert_match(/test:4/, e.backtrace.first)
1019
- end
1020
-
1021
- begin
1022
- render("\n\n= 123\n\n= nil[]", :filename => 'test', :line => 2)
1023
- rescue Exception => e
1024
- assert_kind_of NoMethodError, e
1025
- backtrace = e.backtrace
1026
- backtrace.shift if rubinius?
1027
- assert_match(/test:6/, backtrace.first)
1028
- end
1029
- end
1030
-
1031
- def test_stop_eval
1032
- assert_equal("", render("= 'Hello'", :suppress_eval => true))
1033
- assert_equal("", render("- haml_concat 'foo'", :suppress_eval => true))
1034
- assert_equal("<div id='foo' yes='no'>\n", render("#foo{:yes => 'no'}/", :suppress_eval => true))
1035
- assert_equal("<div id='foo'>\n", render("#foo{:yes => 'no', :call => a_function() }/", :suppress_eval => true))
1036
- assert_equal("<div>\n", render("%div[1]/", :suppress_eval => true))
1037
- assert_equal("", render(":ruby\n Kernel.puts 'hello'", :suppress_eval => true))
1038
- end
1039
-
1040
- def test_doctypes
1041
- assert_equal('<!DOCTYPE html>',
1042
- render('!!!', :format => :html5).strip)
1043
- assert_equal('<!DOCTYPE html>', render('!!! 5').strip)
1044
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
1045
- render('!!! strict', :format => :xhtml).strip)
1046
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
1047
- render('!!! frameset', :format => :xhtml).strip)
1048
- assert_equal('<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">',
1049
- render('!!! mobile', :format => :xhtml).strip)
1050
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
1051
- render('!!! basic', :format => :xhtml).strip)
1052
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
1053
- render('!!! transitional', :format => :xhtml).strip)
1054
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
1055
- render('!!!', :format => :xhtml).strip)
1056
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
1057
- render('!!! strict', :format => :html4).strip)
1058
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
1059
- render('!!! frameset', :format => :html4).strip)
1060
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
1061
- render('!!! transitional', :format => :html4).strip)
1062
- assert_equal('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
1063
- render('!!!', :format => :html4).strip)
1064
- end
1065
-
1066
- def test_attr_wrapper
1067
- assert_equal("<p strange=*attrs*></p>\n", render("%p{ :strange => 'attrs'}", :attr_wrapper => '*'))
1068
- assert_equal("<p escaped='quo\"te'></p>\n", render("%p{ :escaped => 'quo\"te'}", :attr_wrapper => '"'))
1069
- assert_equal("<p escaped=\"quo'te\"></p>\n", render("%p{ :escaped => 'quo\\'te'}", :attr_wrapper => '"'))
1070
- assert_equal("<p escaped=\"q'uo&#x0022;te\"></p>\n", render("%p{ :escaped => 'q\\'uo\"te'}", :attr_wrapper => '"'))
1071
- assert_equal("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n", render("!!! XML", :attr_wrapper => '"', :format => :xhtml))
1072
- end
1073
-
1074
- def test_autoclose_option
1075
- assert_equal("<flaz foo='bar'>\n", render("%flaz{:foo => 'bar'}", :autoclose => ["flaz"]))
1076
- assert_equal(<<HTML, render(<<HAML, :autoclose => [/^flaz/]))
1077
- <flaz>
1078
- <flaznicate>
1079
- <flan></flan>
1080
- HTML
1081
- %flaz
1082
- %flaznicate
1083
- %flan
1084
- HAML
1085
- end
1086
-
1087
- def test_attrs_parsed_correctly
1088
- assert_equal("<p boom=>biddly='bar =&gt; baz'></p>\n", render("%p{'boom=>biddly' => 'bar => baz'}"))
1089
- assert_equal("<p foo,bar='baz, qux'></p>\n", render("%p{'foo,bar' => 'baz, qux'}"))
1090
- assert_equal("<p escaped='quo&#x000A;te'></p>\n", render("%p{ :escaped => \"quo\\nte\"}"))
1091
- assert_equal("<p escaped='quo4te'></p>\n", render("%p{ :escaped => \"quo\#{2 + 2}te\"}"))
1092
- end
1093
-
1094
- def test_correct_parsing_with_brackets
1095
- assert_equal("<p class='foo'>{tada} foo</p>\n", render("%p{:class => 'foo'} {tada} foo"))
1096
- assert_equal("<p class='foo'>deep {nested { things }}</p>\n", render("%p{:class => 'foo'} deep {nested { things }}"))
1097
- assert_equal("<p class='bar foo'>{a { d</p>\n", render("%p{{:class => 'foo'}, :class => 'bar'} {a { d"))
1098
- assert_equal("<p foo='bar'>a}</p>\n", render("%p{:foo => 'bar'} a}"))
1099
-
1100
- foo = []
1101
- foo[0] = Struct.new('Foo', :id).new
1102
- assert_equal("<p class='struct_foo' id='struct_foo_new'>New User]</p>\n",
1103
- render("%p[foo[0]] New User]", :locals => {:foo => foo}))
1104
- assert_equal("<p class='prefix_struct_foo' id='prefix_struct_foo_new'>New User]</p>\n",
1105
- render("%p[foo[0], :prefix] New User]", :locals => {:foo => foo}))
1106
-
1107
- foo[0].id = 1
1108
- assert_equal("<p class='struct_foo' id='struct_foo_1'>New User]</p>\n",
1109
- render("%p[foo[0]] New User]", :locals => {:foo => foo}))
1110
- assert_equal("<p class='prefix_struct_foo' id='prefix_struct_foo_1'>New User]</p>\n",
1111
- render("%p[foo[0], :prefix] New User]", :locals => {:foo => foo}))
1112
- end
1113
-
1114
- def test_empty_attrs
1115
- assert_equal("<p attr=''>empty</p>\n", render("%p{ :attr => '' } empty"))
1116
- assert_equal("<p attr=''>empty</p>\n", render("%p{ :attr => x } empty", :locals => {:x => ''}))
1117
- end
1118
-
1119
- def test_nil_attrs
1120
- assert_equal("<p>nil</p>\n", render("%p{ :attr => nil } nil"))
1121
- assert_equal("<p>nil</p>\n", render("%p{ :attr => x } nil", :locals => {:x => nil}))
1122
- end
1123
-
1124
- def test_nil_id_with_syntactic_id
1125
- assert_equal("<p id='foo'>nil</p>\n", render("%p#foo{:id => nil} nil"))
1126
- assert_equal("<p id='foo_bar'>nil</p>\n", render("%p#foo{{:id => 'bar'}, :id => nil} nil"))
1127
- assert_equal("<p id='foo_bar'>nil</p>\n", render("%p#foo{{:id => nil}, :id => 'bar'} nil"))
1128
- end
1129
-
1130
- def test_nil_class_with_syntactic_class
1131
- assert_equal("<p class='foo'>nil</p>\n", render("%p.foo{:class => nil} nil"))
1132
- assert_equal("<p class='bar foo'>nil</p>\n", render("%p.bar.foo{:class => nil} nil"))
1133
- assert_equal("<p class='bar foo'>nil</p>\n", render("%p.foo{{:class => 'bar'}, :class => nil} nil"))
1134
- assert_equal("<p class='bar foo'>nil</p>\n", render("%p.foo{{:class => nil}, :class => 'bar'} nil"))
1135
- end
1136
-
1137
- def test_locals
1138
- assert_equal("<p>Paragraph!</p>\n", render("%p= text", :locals => { :text => "Paragraph!" }))
1139
- end
1140
-
1141
- def test_dynamic_attrs_shouldnt_register_as_literal_values
1142
- assert_equal("<p a='b2c'></p>\n", render('%p{:a => "b#{1 + 1}c"}'))
1143
- assert_equal("<p a='b2c'></p>\n", render("%p{:a => 'b' + (1 + 1).to_s + 'c'}"))
1144
- end
1145
-
1146
- def test_dynamic_attrs_with_self_closed_tag
1147
- assert_equal("<a b='2'>\nc\n", render("%a{'b' => 1 + 1}/\n= 'c'\n"))
1148
- end
1149
-
1150
- EXCEPTION_MAP.each do |key, value|
1151
- define_method("test_exception (#{key.inspect})") do
1152
- begin
1153
- silence_warnings do
1154
- render(key, :filename => "(test_exception (#{key.inspect}))")
1155
- end
1156
- rescue Exception => err
1157
- value = [value] unless value.is_a?(Array)
1158
- expected_message, line_no = value
1159
- line_no ||= key.split("\n").length
1160
-
1161
-
1162
- if expected_message == :compile
1163
- assert_match(/(compile error|syntax error|unterminated string|expecting)/, err.message, "Line: #{key}")
1164
- else
1165
- assert_equal(expected_message, err.message, "Line: #{key}")
1166
- end
1167
-
1168
- else
1169
- assert(false, "Exception not raised for\n#{key}")
1170
- end
1171
- end
1172
- end
1173
-
1174
- def test_exception_line
1175
- render("a\nb\n!!!\n c\nd")
1176
- rescue Haml::SyntaxError => e
1177
- assert_equal("(test_exception_line):4", e.backtrace[0])
1178
- else
1179
- assert(false, '"a\nb\n!!!\n c\nd" doesn\'t produce an exception')
1180
- end
1181
-
1182
- def test_exception
1183
- render("%p\n hi\n %a= undefined\n= 12")
1184
- rescue Exception => e
1185
- backtrace = e.backtrace
1186
- backtrace.shift if rubinius?
1187
- assert_match("(test_exception):3", backtrace[0])
1188
- else
1189
- # Test failed... should have raised an exception
1190
- assert(false)
1191
- end
1192
-
1193
- def test_compile_error
1194
- render("a\nb\n- fee)\nc")
1195
- rescue Exception => e
1196
- assert_match(/\(test_compile_error\):3: (syntax error|expecting \$end)/i, e.message)
1197
- else
1198
- assert(false,
1199
- '"a\nb\n- fee)\nc" doesn\'t produce an exception!')
1200
- end
1201
-
1202
- def test_unbalanced_brackets
1203
- render('foo #{1 + 5} foo #{6 + 7 bar #{8 + 9}')
1204
- rescue Haml::SyntaxError => e
1205
- assert_equal(Haml::Error.message(:unbalanced_brackets), e.message)
1206
- end
1207
-
1208
- def test_balanced_conditional_comments
1209
- assert_equal("<!--[if !(IE 6)|(IE 7)]> Bracket: ] <![endif]-->\n",
1210
- render("/[if !(IE 6)|(IE 7)] Bracket: ]"))
1211
- end
1212
-
1213
- def test_local_assigns_dont_modify_class
1214
- assert_equal("bar\n", render("= foo", :locals => {:foo => 'bar'}))
1215
- assert_equal(nil, defined?(foo))
1216
- end
1217
-
1218
- def test_object_ref_with_nil_id
1219
- user = User.new
1220
- assert_equal("<p class='struct_user' id='struct_user_new'>New User</p>\n",
1221
- render("%p[user] New User", :locals => {:user => user}))
1222
- end
1223
-
1224
- def test_object_ref_before_attrs
1225
- user = User.new 42
1226
- assert_equal("<p class='struct_user' id='struct_user_42' style='width: 100px;'>New User</p>\n",
1227
- render("%p[user]{:style => 'width: 100px;'} New User", :locals => {:user => user}))
1228
- end
1229
-
1230
- def test_object_ref_with_custom_haml_class
1231
- custom = CustomHamlClass.new 42
1232
- assert_equal("<p class='my_thing' id='my_thing_42' style='width: 100px;'>My Thing</p>\n",
1233
- render("%p[custom]{:style => 'width: 100px;'} My Thing", :locals => {:custom => custom}))
1234
- end
1235
-
1236
- def test_object_ref_with_multiple_ids
1237
- cpk_record = CpkRecord.new([42,6,9])
1238
- assert_equal("<p class='struct_cpk_record' id='struct_cpk_record_42_6_9' style='width: 100px;'>CPK Record</p>\n",
1239
- render("%p[cpk_record]{:style => 'width: 100px;'} CPK Record", :locals => {:cpk_record => cpk_record}))
1240
- end
1241
-
1242
- def test_non_literal_attributes
1243
- assert_equal("<p a1='foo' a2='bar' a3='baz'></p>\n",
1244
- render("%p{a2, a1, :a3 => 'baz'}",
1245
- :locals => {:a1 => {:a1 => 'foo'}, :a2 => {:a2 => 'bar'}}))
1246
- end
1247
-
1248
- def test_render_should_accept_a_binding_as_scope
1249
- string = "This is a string!"
1250
- string.instance_variable_set("@var", "Instance variable")
1251
- b = string.instance_eval do
1252
- var = "Local variable"
1253
- # Silence unavoidable warning; Ruby doesn't know we're going to use this
1254
- # later.
1255
- nil if var
1256
- binding
1257
- end
1258
-
1259
- assert_equal("<p>THIS IS A STRING!</p>\n<p>Instance variable</p>\n<p>Local variable</p>\n",
1260
- render("%p= upcase\n%p= @var\n%p= var", :scope => b))
1261
- end
1262
-
1263
- def test_yield_should_work_with_binding
1264
- assert_equal("12\nFOO\n", render("= yield\n= upcase", :scope => "foo".instance_eval{binding}) { 12 })
1265
- end
1266
-
1267
- def test_yield_should_work_with_def_method
1268
- s = "foo"
1269
- engine("= yield\n= upcase").def_method(s, :render)
1270
- assert_equal("12\nFOO\n", s.render { 12 })
1271
- end
1272
-
1273
- def test_def_method_with_module
1274
- engine("= yield\n= upcase").def_method(String, :render_haml)
1275
- assert_equal("12\nFOO\n", "foo".render_haml { 12 })
1276
- end
1277
-
1278
- def test_def_method_locals
1279
- obj = Object.new
1280
- engine("%p= foo\n.bar{:baz => baz}= boom").def_method(obj, :render, :foo, :baz, :boom)
1281
- assert_equal("<p>1</p>\n<div baz='2' class='bar'>3</div>\n", obj.render(:foo => 1, :baz => 2, :boom => 3))
1282
- end
1283
-
1284
- def test_render_proc_locals
1285
- proc = engine("%p= foo\n.bar{:baz => baz}= boom").render_proc(Object.new, :foo, :baz, :boom)
1286
- assert_equal("<p>1</p>\n<div baz='2' class='bar'>3</div>\n", proc[:foo => 1, :baz => 2, :boom => 3])
1287
- end
1288
-
1289
- def test_render_proc_with_binding
1290
- assert_equal("FOO\n", engine("= upcase").render_proc("foo".instance_eval{binding}).call)
1291
- end
1292
-
1293
- def test_haml_buffer_gets_reset_even_with_exception
1294
- scope = Object.new
1295
- render("- raise Haml::Error", :scope => scope)
1296
- assert(false, "Expected exception")
1297
- rescue Exception
1298
- assert_nil(scope.send(:haml_buffer))
1299
- end
1300
-
1301
- def test_def_method_haml_buffer_gets_reset_even_with_exception
1302
- scope = Object.new
1303
- engine("- raise Haml::Error").def_method(scope, :render)
1304
- scope.render
1305
- assert(false, "Expected exception")
1306
- rescue Exception
1307
- assert_nil(scope.send(:haml_buffer))
1308
- end
1309
-
1310
- def test_render_proc_haml_buffer_gets_reset_even_with_exception
1311
- scope = Object.new
1312
- proc = engine("- raise Haml::Error").render_proc(scope)
1313
- proc.call
1314
- assert(false, "Expected exception")
1315
- rescue Exception
1316
- assert_nil(scope.send(:haml_buffer))
1317
- end
1318
-
1319
- def test_render_proc_should_raise_haml_syntax_error_not_ruby_syntax_error
1320
- assert_raises(Haml::SyntaxError) do
1321
- Haml::Engine.new("%p{:foo => !}").render_proc(Object.new, :foo).call
1322
- end
1323
- end
1324
-
1325
- def test_render_should_raise_haml_syntax_error_not_ruby_syntax_error
1326
- assert_raises(Haml::SyntaxError) do
1327
- Haml::Engine.new("%p{:foo => !}").render
1328
- end
1329
- end
1330
-
1331
- def test_ugly_true
1332
- assert_equal("<div id='outer'>\n<div id='inner'>\n<p>hello world</p>\n</div>\n</div>\n",
1333
- render("#outer\n #inner\n %p hello world", :ugly => true))
1334
-
1335
- assert_equal("<p>#{'s' * 75}</p>\n",
1336
- render("%p #{'s' * 75}", :ugly => true))
1337
-
1338
- assert_equal("<p>#{'s' * 75}</p>\n",
1339
- render("%p= 's' * 75", :ugly => true))
1340
- end
1341
-
1342
- def test_remove_whitespace_true
1343
- assert_equal("<div id='outer'><div id='inner'><p>hello world</p></div></div>",
1344
- render("#outer\n #inner\n %p hello world", :remove_whitespace => true))
1345
- assert_equal("<p>hello world<pre>foo bar\nbaz</pre></p>", render(<<HAML, :remove_whitespace => true))
1346
- %p
1347
- hello world
1348
- %pre
1349
- foo bar
1350
- baz
1351
- HAML
1352
- assert_equal("<div><span>foo</span> <span>bar</span></div>",
1353
- render('%div <span>foo</span> <span>bar</span>', :remove_whitespace => true))
1354
- end
1355
-
1356
- def test_auto_preserve_unless_ugly
1357
- assert_equal("<pre>foo&#x000A;bar</pre>\n", render('%pre="foo\nbar"'))
1358
- assert_equal("<pre>foo\nbar</pre>\n", render("%pre\n foo\n bar"))
1359
- assert_equal("<pre>foo\nbar</pre>\n", render('%pre="foo\nbar"', :ugly => true))
1360
- assert_equal("<pre>foo\nbar</pre>\n", render("%pre\n foo\n bar", :ugly => true))
1361
- end
1362
-
1363
- def test_xhtml_output_option
1364
- assert_equal "<p>\n <br />\n</p>\n", render("%p\n %br", :format => :xhtml)
1365
- assert_equal "<a />\n", render("%a/", :format => :xhtml)
1366
- end
1367
-
1368
- def test_arbitrary_output_option
1369
- assert_raises_message(Haml::Error, "Invalid output format :html1") do
1370
- engine("%br", :format => :html1)
1371
- end
1372
- end
1373
-
1374
- def test_static_hashes
1375
- assert_equal("<a b='a =&gt; b'></a>\n", render("%a{:b => 'a => b'}", :suppress_eval => true))
1376
- assert_equal("<a b='a, b'></a>\n", render("%a{:b => 'a, b'}", :suppress_eval => true))
1377
- assert_equal("<a b='a\tb'></a>\n", render('%a{:b => "a\tb"}', :suppress_eval => true))
1378
- assert_equal("<a b='a\#{foo}b'></a>\n", render('%a{:b => "a\\#{foo}b"}', :suppress_eval => true))
1379
- assert_equal("<a b='#f00'></a>\n", render("%a{:b => '#f00'}", :suppress_eval => true))
1380
- end
1381
-
1382
- def test_dynamic_hashes_with_suppress_eval
1383
- assert_equal("<a></a>\n", render('%a{:b => "a #{1 + 1} b", :c => "d"}', :suppress_eval => true))
1384
- end
1385
-
1386
- def test_interpolates_instance_vars_in_attribute_values
1387
- scope = Object.new
1388
- scope.instance_variable_set :@foo, 'bar'
1389
- assert_equal("<a b='a bar b'></a>\n", render('%a{:b => "a #@foo b"}', :scope => scope))
1390
- end
1391
-
1392
- def test_interpolates_global_vars_in_attribute_values
1393
- # make sure the value isn't just interpolated in during template compilation
1394
- engine = Haml::Engine.new('%a{:b => "a #$global_var_for_testing b"}')
1395
- $global_var_for_testing = 'bar'
1396
- assert_equal("<a b='a bar b'></a>\n", engine.to_html)
1397
- end
1398
-
1399
- def test_utf8_attrs
1400
- assert_equal("<a href='héllo'></a>\n", render("%a{:href => 'héllo'}"))
1401
- assert_equal("<a href='héllo'></a>\n", render("%a(href='héllo')"))
1402
- end
1403
-
1404
- # HTML 4.0
1405
-
1406
- def test_html_has_no_self_closing_tags
1407
- assert_equal "<p>\n <br>\n</p>\n", render("%p\n %br", :format => :html4)
1408
- assert_equal "<br>\n", render("%br/", :format => :html4)
1409
- end
1410
-
1411
- def test_html_renders_empty_node_with_closing_tag
1412
- assert_equal "<div class='foo'></div>\n", render(".foo", :format => :html4)
1413
- end
1414
-
1415
- def test_html_doesnt_add_slash_to_self_closing_tags
1416
- assert_equal "<a>\n", render("%a/", :format => :html4)
1417
- assert_equal "<a foo='2'>\n", render("%a{:foo => 1 + 1}/", :format => :html4)
1418
- assert_equal "<meta>\n", render("%meta", :format => :html4)
1419
- assert_equal "<meta foo='2'>\n", render("%meta{:foo => 1 + 1}", :format => :html4)
1420
- end
1421
-
1422
- def test_html_ignores_xml_prolog_declaration
1423
- assert_equal "", render('!!! XML', :format => :html4)
1424
- end
1425
-
1426
- def test_html_has_different_doctype
1427
- assert_equal %{<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n},
1428
- render('!!!', :format => :html4)
1429
- end
1430
-
1431
- # because anything before the doctype triggers quirks mode in IE
1432
- def test_xml_prolog_and_doctype_dont_result_in_a_leading_whitespace_in_html
1433
- refute_match(/^\s+/, render("!!! xml\n!!!", :format => :html4))
1434
- end
1435
-
1436
- # HTML5
1437
- def test_html5_doctype
1438
- assert_equal %{<!DOCTYPE html>\n}, render('!!!', :format => :html5)
1439
- end
1440
-
1441
- # HTML5 custom data attributes
1442
- def test_html5_data_attributes_without_hyphenation
1443
- assert_equal("<div data-author_id='123' data-biz='baz' data-foo='bar'></div>\n",
1444
- render("%div{:data => {:author_id => 123, :foo => 'bar', :biz => 'baz'}}",
1445
- :hyphenate_data_attrs => false))
1446
-
1447
- assert_equal("<div data-one_plus_one='2'></div>\n",
1448
- render("%div{:data => {:one_plus_one => 1+1}}",
1449
- :hyphenate_data_attrs => false))
1450
-
1451
- assert_equal("<div data-foo='Here&#x0027;s a \"quoteful\" string.'></div>\n",
1452
- render(%{%div{:data => {:foo => %{Here's a "quoteful" string.}}}},
1453
- :hyphenate_data_attrs => false)) #'
1454
- end
1455
-
1456
- def test_html5_data_attributes_with_hyphens
1457
- assert_equal("<div data-foo-bar='blip'></div>\n",
1458
- render("%div{:data => {:foo_bar => 'blip'}}"))
1459
- assert_equal("<div data-baz='bang' data-foo-bar='blip'></div>\n",
1460
- render("%div{:data => {:foo_bar => 'blip', :baz => 'bang'}}"))
1461
- end
1462
-
1463
- def test_html5_arbitrary_hash_valued_attributes_with
1464
- assert_equal("<div aria-foo='blip'></div>\n",
1465
- render("%div{:aria => {:foo => 'blip'}}"))
1466
- assert_equal("<div foo-baz='bang'></div>\n",
1467
- render("%div{:foo => {:baz => 'bang'}}"))
1468
- end
1469
-
1470
- def test_html5_data_attributes_with_nested_hash
1471
- assert_equal("<div data-a-b='c'></div>\n", render(<<-HAML))
1472
- - hash = {:a => {:b => 'c'}}
1473
- - hash[:d] = hash
1474
- %div{:data => hash}
1475
- HAML
1476
- end
1477
-
1478
- def test_html5_data_attributes_with_nested_hash_and_without_hyphenation
1479
- assert_equal("<div data-a_b='c'></div>\n", render(<<-HAML, :hyphenate_data_attrs => false))
1480
- - hash = {:a => {:b => 'c'}}
1481
- - hash[:d] = hash
1482
- %div{:data => hash}
1483
- HAML
1484
- end
1485
-
1486
- def test_html5_data_attributes_with_multiple_defs
1487
- # Should always use the more-explicit attribute
1488
- assert_equal("<div data-foo='second'></div>\n",
1489
- render("%div{:data => {:foo => 'first'}, 'data-foo' => 'second'}"))
1490
- assert_equal("<div data-foo='first'></div>\n",
1491
- render("%div{'data-foo' => 'first', :data => {:foo => 'second'}}"))
1492
- end
1493
-
1494
- def test_html5_data_attributes_with_attr_method
1495
- Haml::Helpers.module_eval do
1496
- def data_hash
1497
- {:data => {:foo => "bar", :baz => "bang"}}
1498
- end
1499
-
1500
- def data_val
1501
- {:data => "dat"}
1502
- end
1503
- end
1504
-
1505
- assert_equal("<div data-baz='bang' data-brat='wurst' data-foo='blip'></div>\n",
1506
- render("%div{data_hash, :data => {:foo => 'blip', :brat => 'wurst'}}"))
1507
- assert_equal("<div data-baz='bang' data-foo='blip'></div>\n",
1508
- render("%div{data_hash, 'data-foo' => 'blip'}"))
1509
- assert_equal("<div data-baz='bang' data-foo='bar' data='dat'></div>\n",
1510
- render("%div{data_hash, :data => 'dat'}"))
1511
- assert_equal("<div data-brat='wurst' data-foo='blip' data='dat'></div>\n",
1512
- render("%div{data_val, :data => {:foo => 'blip', :brat => 'wurst'}}"))
1513
- end
1514
-
1515
- def test_html5_data_attributes_with_identical_attribute_values
1516
- assert_equal("<div data-x='50' data-y='50'></div>\n",
1517
- render("%div{:data => {:x => 50, :y => 50}}"))
1518
- end
1519
-
1520
- def test_xml_doc_using_html5_format_and_mime_type
1521
- assert_equal(<<XML, render(<<HAML, { :format => :html5, :mime_type => 'text/xml' }))
1522
- <?xml version='1.0' encoding='utf-8' ?>
1523
- <root>
1524
- <element />
1525
- <hr />
1526
- </root>
1527
- XML
1528
- !!! XML
1529
- %root
1530
- %element/
1531
- %hr
1532
- HAML
1533
- end
1534
-
1535
- def test_xml_doc_using_html4_format_and_mime_type
1536
- assert_equal(<<XML, render(<<HAML, { :format => :html4, :mime_type => 'text/xml' }))
1537
- <?xml version='1.0' encoding='utf-8' ?>
1538
- <root>
1539
- <element />
1540
- <hr />
1541
- </root>
1542
- XML
1543
- !!! XML
1544
- %root
1545
- %element/
1546
- %hr
1547
- HAML
1548
- end
1549
-
1550
- # New attributes
1551
-
1552
- def test_basic_new_attributes
1553
- assert_equal("<a>bar</a>\n", render("%a() bar"))
1554
- assert_equal("<a href='foo'>bar</a>\n", render("%a(href='foo') bar"))
1555
- assert_equal("<a b='c' c='d' d='e'>baz</a>\n", render(%q{%a(b="c" c='d' d="e") baz}))
1556
- end
1557
-
1558
- def test_new_attribute_ids
1559
- assert_equal("<div id='foo_bar'></div>\n", render("#foo(id='bar')"))
1560
- assert_equal("<div id='foo_baz_bar'></div>\n", render("#foo{:id => 'bar'}(id='baz')"))
1561
- assert_equal("<div id='foo_baz_bar'></div>\n", render("#foo(id='baz'){:id => 'bar'}"))
1562
- foo = User.new(42)
1563
- assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
1564
- render("#foo(id='baz'){:id => 'bar'}[foo]", :locals => {:foo => foo}))
1565
- assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
1566
- render("#foo(id='baz')[foo]{:id => 'bar'}", :locals => {:foo => foo}))
1567
- assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
1568
- render("#foo[foo](id='baz'){:id => 'bar'}", :locals => {:foo => foo}))
1569
- assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
1570
- render("#foo[foo]{:id => 'bar'}(id='baz')", :locals => {:foo => foo}))
1571
- end
1572
-
1573
- def test_new_attribute_classes
1574
- assert_equal("<div class='bar foo'></div>\n", render(".foo(class='bar')"))
1575
- assert_equal("<div class='bar baz foo'></div>\n", render(".foo{:class => 'bar'}(class='baz')"))
1576
- assert_equal("<div class='bar baz foo'></div>\n", render(".foo(class='baz'){:class => 'bar'}"))
1577
- foo = User.new(42)
1578
- assert_equal("<div class='bar baz foo struct_user' id='struct_user_42'></div>\n",
1579
- render(".foo(class='baz'){:class => 'bar'}[foo]", :locals => {:foo => foo}))
1580
- assert_equal("<div class='bar baz foo struct_user' id='struct_user_42'></div>\n",
1581
- render(".foo[foo](class='baz'){:class => 'bar'}", :locals => {:foo => foo}))
1582
- assert_equal("<div class='bar baz foo struct_user' id='struct_user_42'></div>\n",
1583
- render(".foo[foo]{:class => 'bar'}(class='baz')", :locals => {:foo => foo}))
1584
- end
1585
-
1586
- def test_dynamic_new_attributes
1587
- assert_equal("<a href='12'>bar</a>\n", render("%a(href=foo) bar", :locals => {:foo => 12}))
1588
- assert_equal("<a b='12' c='13' d='14'>bar</a>\n", render("%a(b=b c='13' d=d) bar", :locals => {:b => 12, :d => 14}))
1589
- end
1590
-
1591
- def test_new_attribute_interpolation
1592
- assert_equal("<a href='12'>bar</a>\n", render('%a(href="1#{1 + 1}") bar'))
1593
- assert_equal("<a href='2: 2, 3: 3'>bar</a>\n", render(%q{%a(href='2: #{1 + 1}, 3: #{foo}') bar}, :locals => {:foo => 3}))
1594
- assert_equal(%Q{<a href='1\#{1 + 1}'>bar</a>\n}, render('%a(href="1\#{1 + 1}") bar'))
1595
- end
1596
-
1597
- def test_truthy_new_attributes
1598
- assert_equal("<a href='href'>bar</a>\n", render("%a(href) bar", :format => :xhtml))
1599
- assert_equal("<a bar='baz' href>bar</a>\n", render("%a(href bar='baz') bar", :format => :html5))
1600
- assert_equal("<a href>bar</a>\n", render("%a(href=true) bar"))
1601
- assert_equal("<a>bar</a>\n", render("%a(href=false) bar"))
1602
- end
1603
-
1604
- def test_new_attribute_parsing
1605
- assert_equal("<a a2='b2'>bar</a>\n", render("%a(a2=b2) bar", :locals => {:b2 => 'b2'}))
1606
- assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a="#{'foo"bar'}") bar})) #'
1607
- assert_equal(%Q{<a a="foo'bar">bar</a>\n}, render(%q{%a(a="#{"foo'bar"}") bar})) #'
1608
- assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a='foo"bar') bar}))
1609
- assert_equal(%Q{<a a="foo'bar">bar</a>\n}, render(%q{%a(a="foo'bar") bar}))
1610
- assert_equal("<a a:b='foo'>bar</a>\n", render("%a(a:b='foo') bar"))
1611
- assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = 'foo' b = 'bar') bar"))
1612
- assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = foo b = bar) bar", :locals => {:foo => 'foo', :bar => 'bar'}))
1613
- assert_equal("<a a='foo'>(b='bar')</a>\n", render("%a(a='foo')(b='bar')"))
1614
- assert_equal("<a a='foo)bar'>baz</a>\n", render("%a(a='foo)bar') baz"))
1615
- assert_equal("<a a='foo'>baz</a>\n", render("%a( a = 'foo' ) baz"))
1616
- end
1617
-
1618
- def test_new_attribute_escaping
1619
- assert_equal(%Q{<a a='foo " bar'>bar</a>\n}, render(%q{%a(a="foo \" bar") bar}))
1620
- assert_equal(%Q{<a a='foo \\" bar'>bar</a>\n}, render(%q{%a(a="foo \\\\\" bar") bar}))
1621
-
1622
- assert_equal(%Q{<a a="foo ' bar">bar</a>\n}, render(%q{%a(a='foo \' bar') bar}))
1623
- assert_equal(%Q{<a a="foo \\' bar">bar</a>\n}, render(%q{%a(a='foo \\\\\' bar') bar}))
1624
-
1625
- assert_equal(%Q{<a a='foo \\ bar'>bar</a>\n}, render(%q{%a(a="foo \\\\ bar") bar}))
1626
- assert_equal(%Q{<a a='foo \#{1 + 1} bar'>bar</a>\n}, render(%q{%a(a="foo \#{1 + 1} bar") bar}))
1627
- end
1628
-
1629
- def test_multiline_new_attribute
1630
- assert_equal("<a a='b' c='d'>bar</a>\n", render("%a(a='b'\n c='d') bar"))
1631
- assert_equal("<a a='b' b='c' c='d' d='e' e='f' f='j'>bar</a>\n",
1632
- render("%a(a='b' b='c'\n c='d' d=e\n e='f' f='j') bar", :locals => {:e => 'e'}))
1633
- end
1634
-
1635
- def test_new_and_old_attributes
1636
- assert_equal("<a a='b' c='d'>bar</a>\n", render("%a(a='b'){:c => 'd'} bar"))
1637
- assert_equal("<a a='b' c='d'>bar</a>\n", render("%a{:c => 'd'}(a='b') bar"))
1638
- assert_equal("<a a='b' c='d'>bar</a>\n", render("%a(c='d'){:a => 'b'} bar"))
1639
- assert_equal("<a a='b' c='d'>bar</a>\n", render("%a{:a => 'b'}(c='d') bar"))
1640
-
1641
- # Old-style always takes precedence over new-style,
1642
- # because theoretically old-style could have arbitrary end-of-method-call syntax.
1643
- assert_equal("<a a='b'>bar</a>\n", render("%a{:a => 'b'}(a='d') bar"))
1644
- assert_equal("<a a='b'>bar</a>\n", render("%a(a='d'){:a => 'b'} bar"))
1645
-
1646
- assert_equal("<a a='b' b='c' c='d' d='e'>bar</a>\n",
1647
- render("%a{:a => 'b',\n:b => 'c'}(c='d'\nd='e') bar"))
1648
-
1649
- locals = {:b => 'b', :d => 'd'}
1650
- assert_equal("<p a='b' c='d'></p>\n", render("%p{:a => b}(c=d)", :locals => locals))
1651
- assert_equal("<p a='b' c='d'></p>\n", render("%p(a=b){:c => d}", :locals => locals))
1652
- end
1653
-
1654
- # Ruby Multiline
1655
-
1656
- def test_silent_ruby_multiline
1657
- assert_equal(<<HTML, render(<<HAML))
1658
- bar, baz, bang
1659
- <p>foo</p>
1660
- HTML
1661
- - foo = ["bar",
1662
- "baz",
1663
- "bang"]
1664
- = foo.join(", ")
1665
- %p foo
1666
- HAML
1667
- end
1668
-
1669
- def test_loud_ruby_multiline
1670
- assert_equal(<<HTML, render(<<HAML))
1671
- bar, baz, bang
1672
- <p>foo</p>
1673
- <p>bar</p>
1674
- HTML
1675
- = ["bar",
1676
- "baz",
1677
- "bang"].join(", ")
1678
- %p foo
1679
- %p bar
1680
- HAML
1681
- end
1682
-
1683
- def test_ruby_multiline_with_punctuated_methods_is_continuation
1684
- assert_equal(<<HTML, render(<<HAML))
1685
- bar, , true, bang
1686
- <p>foo</p>
1687
- <p>bar</p>
1688
- HTML
1689
- = ["bar",
1690
- " ".strip!,
1691
- "".empty?,
1692
- "bang"].join(", ")
1693
- %p foo
1694
- %p bar
1695
- HAML
1696
- end
1697
-
1698
- def test_ruby_character_literals_are_not_continuation
1699
- html = if RUBY_VERSION < "1.9"
1700
- "44\n44\n<p>foo</p>\n"
1701
- else
1702
- ",\n,\n<p>foo</p>\n"
1703
- end
1704
- assert_equal(html, render(<<HAML))
1705
- = ?,
1706
- = ?\,
1707
- %p foo
1708
- HAML
1709
- end
1710
-
1711
- def test_escaped_loud_ruby_multiline
1712
- assert_equal(<<HTML, render(<<HAML))
1713
- bar&lt;, baz, bang
1714
- <p>foo</p>
1715
- <p>bar</p>
1716
- HTML
1717
- &= ["bar<",
1718
- "baz",
1719
- "bang"].join(", ")
1720
- %p foo
1721
- %p bar
1722
- HAML
1723
- end
1724
-
1725
- def test_unescaped_loud_ruby_multiline
1726
- assert_equal(<<HTML, render(<<HAML, :escape_html => true))
1727
- bar<, baz, bang
1728
- <p>foo</p>
1729
- <p>bar</p>
1730
- HTML
1731
- != ["bar<",
1732
- "baz",
1733
- "bang"].join(", ")
1734
- %p foo
1735
- %p bar
1736
- HAML
1737
- end
1738
-
1739
- def test_flattened_loud_ruby_multiline
1740
- assert_equal(<<HTML, render(<<HAML))
1741
- <pre>bar&#x000A;baz&#x000A;bang</pre>
1742
- <p>foo</p>
1743
- <p>bar</p>
1744
- HTML
1745
- ~ "<pre>" + ["bar",
1746
- "baz",
1747
- "bang"].join("\\n") + "</pre>"
1748
- %p foo
1749
- %p bar
1750
- HAML
1751
- end
1752
-
1753
- def test_loud_ruby_multiline_with_block
1754
- assert_equal(<<HTML, render(<<HAML))
1755
- #{%w[far faz fang]}
1756
- <p>foo</p>
1757
- <p>bar</p>
1758
- HTML
1759
- = ["bar",
1760
- "baz",
1761
- "bang"].map do |str|
1762
- - str.gsub("ba",
1763
- "fa")
1764
- %p foo
1765
- %p bar
1766
- HAML
1767
- end
1768
-
1769
- def test_silent_ruby_multiline_with_block
1770
- assert_equal(<<HTML, render(<<HAML))
1771
- far
1772
- faz
1773
- fang
1774
- <p>foo</p>
1775
- <p>bar</p>
1776
- HTML
1777
- - ["bar",
1778
- "baz",
1779
- "bang"].map do |str|
1780
- = str.gsub("ba",
1781
- "fa")
1782
- %p foo
1783
- %p bar
1784
- HAML
1785
- end
1786
-
1787
- def test_ruby_multiline_in_tag
1788
- assert_equal(<<HTML, render(<<HAML))
1789
- <p>foo, bar, baz</p>
1790
- <p>foo</p>
1791
- <p>bar</p>
1792
- HTML
1793
- %p= ["foo",
1794
- "bar",
1795
- "baz"].join(", ")
1796
- %p foo
1797
- %p bar
1798
- HAML
1799
- end
1800
-
1801
- def test_escaped_ruby_multiline_in_tag
1802
- assert_equal(<<HTML, render(<<HAML))
1803
- <p>foo&lt;, bar, baz</p>
1804
- <p>foo</p>
1805
- <p>bar</p>
1806
- HTML
1807
- %p&= ["foo<",
1808
- "bar",
1809
- "baz"].join(", ")
1810
- %p foo
1811
- %p bar
1812
- HAML
1813
- end
1814
-
1815
- def test_unescaped_ruby_multiline_in_tag
1816
- assert_equal(<<HTML, render(<<HAML, :escape_html => true))
1817
- <p>foo<, bar, baz</p>
1818
- <p>foo</p>
1819
- <p>bar</p>
1820
- HTML
1821
- %p!= ["foo<",
1822
- "bar",
1823
- "baz"].join(", ")
1824
- %p foo
1825
- %p bar
1826
- HAML
1827
- end
1828
-
1829
- def test_ruby_multiline_with_normal_multiline
1830
- assert_equal(<<HTML, render(<<HAML))
1831
- foobarbar, baz, bang
1832
- <p>foo</p>
1833
- <p>bar</p>
1834
- HTML
1835
- = "foo" + |
1836
- "bar" + |
1837
- ["bar", |
1838
- "baz",
1839
- "bang"].join(", ")
1840
- %p foo
1841
- %p bar
1842
- HAML
1843
- end
1844
-
1845
- def test_ruby_multiline_after_filter
1846
- assert_equal(<<HTML, render(<<HAML))
1847
- foo
1848
- bar
1849
- bar, baz, bang
1850
- <p>foo</p>
1851
- <p>bar</p>
1852
- HTML
1853
- :plain
1854
- foo
1855
- bar
1856
- = ["bar",
1857
- "baz",
1858
- "bang"].join(", ")
1859
- %p foo
1860
- %p bar
1861
- HAML
1862
- end
1863
-
1864
- # Encodings
1865
-
1866
- def test_utf_8_bom
1867
- assert_equal <<HTML, render(<<HAML)
1868
- <div class='foo'>
1869
- <p>baz</p>
1870
- </div>
1871
- HTML
1872
- \xEF\xBB\xBF.foo
1873
- %p baz
1874
- HAML
1875
- end
1876
-
1877
- unless RUBY_VERSION < "1.9"
1878
- def test_default_encoding
1879
- assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
1880
- %p bar
1881
- %p foo
1882
- HAML
1883
- end
1884
-
1885
- def test_fake_ascii_encoding
1886
- assert_encoded_equal(<<HTML.force_encoding("ascii-8bit"), render(<<HAML, :encoding => "ascii-8bit"))
1887
- <p>bâr</p>
1888
- <p>föö</p>
1889
- HTML
1890
- %p bâr
1891
- %p föö
1892
- HAML
1893
- end
1894
-
1895
- def test_convert_template_render_proc
1896
- assert_converts_template_properly {|e| e.render_proc.call}
1897
- end
1898
-
1899
- def test_convert_template_render
1900
- assert_converts_template_properly {|e| e.render}
1901
- end
1902
-
1903
- def test_convert_template_def_method
1904
- assert_converts_template_properly do |e|
1905
- o = Object.new
1906
- e.def_method(o, :render)
1907
- o.render
1908
- end
1909
- end
1910
-
1911
- def test_encoding_error
1912
- render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
1913
- assert(false, "Expected exception")
1914
- rescue Haml::Error => e
1915
- assert_equal(3, e.line)
1916
- assert_match(/Invalid .* character/, e.message)
1917
- end
1918
-
1919
- def test_ascii_incompatible_encoding_error
1920
- template = "foo\nbar\nb_z".encode("utf-16le")
1921
- template[9] = "\xFE".force_encoding("utf-16le")
1922
- render(template)
1923
- assert(false, "Expected exception")
1924
- rescue Haml::Error => e
1925
- assert_equal(3, e.line)
1926
- assert_match(/Invalid .* character/, e.message)
1927
- end
1928
-
1929
- def test_same_coding_comment_as_encoding
1930
- assert_renders_encoded(<<HTML, <<HAML)
1931
- <p>bâr</p>
1932
- <p>föö</p>
1933
- HTML
1934
- -# coding: utf-8
1935
- %p bâr
1936
- %p föö
1937
- HAML
1938
- end
1939
-
1940
- def test_coding_comments
1941
- assert_valid_encoding_comment("-# coding: ibm866")
1942
- assert_valid_encoding_comment("-# CodINg: IbM866")
1943
- assert_valid_encoding_comment("-#coding:ibm866")
1944
- assert_valid_encoding_comment("-# CodINg= ibm866")
1945
- assert_valid_encoding_comment("-# foo BAR FAOJcoding: ibm866")
1946
- assert_valid_encoding_comment("-# coding: ibm866 ASFJ (&(&#!$")
1947
- assert_valid_encoding_comment("-# -*- coding: ibm866")
1948
- assert_valid_encoding_comment("-# coding: ibm866 -*- coding: blah")
1949
- assert_valid_encoding_comment("-# -*- coding: ibm866 -*-")
1950
- assert_valid_encoding_comment("-# -*- encoding: ibm866 -*-")
1951
- assert_valid_encoding_comment('-# -*- coding: "ibm866" -*-')
1952
- assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
1953
- assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
1954
- assert_valid_encoding_comment("-# -*- foo: bar; coding: ibm866; baz: bang -*-")
1955
- assert_valid_encoding_comment("-# foo bar coding: baz -*- coding: ibm866 -*-")
1956
- assert_valid_encoding_comment("-# -*- coding: ibm866 -*- foo bar coding: baz")
1957
- end
1958
-
1959
- def test_different_coding_than_system
1960
- assert_renders_encoded(<<HTML.encode("IBM866"), <<HAML.encode("IBM866"))
1961
- <p>тАЬ</p>
1962
- HTML
1963
- %p тАЬ
1964
- HAML
1965
- end
1966
- end
1967
-
1968
- def test_block_spacing
1969
- begin
1970
- assert render(<<-HAML)
1971
- - foo = ["bar", "baz", "kni"]
1972
- - foo.each do | item |
1973
- = item
1974
- HAML
1975
- rescue ::SyntaxError
1976
- flunk("Should not have raised syntax error")
1977
- end
1978
- end
1979
-
1980
- private
1981
-
1982
- def assert_valid_encoding_comment(comment)
1983
- assert_renders_encoded(<<HTML.encode("IBM866"), <<HAML.encode("IBM866").force_encoding("UTF-8"))
1984
- <p>ЖЛЫ</p>
1985
- <p>тАЬ</p>
1986
- HTML
1987
- #{comment}
1988
- %p ЖЛЫ
1989
- %p тАЬ
1990
- HAML
1991
- end
1992
-
1993
- def assert_converts_template_properly
1994
- engine = Haml::Engine.new(<<HAML.encode("iso-8859-1"), :encoding => "macRoman")
1995
- %p bâr
1996
- %p föö
1997
- HAML
1998
- assert_encoded_equal(<<HTML.encode("macRoman"), yield(engine))
1999
- <p>bâr</p>
2000
- <p>föö</p>
2001
- HTML
2002
- end
2003
-
2004
- def assert_renders_encoded(html, haml)
2005
- result = render(haml)
2006
- assert_encoded_equal html, result
2007
- end
2008
-
2009
- def assert_encoded_equal(expected, actual)
2010
- assert_equal expected.encoding, actual.encoding
2011
- assert_equal expected, actual
2012
- end
2013
- end