radiant 0.6.7 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of radiant might be problematic. Click here for more details.

Files changed (96) hide show
  1. data/CHANGELOG +35 -3
  2. data/CONTRIBUTORS +11 -1
  3. data/README +5 -3
  4. data/app/controllers/admin/welcome_controller.rb +7 -0
  5. data/app/migrate/020_add_session_info_to_users.rb +11 -0
  6. data/app/models/page.rb +22 -9
  7. data/app/models/standard_tags.rb +133 -10
  8. data/app/models/user.rb +9 -1
  9. data/app/views/admin/page/edit.html.haml +5 -4
  10. data/app/views/admin/welcome/login.html.haml +42 -24
  11. data/app/views/layouts/application.html.haml +1 -1
  12. data/config/environment.rb +4 -2
  13. data/db/migrate/020_add_session_info_to_users.rb +11 -0
  14. data/db/migrate/021_remove_session_expire_from_users.rb +9 -0
  15. data/db/schema.rb +3 -2
  16. data/lib/generators/instance/instance_generator.rb +2 -1
  17. data/lib/generators/instance/templates/instance_environment.rb +5 -3
  18. data/lib/login_system.rb +13 -0
  19. data/lib/radiant.rb +1 -1
  20. data/lib/radiant/admin_ui.rb +21 -21
  21. data/lib/radiant/extension/script.rb +251 -0
  22. data/lib/radiant/extension_loader.rb +22 -20
  23. data/lib/radiant/initializer.rb +1 -1
  24. data/lib/radiant/setup.rb +2 -0
  25. data/lib/tasks/framework.rake +39 -29
  26. data/public/500.html +1 -1
  27. data/public/javascripts/admin/admin.js +11 -9
  28. data/script/extension +5 -0
  29. data/spec/controllers/admin/user_controller_spec.rb +1 -1
  30. data/spec/controllers/admin/welcome_controller_spec.rb +31 -5
  31. data/spec/controllers/site_controller_spec.rb +15 -2
  32. data/spec/lib/login_system_spec.rb +106 -60
  33. data/spec/lib/radiant/extension/script_spec.rb +349 -0
  34. data/spec/lib/radiant/extension_loader_spec.rb +3 -0
  35. data/spec/models/page_spec.rb +62 -2
  36. data/spec/models/standard_tags_spec.rb +150 -3
  37. data/spec/models/user_spec.rb +28 -0
  38. data/spec/scenarios/file_not_found_scenario.rb +5 -0
  39. data/spec/scenarios/pages_scenario.rb +6 -0
  40. data/spec/scenarios/snippets_scenario.rb +4 -0
  41. data/test/fixtures/users.yml +11 -6
  42. data/vendor/plugins/haml/FAQ +138 -0
  43. data/vendor/plugins/haml/REVISION +1 -0
  44. data/vendor/plugins/haml/Rakefile +54 -62
  45. data/vendor/plugins/haml/VERSION +1 -1
  46. data/vendor/plugins/haml/init.rb +6 -1
  47. data/vendor/plugins/haml/lib/haml.rb +72 -12
  48. data/vendor/plugins/haml/lib/haml/buffer.rb +47 -40
  49. data/vendor/plugins/haml/lib/haml/engine.rb +20 -30
  50. data/vendor/plugins/haml/lib/haml/error.rb +4 -5
  51. data/vendor/plugins/haml/lib/haml/exec.rb +4 -2
  52. data/vendor/plugins/haml/lib/haml/filters.rb +30 -15
  53. data/vendor/plugins/haml/lib/haml/helpers.rb +47 -28
  54. data/vendor/plugins/haml/lib/haml/helpers/action_view_mods.rb +74 -25
  55. data/vendor/plugins/haml/lib/haml/precompiler.rb +92 -51
  56. data/vendor/plugins/haml/lib/haml/template.rb +11 -3
  57. data/vendor/plugins/haml/lib/haml/template/patch.rb +1 -1
  58. data/vendor/plugins/haml/lib/sass.rb +26 -3
  59. data/vendor/plugins/haml/lib/sass/constant.rb +26 -57
  60. data/vendor/plugins/haml/lib/sass/constant/literal.rb +1 -0
  61. data/vendor/plugins/haml/lib/sass/constant/nil.rb +9 -0
  62. data/vendor/plugins/haml/lib/sass/css.rb +17 -2
  63. data/vendor/plugins/haml/lib/sass/engine.rb +11 -5
  64. data/vendor/plugins/haml/test/haml/engine_test.rb +57 -39
  65. data/vendor/plugins/haml/test/haml/helper_test.rb +20 -4
  66. data/vendor/plugins/haml/test/haml/html2haml_test.rb +1 -3
  67. data/vendor/plugins/haml/test/haml/results/content_for_layout.xhtml +1 -2
  68. data/vendor/plugins/haml/test/haml/results/eval_suppressed.xhtml +2 -4
  69. data/vendor/plugins/haml/test/haml/results/filters.xhtml +12 -8
  70. data/vendor/plugins/haml/test/haml/results/helpers.xhtml +2 -5
  71. data/vendor/plugins/haml/test/haml/results/just_stuff.xhtml +1 -3
  72. data/vendor/plugins/haml/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  73. data/vendor/plugins/haml/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  74. data/vendor/plugins/haml/test/haml/results/original_engine.xhtml +2 -4
  75. data/vendor/plugins/haml/test/haml/results/tag_parsing.xhtml +1 -6
  76. data/vendor/plugins/haml/test/haml/results/very_basic.xhtml +2 -4
  77. data/vendor/plugins/haml/test/haml/results/whitespace_handling.xhtml +13 -21
  78. data/vendor/plugins/haml/test/haml/template_test.rb +31 -48
  79. data/vendor/plugins/haml/test/haml/templates/filters.haml +13 -0
  80. data/vendor/plugins/haml/test/haml/templates/helpers.haml +1 -1
  81. data/vendor/plugins/haml/test/haml/templates/just_stuff.haml +0 -1
  82. data/vendor/plugins/haml/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  83. data/vendor/plugins/haml/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  84. data/vendor/plugins/haml/test/haml/templates/partials.haml +1 -1
  85. data/vendor/plugins/haml/test/haml/templates/tag_parsing.haml +0 -3
  86. data/vendor/plugins/haml/test/haml/templates/whitespace_handling.haml +10 -10
  87. data/vendor/plugins/haml/test/sass/engine_test.rb +11 -5
  88. data/vendor/plugins/haml/test/sass/plugin_test.rb +2 -6
  89. data/vendor/plugins/haml/test/sass/results/constants.css +2 -0
  90. data/vendor/plugins/haml/test/sass/templates/constants.sass +3 -0
  91. data/vendor/plugins/haml/test/{haml/test_helper.rb → test_helper.rb} +4 -3
  92. metadata +21 -11
  93. data/vendor/plugins/haml/TODO +0 -9
  94. data/vendor/plugins/haml/extra/haml-mode.el +0 -328
  95. data/vendor/plugins/haml/extra/sass-mode.el +0 -88
  96. data/vendor/plugins/haml/test/profile.rb +0 -65
@@ -56,8 +56,11 @@ describe "Standard Tags" do
56
56
  end
57
57
 
58
58
  it 'should not list virtual pages' do
59
- page.should render('<r:children:each><r:slug /> </r:children:each>').as('a b c d e f g h i j ')
60
- page.should render('<r:children:each status="all"><r:slug /> </r:children:each>').as('a b c d e f g h i j draft ')
59
+ page.should render('<r:children:each by="title"><r:slug /> </r:children:each>').as('a b c d e f g h i j ')
60
+ end
61
+
62
+ it 'should include virtual pages with status="all"' do
63
+ page.should render('<r:children:each status="all" by="slug"><r:slug /> </r:children:each>').as('a b c d draft e f g h i j ')
61
64
  end
62
65
 
63
66
  it 'should error with invalid "limit" attribute' do
@@ -246,6 +249,7 @@ describe "Standard Tags" do
246
249
  end
247
250
 
248
251
  describe "<r:if_content>" do
252
+
249
253
  it "without 'part' attribute should render the contained block if the 'body' part exists" do
250
254
  page.should render('<r:if_content>true</r:if_content>').as('true')
251
255
  end
@@ -257,9 +261,62 @@ describe "Standard Tags" do
257
261
  it "should not render the contained block if the specified part does not exist" do
258
262
  page.should render('<r:if_content part="asdf">true</r:if_content>').as('')
259
263
  end
264
+
265
+ describe "with more than one part given (separated by comma)" do
266
+
267
+ it "should render the contained block only if all specified parts exist" do
268
+ page(:home).should render('<r:if_content part="body, extended">true</r:if_content>').as('true')
269
+ end
270
+
271
+ it "should not render the contained block if at least one of the specified parts does not exist" do
272
+ page(:home).should render('<r:if_content part="body, madeup">true</r:if_content>').as('')
273
+ end
274
+
275
+ describe "with inherit attribute set to 'true'" do
276
+ it 'should render the contained block if the current or ancestor pages have the specified parts' do
277
+ page(:guests).should render('<r:if_content part="favors, extended" inherit="true">true</r:if_content>').as('true')
278
+ end
279
+
280
+ it 'should not render the contained block if the current or ancestor pages do not have all of the specified parts' do
281
+ page(:guests).should render('<r:if_content part="favors, madeup" inherit="true">true</r:if_content>').as('')
282
+ end
283
+ end
284
+ describe "with inherit attribute set to 'false'" do
285
+ it 'should render the contained block if the current page has the specified parts' do
286
+ page(:guests).should render('<r:if_content part="favors, games" inherit="false">true</r:if_content>').as('')
287
+ end
288
+
289
+ it 'should not render the contained block if the current or ancestor pages do not have all of the specified parts' do
290
+ page(:guests).should render('<r:if_content part="favors, madeup" inherit="false">true</r:if_content>').as('')
291
+ end
292
+ end
293
+ describe "with the 'find' attribute set to 'any'" do
294
+ it "should render the contained block if any of the specified parts exist" do
295
+ page.should render('<r:if_content part="body, asdf" find="any">true</r:if_content>').as('true')
296
+ end
297
+ end
298
+ describe "with the 'find' attribute set to 'all'" do
299
+ it "should render the contained block if all of the specified parts exist" do
300
+ page(:home).should render('<r:if_content part="body, sidebar" find="all">true</r:if_content>').as('true')
301
+ end
302
+
303
+ it "should not render the contained block if all of the specified parts do not exist" do
304
+ page.should render('<r:if_content part="asdf, madeup" find="all">true</r:if_content>').as('')
305
+ end
306
+ end
307
+ end
260
308
  end
261
309
 
262
310
  describe "<r:unless_content>" do
311
+ describe "with inherit attribute set to 'true'" do
312
+ it 'should not render the contained block if the current or ancestor pages have the specified parts' do
313
+ page(:guests).should render('<r:unless_content part="favors, extended" inherit="true">true</r:unless_content>').as('')
314
+ end
315
+
316
+ it 'should render the contained block if the current or ancestor pages do not have the specified parts' do
317
+ page(:guests).should render('<r:unless_content part="madeup, imaginary" inherit="true">true</r:unless_content>').as('true')
318
+ end
319
+ end
263
320
  it "without 'part' attribute should not render the contained block if the 'body' part exists" do
264
321
  page.should render('<r:unless_content>false</r:unless_content>').as('')
265
322
  end
@@ -271,6 +328,43 @@ describe "Standard Tags" do
271
328
  it "should render the contained block if the specified part does not exist" do
272
329
  page.should render('<r:unless_content part="asdf">false</r:unless_content>').as('false')
273
330
  end
331
+
332
+ describe "with more than one part given (separated by comma)" do
333
+
334
+ it "should not render the contained block if all of the specified parts exist" do
335
+ page(:home).should render('<r:unless_content part="body, extended">true</r:unless_content>').as('')
336
+ end
337
+
338
+ it "should render the contained block if at least one of the specified parts exists" do
339
+ page(:home).should render('<r:unless_content part="body, madeup">true</r:unless_content>').as('true')
340
+ end
341
+
342
+ describe "with the 'inherit' attribute set to 'true'" do
343
+ it "should render the contained block if the current or ancestor pages have none of the specified parts" do
344
+ page.should render('<r:unless_content part="imaginary, madeup">true</r:unless_content>').as('true')
345
+ end
346
+
347
+ it "should not render the contained block if all of the specified parts are present on the current or ancestor pages" do
348
+ page(:party).should render('<r:unless_content part="favors, extended">true</r:unless_content>').as('')
349
+ end
350
+ end
351
+
352
+ describe "with the 'find' attribute set to 'all'" do
353
+ it "should not render the contained block if all of the specified parts exist" do
354
+ page.should render('<r:unless_content part="body, sidebar" find="all">true</r:unless_content>').as('')
355
+ end
356
+
357
+ it "should render the contained block unless all of the specified parts exist" do
358
+ page.should render('<r:unless_content part="body, madeup" find="all">true</r:unless_content>').as('true')
359
+ end
360
+ end
361
+
362
+ describe "with the 'find' attribute set to 'any'" do
363
+ it "should not render the contained block if any of the specified parts exist" do
364
+ page.should render('<r:unless_content part="body, madeup" find="any">true</r:unless_content>').as('')
365
+ end
366
+ end
367
+ end
274
368
  end
275
369
 
276
370
  describe "<r:author>" do
@@ -355,7 +449,7 @@ describe "Standard Tags" do
355
449
  end
356
450
 
357
451
  describe "<r:snippet>" do
358
- it "should the contents of the specified snippet" do
452
+ it "should render the contents of the specified snippet" do
359
453
  page.should render('<r:snippet name="first" />').as('test')
360
454
  end
361
455
 
@@ -378,6 +472,39 @@ describe "Standard Tags" do
378
472
  it "should maintain the global page when the snippet renders recursively" do
379
473
  page(:child).should render('<r:snippet name="recursive" />').as("Great GrandchildGrandchildChild")
380
474
  end
475
+
476
+ it "should render the specified snippet when called as an empty double-tag" do
477
+ page.should render('<r:snippet name="first"></r:snippet>').as('test')
478
+ end
479
+
480
+ it "should capture contents of a double tag, substituting for <r:yield/> in snippet" do
481
+ page.should render('<r:snippet name="yielding">inner</r:snippet>').
482
+ as('Before...inner...and after')
483
+ end
484
+
485
+ it "should do nothing with contents of double tag when snippet doesn't yield" do
486
+ page.should render('<r:snippet name="first">content disappears!</r:snippet>').
487
+ as('test')
488
+ end
489
+
490
+ it "should render nested yielding snippets" do
491
+ page.should render('<r:snippet name="div_wrap"><r:snippet name="yielding">Hello, World!</r:snippet></r:snippet>').
492
+ as('<div>Before...Hello, World!...and after</div>')
493
+ end
494
+
495
+ it "should render double-tag snippets called from within a snippet" do
496
+ page.should render('<r:snippet name="nested_yields">the content</r:snippet>').
497
+ as('<snippet name="div_wrap">above the content below</snippet>')
498
+ end
499
+
500
+ it "should render contents each time yield is called" do
501
+ page.should render('<r:snippet name="yielding_often">French</r:snippet>').
502
+ as('French is Frencher than French')
503
+ end
504
+ end
505
+
506
+ it "should do nothing when called from page body" do
507
+ page.should render('<r:yield/>').as("")
381
508
  end
382
509
 
383
510
  it '<r:random> should render a randomly selected contained <r:option>' do
@@ -672,6 +799,16 @@ describe "Standard Tags" do
672
799
  page(:parent).should render(%{<r:find url="/radius"><r:if_ancestor_or_self>true</r:if_ancestor_or_self></r:find>}).as('')
673
800
  end
674
801
  end
802
+
803
+ describe "<r:unless_ancestor_or_self>" do
804
+ it "should render the tag's content when the current page is not an ancestor of tag.locals.page" do
805
+ page(:radius).should render(%{<r:find url="/"><r:unless_ancestor_or_self>true</r:unless_ancestor_or_self></r:find>}).as('')
806
+ end
807
+
808
+ it "should not render the tag's content when current page is an ancestor of tag.locals.page" do
809
+ page(:parent).should render(%{<r:find url="/radius"><r:unless_ancestor_or_self>true</r:unless_ancestor_or_self></r:find>}).as('true')
810
+ end
811
+ end
675
812
 
676
813
  describe "<r:if_self>" do
677
814
  it "should render the tag's content when the current page is the same as the local contextual page" do
@@ -682,6 +819,16 @@ describe "Standard Tags" do
682
819
  page(:radius).should render(%{<r:find url="/"><r:if_self>true</r:if_self></r:find>}).as('')
683
820
  end
684
821
  end
822
+
823
+ describe "<r:unless_self>" do
824
+ it "should render the tag's content when the current page is not the same as the local contextual page" do
825
+ page(:home).should render(%{<r:find url="/"><r:unless_self>true</r:unless_self></r:find>}).as('')
826
+ end
827
+
828
+ it "should not render the tag's content when the current page is the same as the local contextual page" do
829
+ page(:radius).should render(%{<r:find url="/"><r:unless_self>true</r:unless_self></r:find>}).as('true')
830
+ end
831
+ end
685
832
 
686
833
  describe "<r:meta>" do
687
834
  it "should render <meta> tags for the description and keywords" do
@@ -121,6 +121,34 @@ describe User do
121
121
  @user.salt.should_not be_nil
122
122
  @user.password.should == @user.sha1('password')
123
123
  end
124
+
125
+ describe ".remember_me" do
126
+ before do
127
+ Radiant::Config.stub!(:[]).with('session_timeout').and_return(2.weeks)
128
+ @user.save
129
+ @user.remember_me
130
+ @user.reload
131
+ end
132
+
133
+ it "should remember user" do
134
+ @user.session_token.should_not be_nil
135
+ end
136
+ end
137
+
138
+ describe ".forget_me" do
139
+
140
+ before do
141
+ Radiant::Config.stub!(:[]).with('session_timeout').and_return(2.weeks)
142
+ @user.save
143
+ @user.remember_me
144
+ end
145
+
146
+ it "should forget user" do
147
+ @user.forget_me
148
+ @user.session_token.should be_nil
149
+ end
150
+ end
151
+
124
152
  end
125
153
 
126
154
  describe User, "class methods" do
@@ -5,9 +5,14 @@ class FileNotFoundScenario < Scenario::Base
5
5
  uses :home_page
6
6
 
7
7
  def load
8
+ create_page "Draft File Not Found", :class_name => "FileNotFoundPage", :status_id => Status[:draft].id
8
9
  create_page "File Not Found", :slug => "missing", :class_name => "FileNotFoundPage"
9
10
  create_page "Gallery" do
11
+ create_page "Draft No Picture", :class_name => "CustomFileNotFoundPage", :status_id => Status[:draft].id
10
12
  create_page "No Picture", :class_name => "CustomFileNotFoundPage"
11
13
  end
14
+ create_page "Drafts" do
15
+ create_page "Lonely Draft File Not Found", :class_name => "FileNotFoundPage", :status_id => Status[:draft].id
16
+ end
12
17
  end
13
18
  end
@@ -40,11 +40,17 @@ class PagesScenario < Scenario::Base
40
40
  create_page "Hidden", :status_id => Status[:hidden].id
41
41
  date = Time.utc(2006, 1, 11)
42
42
  create_page "Dated", :published_at => date, :created_at => (date - 1.day), :updated_at => (date + 1.day)
43
+
43
44
  create_page "Devtags" do
44
45
  create_page_part "if_dev", :content => "<r:if_dev>dev</r:if_dev>"
45
46
  create_page_part "unless_dev", :content => "<r:unless_dev>not dev</r:unless_dev>"
46
47
  end
47
48
  create_page "Virtual", :class_name => "VirtualPage", :virtual => true
49
+ create_page "Party" do
50
+ create_page_part "favors"
51
+ create_page_part "games"
52
+ create_page "Guests"
53
+ end
48
54
  end
49
55
 
50
56
  end
@@ -7,6 +7,10 @@ class SnippetsScenario < Scenario::Base
7
7
  create_snippet "radius", :content => "<r:title />"
8
8
  create_snippet "global_page_cascade", :content => "<r:children:each><r:page:title /> </r:children:each>"
9
9
  create_snippet "recursive", :content => "<r:children:each><r:snippet name='recursive' /></r:children:each><r:title />"
10
+ create_snippet "yielding", :content => "Before...<r:yield/>...and after"
11
+ create_snippet "div_wrap", :content => "<div><r:yield/></div>"
12
+ create_snippet "nested_yields", :content => '<snippet name="div_wrap">above <r:yield/> below</snippet>'
13
+ create_snippet "yielding_often", :content => '<r:yield/> is <r:yield/>er than <r:yield/>'
10
14
  end
11
15
 
12
16
  helpers do
@@ -3,28 +3,33 @@ existing:
3
3
  id: 1
4
4
  name: Existing User
5
5
  login: existing
6
- password: <%= User.sha1 'password' %>
6
+ salt: 42ddb5b6479872565981adc78e86ddc50fa21637
7
+ password: 4c5f9d5a0d4cd65d61f6b1505890576d1272986c # password
7
8
  email: existing.user@gmail.com
8
9
  another:
9
10
  id: 2
10
11
  name: Another User
11
12
  login: another
12
- password: <%= User.sha1 'password' %>
13
+ salt: 42ddb5b6479872565981adc78e86ddc50fa21637
14
+ password: 4c5f9d5a0d4cd65d61f6b1505890576d1272986c # password
13
15
  admin:
14
16
  id: 3
15
17
  name: Admin User
16
18
  login: admin
17
- password: <%= User.sha1 'password' %>
19
+ salt: 42ddb5b6479872565981adc78e86ddc50fa21637
20
+ password: 4c5f9d5a0d4cd65d61f6b1505890576d1272986c # password
18
21
  admin: true
19
22
  developer:
20
23
  id: 4
21
24
  name: Developer User
22
25
  login: developer
23
- password: <%= User.sha1 'password' %>
26
+ salt: 42ddb5b6479872565981adc78e86ddc50fa21637
27
+ password: 4c5f9d5a0d4cd65d61f6b1505890576d1272986c # password
24
28
  developer: true
25
29
  non_admin:
26
30
  id: 5
27
31
  name: Non-Admin User
28
32
  login: non-admin
29
- password: <%= User.sha1 'password' %>
30
- admin: false
33
+ salt: 42ddb5b6479872565981adc78e86ddc50fa21637
34
+ password: 4c5f9d5a0d4cd65d61f6b1505890576d1272986c # password
35
+ admin: false
@@ -0,0 +1,138 @@
1
+ = Frequently Asked Questions
2
+
3
+ == Haml
4
+
5
+ === How do I put a punctuation mark after an element, like "<tt>I like <strong>cake</strong>!</tt>"?
6
+
7
+ Expressing the structure of a document
8
+ and expressing inline formatting are two very different problems.
9
+ Haml is mostly designed for structure,
10
+ so the best way to deal with formatting is to leave it to other languages
11
+ that are designed for it.
12
+ You could use Textile:
13
+
14
+ %p
15
+ :textile
16
+ I like *cake*!
17
+
18
+ or Markdown:
19
+
20
+ %p
21
+ :markdown
22
+ I like **cake**!
23
+
24
+ or plain old XHTML:
25
+
26
+ %p I like <strong>cake</strong>!
27
+
28
+ If you're inserting something that's generated by a helper, like a link,
29
+ then it's even easier:
30
+
31
+ %p== I like #{link_to 'chocolate', 'http://franschocolates.com'}!
32
+
33
+ === How do I stop Haml from indenting the contents of my +pre+ and +textarea+ tags?
34
+
35
+ Because Haml automatically indents the HTML source code,
36
+ the contents of whitespace-sensitive tags like +pre+ and +textarea+
37
+ can get screwed up.
38
+ The solution is to replace the newlines inside these tags
39
+ with HTML newline entities (<tt>&#x000A;</tt>),
40
+ which Haml does using the Haml::Helpers#preserve and Haml::Helpers#find_and_preserve helpers.
41
+
42
+ Normally, Haml will do this for you automatically
43
+ when you're using a tag that needs it
44
+ (this can be customized using the <tt>:preserve</tt> option;
45
+ see the Options section of the {Haml reference}(../classes/Haml.html)).
46
+ For example,
47
+
48
+ %p
49
+ %textarea= "Foo\nBar"
50
+
51
+ will be compiled to
52
+
53
+ <p>
54
+ <textarea>Foo&#x000A;Bar</textarea>
55
+ </p>
56
+
57
+ However, if a helper is generating the tag,
58
+ Haml can't detect that and so you'll have to call +find_and_preserve+ yourself.
59
+ You can also use <tt>~</tt>, which is the same as <tt>=</tt>
60
+ except that it automatically runs +find_and_preserve+ on its input.
61
+ For example:
62
+
63
+ %p= find_and_preserve "<textarea>Foo\nBar</textarea>"
64
+
65
+ is the same as
66
+
67
+ %p~ "<textarea>Foo\nBar</textarea>"
68
+
69
+ and renders
70
+
71
+ <p><textarea>Foo&#x000A;Bar</textarea></p>
72
+
73
+ === How do I make my long lines of Ruby code look nicer in my Haml document?
74
+
75
+ Put them in a helper or your model.
76
+
77
+ Haml purposefully makes it annoying to put lots of Ruby code into your templates,
78
+ because lots of code doesn't belong in the view.
79
+ If you take that huge +link_to_remote+ call
80
+ and move it to a +update_sidebar_link+ helper,
81
+ it'll make your view both easier to read and more semantic.
82
+
83
+ If you absolutely must put lots of code in your template,
84
+ Haml offers a somewhat awkward multiline-continuation tool.
85
+ Put a <tt>|</tt> (pipe character) at the end of each line you want to be merged into one
86
+ (including the last line!).
87
+ For example:
88
+
89
+ %p= @this.is(way.too.much). |
90
+ code("and I should"). |
91
+ really_move.it.into( |
92
+ :a => @helper) |
93
+
94
+ === I have Haml installed. Why is Rails (only looking for <tt>.html.erb</tt> files | rendering Haml files as plain text | rendering Haml files as blank pages)?
95
+
96
+ There are several reasons these things might be happening.
97
+ First of all, make sure vendor/plugins/haml really exists
98
+ and has an init.rb file in there.
99
+ Then try restarting Mongrel or WEBrick or whatever you might be using.
100
+
101
+ Finally, if none of these work,
102
+ chances are you've got some localization plugin like Globalize installed.
103
+ Such plugins often don't play nicely with Haml.
104
+ Luckily, there's usually an easy fix.
105
+ For Globalize, just edit globalize/lib/globalize/rails/action_view.rb
106
+ and change
107
+
108
+ @@re_extension = /\.(rjs|rhtml|rxml)$/
109
+
110
+ to
111
+
112
+ @@re_extension = /\.(rjs|rhtml|rxml|erb|builder|haml)$/
113
+
114
+ For other plugins, a little searching will probably turn up a way to fix them as well.
115
+
116
+ == Sass
117
+
118
+ === Can I use a variable from my controller in my Sass file?
119
+
120
+ No. Sass files aren't views.
121
+ They're compiled once into static CSS files,
122
+ then left along until they're changed and need to be compiled again.
123
+ Not only don't you want to be running a full request cycle
124
+ every time someone requests a stylesheet,
125
+ but it's not a great idea to put much logic in there anyway
126
+ due to how browsers handle them.
127
+
128
+ If you really need some sort of dynamic CSS,
129
+ the best thing to do is put only the snippet you need to dynamically set
130
+ in the +head+ of your HTML document.
131
+
132
+ == You still haven't answered my question!
133
+
134
+ Sorry! Try looking at the Haml or Sass references,
135
+ in the doucmentation for the haml and Sass modules, respectively.
136
+ If you can't find an answer there,
137
+ feel free to ask in #haml on irc.freenode.net
138
+ or send an email to the {mailing list}[http://groups.google.com/group/haml?hl=en].