slim 2.1.0 → 3.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- 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!
|