slim 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- slim (0.7.0)
5
- temple (~> 0.1.4)
4
+ slim (0.7.2)
5
+ temple (~> 0.1.5)
6
6
  tilt (~> 1.1)
7
7
 
8
8
  GEM
@@ -17,7 +17,7 @@ GEM
17
17
  rake (0.8.7)
18
18
  rcov (0.9.9)
19
19
  rdiscount (1.6.5)
20
- temple (0.1.4)
20
+ temple (0.1.5)
21
21
  tilt (1.1)
22
22
  yard (0.6.1)
23
23
 
@@ -33,6 +33,6 @@ DEPENDENCIES
33
33
  rcov
34
34
  rdiscount
35
35
  slim!
36
- temple (~> 0.1.4)
36
+ temple (~> 0.1.5)
37
37
  tilt (~> 1.1)
38
38
  yard
data/README.md CHANGED
@@ -86,8 +86,6 @@ Here's a quick example to demonstrate what a Slim template looks like:
86
86
 
87
87
  ### Line indicators
88
88
 
89
- __Please note that all line indicators must be followed by a space__
90
-
91
89
  #### `|`
92
90
 
93
91
  > The pipe tells Slim to just copy the line. It essentially escapes any processing.
@@ -148,7 +146,7 @@ __Please note that all line indicators must be followed by a space__
148
146
  body
149
147
  h1 id="headline" Welcome to my site.
150
148
 
151
- Or nest it. __Note:__ Must use a pipe or a backtick (followed by a space) to escape processing
149
+ Or nest it. __Note:__ Must use a pipe or a backtick to escape processing
152
150
 
153
151
  body
154
152
  h1 id="headline"
@@ -19,15 +19,42 @@ let b:ruby_no_expensive = 1
19
19
 
20
20
  " Include Ruby syntax highlighting
21
21
  syn include @slimRuby syntax/ruby.vim
22
+ unlet! b:current_syntax
23
+ " Include Haml syntax highlighting
24
+ syn include @slimHaml syntax/haml.vim
25
+ unlet! b:current_syntax
26
+ " Include Erb syntax highlighting
27
+ syn include @slimErb syntax/eruby.vim
28
+ unlet! b:current_syntax
22
29
 
23
30
  " Include HTML
24
31
  runtime! syntax/html.vim
25
32
  unlet! b:current_syntax
26
33
 
27
- syntax region slimHtml start="^\s*[^-=]\w" end="$" contains=htmlTagName, htmlArg, htmlString
34
+ setlocal iskeyword+=:
35
+
36
+
37
+ syn region slimHtml start="^\s*[^-=]\w" end="$" contains=htmlTagName,htmlArg,htmlString
38
+ syn region slimControl start="-" end="$" contains=@slimRuby keepend
39
+
40
+ syn match slimFilter /\s*\w\+:\s*/ contained
41
+
42
+ syn match slimCode /^\s*[-=#.].*/ contained
43
+ syn match slimComment /^\(\s\+\)[/].*\(\n\1\s.*\)*/
44
+ syn match slimText /^\(\s\+\)[`|'].*\(\n\1\s.*\)*/
45
+
46
+ syn match slimJs /^\(\s\+\)\<javascript:\>.*\(\n\1\s.*\)*/ contains=@htmlJavaScript,slimFilter
47
+ syn match slimHaml /^\(\s\+\)\<haml:\>.*\(\n\1\s.*\)*/ contains=@slimHaml,slimFilter
48
+ syn match slimHaml /^\(\s\+\)\<erb:\>.*\(\n\1\s.*\)*/ contains=@slimErb,slimFilter
49
+
50
+
51
+ "syn match slimFilter /\s*\<javascript:\>\s*/
52
+
28
53
 
29
- syntax region slimControl start="-" end="$" contains=@slimRuby keepend
30
- syntax region slimOutput start=".*=\s" end="$" contains=@slimRuby keepend
54
+ "contained containedin=slimJs
31
55
 
56
+ hi def link slimText String
57
+ hi def link slimComment Comment
58
+ hi def link slimFilter Special
32
59
 
33
60
  let b:current_syntax = "slim"
@@ -9,15 +9,21 @@ html
9
9
  alert('Hello World');
10
10
  });
11
11
 
12
+ haml:
13
+ #someid.someclass{:this => 'test'} Content in haml
14
+
15
+ erb:
16
+ <%= some_method(@request) %>
17
+
12
18
  body
13
19
  / comment block
14
20
  with multiple lines
15
-
21
+ This is another line
16
22
  h1 = @page_title
17
23
  p#notice.message
18
24
  | Welcome to the the syntax test.
19
25
  This file is to excercise the various markup.
20
-
26
+ This is another line
21
27
  - unless @users.empty?
22
28
  table
23
29
  - for user in users do
@@ -26,6 +32,7 @@ html
26
32
  - else
27
33
  p There are no users.
28
34
 
35
+ / Single comment line
29
36
  #content Hello #{@user.name}! Welcome to the test page!
30
37
  Try out Slim!
31
38
 
@@ -5,6 +5,8 @@ require 'slim/parser'
5
5
  require 'slim/filter'
6
6
  require 'slim/end_inserter'
7
7
  require 'slim/embedded_engine'
8
+ require 'slim/interpolation'
9
+ require 'slim/sections'
8
10
  require 'slim/compiler'
9
11
  require 'slim/engine'
10
12
  require 'slim/template'
@@ -40,6 +40,14 @@ module Slim
40
40
  @options[:compile] = true
41
41
  end
42
42
 
43
+ opts.on('-S', '--sections', :NONE, 'Logic-less sections mode') do
44
+ @options[:sections] = true
45
+ end
46
+
47
+ opts.on('-p', '--pretty', :NONE, 'Produce pretty html') do
48
+ @options[:pretty] = true
49
+ end
50
+
43
51
  opts.on_tail('-h', '--help', 'Show this message') do
44
52
  puts opts
45
53
  exit
@@ -71,9 +79,13 @@ module Slim
71
79
  end
72
80
 
73
81
  if @options[:compile]
74
- @options[:output].puts(Slim::Engine.new(:file => @options[:file]).compile(@options[:input].read))
82
+ @options[:output].puts(Slim::Engine.new(:file => @options[:file],
83
+ :pretty => @options[:pretty],
84
+ :sections => @options[:sections]).compile(@options[:input].read))
75
85
  else
76
- @options[:output].puts(Slim::Template.new(@options[:file]) { @options[:input].read }.render)
86
+ @options[:output].puts(Slim::Template.new(@options[:file],
87
+ :pretty => @options[:pretty],
88
+ :sections => @options[:sections]) { @options[:input].read }.render)
77
89
  end
78
90
  end
79
91
  end
@@ -2,31 +2,6 @@ module Slim
2
2
  # Compiles Slim expressions into Temple::HTML expressions.
3
3
  # @api private
4
4
  class Compiler < Filter
5
- # Handle text expression `[:slim, :text, string]`
6
- #
7
- # @param [String] string Static text
8
- # @return [Array] Compiled temple expression
9
- def on_slim_text(string)
10
- # Interpolate variables in text (#{variable}).
11
- # Split the text into multiple dynamic and static parts.
12
- block = [:multi]
13
- until string.empty?
14
- case string
15
- when /^\\(\#\{[^\}]*\})/
16
- # Escaped interpolation
17
- block << [:static, $1]
18
- when /^\#\{([^\}]*)\}/
19
- # Interpolation
20
- block << [:escape, :dynamic, $1]
21
- when /^([^\#]+|\#)/
22
- # Static text
23
- block << [:static, $&]
24
- end
25
- string = $'
26
- end
27
- block
28
- end
29
-
30
5
  # Handle control expression `[:slim, :control, code, content]`
31
6
  #
32
7
  # @param [String] ruby code
@@ -60,7 +35,7 @@ module Slim
60
35
  # @param [Array] content Temple expression
61
36
  # @return [Array] Compiled temple expression
62
37
  def on_slim_output_block(escape, code, content)
63
- tmp1, tmp2 = tmp_var, tmp_var
38
+ tmp1, tmp2 = tmp_var('capture'), tmp_var('capture')
64
39
 
65
40
  [:multi,
66
41
  # Capture the result of the code in a variable. We can't do
@@ -94,32 +69,22 @@ module Slim
94
69
  end
95
70
  end
96
71
 
97
- # Handle tag expression `[:slim, :tag, name, attrs, content]`
72
+ # Handle tag expression `[:slim, :tag, name, attrs, closed, content]`
98
73
  #
99
74
  # @param [String] name Tag name
100
75
  # @param [Array] attrs Attributes
101
76
  # @param [Array] content Temple expression
102
77
  # @return [Array] Compiled temple expression
103
78
  def on_slim_tag(name, attrs, closed, content)
104
- attrs = attrs.inject([:html, :staticattrs]) do |m, (key, dynamic, value)|
105
- value = if dynamic
106
- [:escape, :dynamic, value]
107
- else
108
- on_slim_text(value)
109
- end
110
- m << [key.to_s, value]
111
- end
112
- [:html, :tag, name, attrs, closed, compile!(content)]
79
+ [:html, :tag, name, compile!(attrs), closed, compile!(content)]
113
80
  end
114
81
 
115
- private
116
-
117
- # Generate unique temporary variable name
82
+ # Handle tag attributes expression `[:slim, :attrs, *attrs]`
118
83
  #
119
- # @return [String] Variable name
120
- def tmp_var
121
- @tmp_var ||= 0
122
- "_slimtmp#{@tmp_var += 1}"
84
+ # @param [Array] attrs Attributes
85
+ # @return [Array] Compiled temple expression
86
+ def on_slim_attrs(*attrs)
87
+ [:html, :staticattrs, *attrs.map {|k, v| [k.to_s, compile!(v)] }]
123
88
  end
124
89
  end
125
90
  end
@@ -64,7 +64,7 @@ module Slim
64
64
  class TagEngine < EmbeddedEngine
65
65
  def on_slim_embedded(engine, *body)
66
66
  content = options[:engine] ? options[:engine].new.on_slim_embedded(engine, *body) : [:multi, *body]
67
- [:slim, :tag, options[:tag], options[:attributes].map {|k, v| [k, false, v] }, false, content]
67
+ [:slim, :tag, options[:tag], [:slim, :attrs, *options[:attributes].map {|k, v| [k, [:static, v]] }], false, content]
68
68
  end
69
69
  end
70
70
 
@@ -2,17 +2,24 @@ module Slim
2
2
  # Slim engine which transforms slim code to executable ruby code
3
3
  # @api public
4
4
  class Engine < Temple::Engine
5
+ # Allow users to set default options, particularly useful in Rails' environment files.
6
+ # For instance, in config/environments/development.rb you probably want:
7
+ # # Indent html for pretty debugging
8
+ # Slim::Engine.set_default_options :pretty => true
9
+ #
10
+ set_default_options :pretty => false,
11
+ :attr_wrapper => '"',
12
+ :format => :html5,
13
+ :id_delimiter => nil
14
+
5
15
  use Slim::Parser, :file
6
- filter :Debugger, :debug, :prefix => 'before end insertion'
7
- use Slim::EndInserter
8
- filter :Debugger, :debug, :prefix => 'after end insertion'
9
16
  use Slim::EmbeddedEngine
17
+ use Slim::Interpolation
18
+ use Slim::Sections, :sections, :dictionary, :dictionary_access
19
+ use Slim::EndInserter
10
20
  use Slim::Compiler
11
- filter :Debugger, :debug, :prefix => 'after compilation'
12
21
  filter :EscapeHTML, :use_html_safe
13
- use Temple::HTML::Pretty, :format, :attr_wrapper, :id_delimiter, :id_concat, :pretty,
14
- :pretty => false, :attr_wrapper => '"', :format => :html5, :id_delimiter => nil
15
- filter :Debugger, :debug, :prefix => 'after html'
22
+ use Temple::HTML::Pretty, :format, :attr_wrapper, :id_delimiter, :pretty
16
23
  filter :MultiFlattener
17
24
  filter :StaticMerger
18
25
  filter :DynamicInliner
@@ -2,6 +2,7 @@ module Slim
2
2
  # Base class for Temple filters used in Slim
3
3
  # @api private
4
4
  class Filter < Temple::Filter
5
+ # Dispatch on_slim_*
5
6
  temple_dispatch :slim
6
7
 
7
8
  def on_slim_control(code, content)
@@ -13,7 +14,19 @@ module Slim
13
14
  end
14
15
 
15
16
  def on_slim_tag(name, attrs, closed, content)
16
- [:slim, :tag, name, attrs, closed, compile!(content)]
17
+ [:slim, :tag, name, compile!(attrs), closed, compile!(content)]
18
+ end
19
+
20
+ def on_slim_attrs(*attrs)
21
+ [:slim, :attrs, *attrs.map {|k, v| [k, compile!(v)] }]
22
+ end
23
+
24
+ # Generate unique temporary variable name
25
+ #
26
+ # @return [String] Variable name
27
+ def tmp_var(prefix)
28
+ @tmp_var ||= 0
29
+ "_slim#{prefix}#{@tmp_var += 1}"
17
30
  end
18
31
  end
19
32
  end
@@ -0,0 +1,30 @@
1
+ module Slim
2
+ # Perform interpolation of #{var_name}
3
+ # @api private
4
+ class Interpolation < Filter
5
+ # Handle text expression `[:slim, :text, string]`
6
+ #
7
+ # @param [String] string Static text
8
+ # @return [Array] Compiled temple expression
9
+ def on_slim_text(string)
10
+ # Interpolate variables in text (#{variable}).
11
+ # Split the text into multiple dynamic and static parts.
12
+ block = [:multi]
13
+ until string.empty?
14
+ case string
15
+ when /^\\(\#\{[^\}]*\})/
16
+ # Escaped interpolation
17
+ block << [:static, $1]
18
+ when /^\#\{([^\}]*)\}/
19
+ # Interpolation
20
+ block << [:slim, :output, true, $1, [:multi]]
21
+ when /^([^\#]+|\#)/
22
+ # Static text
23
+ block << [:static, $&]
24
+ end
25
+ string = $'
26
+ end
27
+ block
28
+ end
29
+ end
30
+ end
@@ -259,11 +259,11 @@ module Slim
259
259
  # Now we'll have to find all the attributes. We'll store these in an
260
260
  # nested array: [[name, value], [name2, value2]]. The value is a piece
261
261
  # of Ruby code.
262
- attributes = []
262
+ attributes = [:slim, :attrs]
263
263
 
264
264
  # Find any literal class/id attributes
265
265
  while line =~ CLASS_ID_REGEX
266
- attributes << [ATTR_SHORTHAND[$1], false, $2]
266
+ attributes << [ATTR_SHORTHAND[$1], [:static, $2]]
267
267
  line = $'
268
268
  end
269
269
 
@@ -282,11 +282,11 @@ module Slim
282
282
  if line =~ QUOTED_VALUE_REGEX
283
283
  # Value is quoted (static)
284
284
  line = $'
285
- attributes << [key, false, $1[1..-2]]
285
+ attributes << [key, [:slim, :text, $1[1..-2]]]
286
286
  else
287
287
  # Value is ruby code
288
288
  line, value = parse_ruby_attribute(orig_line, line, lineno, delimiter)
289
- attributes << [key, true, value]
289
+ attributes << [key, [:slim, :output, true, value, [:multi]]]
290
290
  end
291
291
  end
292
292
 
@@ -2,12 +2,23 @@ require 'slim'
2
2
 
3
3
  module ActionView
4
4
  module TemplateHandlers
5
- # Slim handler for Rails 3
6
- class SlimHandler < TemplateHandler
7
- include Compilable
5
+ raise "Slim supports only Rails 3.x and greater, your Rails version is #{Rails::VERSION::STRING}" if Rails::VERSION::MAJOR < 3
8
6
 
9
- def compile(template)
10
- Slim::Engine.new(:use_html_safe => true).compile(template.source)
7
+ if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR < 1
8
+ # Slim handler for Rails 3.0
9
+ class SlimHandler < TemplateHandler
10
+ include Compilable
11
+
12
+ def compile(template)
13
+ Slim::Engine.new.compile(template.source)
14
+ end
15
+ end
16
+ else
17
+ # Slim handler for Rails 3.1 and greater
18
+ class SlimHandler
19
+ def call(template)
20
+ Slim::Engine.new.compile(template.source)
21
+ end
11
22
  end
12
23
  end
13
24
  end
@@ -0,0 +1,79 @@
1
+ module Slim
2
+ # Handle logic-less mode
3
+ # This filter can be activated with the option "sections"
4
+ # @api private
5
+ class Sections < Filter
6
+ set_default_options :dictionary => 'self',
7
+ :sections => false,
8
+ :dictionary_access => :symbol # :symbol, :string
9
+
10
+ def initialize(opts = {})
11
+ super
12
+ unless [:string, :symbol].include?(@options[:dictionary_access])
13
+ raise "Invalid dictionary access #{@options[:dictionary_access].inspect}"
14
+ end
15
+ end
16
+
17
+ def compile(exp)
18
+ if options[:sections]
19
+ # Store the dictionary in the _slimdict variable
20
+ [:multi,
21
+ [:block, "_slimdict = #{@options[:dictionary]}"],
22
+ super]
23
+ else
24
+ exp
25
+ end
26
+ end
27
+
28
+ # Interpret control blocks as sections or inverted sections
29
+ def on_slim_control(name, content)
30
+ if name =~ /^!\s*(.*)/
31
+ on_slim_inverted_section($1, content)
32
+ else
33
+ on_slim_section(name, content)
34
+ end
35
+ end
36
+
37
+ def on_slim_inverted_section(name, content)
38
+ tmp = tmp_var('section')
39
+ [:multi,
40
+ [:block, "#{tmp} = #{access name}"],
41
+ [:block, "if !#{tmp} || #{tmp}.respond_to?(:empty) && #{tmp}.empty?"],
42
+ compile!(content),
43
+ [:block, 'end']]
44
+ end
45
+
46
+ def on_slim_section(name, content)
47
+ content = compile!(content)
48
+ tmp1, tmp2 = tmp_var('dict'), tmp_var('dict')
49
+
50
+ [:multi,
51
+ [:block, "if #{tmp1} = #{access name}"],
52
+ [:block, "if #{tmp1} == true"],
53
+ content,
54
+ [:block, 'else'],
55
+ [:block, "#{tmp1} = [#{tmp1}] if #{tmp1}.respond_to?(:has_key?) || !#{tmp1}.respond_to?(:map)"],
56
+ [:block, "#{tmp2} = _slimdict"],
57
+ [:block, "#{tmp1}.each do |_slimdict|"],
58
+ content,
59
+ [:block, 'end'],
60
+ [:block, "_slimdict = #{tmp2}"],
61
+ [:block, 'end'],
62
+ [:block, 'end']]
63
+ end
64
+
65
+ def on_slim_output(escape, name, content)
66
+ raise 'Output statements with content are forbidden in sections mode' if !empty_exp?(content)
67
+ [:slim, :output, escape, access(name), content]
68
+ end
69
+
70
+ def access(name)
71
+ case options[:dictionary_access]
72
+ when :symbol
73
+ "_slimdict[#{name.to_sym.inspect}]"
74
+ when :string
75
+ "_slimdict[#{name.to_s.inspect}]"
76
+ end
77
+ end
78
+ end
79
+ end
@@ -1,3 +1,3 @@
1
1
  module Slim
2
- VERSION = "0.7.1"
2
+ VERSION = "0.7.2"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require File.dirname(__FILE__) + "/lib/slim/version"
3
+ require "date"
3
4
 
4
5
  Gem::Specification.new do |s|
5
6
  s.name = "slim"
@@ -20,7 +21,7 @@ Gem::Specification.new do |s|
20
21
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
22
  s.require_paths = ["lib"]
22
23
 
23
- s.add_runtime_dependency(%q<temple>, ["~> 0.1.4"])
24
+ s.add_runtime_dependency(%q<temple>, ["~> 0.1.5"])
24
25
  s.add_runtime_dependency(%q<tilt>, ["~> 1.1"])
25
26
  s.add_development_dependency(%q<rake>, [">= 0.8.7"])
26
27
  s.add_development_dependency(%q<haml>, [">= 0"])
@@ -20,7 +20,7 @@ class TestSlim < MiniTest::Unit::TestCase
20
20
  end
21
21
 
22
22
  def render(source, options = {}, &block)
23
- Slim::Template.new(options[:file], options) { source }.render(@env, &block)
23
+ Slim::Template.new(options[:file], options) { source }.render(options[:scope] || @env, &block)
24
24
  end
25
25
 
26
26
  def assert_html(expected, source, options = {}, &block)
@@ -0,0 +1,74 @@
1
+ require 'helper'
2
+
3
+ class TestSlimLogicLess < TestSlim
4
+ def test_sections
5
+ source = %q{
6
+ p
7
+ - person
8
+ .name = name
9
+ }
10
+
11
+ hash = {
12
+ :person => [
13
+ { :name => 'Joe', },
14
+ { :name => 'Jack', }
15
+ ]
16
+ }
17
+
18
+ assert_html '<p><div class="name">Joe</div><div class="name">Jack</div></p>', source, :scope => hash, :sections => true
19
+ end
20
+
21
+ def test_sections_string_access
22
+ source = %q{
23
+ p
24
+ - person
25
+ .name = name
26
+ }
27
+
28
+ hash = {
29
+ 'person' => [
30
+ { 'name' => 'Joe', },
31
+ { 'name' => 'Jack', }
32
+ ]
33
+ }
34
+
35
+ assert_html '<p><div class="name">Joe</div><div class="name">Jack</div></p>', source, :scope => hash, :sections => true, :dictionary_access => :string
36
+ end
37
+
38
+ def test_flag_section
39
+ source = %q{
40
+ p
41
+ - show_person
42
+ - person
43
+ .name = name
44
+ - show_person
45
+ | shown
46
+ }
47
+
48
+ hash = {
49
+ :show_person => true,
50
+ :person => [
51
+ { :name => 'Joe', },
52
+ { :name => 'Jack', }
53
+ ]
54
+ }
55
+
56
+ assert_html '<p><div class="name">Joe</div><div class="name">Jack</div>shown</p>', source, :scope => hash, :sections => true
57
+ end
58
+
59
+ def test_inverted_section
60
+ source = %q{
61
+ p
62
+ - person
63
+ .name = name
64
+ -! person
65
+ | No person
66
+ - !person
67
+ | No person 2
68
+ }
69
+
70
+ hash = {}
71
+
72
+ assert_html '<p>No person No person 2</p>', source, :scope => hash, :sections => true
73
+ end
74
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 1
9
- version: 0.7.1
8
+ - 2
9
+ version: 0.7.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Andrew Stone
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-11-03 00:00:00 -04:00
19
+ date: 2010-11-09 00:00:00 -05:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -30,8 +30,8 @@ dependencies:
30
30
  segments:
31
31
  - 0
32
32
  - 1
33
- - 4
34
- version: 0.1.4
33
+ - 5
34
+ version: 0.1.5
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -187,8 +187,10 @@ files:
187
187
  - lib/slim/end_inserter.rb
188
188
  - lib/slim/engine.rb
189
189
  - lib/slim/filter.rb
190
+ - lib/slim/interpolation.rb
190
191
  - lib/slim/parser.rb
191
192
  - lib/slim/rails.rb
193
+ - lib/slim/sections.rb
192
194
  - lib/slim/template.rb
193
195
  - lib/slim/version.rb
194
196
  - slim.gemspec
@@ -203,6 +205,7 @@ files:
203
205
  - test/slim/test_html_structure.rb
204
206
  - test/slim/test_parser_errors.rb
205
207
  - test/slim/test_ruby_errors.rb
208
+ - test/slim/test_sections.rb
206
209
  - test/slim/test_slim_template.rb
207
210
  has_rdoc: true
208
211
  homepage: http://github.com/stonean/slim