slim 4.1.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/slim/embedded.rb CHANGED
@@ -30,7 +30,7 @@ module Slim
30
30
  # @api private
31
31
  class OutputProtector < Filter
32
32
  def call(exp)
33
- @protect, @collected, @tag = [], '', "%#{object_id.abs.to_s(36)}%"
33
+ @protect, @collected, @tag = [], '', object_id.abs.to_s(36)
34
34
  super(exp)
35
35
  @collected
36
36
  end
@@ -41,16 +41,16 @@ module Slim
41
41
  end
42
42
 
43
43
  def on_slim_output(escape, text, content)
44
- @collected << @tag
44
+ @collected << "%#{@tag}%#{@protect.length}%"
45
45
  @protect << [:slim, :output, escape, text, content]
46
46
  nil
47
47
  end
48
48
 
49
49
  def unprotect(text)
50
50
  block = [:multi]
51
- while text =~ /#{@tag}/
51
+ while text =~ /%#{@tag}%(\d+)%/
52
52
  block << [:static, $`]
53
- block << @protect.shift
53
+ block << @protect[$1.to_i]
54
54
  text = $'
55
55
  end
56
56
  block << [:static, text]
@@ -155,7 +155,7 @@ module Slim
155
155
  text = tilt_engine.new(tilt_options.merge(
156
156
  style: options[:pretty] ? :expanded : :compressed,
157
157
  cache: false)) { text }.render
158
- text.chomp!
158
+ text = text.chomp
159
159
  [:static, text]
160
160
  end
161
161
  end
@@ -185,6 +185,7 @@ module Slim
185
185
  # Generates a html tag and wraps another engine (specified via :engine option)
186
186
  class TagEngine < Engine
187
187
  disable_option_validator!
188
+ set_options attributes: {}
188
189
 
189
190
  def on_slim_embedded(engine, body, attrs)
190
191
 
@@ -213,7 +214,7 @@ module Slim
213
214
  class JavaScriptEngine < TagEngine
214
215
  disable_option_validator!
215
216
 
216
- set_options tag: :script, attributes: {}
217
+ set_options tag: :script
217
218
 
218
219
  def on_slim_embedded(engine, body, attrs)
219
220
  super(engine, [:html, :js, body], attrs)
@@ -233,14 +234,14 @@ module Slim
233
234
  register :rdoc, InterpolateTiltEngine
234
235
 
235
236
  # These engines are executed at compile time
236
- register :coffee, JavaScriptEngine, engine: TiltEngine
237
- register :less, TagEngine, tag: :style, attributes: { type: 'text/css' }, engine: TiltEngine
238
- register :sass, TagEngine, :pretty, tag: :style, attributes: { type: 'text/css' }, engine: SassEngine
239
- register :scss, TagEngine, :pretty, tag: :style, attributes: { type: 'text/css' }, engine: SassEngine
237
+ register :coffee, JavaScriptEngine, engine: TiltEngine
238
+ register :less, TagEngine, tag: :style, engine: TiltEngine
239
+ register :sass, TagEngine, :pretty, tag: :style, engine: SassEngine
240
+ register :scss, TagEngine, :pretty, tag: :style, engine: SassEngine
240
241
 
241
242
  # Embedded javascript/css
242
243
  register :javascript, JavaScriptEngine
243
- register :css, TagEngine, tag: :style, attributes: { type: 'text/css' }
244
+ register :css, TagEngine, tag: :style
244
245
 
245
246
  # Embedded ruby code
246
247
  register :ruby, RubyEngine
@@ -10,8 +10,8 @@ module Slim
10
10
  #
11
11
  # @api private
12
12
  class EndInserter < Filter
13
- IF_RE = /\A(if|begin|unless|else|elsif|when|rescue|ensure)\b|\bdo\s*(\|[^\|]*\|)?\s*$/
14
- ELSE_RE = /\A(else|elsif|when|rescue|ensure)\b/
13
+ IF_RE = /\A(if|begin|unless|else|elsif|when|in|rescue|ensure)\b|\bdo\s*(\|[^\|]*\|)?\s*$/
14
+ ELSE_RE = /\A(else|elsif|when|in|rescue|ensure)\b/
15
15
  END_RE = /\Aend\b/
16
16
 
17
17
  # Handle multi expression `[:multi, *exps]`
data/lib/slim/engine.rb CHANGED
@@ -30,7 +30,9 @@ module Slim
30
30
  use Slim::CodeAttributes
31
31
  use(:AttributeRemover) { Temple::HTML::AttributeRemover.new(remove_empty_attrs: options[:merge_attrs].keys) }
32
32
  html :Pretty
33
+ filter :Ambles
33
34
  filter :Escapable
35
+ filter :StaticAnalyzer
34
36
  filter :ControlFlow
35
37
  filter :MultiFlattener
36
38
  filter :StaticMerger
data/lib/slim/parser.rb CHANGED
@@ -231,10 +231,6 @@ module Slim
231
231
  # We expect the line to be broken or the next line to be indented.
232
232
  @line = $'
233
233
  trailing_ws = $2.include?('>'.freeze)
234
- if $2.include?('\''.freeze)
235
- deprecated_syntax '=\' for trailing whitespace is deprecated in favor of =>'
236
- trailing_ws = true
237
- end
238
234
  block = [:multi]
239
235
  @stacks.last << [:static, ' '] if $2.include?('<'.freeze)
240
236
  @stacks.last << [:slim, :output, $1.empty?, parse_broken_line, block]
@@ -348,11 +344,6 @@ module Slim
348
344
  @line =~ /\A[<>']*/
349
345
  @line = $'
350
346
  trailing_ws = $&.include?('>'.freeze)
351
- if $&.include?('\''.freeze)
352
- deprecated_syntax 'tag\' for trailing whitespace is deprecated in favor of tag>'
353
- trailing_ws = true
354
- end
355
-
356
347
  leading_ws = $&.include?('<'.freeze)
357
348
 
358
349
  parse_attributes(attributes)
@@ -387,10 +378,6 @@ module Slim
387
378
  # Handle output code
388
379
  @line = $'
389
380
  trailing_ws2 = $2.include?('>'.freeze)
390
- if $2.include?('\''.freeze)
391
- deprecated_syntax '=\' for trailing whitespace is deprecated in favor of =>'
392
- trailing_ws2 = true
393
- end
394
381
  block = [:multi]
395
382
  @stacks.last.insert(-2, [:static, ' ']) if !leading_ws && $2.include?('<'.freeze)
396
383
  tag << [:slim, :output, $1 != '=', parse_broken_line, block]
@@ -530,16 +517,6 @@ module Slim
530
517
  raise
531
518
  end
532
519
 
533
- def deprecated_syntax(message)
534
- line = @orig_line.lstrip
535
- column = (@orig_line && @line ? @orig_line.size - @line.size : 0) + line.size - @orig_line.size
536
- warn %{Deprecated syntax: #{message}
537
- #{options[:file]}, Line #{@lineno}, Column #{column + 1}
538
- #{line}
539
- #{' ' * column}^
540
- }
541
- end
542
-
543
520
  def expect_next_line
544
521
  next_line || syntax_error!('Unexpected end of file')
545
522
  @line.strip!
@@ -0,0 +1,17 @@
1
+ module Slim
2
+ class Railtie < Rails::Railtie
3
+ initializer "initialize slim template handler" do
4
+ ActiveSupport.on_load(:action_view) do
5
+ Slim::RailsTemplate = Temple::Templates::Rails(Slim::Engine,
6
+ register_as: :slim,
7
+ # Use rails-specific generator. This is necessary
8
+ # to support block capturing and streaming.
9
+ generator: Temple::Generators::RailsOutputBuffer,
10
+ # Disable the internal slim capturing.
11
+ # Rails takes care of the capturing by itself.
12
+ disable_capture: true,
13
+ streaming: true)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -90,8 +90,14 @@ module Slim
90
90
 
91
91
  def hyphen_attr(name, escape, value)
92
92
  if Hash === value
93
- value.each do |n, v|
94
- hyphen_attr("#{name}-#{n}", escape, v)
93
+ if @options[:hyphen_underscore_attrs]
94
+ value.each do |n, v|
95
+ hyphen_attr("#{name}-#{n.to_s.gsub('_', '-')}", escape, v)
96
+ end
97
+ else
98
+ value.each do |n, v|
99
+ hyphen_attr("#{name}-#{n}", escape, v)
100
+ end
95
101
  end
96
102
  else
97
103
  attr(name, escape_html(value != true && escape, value))
@@ -3,7 +3,8 @@ module Slim
3
3
  # @api private
4
4
  class Filter < ::Slim::Filter
5
5
  define_options :merge_attrs, :attr_quote, :sort_attrs, :default_tag, :format, :disable_capture,
6
- hyphen_attrs: %w(data aria), use_html_safe: ''.respond_to?(:html_safe?)
6
+ hyphen_attrs: %w(data aria), use_html_safe: ''.respond_to?(:html_safe?),
7
+ hyphen_underscore_attrs: false
7
8
 
8
9
  def call(exp)
9
10
  @splat_options = nil
data/lib/slim/template.rb CHANGED
@@ -2,18 +2,4 @@ module Slim
2
2
  # Tilt template implementation for Slim
3
3
  # @api public
4
4
  Template = Temple::Templates::Tilt(Slim::Engine, register_as: :slim)
5
-
6
- if defined?(::ActionView)
7
- # Rails template implementation for Slim
8
- # @api public
9
- RailsTemplate = Temple::Templates::Rails(Slim::Engine,
10
- register_as: :slim,
11
- # Use rails-specific generator. This is necessary
12
- # to support block capturing and streaming.
13
- generator: Temple::Generators::RailsOutputBuffer,
14
- # Disable the internal slim capturing.
15
- # Rails takes care of the capturing by itself.
16
- disable_capture: true,
17
- streaming: true)
18
- end
19
5
  end
data/lib/slim/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Slim
2
2
  # Slim version string
3
3
  # @api public
4
- VERSION = '4.1.0'
4
+ VERSION = '5.0.0'
5
5
  end
data/lib/slim.rb CHANGED
@@ -12,3 +12,4 @@ require 'slim/code_attributes'
12
12
  require 'slim/engine'
13
13
  require 'slim/template'
14
14
  require 'slim/version'
15
+ require 'slim/railtie' if defined?(Rails::Railtie)
data/slim.gemspec CHANGED
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  require File.dirname(__FILE__) + '/lib/slim/version'
3
2
  require 'date'
4
3
 
@@ -10,15 +9,15 @@ Gem::Specification.new do |s|
10
9
  s.email = ['mail@daniel-mendler.de', 'andy@stonean.com', 'ifredwu@gmail.com']
11
10
  s.summary = 'Slim is a template language.'
12
11
  s.description = 'Slim is a template language whose goal is reduce the syntax to the essential parts without becoming cryptic.'
13
- s.homepage = 'http://slim-lang.com/'
12
+ s.homepage = 'http://github.com/slim-template/slim/'
14
13
  s.license = 'MIT'
15
14
 
16
15
  s.files = `git ls-files`.split("\n")
17
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
17
  s.require_paths = %w(lib)
19
18
 
20
- s.required_ruby_version = '>=2.0.0'
19
+ s.required_ruby_version = '>= 2.5.0'
21
20
 
22
- s.add_runtime_dependency('temple', ['>= 0.7.6', '< 0.9'])
21
+ s.add_runtime_dependency('temple', ['~> 0.10.0'])
23
22
  s.add_runtime_dependency('tilt', ['>= 2.0.6', '< 2.1'])
24
23
  end
@@ -163,6 +163,7 @@ p id=(1 + 1)*5 Test it
163
163
  end
164
164
 
165
165
  def test_code_attribute_does_not_modify_argument
166
+ require 'ostruct'
166
167
  template = 'span class=attribute'
167
168
  model = OpenStruct.new(attribute: [:a, :b, [:c, :d]])
168
169
  output = Slim::Template.new { template }.render(model)
@@ -120,6 +120,23 @@ p
120
120
  assert_html '<p>42 is the answer</p><p>41 is the answer</p><p>42 is the answer</p><p>41 is the answer</p>', source
121
121
  end
122
122
 
123
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7")
124
+ def test_render_with_case_in
125
+ source = %q{
126
+ p
127
+ - case [:greet, "world"]
128
+ - in :greet, value if false
129
+ = "Goodbye #{value}"
130
+ - in :greet, value unless true
131
+ = "Top of the morning to you, #{value}"
132
+ - in :greet, value
133
+ = "Hello #{value}"
134
+ }
135
+
136
+ assert_html '<p>Hello world</p>', source
137
+ end
138
+ end
139
+
123
140
  def test_render_with_slim_comments
124
141
  source = %q{
125
142
  p Hello
@@ -15,9 +15,6 @@ class TestSlimCommands < Minitest::Test
15
15
  # exception raising example
16
16
  EXCEPTION_TEMPLATE = '- raise NotImplementedError'
17
17
 
18
- # Temple has this feature...
19
- STRING_FREEZER = RUBY_VERSION >= '2.1' ? '.freeze' : ''
20
-
21
18
  def test_option_help
22
19
  out, err = exec_slimrb '--help'
23
20
 
@@ -43,7 +40,7 @@ class TestSlimCommands < Minitest::Test
43
40
  def test_compile
44
41
  prepare_common_test STATIC_TEMPLATE, '--compile' do |out, err|
45
42
  assert err.empty?
46
- assert_match %r{\"<p>Hello World!<\/p>\"#{STRING_FREEZER}}, out
43
+ assert_match %r{\"<p>Hello World!<\/p>\".freeze}, out
47
44
  end
48
45
  end
49
46
 
@@ -58,10 +55,14 @@ class TestSlimCommands < Minitest::Test
58
55
  prepare_common_test DYNAMIC_TEMPLATE, '--rails' do |out, err|
59
56
  assert err.empty?
60
57
 
61
- assert out.include? %Q{@output_buffer = ActiveSupport::SafeBuffer.new;}
62
- assert out.include? %Q{@output_buffer.safe_concat(("<p>Hello "#{STRING_FREEZER}));}
58
+ if Gem::Version.new(Temple::VERSION) >= Gem::Version.new('0.9')
59
+ assert out.include? %Q{@output_buffer = output_buffer || ActionView::OutputBuffer.new;}
60
+ else
61
+ assert out.include? %Q{@output_buffer = ActiveSupport::SafeBuffer.new;}
62
+ end
63
+ assert out.include? %Q{@output_buffer.safe_concat(("<p>Hello ".freeze));}
63
64
  assert out.include? %Q{@output_buffer.safe_concat(((::Temple::Utils.escape_html((name))).to_s));}
64
- assert out.include? %Q{@output_buffer.safe_concat(("!</p>"#{STRING_FREEZER}));}
65
+ assert out.include? %Q{@output_buffer.safe_concat(("!</p>".freeze));}
65
66
  end
66
67
  end
67
68
 
@@ -11,24 +11,26 @@ markdown:
11
11
 
12
12
  #{1+2}
13
13
 
14
+ [#{1}](#{"#2"})
15
+
14
16
  * one
15
17
  * two
16
18
  }
17
19
  if ::Tilt['md'].name =~ /Redcarpet/
18
20
  # redcarpet
19
- assert_html "<h1>Header</h1>\n\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<ul>\n<li>one</li>\n<li>two</li>\n</ul>\n", source
21
+ assert_html "<h1>Header</h1>\n\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<p><a href=\"#2\">1</a></p>\n\n<ul>\n<li>one</li>\n<li>two</li>\n</ul>\n", source
20
22
  elsif ::Tilt['md'].name =~ /RDiscount/
21
23
  # rdiscount
22
- assert_html "<h1>Header</h1>\n\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<ul>\n<li>one</li>\n<li>two</li>\n</ul>\n\n", source
24
+ assert_html "<h1>Header</h1>\n\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<p><a href=\"#2\">1</a></p>\n\n<ul>\n<li>one</li>\n<li>two</li>\n</ul>\n\n", source
23
25
  else
24
26
  # kramdown, :auto_ids by default
25
- assert_html "<h1 id=\"header\">Header</h1>\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<ul>\n <li>one</li>\n <li>two</li>\n</ul>\n", source
27
+ assert_html "<h1 id=\"header\">Header</h1>\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<p><a href=\"#2\">1</a></p>\n\n<ul>\n <li>one</li>\n <li>two</li>\n</ul>\n", source
26
28
 
27
29
  Slim::Embedded.with_options(markdown: {auto_ids: false}) do
28
- assert_html "<h1>Header</h1>\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<ul>\n <li>one</li>\n <li>two</li>\n</ul>\n", source
30
+ assert_html "<h1>Header</h1>\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<p><a href=\"#2\">1</a></p>\n\n<ul>\n <li>one</li>\n <li>two</li>\n</ul>\n", source
29
31
  end
30
32
 
31
- assert_html "<h1 id=\"header\">Header</h1>\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<ul>\n <li>one</li>\n <li>two</li>\n</ul>\n", source
33
+ assert_html "<h1 id=\"header\">Header</h1>\n<p>Hello from Markdown!</p>\n\n<p>3</p>\n\n<p><a href=\"#2\">1</a></p>\n\n<ul>\n <li>one</li>\n <li>two</li>\n</ul>\n", source
32
34
  end
33
35
  end
34
36
 
@@ -37,7 +39,7 @@ markdown:
37
39
  css:
38
40
  h1 { color: blue }
39
41
  }
40
- assert_html "<style type=\"text/css\">h1 { color: blue }</style>", source
42
+ assert_html "<style>h1 { color: blue }</style>", source
41
43
  end
42
44
 
43
45
  def test_render_with_css_empty_attributes
@@ -45,7 +47,7 @@ css:
45
47
  css []:
46
48
  h1 { color: blue }
47
49
  }
48
- assert_html "<style type=\"text/css\">h1 { color: blue }</style>", source
50
+ assert_html "<style>h1 { color: blue }</style>", source
49
51
  end
50
52
 
51
53
  def test_render_with_css_attribute
@@ -53,7 +55,7 @@ css []:
53
55
  css scoped = "true":
54
56
  h1 { color: blue }
55
57
  }
56
- assert_html "<style scoped=\"true\" type=\"text/css\">h1 { color: blue }</style>", source
58
+ assert_html "<style scoped=\"true\">h1 { color: blue }</style>", source
57
59
  end
58
60
 
59
61
  def test_render_with_css_multiple_attributes
@@ -61,7 +63,7 @@ css scoped = "true":
61
63
  css class="myClass" scoped = "true" :
62
64
  h1 { color: blue }
63
65
  }
64
- assert_html "<style class=\"myClass\" scoped=\"true\" type=\"text/css\">h1 { color: blue }</style>", source
66
+ assert_html "<style class=\"myClass\" scoped=\"true\">h1 { color: blue }</style>", source
65
67
  end
66
68
 
67
69
  def test_render_with_javascript
@@ -163,13 +165,15 @@ ruby:
163
165
  assert_html "foobar\n", source
164
166
  end
165
167
 
168
+ # TODO: Reactivate sass tests
169
+ if false
166
170
  def test_render_with_scss
167
171
  source = %q{
168
172
  scss:
169
173
  $color: #f00;
170
174
  body { color: $color; }
171
175
  }
172
- assert_html "<style type=\"text/css\">body{color:red}</style>", source
176
+ assert_html "<style>body{color:red}</style>", source
173
177
  end
174
178
 
175
179
  def test_render_with_scss_attribute
@@ -178,7 +182,7 @@ scss [class="myClass"]:
178
182
  $color: #f00;
179
183
  body { color: $color; }
180
184
  }
181
- assert_html "<style class=\"myClass\" type=\"text/css\">body{color:red}</style>", source
185
+ assert_html "<style class=\"myClass\">body{color:red}</style>", source
182
186
  end
183
187
 
184
188
  def test_render_with_sass
@@ -188,7 +192,7 @@ sass:
188
192
  body
189
193
  color: $color
190
194
  }
191
- assert_html "<style type=\"text/css\">body{color:red}</style>", source
195
+ assert_html "<style>body{color:red}</style>", source
192
196
  end
193
197
 
194
198
  def test_render_with_sass_attribute
@@ -198,9 +202,9 @@ sass [class="myClass"]:
198
202
  body
199
203
  color: $color
200
204
  }
201
- assert_html "<style class=\"myClass\" type=\"text/css\">body{color:red}</style>", source
205
+ assert_html "<style class=\"myClass\">body{color:red}</style>", source
202
206
  end
203
-
207
+ end
204
208
 
205
209
  def test_disabled_embedded_engine
206
210
  source = %{
@@ -21,9 +21,8 @@ html
21
21
  /[if lt IE 9]
22
22
  script src="old-ie1.js"
23
23
  script src="old-ie2.js"
24
- sass:
25
- body
26
- background-color: red
24
+ css:
25
+ body { background-color: red; }
27
26
  body
28
27
  #container
29
28
  p Hello
@@ -51,9 +50,8 @@ multiline comment-->
51
50
  </script><!--[if lt IE 9]>
52
51
  <script src="old-ie1.js">
53
52
  </script><script src="old-ie2.js">
54
- </script><![endif]--><style type="text/css">body{background-color:red}
55
-
56
- </style>
53
+ </script><![endif]--><style>
54
+ body { background-color: red; }</style>
57
55
  </head><body>
58
56
  <div id="container">
59
57
  <p>Hello
@@ -116,6 +116,14 @@ option(selected class="clazz") Text
116
116
  assert_html '<div class="alpha" data-a="alpha" data-b="beta" data-c-e="epsilon" data-c_d="gamma"></div>', source
117
117
  end
118
118
 
119
+ def test_hyphenated_underscore_attribute
120
+ source = %{
121
+ .alpha data={a: 'alpha', b: 'beta', c_d: 'gamma', c: {e: 'epsilon'}}
122
+ }
123
+
124
+ assert_html '<div class="alpha" data-a="alpha" data-b="beta" data-c-d="gamma" data-c-e="epsilon"></div>', source, hyphen_underscore_attrs: true
125
+ end
126
+
119
127
  def test_splat_without_content
120
128
  source = %q{
121
129
  *hash
@@ -29,9 +29,8 @@ html
29
29
  /[if lt IE 9]
30
30
  script src="old-ie1.js"
31
31
  script src="old-ie2.js"
32
- sass:
33
- body
34
- background-color: red
32
+ css:
33
+ body { background-color: red; }
35
34
  body
36
35
  #container
37
36
  p Hello
@@ -56,10 +55,8 @@ html
56
55
  <script src="old-ie1.js"></script>
57
56
  <script src="old-ie2.js"></script>
58
57
  <![endif]-->
59
- <style type="text/css">
60
- body {
61
- background-color: red;
62
- }
58
+ <style>
59
+ body { background-color: red; }
63
60
  </style>
64
61
  </head>
65
62
  <body>