slim 2.1.0 → 3.0.0.beta.2
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.
- checksums.yaml +4 -4
- data/.travis.yml +10 -24
- data/CHANGES +8 -0
- data/Gemfile +5 -7
- data/README.jp.md +29 -31
- data/README.md +34 -34
- data/Rakefile +9 -7
- data/benchmarks/context.rb +3 -3
- data/benchmarks/run-benchmarks.rb +9 -9
- data/benchmarks/view.slim +1 -1
- data/doc/jp/logic_less.md +7 -7
- data/doc/logic_less.md +7 -7
- data/lib/slim/command.rb +6 -16
- data/lib/slim/embedded.rb +10 -13
- data/lib/slim/engine.rb +21 -23
- data/lib/slim/erb_converter.rb +2 -1
- data/lib/slim/include.rb +2 -2
- data/lib/slim/logic_less.rb +1 -2
- data/lib/slim/logic_less/filter.rb +3 -3
- data/lib/slim/parser.rb +43 -19
- data/lib/slim/smart.rb +3 -3
- data/lib/slim/smart/escaper.rb +1 -1
- data/lib/slim/smart/filter.rb +3 -3
- data/lib/slim/smart/parser.rb +6 -4
- data/lib/slim/splat/builder.rb +9 -4
- data/lib/slim/splat/filter.rb +3 -4
- data/lib/slim/template.rb +5 -5
- data/lib/slim/translator.rb +12 -13
- data/lib/slim/version.rb +1 -1
- data/slim.gemspec +3 -1
- data/test/core/helper.rb +3 -3
- data/test/core/test_code_escaping.rb +14 -14
- data/test/core/test_code_evaluation.rb +1 -1
- data/test/core/test_code_output.rb +1 -1
- data/test/core/test_embedded_engines.rb +16 -16
- data/test/core/test_encoding.rb +4 -4
- data/test/core/test_html_attributes.rb +9 -9
- data/test/core/test_html_structure.rb +20 -20
- data/test/core/test_parser_errors.rb +1 -1
- data/test/core/test_pretty.rb +4 -4
- data/test/core/test_ruby_errors.rb +5 -5
- data/test/core/test_slim_template.rb +2 -2
- data/test/core/test_tabs.rb +5 -5
- data/test/core/test_thread_options.rb +4 -4
- data/test/core/test_unicode.rb +11 -13
- data/test/include/test_include.rb +2 -2
- data/test/literate/TESTS.md +37 -8
- data/test/literate/helper.rb +2 -2
- data/test/logic_less/test_logic_less.rb +37 -37
- data/test/rails/app/controllers/slim_controller.rb +3 -3
- data/test/rails/config/initializers/session_store.rb +1 -1
- data/test/rails/config/routes.rb +4 -4
- data/test/rails/test/test_slim.rb +9 -15
- data/test/smart/test_smart_text.rb +5 -9
- data/test/translator/test_translator.rb +14 -14
- metadata +7 -7
data/Rakefile
CHANGED
@@ -60,15 +60,17 @@ namespace 'test' do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
begin
|
63
|
-
require 'rubygems'
|
64
63
|
require 'sinatra'
|
65
64
|
spec = Gem::Specification.find_by_name('sinatra')
|
66
65
|
Rake::TestTask.new('sinatra') do |t|
|
67
|
-
# FIXME: Rename deprecated attribute
|
68
66
|
file = "#{spec.gem_dir}/test/slim_test.rb"
|
69
|
-
|
70
|
-
|
71
|
-
|
67
|
+
|
68
|
+
if Sinatra::VERSION =~ /\A1\.3/
|
69
|
+
# FIXME: Rename deprecated attribute
|
70
|
+
code = File.read(file)
|
71
|
+
code.gsub!('attr_wrapper', 'attr_quote')
|
72
|
+
File.open(file, 'w') {|out| out.write(code) }
|
73
|
+
end
|
72
74
|
|
73
75
|
# Run Slim integration test in Sinatra
|
74
76
|
t.test_files = FileList[file]
|
@@ -93,6 +95,6 @@ rescue LoadError
|
|
93
95
|
end
|
94
96
|
|
95
97
|
desc "Generate Documentation"
|
96
|
-
task :
|
98
|
+
task doc: :yard
|
97
99
|
|
98
|
-
task :
|
100
|
+
task default: 'test'
|
data/benchmarks/context.rb
CHANGED
@@ -4,8 +4,8 @@ class Context
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def item
|
7
|
-
[ { :
|
8
|
-
{ :
|
9
|
-
{ :
|
7
|
+
[ { name: 'red', current: true, url: '#red' },
|
8
|
+
{ name: 'green', current: false, url: '#green' },
|
9
|
+
{ name: 'blue', current: false, url: '#blue' } ]
|
10
10
|
end
|
11
11
|
end
|
@@ -29,8 +29,8 @@ class SlimBenchmarks
|
|
29
29
|
erb = ERB.new(@erb_code)
|
30
30
|
erubis = Erubis::Eruby.new(@erb_code)
|
31
31
|
fast_erubis = Erubis::FastEruby.new(@erb_code)
|
32
|
-
haml_pretty = Haml::Engine.new(@haml_code, :
|
33
|
-
haml_ugly = Haml::Engine.new(@haml_code, :
|
32
|
+
haml_pretty = Haml::Engine.new(@haml_code, format: :html5)
|
33
|
+
haml_ugly = Haml::Engine.new(@haml_code, format: :html5, ugly: true)
|
34
34
|
|
35
35
|
context = Context.new
|
36
36
|
|
@@ -41,7 +41,7 @@ class SlimBenchmarks
|
|
41
41
|
def run_erubis; #{erubis.src}; end
|
42
42
|
def run_temple_erb; #{Temple::ERB::Engine.new.call @erb_code}; end
|
43
43
|
def run_fast_erubis; #{fast_erubis.src}; end
|
44
|
-
def run_slim_pretty; #{Slim::Engine.new(:
|
44
|
+
def run_slim_pretty; #{Slim::Engine.new(pretty: true).call @slim_code}; end
|
45
45
|
def run_slim_ugly; #{Slim::Engine.new.call @slim_code}; end
|
46
46
|
}
|
47
47
|
|
@@ -59,9 +59,9 @@ class SlimBenchmarks
|
|
59
59
|
tilt_erb = Tilt::ERBTemplate.new { @erb_code }
|
60
60
|
tilt_erubis = Tilt::ErubisTemplate.new { @erb_code }
|
61
61
|
tilt_temple_erb = Temple::ERB::Template.new { @erb_code }
|
62
|
-
tilt_haml_pretty= Tilt::HamlTemplate.new(:
|
63
|
-
tilt_haml_ugly = Tilt::HamlTemplate.new(:
|
64
|
-
tilt_slim_pretty= Slim::Template.new(:
|
62
|
+
tilt_haml_pretty= Tilt::HamlTemplate.new(format: :html5){ @haml_code }
|
63
|
+
tilt_haml_ugly = Tilt::HamlTemplate.new(format: :html5, ugly: true){ @haml_code }
|
64
|
+
tilt_slim_pretty= Slim::Template.new(pretty: true) { @slim_code }
|
65
65
|
tilt_slim_ugly = Slim::Template.new { @slim_code }
|
66
66
|
|
67
67
|
context = Context.new
|
@@ -83,10 +83,10 @@ class SlimBenchmarks
|
|
83
83
|
bench('(3) erubis') { Erubis::Eruby.new(@erb_code).result(context_binding) }
|
84
84
|
bench('(3) fast erubis') { Erubis::FastEruby.new(@erb_code).result(context_binding) }
|
85
85
|
bench('(3) temple erb') { Temple::ERB::Template.new { @erb_code }.render(context) }
|
86
|
-
bench('(3) slim pretty') { Slim::Template.new(:
|
86
|
+
bench('(3) slim pretty') { Slim::Template.new(pretty: true) { @slim_code }.render(context) }
|
87
87
|
bench('(3) slim ugly') { Slim::Template.new { @slim_code }.render(context) }
|
88
|
-
bench('(3) haml pretty') { Haml::Engine.new(@haml_code, :
|
89
|
-
bench('(3) haml ugly') { Haml::Engine.new(@haml_code, :
|
88
|
+
bench('(3) haml pretty') { Haml::Engine.new(@haml_code, format: :html5).render(context) }
|
89
|
+
bench('(3) haml ugly') { Haml::Engine.new(@haml_code, format: :html5, ugly: true).render(context) }
|
90
90
|
end
|
91
91
|
|
92
92
|
def run
|
data/benchmarks/view.slim
CHANGED
data/doc/jp/logic_less.md
CHANGED
@@ -34,7 +34,7 @@ Mustache のように, Slim はラムダ式をサポートします。
|
|
34
34
|
ラムダ式は次のように定義できます:
|
35
35
|
|
36
36
|
def lambda_method
|
37
|
-
"<div class='person'>#{yield(:
|
37
|
+
"<div class='person'>#{yield(name: 'Andrew')}</div>"
|
38
38
|
end
|
39
39
|
|
40
40
|
任意に 1 つ以上のハッシュを `yield` に渡すことができます。複数のハッシュを渡した場合, 先述したようにブロックが繰り返されます。
|
@@ -65,7 +65,7 @@ Mustache のように, Slim はラムダ式をサポートします。
|
|
65
65
|
辞書オブジェクトを与え,
|
66
66
|
|
67
67
|
{
|
68
|
-
:
|
68
|
+
article: [
|
69
69
|
'Article 1',
|
70
70
|
'Article 2'
|
71
71
|
]
|
@@ -94,17 +94,17 @@ Mustache のように, Slim はラムダ式をサポートします。
|
|
94
94
|
|
95
95
|
require で指定:
|
96
96
|
|
97
|
-
gem 'slim', :
|
97
|
+
gem 'slim', require: 'slim/logic_less'
|
98
98
|
|
99
99
|
特定のアクションでのみロジックレスモードを有効化したい場合, まず設定でロジックレスモードを global に無効化します。
|
100
100
|
|
101
|
-
Slim::Engine.
|
101
|
+
Slim::Engine.set_options logic_less: false
|
102
102
|
|
103
103
|
さらに, アクションの中でレンダリングする度にロジックレスモードを有効化します。
|
104
104
|
|
105
105
|
class Controller
|
106
106
|
def action
|
107
|
-
Slim::Engine.with_options(:
|
107
|
+
Slim::Engine.with_options(logic_less: true) do
|
108
108
|
render
|
109
109
|
end
|
110
110
|
end
|
@@ -120,12 +120,12 @@ Sinatra には Slim のビルトインサポートがあります。しなけれ
|
|
120
120
|
|
121
121
|
特定のアクションでのみロジックレスモードを有効化したい場合, まず設定でロジックレスモードを global に無効化します。
|
122
122
|
|
123
|
-
Slim::Engine.
|
123
|
+
Slim::Engine.set_options logic_less: false
|
124
124
|
|
125
125
|
さらに, アクションの中でレンダリングする度にロジックレスモードを有効化します。
|
126
126
|
|
127
127
|
get '/page'
|
128
|
-
slim :page, :
|
128
|
+
slim :page, logic_less: true
|
129
129
|
end
|
130
130
|
|
131
131
|
## オプション
|
data/doc/logic_less.md
CHANGED
@@ -34,7 +34,7 @@ Like mustache, Slim supports lambdas.
|
|
34
34
|
The lambda method could be defined like this
|
35
35
|
|
36
36
|
def lambda_method
|
37
|
-
"<div class='person'>#{yield(:
|
37
|
+
"<div class='person'>#{yield(name: 'Andrew')}</div>"
|
38
38
|
end
|
39
39
|
|
40
40
|
You can optionally pass one or more hashes to `yield`. If you pass multiple hashes, the block will be iterated as described above.
|
@@ -65,7 +65,7 @@ The `self` keyword will return the `.to_s` value for the element under considera
|
|
65
65
|
Given
|
66
66
|
|
67
67
|
{
|
68
|
-
:
|
68
|
+
article: [
|
69
69
|
'Article 1',
|
70
70
|
'Article 2'
|
71
71
|
]
|
@@ -94,17 +94,17 @@ Install:
|
|
94
94
|
|
95
95
|
Require:
|
96
96
|
|
97
|
-
gem 'slim', :
|
97
|
+
gem 'slim', require: 'slim/logic_less'
|
98
98
|
|
99
99
|
You might want to activate logic less mode only for a few actions, you should disable logic-less mode globally at first in the configuration
|
100
100
|
|
101
|
-
Slim::Engine.
|
101
|
+
Slim::Engine.set_options logic_less: false
|
102
102
|
|
103
103
|
and activate logic less mode per render call in your action
|
104
104
|
|
105
105
|
class Controller
|
106
106
|
def action
|
107
|
-
Slim::Engine.with_options(:
|
107
|
+
Slim::Engine.with_options(logic_less: true) do
|
108
108
|
render
|
109
109
|
end
|
110
110
|
end
|
@@ -120,12 +120,12 @@ You are then ready to rock!
|
|
120
120
|
|
121
121
|
You might want to activate logic less mode only for a few actions, you should disable logic-less mode globally at first in the configuration
|
122
122
|
|
123
|
-
Slim::Engine.
|
123
|
+
Slim::Engine.set_options logic_less: false
|
124
124
|
|
125
125
|
and activate logic less mode per render call in your application
|
126
126
|
|
127
127
|
get '/page'
|
128
|
-
slim :page, :
|
128
|
+
slim :page, logic_less: true
|
129
129
|
end
|
130
130
|
|
131
131
|
## Options
|
data/lib/slim/command.rb
CHANGED
@@ -2,7 +2,7 @@ require 'slim'
|
|
2
2
|
require 'optparse'
|
3
3
|
|
4
4
|
module Slim
|
5
|
-
Engine.
|
5
|
+
Engine.set_options pretty: false
|
6
6
|
|
7
7
|
# Slim commandline interface
|
8
8
|
# @api private
|
@@ -40,7 +40,7 @@ module Slim
|
|
40
40
|
end
|
41
41
|
|
42
42
|
opts.on('--rails', 'Generate rails compatible code (Implies --compile)') do
|
43
|
-
Engine.
|
43
|
+
Engine.set_options disable_capture: true, generator: Temple::Generators::RailsOutputBuffer
|
44
44
|
@options[:compile] = true
|
45
45
|
end
|
46
46
|
|
@@ -48,23 +48,13 @@ module Slim
|
|
48
48
|
require lib
|
49
49
|
end
|
50
50
|
|
51
|
-
opts.on('-t', '--translator', 'Enable translator plugin') do
|
52
|
-
puts "Deprecated option: Use -r slim/translator"
|
53
|
-
require 'slim/translator'
|
54
|
-
end
|
55
|
-
|
56
|
-
opts.on('-l', '--logic-less', 'Enable logic less plugin') do
|
57
|
-
puts "Deprecated option: Use -r slim/logic_less"
|
58
|
-
require 'slim/logic_less'
|
59
|
-
end
|
60
|
-
|
61
51
|
opts.on('-p', '--pretty', 'Produce pretty html') do
|
62
|
-
Engine.
|
52
|
+
Engine.set_options pretty: true
|
63
53
|
end
|
64
54
|
|
65
55
|
opts.on('-o', '--option name=code', String, 'Set slim option') do |str|
|
66
56
|
parts = str.split('=', 2)
|
67
|
-
Engine.
|
57
|
+
Engine.options[parts.first.gsub(/\A:/, '').to_sym] = eval(parts.last)
|
68
58
|
end
|
69
59
|
|
70
60
|
opts.on_tail('-h', '--help', 'Show this message') do
|
@@ -95,9 +85,9 @@ module Slim
|
|
95
85
|
result =
|
96
86
|
if @options[:erb]
|
97
87
|
require 'slim/erb_converter'
|
98
|
-
ERBConverter.new(:
|
88
|
+
ERBConverter.new(file: @options[:file]).call(@options[:input].read)
|
99
89
|
elsif @options[:compile]
|
100
|
-
Engine.new(:
|
90
|
+
Engine.new(file: @options[:file]).call(@options[:input].read)
|
101
91
|
else
|
102
92
|
Template.new(@options[:file]) { @options[:input].read }.render
|
103
93
|
end
|
data/lib/slim/embedded.rb
CHANGED
@@ -136,10 +136,7 @@ module Slim
|
|
136
136
|
tilt_options = options[engine.to_sym] || {}
|
137
137
|
[:multi, tilt_render(tilt_engine, tilt_options, collect_text(body)), collect_newlines(body)]
|
138
138
|
end
|
139
|
-
end
|
140
139
|
|
141
|
-
# Tilt-based static template (evaluated at compile-time)
|
142
|
-
class StaticTiltEngine < TiltEngine
|
143
140
|
protected
|
144
141
|
|
145
142
|
def tilt_render(tilt_engine, tilt_options, text)
|
@@ -155,8 +152,8 @@ module Slim
|
|
155
152
|
|
156
153
|
def tilt_render(tilt_engine, tilt_options, text)
|
157
154
|
text = tilt_engine.new(tilt_options.merge(
|
158
|
-
:
|
159
|
-
:
|
155
|
+
style: options[:pretty] ? :expanded : :compressed,
|
156
|
+
cache: false)) { text }.render
|
160
157
|
text.chomp!
|
161
158
|
[:static, text]
|
162
159
|
end
|
@@ -229,7 +226,7 @@ module Slim
|
|
229
226
|
class JavaScriptEngine < TagEngine
|
230
227
|
disable_option_validator!
|
231
228
|
|
232
|
-
|
229
|
+
set_options tag: :script, attributes: { type: 'text/javascript' }
|
233
230
|
|
234
231
|
def on_slim_embedded(engine, body)
|
235
232
|
super(engine, [:html, :js, body])
|
@@ -254,12 +251,12 @@ module Slim
|
|
254
251
|
register :org, InterpolateTiltEngine
|
255
252
|
|
256
253
|
# These engines are executed at compile time
|
257
|
-
register :coffee, JavaScriptEngine, :
|
258
|
-
register :opal, JavaScriptEngine, :
|
259
|
-
register :less, TagEngine, :
|
260
|
-
register :styl, TagEngine, :
|
261
|
-
register :sass, TagEngine, :pretty, :
|
262
|
-
register :scss, TagEngine, :pretty, :
|
254
|
+
register :coffee, JavaScriptEngine, engine: TiltEngine
|
255
|
+
register :opal, JavaScriptEngine, engine: TiltEngine
|
256
|
+
register :less, TagEngine, tag: :style, attributes: { type: 'text/css' }, engine: TiltEngine
|
257
|
+
register :styl, TagEngine, tag: :style, attributes: { type: 'text/css' }, engine: TiltEngine
|
258
|
+
register :sass, TagEngine, :pretty, tag: :style, attributes: { type: 'text/css' }, engine: SassEngine
|
259
|
+
register :scss, TagEngine, :pretty, tag: :style, attributes: { type: 'text/css' }, engine: SassEngine
|
263
260
|
|
264
261
|
# These engines are precompiled, code is embedded
|
265
262
|
register :erb, ERBEngine
|
@@ -268,7 +265,7 @@ module Slim
|
|
268
265
|
|
269
266
|
# Embedded javascript/css
|
270
267
|
register :javascript, JavaScriptEngine
|
271
|
-
register :css, TagEngine, :
|
268
|
+
register :css, TagEngine, tag: :style, attributes: { type: 'text/css' }
|
272
269
|
|
273
270
|
# Embedded ruby code
|
274
271
|
register :ruby, RubyEngine
|
data/lib/slim/engine.rb
CHANGED
@@ -5,37 +5,35 @@ module Slim
|
|
5
5
|
# This overwrites some Temple default options or sets default options for Slim specific filters.
|
6
6
|
# It is recommended to set the default settings only once in the code and avoid duplication. Only use
|
7
7
|
# `define_options` when you have to override some default settings.
|
8
|
-
define_options :
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
define_deprecated_options :attr_delims
|
8
|
+
define_options pretty: false,
|
9
|
+
sort_attrs: true,
|
10
|
+
format: :xhtml,
|
11
|
+
attr_quote: '"',
|
12
|
+
merge_attrs: {'class' => ' '},
|
13
|
+
generator: Temple::Generators::ArrayBuffer,
|
14
|
+
default_tag: 'div'
|
16
15
|
|
17
|
-
filter :Encoding
|
16
|
+
filter :Encoding
|
18
17
|
filter :RemoveBOM
|
19
|
-
use Slim::Parser
|
20
|
-
use Slim::Embedded
|
18
|
+
use Slim::Parser
|
19
|
+
use Slim::Embedded
|
21
20
|
use Slim::Interpolation
|
22
|
-
use Slim::Splat::Filter
|
21
|
+
use Slim::Splat::Filter
|
23
22
|
use Slim::DoInserter
|
24
23
|
use Slim::EndInserter
|
25
|
-
use Slim::Controls
|
26
|
-
html :AttributeSorter
|
27
|
-
html :AttributeMerger
|
28
|
-
use Slim::CodeAttributes
|
29
|
-
use(:AttributeRemover) { Temple::HTML::AttributeRemover.new(:
|
30
|
-
html :Pretty
|
31
|
-
filter :Escapable
|
24
|
+
use Slim::Controls
|
25
|
+
html :AttributeSorter
|
26
|
+
html :AttributeMerger
|
27
|
+
use Slim::CodeAttributes
|
28
|
+
use(:AttributeRemover) { Temple::HTML::AttributeRemover.new(remove_empty_attrs: options[:merge_attrs].keys) }
|
29
|
+
html :Pretty
|
30
|
+
filter :Escapable
|
32
31
|
filter :ControlFlow
|
33
32
|
filter :MultiFlattener
|
34
|
-
|
35
|
-
|
36
|
-
end
|
33
|
+
filter :StaticMerger
|
34
|
+
filter :StaticFreezer
|
37
35
|
use :Generator do
|
38
|
-
options[:generator].new(options.to_hash.reject {|k,v| !options[:generator].
|
36
|
+
options[:generator].new(options.to_hash.reject {|k,v| !options[:generator].options.valid_key?(k) })
|
39
37
|
end
|
40
38
|
end
|
41
39
|
end
|
data/lib/slim/erb_converter.rb
CHANGED
data/lib/slim/include.rb
CHANGED
@@ -7,7 +7,7 @@ module Slim
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class Include < Slim::Filter
|
10
|
-
define_options :file, :
|
10
|
+
define_options :file, include_dirs: [Dir.pwd, '.']
|
11
11
|
|
12
12
|
def on_html_tag(tag, attributes, content)
|
13
13
|
return super if tag != 'include'
|
@@ -35,7 +35,7 @@ module Slim
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class Engine
|
38
|
-
after Slim::Parser, Slim::Include
|
38
|
+
after Slim::Parser, Slim::Include
|
39
39
|
after Slim::Include, :stop do |exp|
|
40
40
|
throw :stop, exp if Thread.current[:slim_include_level] > 1
|
41
41
|
exp
|
data/lib/slim/logic_less.rb
CHANGED
@@ -2,5 +2,4 @@ require 'slim'
|
|
2
2
|
require 'slim/logic_less/filter'
|
3
3
|
require 'slim/logic_less/context'
|
4
4
|
|
5
|
-
|
6
|
-
Slim::Engine.after(Slim::Interpolation, Slim::LogicLess, :logic_less, :dictionary, :dictionary_access)
|
5
|
+
Slim::Engine.after Slim::Interpolation, Slim::LogicLess
|
@@ -6,9 +6,9 @@ module Slim
|
|
6
6
|
# Default dictionary access order, change it with the option :dictionary_access
|
7
7
|
DEFAULT_ACCESS_ORDER = [:symbol, :string, :method, :instance_variable].freeze
|
8
8
|
|
9
|
-
define_options :
|
10
|
-
:
|
11
|
-
:
|
9
|
+
define_options logic_less: true,
|
10
|
+
dictionary: 'self',
|
11
|
+
dictionary_access: DEFAULT_ACCESS_ORDER
|
12
12
|
|
13
13
|
def initialize(opts = {})
|
14
14
|
super
|
data/lib/slim/parser.rb
CHANGED
@@ -5,18 +5,21 @@ module Slim
|
|
5
5
|
class Parser < Temple::Parser
|
6
6
|
define_options :file,
|
7
7
|
:default_tag,
|
8
|
-
:
|
9
|
-
:
|
10
|
-
|
11
|
-
|
12
|
-
'
|
13
|
-
'.' => { :attr => 'class' }
|
8
|
+
tabsize: 4,
|
9
|
+
code_attr_delims: {
|
10
|
+
'(' => ')',
|
11
|
+
'[' => ']',
|
12
|
+
'{' => '}',
|
14
13
|
},
|
15
|
-
:
|
14
|
+
attr_list_delims: {
|
16
15
|
'(' => ')',
|
17
16
|
'[' => ']',
|
18
17
|
'{' => '}',
|
19
|
-
|
18
|
+
},
|
19
|
+
shortcut: {
|
20
|
+
'#' => { attr: 'id' },
|
21
|
+
'.' => { attr: 'class' }
|
22
|
+
}
|
20
23
|
|
21
24
|
class SyntaxError < StandardError
|
22
25
|
attr_reader :error, :file, :line, :lineno, :column
|
@@ -42,8 +45,8 @@ module Slim
|
|
42
45
|
|
43
46
|
def initialize(opts = {})
|
44
47
|
super
|
45
|
-
@attr_list_delims = options[:attr_list_delims]
|
46
|
-
@code_attr_delims = options[:code_attr_delims]
|
48
|
+
@attr_list_delims = options[:attr_list_delims]
|
49
|
+
@code_attr_delims = options[:code_attr_delims]
|
47
50
|
tabsize = options[:tabsize]
|
48
51
|
if tabsize > 1
|
49
52
|
@tab_re = /\G((?: {#{tabsize}})*) {0,#{tabsize-1}}\t/
|
@@ -58,13 +61,13 @@ module Slim
|
|
58
61
|
@tag_shortcut[k] = v[:tag] || options[:default_tag]
|
59
62
|
if v.include?(:attr)
|
60
63
|
@attr_shortcut[k] = [v[:attr]].flatten
|
61
|
-
raise ArgumentError, 'You can only use special characters for attribute shortcuts' if k =~ /(
|
64
|
+
raise ArgumentError, 'You can only use special characters for attribute shortcuts' if k =~ /(\p{Word}|-)/
|
62
65
|
end
|
63
66
|
end
|
64
67
|
keys = Regexp.union @attr_shortcut.keys.sort_by {|k| -k.size }
|
65
|
-
@attr_shortcut_re = /\A(#{keys}+)((
|
68
|
+
@attr_shortcut_re = /\A(#{keys}+)((?:\p{Word}|-)*)/
|
66
69
|
keys = Regexp.union @tag_shortcut.keys.sort_by {|k| -k.size }
|
67
|
-
@tag_re = /\A(?:#{keys}|\*(?=[^\s]+)|(
|
70
|
+
@tag_re = /\A(?:#{keys}|\*(?=[^\s]+)|(\p{Word}(?:\p{Word}|:|-)*\p{Word}|\p{Word}+))/
|
68
71
|
keys = Regexp.escape @code_attr_delims.keys.join
|
69
72
|
@code_attr_delims_re = /\A[#{keys}]/
|
70
73
|
keys = Regexp.escape @attr_list_delims.keys.join
|
@@ -89,9 +92,7 @@ module Slim
|
|
89
92
|
|
90
93
|
protected
|
91
94
|
|
92
|
-
|
93
|
-
LC_WORD_RE = '[_a-z0-9]'
|
94
|
-
ATTR_NAME = "\\A\\s*(#{WORD_RE}(?:#{WORD_RE}|:|-)*)"
|
95
|
+
ATTR_NAME = '\\A\\s*(\p{Word}(?:\p{Word}|:|-)*)'
|
95
96
|
QUOTED_ATTR_RE = /#{ATTR_NAME}\s*=(=?)\s*("|')/
|
96
97
|
CODE_ATTR_RE = /#{ATTR_NAME}\s*=(=?)\s*/
|
97
98
|
|
@@ -221,7 +222,11 @@ module Slim
|
|
221
222
|
# Found an output block.
|
222
223
|
# We expect the line to be broken or the next line to be indented.
|
223
224
|
@line = $'
|
224
|
-
trailing_ws = $2.include?('
|
225
|
+
trailing_ws = $2.include?('>')
|
226
|
+
if $2.include?('\'')
|
227
|
+
deprecated_syntax '=\' for trailing whitespace is deprecated in favor of =>'
|
228
|
+
trailing_ws = true
|
229
|
+
end
|
225
230
|
block = [:multi]
|
226
231
|
@stacks.last << [:static, ' '] if $2.include?('<')
|
227
232
|
@stacks.last << [:slim, :output, $1.empty?, parse_broken_line, block]
|
@@ -324,7 +329,12 @@ module Slim
|
|
324
329
|
|
325
330
|
@line =~ /\A[<>']*/
|
326
331
|
@line = $'
|
327
|
-
trailing_ws = $&.include?('
|
332
|
+
trailing_ws = $&.include?('>')
|
333
|
+
if $&.include?('\'')
|
334
|
+
deprecated_syntax 'tag\' for trailing whitespace is deprecated in favor of tag>'
|
335
|
+
trailing_ws = true
|
336
|
+
end
|
337
|
+
|
328
338
|
leading_ws = $&.include?('<')
|
329
339
|
|
330
340
|
parse_attributes(attributes)
|
@@ -354,7 +364,11 @@ module Slim
|
|
354
364
|
when /\A\s*=(=?)(['<>]*)/
|
355
365
|
# Handle output code
|
356
366
|
@line = $'
|
357
|
-
trailing_ws2 = $2.include?('
|
367
|
+
trailing_ws2 = $2.include?('>')
|
368
|
+
if $2.include?('\'')
|
369
|
+
deprecated_syntax '=\' for trailing whitespace is deprecated in favor of =>'
|
370
|
+
trailing_ws2 = true
|
371
|
+
end
|
358
372
|
block = [:multi]
|
359
373
|
@stacks.last.insert(-2, [:static, ' ']) if !leading_ws && $2.include?('<')
|
360
374
|
tag << [:slim, :output, $1 != '=', parse_broken_line, block]
|
@@ -495,6 +509,16 @@ module Slim
|
|
495
509
|
raise
|
496
510
|
end
|
497
511
|
|
512
|
+
def deprecated_syntax(message)
|
513
|
+
line = @orig_line.lstrip
|
514
|
+
column = (@orig_line && @line ? @orig_line.size - @line.size : 0) + line.size - @orig_line.size
|
515
|
+
warn %{Deprecated syntax: #{message}
|
516
|
+
#{options[:file]}, Line #{@lineno}, Column #{@column}
|
517
|
+
#{line}
|
518
|
+
#{' ' * column}^
|
519
|
+
}
|
520
|
+
end
|
521
|
+
|
498
522
|
def expect_next_line
|
499
523
|
next_line || syntax_error!('Unexpected end of file')
|
500
524
|
@line.strip!
|