slim 1.3.9 → 2.0.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -8
  3. data/.travis.yml +8 -7
  4. data/CHANGES +35 -0
  5. data/Gemfile +9 -9
  6. data/README.md +94 -176
  7. data/Rakefile +7 -14
  8. data/benchmarks/run-benchmarks.rb +9 -37
  9. data/doc/logic_less.md +140 -0
  10. data/doc/translator.md +31 -0
  11. data/lib/slim.rb +3 -1
  12. data/lib/slim/code_attributes.rb +20 -20
  13. data/lib/slim/command.rb +16 -6
  14. data/lib/slim/do_inserter.rb +33 -0
  15. data/lib/slim/embedded.rb +0 -6
  16. data/lib/slim/end_inserter.rb +2 -2
  17. data/lib/slim/engine.rb +9 -23
  18. data/lib/slim/erb_converter.rb +14 -0
  19. data/lib/slim/filter.rb +2 -2
  20. data/lib/slim/logic_less/context.rb +8 -0
  21. data/lib/slim/logic_less/filter.rb +12 -11
  22. data/lib/slim/parser.rb +57 -113
  23. data/lib/slim/splat/builder.rb +79 -0
  24. data/lib/slim/splat/filter.rb +93 -0
  25. data/lib/slim/version.rb +1 -1
  26. data/slim.gemspec +1 -1
  27. data/test/core/helper.rb +1 -3
  28. data/test/core/test_code_blocks.rb +51 -0
  29. data/test/core/test_code_evaluation.rb +4 -12
  30. data/test/core/test_embedded_engines.rb +18 -44
  31. data/test/core/test_encoding.rb +8 -1
  32. data/test/core/test_erb_converter.rb +67 -0
  33. data/test/core/test_html_attributes.rb +19 -25
  34. data/test/core/test_html_escaping.rb +10 -2
  35. data/test/core/test_html_structure.rb +6 -6
  36. data/test/core/test_parser_errors.rb +1 -1
  37. data/test/core/test_ruby_errors.rb +2 -6
  38. data/test/core/test_thread_options.rb +4 -4
  39. data/test/core/test_unicode.rb +18 -0
  40. data/test/literate/TESTS.md +193 -34
  41. data/test/logic_less/test_logic_less.rb +17 -0
  42. data/test/rails/app/controllers/application_controller.rb +0 -1
  43. data/test/rails/app/controllers/entries_controller.rb +5 -0
  44. data/test/rails/app/controllers/slim_controller.rb +3 -0
  45. data/test/rails/app/models/entry.rb +16 -0
  46. data/test/rails/app/views/entries/edit.html.slim +3 -0
  47. data/test/rails/app/views/slim/form_for.html.slim +2 -0
  48. data/test/rails/app/views/slim/xml.slim +1 -0
  49. data/test/rails/config/application.rb +2 -2
  50. data/test/rails/config/environments/test.rb +1 -1
  51. data/test/rails/config/routes.rb +1 -1
  52. data/test/rails/test/helper.rb +0 -3
  53. data/test/rails/test/test_slim.rb +13 -8
  54. data/test/translator/test_translator.rb +13 -2
  55. metadata +17 -14
  56. data/lib/slim/splat_attributes.rb +0 -113
  57. data/test/rails/app/controllers/parents_controller.rb +0 -85
  58. data/test/rails/app/models/child.rb +0 -3
  59. data/test/rails/app/models/parent.rb +0 -4
  60. data/test/rails/app/views/parents/_form.html.slim +0 -8
  61. data/test/rails/app/views/parents/edit.html.slim +0 -2
  62. data/test/rails/app/views/parents/new.html.slim +0 -2
  63. data/test/rails/app/views/parents/show.html.slim +0 -5
  64. data/test/rails/config/database.yml +0 -4
  65. data/test/rails/db/migrate/20101220223037_parents_and_children.rb +0 -17
@@ -41,25 +41,11 @@ p id=(false ? 'notshown' : 'shown') = output_number
41
41
  def test_id_attribute_merging
42
42
  source = %{
43
43
  #alpha id="beta" Test it
44
- }
45
- assert_html '<div id="alpha_beta">Test it</div>', source, :attr_delimiter => {'class' => ' ', 'id' => '_' }
46
- end
47
-
48
- def test_id_attribute_merging2
49
- source = %{
50
- #alpha id="beta" Test it
51
- }
52
- assert_html '<div id="alpha-beta">Test it</div>', source, :attr_delimiter => {'class' => ' ', 'id' => '-' }
53
- end
54
-
55
- def test_id_attribute_merging3
56
- source = %{
57
- #alpha id="beta" Test it
58
44
  }
59
45
  assert_html '<div id="alpha_beta">Test it</div>', source, :merge_attrs => {'class' => ' ', 'id' => '_' }
60
46
  end
61
47
 
62
- def test_id_attribute_merging4
48
+ def test_id_attribute_merging2
63
49
  source = %{
64
50
  #alpha id="beta" Test it
65
51
  }
@@ -122,6 +108,14 @@ option(selected class="clazz") Text
122
108
  assert_html '<div class="alpha beta gamma delta true false"></div><div class="alpha beta gamma"></div>', source
123
109
  end
124
110
 
111
+ def test_hyphenated_attribute
112
+ source = %{
113
+ .alpha data={:a => 'alpha', :b => 'beta', :c_d => 'gamma', :c => {:e => 'epsilon'}}
114
+ }
115
+
116
+ assert_html '<div class="alpha" data-a="alpha" data-b="beta" data-c-d="gamma" data-c-e="epsilon"></div>', source
117
+ end
118
+
125
119
  def test_shortcut_splat
126
120
  source = %q{
127
121
  *hash This is my title
@@ -132,12 +126,20 @@ option(selected class="clazz") Text
132
126
 
133
127
  def test_splat
134
128
  source = %q{
135
- h1 *hash This is my title
129
+ h1 *hash class=[] This is my title
136
130
  }
137
131
 
138
132
  assert_html '<h1 a="The letter a" b="The letter b">This is my title</h1>', source
139
133
  end
140
134
 
135
+ def test_closed_splat
136
+ source = %q{
137
+ *hash /
138
+ }
139
+
140
+ assert_html '<div a="The letter a" b="The letter b" />', source
141
+ end
142
+
141
143
  def test_splat_tag_name
142
144
  source = %q{
143
145
  *{:tag => 'h1', :id => 'title'} This is my title
@@ -160,7 +162,7 @@ h1 *hash This is my title
160
162
  *hash /
161
163
  }
162
164
 
163
- assert_html '<div a="The letter a" b="The letter b"/>', source
165
+ assert_html '<div a="The letter a" b="The letter b" />', source
164
166
  end
165
167
 
166
168
  def test_splat_with_id_shortcut
@@ -245,12 +247,4 @@ p(id="marvin" class=nil nonempty=("".to_s) data-info="Illudium Q-36")= output_nu
245
247
 
246
248
  assert_html '<p data-info="Illudium Q-36" id="marvin" nonempty="">1337</p>', source
247
249
  end
248
-
249
- def test_double_escape_warning
250
- source = %q{
251
- a href='http://slim-lang.com?a=1&amp;b=2'
252
- }
253
-
254
- assert_html '<a href="http://slim-lang.com?a=1&amp;b=2"></a>', source
255
- end
256
250
  end
@@ -43,8 +43,16 @@ p class="#{x}" test #{content}
43
43
  p id="&" class=="&amp;"
44
44
  }
45
45
 
46
- assert_html '<p class="&amp;" id="&"></p>', source
47
- assert_html '<p class="&amp;" id="&amp;"></p>', source, :escape_quoted_attrs => true
46
+ assert_html '<p class="&amp;" id="&amp;"></p>', source
47
+ end
48
+
49
+ def test_html_quoted_attr_escape_with_interpolation
50
+ source = %q{
51
+ p id="&#{'"'}" class=="&amp;#{'"'}"
52
+ p id="&#{{'"'}}" class=="&amp;#{{'"'}}"
53
+ }
54
+
55
+ assert_html '<p class="&amp;&quot;" id="&amp;&quot;"></p><p class="&amp;"" id="&amp;""></p>', source
48
56
  end
49
57
 
50
58
  def test_html_ruby_attr_escape
@@ -358,7 +358,7 @@ p<id="marvin"
358
358
  class="martian"
359
359
  data-info="Illudium Q-36"> = output_number
360
360
  }
361
- Slim::Parser::DELIMITERS.each do |k,v|
361
+ Slim::Parser::DELIMS.each do |k,v|
362
362
  str = source.sub('<',k).sub('>',v)
363
363
  assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">1337</p>', str
364
364
  end
@@ -370,7 +370,7 @@ p<id="marvin"
370
370
  class="martian"
371
371
  data-info="Illudium Q-36"> THE space modulator
372
372
  }
373
- Slim::Parser::DELIMITERS.each do |k,v|
373
+ Slim::Parser::DELIMS.each do |k,v|
374
374
  str = source.sub('<',k).sub('>',v)
375
375
  assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">THE space modulator</p>', str
376
376
  end
@@ -383,7 +383,7 @@ p<id="marvin"
383
383
  data-info="Illudium Q-36">
384
384
  | THE space modulator
385
385
  }
386
- Slim::Parser::DELIMITERS.each do |k,v|
386
+ Slim::Parser::DELIMS.each do |k,v|
387
387
  str = source.sub('<',k).sub('>',v)
388
388
  assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">THE space modulator</p>', str
389
389
  end
@@ -396,7 +396,7 @@ p<id=id_helper
396
396
  data-info="Illudium Q-36">
397
397
  | THE space modulator
398
398
  }
399
- Slim::Parser::DELIMITERS.each do |k,v|
399
+ Slim::Parser::DELIMS.each do |k,v|
400
400
  str = source.sub('<',k).sub('>',v)
401
401
  assert_html '<p class="martian" data-info="Illudium Q-36" id="notice">THE space modulator</p>', str
402
402
  end
@@ -410,7 +410,7 @@ p<id=id_helper
410
410
  span.emphasis THE
411
411
  | space modulator
412
412
  }
413
- Slim::Parser::DELIMITERS.each do |k,v|
413
+ Slim::Parser::DELIMS.each do |k,v|
414
414
  str = source.sub('<',k).sub('>',v)
415
415
  assert_html '<p class="martian" data-info="Illudium Q-36" id="notice"><span class="emphasis">THE</span> space modulator</p>', str
416
416
  end
@@ -423,7 +423,7 @@ li< id="myid"
423
423
  data-info="myinfo">
424
424
  a href="link" My Link
425
425
  }
426
- Slim::Parser::DELIMITERS.each do |k,v|
426
+ Slim::Parser::DELIMS.each do |k,v|
427
427
  str = source.sub('<',k).sub('>',v)
428
428
  assert_html '<li class="myclass" data-info="myinfo" id="myid"><a href="link">My Link</a></li>', str
429
429
  end
@@ -109,7 +109,7 @@ p
109
109
  img{src= }
110
110
  }
111
111
 
112
- assert_syntax_error "Invalid empty attribute\n (__TEMPLATE__), Line 3, Column 10\n img{src= }\n ^\n", source
112
+ assert_syntax_error "Invalid empty attribute\n (__TEMPLATE__), Line 3, Column 11\n img{src= }\n ^\n", source
113
113
  end
114
114
 
115
115
  def test_invalid_empty_attribute2
@@ -161,9 +161,7 @@ p
161
161
  - test = 123
162
162
  = "Hello from within a block! "
163
163
  }
164
- # FIXME: Tilt add stupid end;end;end at the end, this leads to wrong line numbers
165
- # See also #342
166
- assert_ruby_syntax_error "(__TEMPLATE__):7", source
164
+ assert_ruby_syntax_error "(__TEMPLATE__):3", source
167
165
  end
168
166
 
169
167
  def test_invalid_nested_output
@@ -172,9 +170,7 @@ p
172
170
  = "Hello Ruby!"
173
171
  = "Hello from within a block! "
174
172
  }
175
- # FIXME: Tilt add stupid end;end;end at the end, this leads to wrong line numbers
176
- # See also #342
177
- assert_ruby_syntax_error "(__TEMPLATE__):7", source
173
+ assert_ruby_syntax_error "(__TEMPLATE__):3", source
178
174
  end
179
175
 
180
176
  def test_invalid_embedded_engine
@@ -5,14 +5,14 @@ class TestSlimThreadOptions < TestSlim
5
5
  source = %q{p.test}
6
6
 
7
7
  assert_html '<p class="test"></p>', source
8
- assert_html "<p class='test'></p>", source, :attr_wrapper => "'"
8
+ assert_html "<p class='test'></p>", source, :attr_quote => "'"
9
9
 
10
- Slim::Engine.with_options(:attr_wrapper => "'") do
10
+ Slim::Engine.with_options(:attr_quote => "'") do
11
11
  assert_html "<p class='test'></p>", source
12
- assert_html '<p class="test"></p>', source, :attr_wrapper => '"'
12
+ assert_html '<p class="test"></p>', source, :attr_quote => '"'
13
13
  end
14
14
 
15
15
  assert_html '<p class="test"></p>', source
16
- assert_html "<p class='test'></p>", source, :attr_wrapper => "'"
16
+ assert_html "<p class='test'></p>", source, :attr_quote => "'"
17
17
  end
18
18
  end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+ if ''.respond_to?(:encoding)
3
+ require 'helper'
4
+
5
+ class TestSlimUnicode < TestSlim
6
+ def test_unicode_tags
7
+ source = "Статья года"
8
+ result = "<Статья>года</Статья>"
9
+ assert_html result, source
10
+ end
11
+
12
+ def test_unicode_attrs
13
+ source = "Статья года=123 content"
14
+ result = "<Статья года=\"123\">content</Статья>"
15
+ assert_html result, source
16
+ end
17
+ end
18
+ end
@@ -260,6 +260,74 @@ renders as
260
260
  Hello, World!
261
261
  ~~~
262
262
 
263
+ You can also write loops like this
264
+
265
+ ~~~ slim
266
+ - items = [{:name => 'table', :price => 10}, {:name => 'chair', :price => 5}]
267
+ table#items
268
+ - for item in items do
269
+ tr
270
+ td.name = item[:name]
271
+ td.price = item[:price]
272
+ ~~~
273
+
274
+ which renders as
275
+
276
+ ~~~ html
277
+ <table id="items">
278
+ <tr>
279
+ <td class="name">
280
+ table
281
+ </td>
282
+ <td class="price">
283
+ 10
284
+ </td>
285
+ </tr>
286
+ <tr>
287
+ <td class="name">
288
+ chair
289
+ </td>
290
+ <td class="price">
291
+ 5
292
+ </td>
293
+ </tr>
294
+ </table>
295
+ ~~~
296
+
297
+ The `do` keyword can be omitted.
298
+
299
+ ~~~ slim
300
+ - items = [{:name => 'table', :price => 10}, {:name => 'chair', :price => 5}]
301
+ table#items
302
+ - for item in items
303
+ tr
304
+ td.name = item[:name]
305
+ td.price = item[:price]
306
+ ~~~
307
+
308
+ which renders as
309
+
310
+ ~~~ html
311
+ <table id="items">
312
+ <tr>
313
+ <td class="name">
314
+ table
315
+ </td>
316
+ <td class="price">
317
+ 10
318
+ </td>
319
+ </tr>
320
+ <tr>
321
+ <td class="name">
322
+ chair
323
+ </td>
324
+ <td class="price">
325
+ 5
326
+ </td>
327
+ </tr>
328
+ </table>
329
+ ~~~
330
+
263
331
  ### Output `=`
264
332
 
265
333
  The equal sign `=` produces dynamic output.
@@ -334,9 +402,19 @@ renders as
334
402
  <script>evil();</script>
335
403
  ~~~
336
404
 
337
- ### Output with trailing white space `='`
405
+ The equal sign with modifier `=>` produces dynamic output with a trailing white space.
338
406
 
339
- The equal sign with apostrophe `='` produces dynamic output with a trailing white space.
407
+ ~~~ slim
408
+ => 7*7
409
+ ~~~
410
+
411
+ renders as
412
+
413
+ ~~~ html
414
+ 49
415
+ ~~~
416
+
417
+ The legacy syntax `='` is also supported.
340
418
 
341
419
  ~~~ slim
342
420
  =' 7*7
@@ -348,6 +426,30 @@ renders as
348
426
  49
349
427
  ~~~
350
428
 
429
+ The equal sign with modifier `=<` produces dynamic output with a leading white space.
430
+
431
+ ~~~ slim
432
+ =< 7*7
433
+ ~~~
434
+
435
+ renders as
436
+
437
+ ~~~ html
438
+ 49
439
+ ~~~
440
+
441
+ The equal sign with modifiers `=<>` produces dynamic output with a leading and trailing white space.
442
+
443
+ ~~~ slim
444
+ =<> 7*7
445
+ ~~~
446
+
447
+ renders as
448
+
449
+ ~~~ html
450
+ 49
451
+ ~~~
452
+
351
453
  ### Output without HTML escaping `==`
352
454
 
353
455
  The double equal sign `==` produces dynamic output without HTML escaping.
@@ -380,10 +482,19 @@ renders as
380
482
  <script>evil();</script>
381
483
  ~~~
382
484
 
383
- ### Output without HTML escaping and trailing ws `=='`
485
+ The double equal sign with modifier `==>` produces dynamic output without HTML escaping and trailing white space.
486
+
487
+ ~~~ slim
488
+ ==> '<script>evil();</script>'
489
+ ~~~
490
+
491
+ renders as
384
492
 
493
+ ~~~ html
494
+ <script>evil();</script>
495
+ ~~~
385
496
 
386
- The double equal sign with apostrophe `=='` produces dynamic output without HTML escaping and trailing white space.
497
+ The legacy syntax `=='` is also supported.
387
498
 
388
499
  ~~~ slim
389
500
  ==' '<script>evil();</script>'
@@ -590,6 +701,64 @@ renders as
590
701
  <img src="image.png" />
591
702
  ~~~
592
703
 
704
+ ### Trailing and leading whitespace
705
+
706
+ You can force a trailing whitespace behind a tag by adding `>`. The legacy syntax with `'` is also supported.
707
+
708
+ ~~~ slim
709
+ a#closed> class="test" /
710
+ a#closed> class="test"/
711
+ a> href='url1' Link1
712
+ a' href='url2' Link2
713
+ ~~~
714
+
715
+ renders as
716
+
717
+ ~~~ html
718
+ <a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a> <a href="url2">Link2</a>
719
+ ~~~
720
+
721
+ If you combine > and =' only one trailing whitespace is added.
722
+
723
+ ~~~ slim
724
+ a> =' 'Text1'
725
+ a =' 'Text2'
726
+ a> = 'Text3'
727
+ a>= 'Text4'
728
+ ~~~
729
+
730
+ renders as
731
+
732
+ ~~~ html
733
+ <a>Text1</a> <a>Text2</a> <a>Text3</a> <a>Text4</a>
734
+ ~~~
735
+
736
+ You can force a leading whitespace before a tag by adding `<`.
737
+
738
+ ~~~ slim
739
+ a#closed< class="test" /
740
+ a#closed< class="test"/
741
+ a< href='url1' Link1
742
+ a< href='url2' Link2
743
+ ~~~
744
+
745
+ ~~~ html
746
+ <a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a> <a href="url2">Link2</a>
747
+ ~~~
748
+
749
+ You can also combine both.
750
+
751
+ ~~~ slim
752
+ a#closed<> class="test" /
753
+ a#closed>< class="test"/
754
+ a<> href='url1' Link1
755
+ a<> href='url2' Link2
756
+ ~~~
757
+
758
+ ~~~ html
759
+ <a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a> <a href="url2">Link2</a>
760
+ ~~~
761
+
593
762
  ### Inline tags
594
763
 
595
764
  Sometimes you may want to be a little more compact and inline the tags.
@@ -695,6 +864,24 @@ renders as
695
864
  <dl itemprop="address" itemscope="itemscope" itemtype="http://schema.org/PostalAddress"></dl>
696
865
  ~~~
697
866
 
867
+ You may use spaces around the wrappers and assignments:
868
+
869
+ ~~~ slim
870
+ h1 id = "logo" Logo
871
+ h2 [ id = "tagline" ] Tagline
872
+ ~~~
873
+
874
+ renders as
875
+
876
+ ~~~ html
877
+ <h1 id="logo">
878
+ Logo
879
+ </h1>
880
+ <h2 id="tagline">
881
+ Tagline
882
+ </h2>
883
+ ~~~
884
+
698
885
  #### Quoted attributes
699
886
 
700
887
  You can use single or double quotes for simple text attributes.
@@ -722,13 +909,7 @@ renders as
722
909
  <a href="http://slim-lang.com">Goto the slim-lang.com</a>
723
910
  ~~~
724
911
 
725
- The attribute value will be escaped if the option
726
-
727
- ~~~ options
728
- :escape_quoted_attrs => true
729
- ~~~
730
-
731
- is set. Use == if you want to disable escaping in the attribute.
912
+ The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute.
732
913
 
733
914
  ~~~ slim
734
915
  li
@@ -833,7 +1014,7 @@ renders as
833
1014
 
834
1015
  #### Attribute merging
835
1016
 
836
- You can configure attributes to be merged if multiple are given (See option `:attr_delimiter`). In the default configuration
1017
+ You can configure attributes to be merged if multiple are given (See option `:merge_attrs`). In the default configuration
837
1018
  this is done for class attributes with the white space as delimiter.
838
1019
 
839
1020
  ~~~ slim
@@ -945,24 +1126,6 @@ renders to
945
1126
  <input name="user" type="text" /><input name="pw" type="password" /><input class="CLASS" id="ID" type="submit" />
946
1127
  ~~~
947
1128
 
948
- Test deprecated shortcuts:
949
-
950
- ~~~ options
951
- :shortcut => {'&' => 'input type', '#' => 'id', '.' => 'class' }
952
- ~~~
953
-
954
- ~~~ slim
955
- &text name="user"
956
- &password name="pw"
957
- &submit.CLASS#ID
958
- ~~~
959
-
960
- renders to
961
-
962
- ~~~ html
963
- <input name="user" type="text" /><input name="pw" type="password" /><input class="CLASS" id="ID" type="submit" />
964
- ~~~
965
-
966
1129
  #### ID shortcut and class shortcut `.`
967
1130
 
968
1131
  ## Text interpolation
@@ -987,7 +1150,3 @@ renders as
987
1150
  ## Configuring Slim
988
1151
 
989
1152
  ## Plugins
990
-
991
- ### Logic less mode
992
-
993
- ### Translator