slim 5.1.0 → 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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +28 -5
  3. data/CHANGES +12 -1
  4. data/Gemfile +6 -7
  5. data/README.jp.md +19 -29
  6. data/README.md +43 -28
  7. data/Rakefile +1 -1
  8. data/lib/slim/code_attributes.rb +2 -1
  9. data/lib/slim/command.rb +2 -8
  10. data/lib/slim/controls.rb +1 -0
  11. data/lib/slim/do_inserter.rb +3 -2
  12. data/lib/slim/embedded.rb +6 -7
  13. data/lib/slim/end_inserter.rb +1 -0
  14. data/lib/slim/engine.rb +1 -0
  15. data/lib/slim/erb_converter.rb +1 -0
  16. data/lib/slim/filter.rb +1 -0
  17. data/lib/slim/grammar.rb +1 -0
  18. data/lib/slim/include.rb +1 -0
  19. data/lib/slim/interpolation.rb +1 -0
  20. data/lib/slim/logic_less/context.rb +6 -7
  21. data/lib/slim/logic_less/filter.rb +1 -0
  22. data/lib/slim/logic_less.rb +1 -0
  23. data/lib/slim/parser.rb +17 -10
  24. data/lib/slim/railtie.rb +3 -1
  25. data/lib/slim/smart/escaper.rb +1 -1
  26. data/lib/slim/smart/filter.rb +3 -2
  27. data/lib/slim/smart/parser.rb +4 -3
  28. data/lib/slim/smart.rb +1 -0
  29. data/lib/slim/splat/builder.rb +10 -8
  30. data/lib/slim/splat/filter.rb +4 -3
  31. data/lib/slim/template.rb +1 -0
  32. data/lib/slim/translator.rb +4 -3
  33. data/lib/slim/version.rb +2 -1
  34. data/lib/slim.rb +1 -0
  35. data/slim.gemspec +1 -1
  36. data/test/core/helper.rb +3 -11
  37. data/test/core/test_commands.rb +11 -15
  38. data/test/core/test_encoding.rb +2 -2
  39. data/test/core/test_html_structure.rb +48 -0
  40. data/test/core/test_ruby_errors.rb +19 -0
  41. data/test/literate/helper.rb +1 -1
  42. data/test/literate/run.rb +1 -1
  43. data/test/logic_less/test_logic_less.rb +15 -0
  44. data/test/rails/app/controllers/slim_controller.rb +7 -1
  45. data/test/rails/app/views/layouts/application.html+testvariant.slim +10 -0
  46. data/test/rails/app/views/slim/attributes.html.slim +3 -0
  47. data/test/rails/app/views/slim/splat_with_delimiter.slim +1 -0
  48. data/test/rails/config/application.rb +1 -1
  49. data/test/rails/test/test_slim.rb +18 -0
  50. metadata +11 -14
data/lib/slim/filter.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Base class for Temple filters used in Slim
3
4
  #
data/lib/slim/grammar.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Slim expression grammar
3
4
  # @api private
data/lib/slim/include.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'slim'
2
3
 
3
4
  module Slim
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Perform interpolation of #{var_name} in the
3
4
  # expressions `[:slim, :interpolate, string]`.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  class LogicLess
3
4
  # @api private
@@ -16,7 +17,7 @@ module Slim
16
17
  yield
17
18
  else
18
19
  new_scope do
19
- dict.inject('') do |result, d|
20
+ dict.inject(''.dup) do |result, d|
20
21
  scope.dict = d
21
22
  result << yield
22
23
  end
@@ -73,7 +74,7 @@ module Slim
73
74
  return @dict.instance_variable_get(var_name).call(&block) if instance_variable?(var_name)
74
75
  end
75
76
  end
76
- @parent.lambda(name) if @parent
77
+ @parent.lambda(name, &block) if @parent
77
78
  end
78
79
 
79
80
  def [](name)
@@ -104,11 +105,9 @@ module Slim
104
105
  end
105
106
 
106
107
  def instance_variable?(name)
107
- begin
108
- @dict.instance_variable_defined?(name)
109
- rescue NameError
110
- false
111
- end
108
+ @dict.instance_variable_defined?(name)
109
+ rescue NameError
110
+ false
112
111
  end
113
112
  end
114
113
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Handle logic less mode
3
4
  # This filter can be activated with the option "logic_less"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'slim'
2
3
  require 'slim/logic_less/filter'
3
4
  require 'slim/logic_less/context'
data/lib/slim/parser.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Parses Slim code and transforms it to a Temple expression
3
4
  # @api private
@@ -49,7 +50,7 @@ module Slim
49
50
  @code_attr_delims = options[:code_attr_delims]
50
51
  tabsize = options[:tabsize]
51
52
  if tabsize > 1
52
- @tab_re = /\G((?: {#{tabsize}})*) {0,#{tabsize-1}}\t/
53
+ @tab_re = /\G((?: {#{tabsize}})*) {0,#{tabsize - 1}}\t/
53
54
  @tab = '\1' + ' ' * tabsize
54
55
  else
55
56
  @tab_re = "\t"
@@ -63,15 +64,15 @@ module Slim
63
64
  raise ArgumentError, 'You can only use special characters for attribute shortcuts' if k =~ /(\p{Word}|-)/
64
65
  end
65
66
  if v.include?(:attr)
66
- @attr_shortcut[k] = [v[:attr]].flatten
67
+ @attr_shortcut[k] = v[:attr].is_a?(Proc) ? v[:attr] : [v[:attr]].flatten
67
68
  end
68
69
  if v.include?(:additional_attrs)
69
70
  @additional_attrs[k] = v[:additional_attrs]
70
71
  end
71
72
  end
72
- keys = Regexp.union @attr_shortcut.keys.sort_by {|k| -k.size }
73
+ keys = Regexp.union @attr_shortcut.keys.sort_by { |k| -k.size }
73
74
  @attr_shortcut_re = /\A(#{keys}+)((?:\p{Word}|-|\/\d+|:(\w|-)+)*)/
74
- keys = Regexp.union @tag_shortcut.keys.sort_by {|k| -k.size }
75
+ keys = Regexp.union @tag_shortcut.keys.sort_by { |k| -k.size }
75
76
  @tag_re = /\A(?:#{keys}|\*(?=[^\s]+)|(\p{Word}(?:\p{Word}|:|-)*\p{Word}|\p{Word}+))/
76
77
  keys = Regexp.escape @code_attr_delims.keys.join
77
78
  @code_attr_delims_re = /\A[#{keys}]/
@@ -84,7 +85,7 @@ module Slim
84
85
  @code_attr_re = /#{@attr_name}\s*=(=?)\s*/
85
86
 
86
87
  splat_prefix = Regexp.escape(options[:splat_prefix])
87
- splat_regexp_source = '\A\s*' << splat_prefix << '(?=[^\s]+)'
88
+ splat_regexp_source = '\A\s*' + splat_prefix + '(?=[^\s]+)'
88
89
  @splat_attrs_regexp = Regexp.new(splat_regexp_source)
89
90
  end
90
91
 
@@ -335,7 +336,13 @@ module Slim
335
336
  # The class/id attribute is :static instead of :slim :interpolate,
336
337
  # because we don't want text interpolation in .class or #id shortcut
337
338
  syntax_error!('Illegal shortcut') unless shortcut = @attr_shortcut[$1]
338
- shortcut.each {|a| attributes << [:html, :attr, a, [:static, $2]] }
339
+
340
+ if shortcut.is_a?(Proc)
341
+ shortcut.call($2).each { |a, v| attributes << [:html, :attr, a, [:static, v]] }
342
+ else
343
+ shortcut.each {|a| attributes << [:html, :attr, a, [:static, $2]] }
344
+ end
345
+
339
346
  if additional_attr_pairs = @additional_attrs[$1]
340
347
  additional_attr_pairs.each do |k,v|
341
348
  attributes << [:html, :attr, k.to_s, [:static, v]]
@@ -461,7 +468,7 @@ module Slim
461
468
  end
462
469
 
463
470
  def parse_ruby_code(outer_delimiter)
464
- code, count, delimiter, close_delimiter = '', 0, nil, nil
471
+ code, count, delimiter, close_delimiter = ''.dup, 0, nil, nil
465
472
 
466
473
  # Attribute ends with space or attribute delimiter
467
474
  end_re = /\A[\s#{Regexp.escape outer_delimiter.to_s}]/
@@ -489,16 +496,16 @@ module Slim
489
496
  end
490
497
 
491
498
  def parse_quoted_attribute(quote)
492
- value, count = '', 0
499
+ value, count = ''.dup, 0
493
500
 
494
501
  until count == 0 && @line[0] == quote[0]
495
502
  if @line =~ /\A(\\)?\Z/
496
503
  value << ($1 ? ' ' : "\n")
497
504
  expect_next_line
498
505
  else
499
- if @line[0] == ?{
506
+ if @line[0] == '{'
500
507
  count += 1
501
- elsif @line[0] == ?}
508
+ elsif @line[0] == '}'
502
509
  count -= 1
503
510
  end
504
511
  value << @line.slice!(0)
data/lib/slim/railtie.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Slim
2
4
  class Railtie < ::Rails::Railtie
3
- initializer "initialize slim template handler" do
5
+ initializer 'initialize slim template handler' do
4
6
  ActiveSupport.on_load(:action_view) do
5
7
  Slim::RailsTemplate = Temple::Templates::Rails(Slim::Engine,
6
8
  register_as: :slim,
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  module Smart
3
4
  # Perform smart entity escaping in the
@@ -36,7 +37,6 @@ module Slim
36
37
  end
37
38
  block
38
39
  end
39
-
40
40
  end
41
41
  end
42
42
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  module Smart
3
4
  # Perform newline processing in the
@@ -50,13 +51,13 @@ module Slim
50
51
  # so we don't have to worry about that at all.
51
52
  block = [:multi]
52
53
  prev = nil
53
- last_exp = exps.reject{ |exp| exp.first == :newline }.last unless @active && @append
54
+ last_exp = exps.reject { |exp| exp.first == :newline }.last unless @active && @append
54
55
  exps.each do |exp|
55
56
  @append = exp.equal?(last_exp)
56
57
  if @active
57
58
  @prepend = false if prev
58
59
  else
59
- @prepend = prev && ( prev.first != :slim || prev[1] != :text )
60
+ @prepend = prev && (prev.first != :slim || prev[1] != :text)
60
61
  end
61
62
  block << compile(exp)
62
63
  prev = exp unless exp.first == :newline
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  module Smart
3
4
  # @api private
@@ -7,9 +8,9 @@ module Slim
7
8
  def initialize(opts = {})
8
9
  super
9
10
  word_re = options[:implicit_text] ? '[_a-z0-9]' : '\p{Word}'
10
- attr_keys = Regexp.union(@attr_shortcut.keys.sort_by {|k| -k.size } )
11
+ attr_keys = Regexp.union(@attr_shortcut.keys.sort_by { |k| -k.size })
11
12
  @attr_shortcut_re = /\A(#{attr_keys}+)((?:\p{Word}|-)*)/
12
- tag_keys = Regexp.union((@tag_shortcut.keys - @attr_shortcut.keys).sort_by {|k| -k.size } )
13
+ tag_keys = Regexp.union((@tag_shortcut.keys - @attr_shortcut.keys).sort_by { |k| -k.size })
13
14
  @tag_re = /\A(?:#{attr_keys}(?=-*\p{Word})|#{tag_keys}|\*(?=[^\s]+)|(#{word_re}(?:#{word_re}|:|-)*#{word_re}|#{word_re}+))/
14
15
  end
15
16
 
@@ -24,7 +25,7 @@ module Slim
24
25
  end
25
26
  # Found implicit smart text block.
26
27
  if line = @lines.first
27
- indent = ( line =~ /\A\s*\Z/ ? @indents.last + 1 : get_indent(line) )
28
+ indent = (line =~ /\A\s*\Z/ ? @indents.last + 1 : get_indent(line))
28
29
  end
29
30
  @stacks.last << [:slim, :text, :implicit, parse_text_block(@line, indent)]
30
31
  end
data/lib/slim/smart.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'slim'
2
3
  require 'slim/smart/filter'
3
4
  require 'slim/smart/escaper'
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  class InvalidAttributeNameError < StandardError; end
3
4
  module Splat
4
5
  # @api private
5
6
  class Builder
6
- # https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
7
- INVALID_ATTRIBUTE_NAME_REGEX = /[ \0"'>\/=]/
7
+ # https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
8
+ INVALID_ATTRIBUTE_NAME_REGEX = /[ \0"'>\/=]/
9
+
8
10
  def initialize(options)
9
11
  @options = options
10
12
  @attrs = {}
@@ -17,7 +19,7 @@ module Slim
17
19
  elsif @options[:hyphen_attrs].include?(name) && Hash === value
18
20
  hyphen_attr(name, escape, value)
19
21
  elsif value != false && value != nil
20
- attr(name, escape_html(value != true && escape, value))
22
+ attr(name, escape_html(escape, value))
21
23
  end
22
24
  end
23
25
 
@@ -33,7 +35,7 @@ module Slim
33
35
  end
34
36
  if @attrs[name]
35
37
  if delim = @options[:merge_attrs][name]
36
- @attrs[name] += delim + value.to_s
38
+ @attrs[name] = @attrs[name].to_s + delim + value.to_s
37
39
  else
38
40
  raise("Multiple #{name} attributes specified")
39
41
  end
@@ -90,9 +92,9 @@ module Slim
90
92
 
91
93
  def hyphen_attr(name, escape, value)
92
94
  if Hash === value
93
- if @options[:hyphen_underscore_attrs]
95
+ if @options[:hyphen_underscore_attrs]
94
96
  value.each do |n, v|
95
- hyphen_attr("#{name}-#{n.to_s.gsub('_', '-')}", escape, v)
97
+ hyphen_attr("#{name}-#{n.to_s.tr('_', '-')}", escape, v)
96
98
  end
97
99
  else
98
100
  value.each do |n, v|
@@ -100,12 +102,12 @@ module Slim
100
102
  end
101
103
  end
102
104
  else
103
- attr(name, escape_html(value != true && escape, value))
105
+ attr(name, escape_html(escape, value))
104
106
  end
105
107
  end
106
108
 
107
109
  def escape_html(escape, value)
108
- return value unless escape
110
+ return value if !escape || value == true
109
111
  @options[:use_html_safe] ? Temple::Utils.escape_html_safe(value) : Temple::Utils.escape_html(value)
110
112
  end
111
113
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  module Splat
3
4
  # @api private
@@ -10,7 +11,7 @@ module Slim
10
11
  @splat_options = nil
11
12
  exp = compile(exp)
12
13
  if @splat_options
13
- opts = options.to_hash.reject {|k,v| !Filter.options.valid_key?(k) }.inspect
14
+ opts = options.to_hash.reject { |k, v| !Filter.options.valid_key?(k) }.inspect
14
15
  [:multi, [:code, "#{@splat_options} = #{opts}"], exp]
15
16
  else
16
17
  exp
@@ -44,7 +45,7 @@ module Slim
44
45
  # @param [Array] attrs Array of temple expressions
45
46
  # @return [Array] Compiled temple expression
46
47
  def on_html_attrs(*attrs)
47
- if attrs.any? {|attr| splat?(attr) }
48
+ if attrs.any? { |attr| splat?(attr) }
48
49
  builder, block = make_builder(attrs)
49
50
  [:multi,
50
51
  block,
@@ -85,7 +86,7 @@ module Slim
85
86
  attr
86
87
  end
87
88
  end
88
- return builder, result
89
+ [builder, result]
89
90
  end
90
91
  end
91
92
  end
data/lib/slim/template.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Tilt template implementation for Slim
3
4
  # @api public
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'slim'
2
3
 
3
4
  module Slim
@@ -62,7 +63,7 @@ module Slim
62
63
  end
63
64
 
64
65
  def call(exp)
65
- @text, @captures = '', []
66
+ @text, @captures = ''.dup, []
66
67
  result = compile(exp)
67
68
 
68
69
  text = @translate.call(@text)
@@ -89,7 +90,7 @@ module Slim
89
90
  define_options :tr_fn
90
91
 
91
92
  def call(exp)
92
- @captures_count, @captures_var, @text = 0, unique_name, ''
93
+ @captures_count, @captures_var, @text = 0, unique_name, ''.dup
93
94
 
94
95
  result = compile(exp)
95
96
 
@@ -109,7 +110,7 @@ module Slim
109
110
  def on_slim_output(escape, code, content)
110
111
  @captures_count += 1
111
112
  @text << "%#{@captures_count}"
112
- [:capture, "#{@captures_var}[#{@captures_count-1}]", [:slim, :output, escape, code, content]]
113
+ [:capture, "#{@captures_var}[#{@captures_count - 1}]", [:slim, :output, escape, code, content]]
113
114
  end
114
115
  end
115
116
  end
data/lib/slim/version.rb CHANGED
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module Slim
2
3
  # Slim version string
3
4
  # @api public
4
- VERSION = '5.1.0'
5
+ VERSION = '5.2.0'
5
6
  end
data/lib/slim.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'temple'
2
3
  require 'slim/parser'
3
4
  require 'slim/filter'
data/slim.gemspec CHANGED
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.required_ruby_version = '>= 2.5.0'
20
20
 
21
21
  s.add_runtime_dependency('temple', ['~> 0.10.0'])
22
- s.add_runtime_dependency('tilt', ['>= 2.0.6', '< 2.2'])
22
+ s.add_runtime_dependency('tilt', ['>= 2.1.0'])
23
23
  end
data/test/core/helper.rb CHANGED
@@ -62,16 +62,8 @@ class TestSlim < Minitest::Test
62
62
  end
63
63
 
64
64
  def assert_backtrace(ex, from)
65
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
66
- # HACK: Rubinius stack trace sometimes has one entry more
67
- if ex.backtrace[0] !~ /^#{Regexp.escape from}/
68
- ex.backtrace[1] =~ /([^\s]+:\d+)/
69
- assert_equal from, $1
70
- end
71
- else
72
- ex.backtrace[0] =~ /([^\s]+:\d+)/
73
- assert_equal from, $1
74
- end
65
+ ex.backtrace[0] =~ /([^\s]+:\d+)/
66
+ assert_equal from, $1
75
67
  end
76
68
 
77
69
  def assert_ruby_syntax_error(from, source, options = {})
@@ -121,7 +113,7 @@ class Env
121
113
  end
122
114
 
123
115
  def hello_world(text = "Hello World from @env", opts = {})
124
- text << opts.to_a * " " if opts.any?
116
+ text = text + (opts.to_a * " ") if opts.any?
125
117
  if block_given?
126
118
  "#{text} #{yield} #{text}"
127
119
  else
@@ -73,23 +73,19 @@ class TestSlimCommands < Minitest::Test
73
73
  end
74
74
  end
75
75
 
76
- # We cannot run these two on Travis, because we can't install libyaml.
77
- # See https://github.com/slim-template/slim/issues/576
78
- if ENV['TRAVIS'] && RUBY_ENGINE != 'rbx'
79
- def test_locals_json
80
- data = '{"name":"from slim"}'
81
- prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err|
82
- assert err.empty?
83
- assert_equal "<p>Hello from slim!</p>\n", out
84
- end
76
+ def test_locals_json
77
+ data = '{"name":"from slim"}'
78
+ prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err|
79
+ assert err.empty?
80
+ assert_equal "<p>Hello from slim!</p>\n", out
85
81
  end
82
+ end
86
83
 
87
- def test_locals_yaml
88
- data = "name: from slim"
89
- prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err|
90
- assert err.empty?
91
- assert_equal "<p>Hello from slim!</p>\n", out
92
- end
84
+ def test_locals_yaml
85
+ data = "name: from slim"
86
+ prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err|
87
+ assert err.empty?
88
+ assert_equal "<p>Hello from slim!</p>\n", out
93
89
  end
94
90
  end
95
91
 
@@ -8,10 +8,10 @@ class TestSlimEncoding < TestSlim
8
8
  end
9
9
 
10
10
  def test_binary
11
- source = "| \xFF\xFF"
11
+ source = "| \xFF\xFF".dup
12
12
  source.force_encoding(Encoding::BINARY)
13
13
 
14
- result = "\xFF\xFF"
14
+ result = "\xFF\xFF".dup
15
15
  result.force_encoding(Encoding::BINARY)
16
16
 
17
17
  out = render(source, default_encoding: 'binary')
@@ -115,6 +115,54 @@ h1#title This is my title
115
115
  source, shortcut: {'^' => {tag: 'script', attr: 'data-binding', additional_attrs: { type: "application/json" }}}
116
116
  end
117
117
 
118
+ def test_render_with_custom_lambda_shortcut
119
+ begin
120
+ Slim::Parser.options[:shortcut]['~'] = {attr: ->(v) {{class: "styled-#{v}", id: "id-#{v}"}}}
121
+ source = %q{
122
+ ~foo Hello
123
+ }
124
+ assert_html '<div class="styled-foo" id="id-foo">Hello</div>', source
125
+ ensure
126
+ Slim::Parser.options[:shortcut].delete('~')
127
+ end
128
+ end
129
+
130
+ def test_render_with_custom_lambda_shortcut_and_multiple_values
131
+ begin
132
+ Slim::Parser.options[:shortcut]['~'] = {attr: ->(v) {{class: "styled-#{v}"}}}
133
+ source = %q{
134
+ ~foo~bar Hello
135
+ }
136
+ assert_html '<div class="styled-foo styled-bar">Hello</div>', source
137
+ ensure
138
+ Slim::Parser.options[:shortcut].delete('~')
139
+ end
140
+ end
141
+
142
+ def test_render_with_custom_lambda_shortcut_and_existing_class
143
+ begin
144
+ Slim::Parser.options[:shortcut]['~'] = {attr: ->(v) {{class: "styled-#{v}"}}}
145
+ source = %q{
146
+ ~foo.baz Hello
147
+ }
148
+ assert_html '<div class="styled-foo baz">Hello</div>', source
149
+ ensure
150
+ Slim::Parser.options[:shortcut].delete('~')
151
+ end
152
+ end
153
+
154
+ def test_render_with_existing_class_and_custom_lambda_shortcut
155
+ begin
156
+ Slim::Parser.options[:shortcut]['~'] = {attr: ->(v) {{class: "styled-#{v}"}}}
157
+ source = %q{
158
+ .baz~foo Hello
159
+ }
160
+ assert_html '<div class="baz styled-foo">Hello</div>', source
161
+ ensure
162
+ Slim::Parser.options[:shortcut].delete('~')
163
+ end
164
+ end
165
+
118
166
  def test_render_with_text_block
119
167
  source = %q{
120
168
  p
@@ -106,6 +106,25 @@ ruby:
106
106
  assert_ruby_error NameError,"(__TEMPLATE__):4", source
107
107
  end
108
108
 
109
+ def test_embedded_ruby3
110
+ source = %q{
111
+ h1 before
112
+ ruby:
113
+ a = 1
114
+
115
+ h1 between
116
+ ruby:
117
+ b = a + 1
118
+
119
+ unknown_ruby_method
120
+
121
+ c = 3
122
+ h1 third
123
+ }
124
+
125
+ assert_ruby_error NameError,"(__TEMPLATE__):10", source
126
+ end
127
+
109
128
  def test_embedded_markdown
110
129
  source = %q{
111
130
  markdown:
@@ -8,7 +8,7 @@ Slim::Engine.after Slim::Parser, Temple::Filters::Validator, grammar: Slim::Gra
8
8
  Slim::Engine.before :Pretty, Temple::Filters::Validator
9
9
  Slim::Engine.set_options tr: false, logic_less: false
10
10
 
11
- class MiniTest::Spec
11
+ class Minitest::Spec
12
12
  def render(source, options = {}, &block)
13
13
  Slim::Template.new(options) { source }.render(self, &block)
14
14
  end
data/test/literate/run.rb CHANGED
@@ -63,7 +63,7 @@ class LiterateTest < Temple::Engine
63
63
  def on_html(code)
64
64
  raise Temple::FilterError, 'Html block must be preceded by slim block' unless @in_testcase
65
65
  @in_testcase = false
66
- result = " html = #{code.inspect}\n"
66
+ result = " html = #{code.inspect}\n".dup
67
67
  if @opts.empty?
68
68
  result << " _(render(slim)).must_equal html\nend\n"
69
69
  else
@@ -312,4 +312,19 @@ div
312
312
  'This is the menu'
313
313
  end
314
314
  end
315
+
316
+ def test_render_parent_lambda
317
+ source = %q{
318
+ - list
319
+ == fn
320
+ p = string
321
+ }
322
+
323
+ assert_html '<fn><p>str</p></fn><fn><p>str</p></fn><fn><p>str</p></fn>',
324
+ source, scope: {
325
+ fn: ->(&block) { "<fn>#{block.call}</fn>" },
326
+ list: [ "item1", "item2", "item3" ],
327
+ string: "str"
328
+ }
329
+ end
315
330
  end
@@ -26,11 +26,17 @@ class SlimController < ApplicationController
26
26
  end
27
27
 
28
28
  def thread_options
29
- Slim::Engine.with_options(shortcut: {'@' => { attr: params[:attr] }}) do
29
+ default_shortcut = {'#' => {attr: 'id'}, '.' => {attr: 'class'} }
30
+ Slim::Engine.with_options(shortcut: default_shortcut.merge({'@' => { attr: params[:attr] }})) do
30
31
  render
31
32
  end
32
33
  end
33
34
 
35
+ def variant
36
+ request.variant = :testvariant
37
+ render :normal
38
+ end
39
+
34
40
  def content_for
35
41
  @hello = "Hello Slim!"
36
42
  end
@@ -0,0 +1,10 @@
1
+ doctype html
2
+
3
+ html
4
+ head
5
+ title Variant
6
+ = csrf_meta_tag
7
+
8
+ body
9
+ = yield :page_heading
10
+ .content= yield
@@ -0,0 +1,3 @@
1
+ / Exercises Temple `:capture` handling (used here for preparing HTML attributes) with the
2
+ / Rails-specific Temple generators
3
+ .static class="#{['a', 'b'].join('-')}"
@@ -0,0 +1 @@
1
+ .cute *{class: "nice"} Hello
@@ -5,7 +5,7 @@ require 'action_controller/railtie'
5
5
  require 'action_view/railtie'
6
6
  #require 'active_record/railtie'
7
7
  #require 'action_mailer/railtie'
8
- require 'sprockets/railtie'
8
+ #require 'sprockets/railtie'
9
9
  require 'slim'
10
10
 
11
11
  module Dummy