skim 0.8.6 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +5 -0
- data/README.md +32 -16
- data/lib/skim.rb +3 -2
- data/lib/skim/code_attributes.rb +66 -0
- data/lib/skim/controls.rb +9 -0
- data/lib/skim/engine.rb +30 -19
- data/lib/skim/interpolation.rb +53 -0
- data/lib/skim/template.rb +7 -4
- data/lib/skim/version.rb +1 -1
- data/lib/temple/coffee_script/filters/attribute_merger.rb +2 -2
- data/lib/temple/coffee_script/filters/attribute_remover.rb +5 -8
- data/lib/temple/coffee_script/filters/escapable.rb +5 -3
- data/lib/temple/coffee_script/generators.rb +3 -4
- data/skim.gemspec +2 -3
- data/test/helper.rb +3 -3
- data/test/test_code_escaping.rb +3 -3
- data/test/test_code_evaluation.rb +10 -123
- data/test/test_html_structure.rb +33 -28
- data/test/test_text_interpolation.rb +4 -3
- data/vendor/assets/javascripts/skim.js.coffee +11 -1
- metadata +26 -49
- data/lib/skim/compiler.rb +0 -36
- data/lib/skim/sections.rb +0 -32
- data/test/test_sections.rb +0 -157
data/History.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Skim [ ![Build status](
|
1
|
+
Skim [ ![Build status](https://travis-ci.org/jfirebaugh/skim.png) ](https://travis-ci.org/jfirebaugh/skim)
|
2
2
|
====
|
3
3
|
|
4
4
|
Take the fat out of your client-side templates with Skim. Skim is the [Slim](http://slim-lang.com/) templating engine
|
@@ -9,17 +9,23 @@ Sprockets-based asset pipeline.
|
|
9
9
|
|
10
10
|
`gem install skim`, or add `skim` to your `Gemfile` in the `:assets` group:
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
```ruby
|
13
|
+
group :assets do
|
14
|
+
gem 'skim'
|
15
|
+
end
|
16
|
+
```
|
15
17
|
|
16
18
|
Create template files with the extension `.jst.skim`. For example, `test.jst.skim`:
|
17
19
|
|
18
|
-
|
20
|
+
```jade
|
21
|
+
p Hello #{@world}!
|
22
|
+
```
|
19
23
|
|
20
24
|
In your JavaScript or CoffeeScript, render the result, passing a context object:
|
21
25
|
|
22
|
-
|
26
|
+
```js
|
27
|
+
$("body").html(JST["test"]({world: "World"}));
|
28
|
+
```
|
23
29
|
|
24
30
|
Order up a skinny latte and enjoy!
|
25
31
|
|
@@ -66,20 +72,26 @@ escaping. In addition, the special `safe` method on the context object tells Ski
|
|
66
72
|
being escaped. You can use this in conjunction with `escape` context method to selectively sanitize parts of the string.
|
67
73
|
For example, given the template:
|
68
74
|
|
69
|
-
|
75
|
+
```jade
|
76
|
+
= @linkTo(@project)
|
77
|
+
```
|
70
78
|
|
71
79
|
you could render it with the following context:
|
72
80
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
81
|
+
```coffeescript
|
82
|
+
JST["my_template"]
|
83
|
+
project: { id: 4, name: "Crate & Barrel" }
|
84
|
+
linkTo: (project) ->
|
85
|
+
url = "/projects/#{project.id}"
|
86
|
+
name = @escape project.name
|
87
|
+
@safe "<a href='#{url}'>#{name}</a>"
|
88
|
+
```
|
79
89
|
|
80
90
|
to produce:
|
81
91
|
|
82
|
-
|
92
|
+
```html
|
93
|
+
<a href='/projects/4'>Crate & Barrel</a>
|
94
|
+
```
|
83
95
|
|
84
96
|
## The Skim asset
|
85
97
|
|
@@ -89,11 +101,15 @@ and setting Skim's `:use_asset` option to true.
|
|
89
101
|
|
90
102
|
In Rails, this can be done by adding the following to `application.js`:
|
91
103
|
|
92
|
-
|
104
|
+
```js
|
105
|
+
//= require skim
|
106
|
+
```
|
93
107
|
|
94
108
|
And the following in an initializer:
|
95
109
|
|
96
|
-
|
110
|
+
```ruby
|
111
|
+
Skim::Engine.default_options[:use_asset] = true
|
112
|
+
```
|
97
113
|
|
98
114
|
# License (MIT)
|
99
115
|
|
data/lib/skim.rb
CHANGED
@@ -2,8 +2,9 @@ require "temple"
|
|
2
2
|
require "temple/coffee_script"
|
3
3
|
|
4
4
|
require "slim"
|
5
|
-
require "skim/
|
6
|
-
require "skim/
|
5
|
+
require "skim/controls"
|
6
|
+
require "skim/code_attributes"
|
7
|
+
require "skim/interpolation"
|
7
8
|
require "skim/engine"
|
8
9
|
require "skim/template"
|
9
10
|
require "skim/version"
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Skim
|
2
|
+
class CodeAttributes < Slim::Filter
|
3
|
+
define_options :merge_attrs
|
4
|
+
|
5
|
+
# Handle attributes expression `[:html, :attrs, *attrs]`
|
6
|
+
#
|
7
|
+
# @param [Array] attrs Array of temple expressions
|
8
|
+
# @return [Array] Compiled temple expression
|
9
|
+
def on_html_attrs(*attrs)
|
10
|
+
[:multi, *attrs.map {|a| compile(a) }]
|
11
|
+
end
|
12
|
+
|
13
|
+
# Handle attribute expression `[:html, :attr, name, value]`
|
14
|
+
#
|
15
|
+
# @param [String] name Attribute name
|
16
|
+
# @param [Array] value Value expression
|
17
|
+
# @return [Array] Compiled temple expression
|
18
|
+
def on_html_attr(name, value)
|
19
|
+
if value[0] == :slim && value[1] == :attrvalue && !options[:merge_attrs][name]
|
20
|
+
# We handle the attribute as a boolean attribute
|
21
|
+
escape, code = value[2], value[3]
|
22
|
+
case code
|
23
|
+
when 'true'
|
24
|
+
[:html, :attr, name, [:static, name]]
|
25
|
+
when 'false', 'null'
|
26
|
+
[:multi]
|
27
|
+
else
|
28
|
+
tmp = unique_name
|
29
|
+
[:multi,
|
30
|
+
[:code, "#{tmp} = #{code}"],
|
31
|
+
[:case, tmp,
|
32
|
+
['true', [:html, :attr, name, [:static, name]]],
|
33
|
+
['false, null', [:multi]],
|
34
|
+
[:else, [:html, :attr, name, [:escape, escape, [:dynamic, tmp]]]]]]
|
35
|
+
end
|
36
|
+
else
|
37
|
+
# Attribute with merging
|
38
|
+
@attr = name
|
39
|
+
return super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Handle attribute expression `[:slim, :attrvalue, escape, code]`
|
44
|
+
#
|
45
|
+
# @param [Boolean] escape Escape html
|
46
|
+
# @param [String] code Ruby code
|
47
|
+
# @return [Array] Compiled temple expression
|
48
|
+
def on_slim_attrvalue(escape, code)
|
49
|
+
# We perform attribute merging on Array values
|
50
|
+
if delimiter = options[:merge_attrs][@attr]
|
51
|
+
tmp = unique_name
|
52
|
+
[:multi,
|
53
|
+
[:code, "#{tmp} = #{code}"],
|
54
|
+
[:if, "@isArray(#{tmp})",
|
55
|
+
[:multi,
|
56
|
+
[:code, "#{tmp} = @flatten(#{tmp})"],
|
57
|
+
[:code, "#{tmp} = item.toString() for item in #{tmp} when item"],
|
58
|
+
[:code, "#{tmp} = item for item in #{tmp} when item.length > 0"],
|
59
|
+
[:escape, escape, [:dynamic, "#{tmp}.join(#{delimiter.inspect})"]]],
|
60
|
+
[:escape, escape, [:dynamic, tmp]]]]
|
61
|
+
else
|
62
|
+
[:escape, escape, [:dynamic, code]]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/skim/engine.rb
CHANGED
@@ -1,27 +1,38 @@
|
|
1
1
|
module Skim
|
2
|
+
# Skim engine which transforms slim code to executable ruby code
|
3
|
+
# @api public
|
2
4
|
class Engine < Temple::Engine
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
# This overwrites some Temple default options or sets default options for Slim specific filters.
|
6
|
+
# It is recommended to set the default settings only once in the code and avoid duplication. Only use
|
7
|
+
# `define_options` when you have to override some default settings.
|
8
|
+
define_options :pretty => false,
|
9
|
+
:sort_attrs => true,
|
10
|
+
:attr_quote => '"',
|
11
|
+
:merge_attrs => {'class' => ' '},
|
12
|
+
:encoding => 'utf-8',
|
13
|
+
:generator => Temple::CoffeeScript::Generator,
|
14
|
+
:default_tag => 'div',
|
15
|
+
:use_asset => false
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
use Slim::
|
15
|
-
use
|
16
|
-
use Skim::
|
17
|
-
use
|
18
|
-
use
|
19
|
-
|
20
|
-
|
21
|
-
use
|
17
|
+
filter :Encoding, :encoding
|
18
|
+
filter :RemoveBOM
|
19
|
+
use Slim::Parser, :file, :tabsize, :shortcut, :default_tag
|
20
|
+
use Slim::Embedded, :enable_engines, :disable_engines, :pretty
|
21
|
+
use Skim::Interpolation
|
22
|
+
use Slim::Splat::Filter, :merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs
|
23
|
+
use Skim::Controls, :disable_capture
|
24
|
+
html :AttributeSorter, :sort_attrs
|
25
|
+
html :AttributeMerger, :merge_attrs
|
26
|
+
use Skim::CodeAttributes, :merge_attrs
|
27
|
+
use(:AttributeRemover) { Temple::CoffeeScript::AttributeRemover.new(:remove_empty_attrs => options[:merge_attrs].keys)}
|
28
|
+
html :Pretty, :format, :attr_quote, :pretty, :indent, :js_wrapper
|
29
|
+
use Temple::HTML::Fast, :format, :attr_quote
|
30
|
+
use Temple::CoffeeScript::Filters::Escapable, :use_html_safe, :disable_escape
|
22
31
|
use Temple::CoffeeScript::Filters::ControlFlow
|
23
32
|
filter :MultiFlattener
|
24
33
|
use(:Optimizer) { Temple::Filters::StaticMerger.new }
|
25
|
-
use
|
34
|
+
use :Generator do
|
35
|
+
options[:generator].new(options.to_hash.reject {|k,v| !options[:generator].default_options.valid_keys.include?(k) })
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Skim
|
2
|
+
# Perform interpolation of #{var_name} in the
|
3
|
+
# expressions `[:slim, :interpolate, string]`.
|
4
|
+
#
|
5
|
+
# @api private
|
6
|
+
class Interpolation < Slim::Filter
|
7
|
+
# Handle interpolate expression `[:slim, :interpolate, string]`
|
8
|
+
#
|
9
|
+
# @param [String] string Static interpolate
|
10
|
+
# @return [Array] Compiled temple expression
|
11
|
+
def on_slim_interpolate(string)
|
12
|
+
# Interpolate variables in text (#{variable}).
|
13
|
+
# Split the text into multiple dynamic and static parts.
|
14
|
+
block = [:multi]
|
15
|
+
begin
|
16
|
+
case string
|
17
|
+
when /\A\\#\{/
|
18
|
+
# Escaped interpolation
|
19
|
+
block << [:dynamic, "'\#{'"]
|
20
|
+
string = $'
|
21
|
+
when /\A#\{/
|
22
|
+
# Interpolation
|
23
|
+
string, code = parse_expression($')
|
24
|
+
escape = code !~ /\A\{.*\}\Z/
|
25
|
+
block << [:slim, :output, escape, escape ? code : code[1..-2], [:multi]]
|
26
|
+
when /\A([#\\]|[^#\\]*)/
|
27
|
+
# Static text
|
28
|
+
block << [:static, $&]
|
29
|
+
string = $'
|
30
|
+
end
|
31
|
+
end until string.empty?
|
32
|
+
block
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def parse_expression(string)
|
38
|
+
count, i = 1, 0
|
39
|
+
while i < string.size && count != 0
|
40
|
+
if string[i] == ?{
|
41
|
+
count += 1
|
42
|
+
elsif string[i] == ?}
|
43
|
+
count -= 1
|
44
|
+
end
|
45
|
+
i += 1
|
46
|
+
end
|
47
|
+
|
48
|
+
raise(Temple::FilterError, "Text interpolation: Expected closing }") if count != 0
|
49
|
+
|
50
|
+
return string[i..-1], string[0, i-1]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/skim/template.rb
CHANGED
@@ -7,15 +7,18 @@ module Skim
|
|
7
7
|
self.default_mime_type = "application/javascript"
|
8
8
|
|
9
9
|
def coffee_script_src
|
10
|
-
|
10
|
+
|
11
|
+
engine = Engine.new(options.merge({
|
11
12
|
:streaming => false, # Overwrite option: No streaming support in Tilt
|
12
13
|
:file => eval_file,
|
13
|
-
:indent => 2
|
14
|
-
|
14
|
+
:indent => 2
|
15
|
+
}))
|
16
|
+
src = engine.call(data)
|
17
|
+
<<-SRC
|
15
18
|
#{self.class.skim_src unless engine.options[:use_asset]}
|
16
19
|
return (context = {}) ->
|
17
20
|
Skim.withContext.call {}, context, ->
|
18
|
-
#{
|
21
|
+
#{src}
|
19
22
|
SRC
|
20
23
|
end
|
21
24
|
|
data/lib/skim/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Temple
|
|
3
3
|
class AttributeMerger < Filter
|
4
4
|
include Temple::HTML::Dispatcher
|
5
5
|
|
6
|
-
|
6
|
+
define_options :merge_attrs => {'id' => '_', 'class' => ' '}
|
7
7
|
|
8
8
|
def on_html_attrs(*attrs)
|
9
9
|
names = []
|
@@ -12,7 +12,7 @@ module Temple
|
|
12
12
|
attrs.each do |html, attr, name, value|
|
13
13
|
raise(InvalidExpression, 'Attribute is not a html attr') if html != :html || attr != :attr
|
14
14
|
name = name.to_s
|
15
|
-
if delimiter = options[:
|
15
|
+
if delimiter = options[:merge_attrs][name]
|
16
16
|
if current = result[name]
|
17
17
|
current << [:static, delimiter] << value
|
18
18
|
else
|
@@ -1,19 +1,16 @@
|
|
1
1
|
module Temple
|
2
2
|
module CoffeeScript
|
3
|
-
class AttributeRemover <
|
3
|
+
class AttributeRemover < Temple::HTML::AttributeRemover
|
4
4
|
include Temple::HTML::Dispatcher
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
def on_html_attrs(*attrs)
|
9
|
-
[:multi, *(options[:remove_empty_attrs] ?
|
10
|
-
attrs.map {|attr| compile(attr) } : attrs)]
|
11
|
-
end
|
6
|
+
define_options :remove_empty_attrs => %w(id class)
|
12
7
|
|
13
8
|
def on_html_attr(name, value)
|
9
|
+
return super unless options[:remove_empty_attrs].include?(name.to_s)
|
10
|
+
|
14
11
|
if empty_exp?(value)
|
15
12
|
value
|
16
|
-
elsif
|
13
|
+
elsif contains_nonempty_static?(value)
|
17
14
|
[:html, :attr, name, value]
|
18
15
|
else
|
19
16
|
tmp = unique_name
|
@@ -3,12 +3,14 @@ module Temple
|
|
3
3
|
module Filters
|
4
4
|
class Escapable < Filter
|
5
5
|
# Activate the usage of html_safe? if it is available (for Rails 3 for example)
|
6
|
-
|
7
|
-
|
6
|
+
define_options :escape_code,
|
7
|
+
:use_html_safe => ''.respond_to?(:html_safe?),
|
8
|
+
:disable_escape => false
|
8
9
|
|
9
10
|
def initialize(opts = {})
|
10
11
|
super
|
11
|
-
@escape_code =
|
12
|
+
@escape_code = options[:escape_code] ||
|
13
|
+
"::Temple::Utils.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))"
|
12
14
|
@escaper = eval("proc {|v| #{@escape_code % 'v'} }")
|
13
15
|
@escape = false
|
14
16
|
end
|
@@ -1,13 +1,12 @@
|
|
1
|
-
require "
|
1
|
+
require "json"
|
2
2
|
|
3
3
|
module Temple
|
4
4
|
module CoffeeScript
|
5
5
|
class Generator < Temple::Generator
|
6
|
-
|
6
|
+
define_options :indent => 0
|
7
7
|
|
8
8
|
def call(exp)
|
9
9
|
@indent = options[:indent]
|
10
|
-
|
11
10
|
compile [:multi,
|
12
11
|
[:code, "#{buffer} = []"],
|
13
12
|
exp,
|
@@ -19,7 +18,7 @@ module Temple
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def on_static(text)
|
22
|
-
concat(
|
21
|
+
concat(JSON.generate(text, :quirks_mode => true))
|
23
22
|
end
|
24
23
|
|
25
24
|
def on_dynamic(code)
|
data/skim.gemspec
CHANGED
@@ -17,15 +17,14 @@ Sprockets-based asset pipeline.}
|
|
17
17
|
gem.require_paths = ["lib"]
|
18
18
|
gem.version = Skim::VERSION
|
19
19
|
|
20
|
-
gem.add_dependency "slim", "
|
21
|
-
gem.add_dependency "temple", "<= 0.4.1"
|
20
|
+
gem.add_dependency "slim", "~> 2.0.0"
|
22
21
|
gem.add_dependency "coffee-script"
|
23
22
|
gem.add_dependency "coffee-script-source", ">= 1.2.0"
|
24
|
-
gem.add_dependency "multi_json"
|
25
23
|
gem.add_dependency "sprockets"
|
26
24
|
|
27
25
|
gem.add_development_dependency "rake"
|
28
26
|
gem.add_development_dependency "execjs"
|
29
27
|
gem.add_development_dependency "minitest-reporters", "~> 0.10"
|
30
28
|
gem.add_development_dependency "therubyracer"
|
29
|
+
gem.add_development_dependency "libv8", "3.11.8.3"
|
31
30
|
end
|
data/test/helper.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
require "minitest/unit"
|
3
3
|
require "minitest/reporters"
|
4
|
-
require "temple"; Temple::Filter # Trigger #13
|
5
4
|
require "skim"
|
6
5
|
require "coffee_script"
|
7
6
|
require "execjs"
|
@@ -28,11 +27,11 @@ class TestSkim < MiniTest::Unit::TestCase
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def context(options)
|
31
|
-
case context = options
|
30
|
+
case context = options.delete(:context)
|
32
31
|
when String
|
33
32
|
context
|
34
33
|
when Hash
|
35
|
-
|
34
|
+
JSON.dump(context)
|
36
35
|
else
|
37
36
|
"new Context()"
|
38
37
|
end
|
@@ -52,6 +51,7 @@ class TestSkim < MiniTest::Unit::TestCase
|
|
52
51
|
if Skim::Engine.default_options[:use_asset]
|
53
52
|
code.unshift skim_source
|
54
53
|
end
|
54
|
+
|
55
55
|
context = ExecJS.compile(code.join(";"))
|
56
56
|
context.call("evaluate")
|
57
57
|
end
|
data/test/test_code_escaping.rb
CHANGED
@@ -6,7 +6,7 @@ class TestSkimCodeEscaping < TestSkim
|
|
6
6
|
p = @evil_method()
|
7
7
|
}
|
8
8
|
|
9
|
-
assert_html '<p><script>do_something_evil();<
|
9
|
+
assert_html '<p><script>do_something_evil();</script></p>', source
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_render_unsafe
|
@@ -14,7 +14,7 @@ p = @evil_method()
|
|
14
14
|
p = "<strong>Hello World\\n, meet \\"Skim\\"</strong>."
|
15
15
|
}
|
16
16
|
|
17
|
-
assert_html "<p><strong>Hello World\n, meet \"Skim\"<
|
17
|
+
assert_html "<p><strong>Hello World\n, meet \"Skim\"</strong>.</p>", source
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_render_safe
|
@@ -31,7 +31,7 @@ p = @safe("<strong>Hello World\\n, meet \\"Skim\\"</strong>.")
|
|
31
31
|
== "<p>World</p>"
|
32
32
|
}
|
33
33
|
|
34
|
-
assert_html "<p>Hello<
|
34
|
+
assert_html "<p>Hello</p><p>World</p>", source
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_render_with_disable_escape_true
|
@@ -68,10 +68,10 @@ p id=@var
|
|
68
68
|
|
69
69
|
def test_method_call_in_attribute_without_quotes
|
70
70
|
source = %q{
|
71
|
-
form action=@action_path(
|
71
|
+
form action=@action_path('page', 'save') method='post'
|
72
72
|
}
|
73
73
|
|
74
|
-
assert_html '<form action="
|
74
|
+
assert_html '<form action="/action-page-save" method="post"></form>', source
|
75
75
|
end
|
76
76
|
|
77
77
|
def test_ruby_attribute_with_unbalanced_delimiters
|
@@ -79,28 +79,20 @@ form action=@action_path("page", "save") method='post'
|
|
79
79
|
div crazy=@action_path('[') id="crazy_delimiters"
|
80
80
|
}
|
81
81
|
|
82
|
-
assert_html '<div crazy="
|
82
|
+
assert_html '<div crazy="/action-[" id="crazy_delimiters"></div>', source
|
83
83
|
end
|
84
84
|
|
85
85
|
def test_method_call_in_delimited_attribute_without_quotes
|
86
86
|
source = %q{
|
87
|
-
form(action=@action_path(
|
87
|
+
form(action=@action_path('page', 'save') method='post')
|
88
88
|
}
|
89
89
|
|
90
|
-
assert_html '<form action="
|
90
|
+
assert_html '<form action="/action-page-save" method="post"></form>', source
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_method_call_in_delimited_attribute_without_quotes2
|
94
94
|
source = %q{
|
95
|
-
form(method='post' action=@action_path(
|
96
|
-
}
|
97
|
-
|
98
|
-
assert_html '<form action="/action-page-save" method="post"></form>', source
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_bypassing_escape_in_attribute
|
102
|
-
source = %q{
|
103
|
-
form action==@action_path("page", "save") method='post'
|
95
|
+
form(method='post' action=@action_path('page', 'save'))
|
104
96
|
}
|
105
97
|
|
106
98
|
assert_html '<form action="/action-page-save" method="post"></form>', source
|
@@ -124,7 +116,7 @@ p(id=@hash()['a']) Test it
|
|
124
116
|
|
125
117
|
def test_hash_call_in_attribute_with_ruby_evaluation
|
126
118
|
source = %q{
|
127
|
-
p id=
|
119
|
+
p id=(@hash()['a'] + @hash()['a']) Test it
|
128
120
|
}
|
129
121
|
|
130
122
|
assert_html '<p id="The letter aThe letter a">Test it</p>', source
|
@@ -148,23 +140,15 @@ p[id=(@hash()['a'] + @hash()['a'])] Test it
|
|
148
140
|
|
149
141
|
def test_hash_call_in_delimited_attribute_with_ruby_evaluation_3
|
150
142
|
source = %q{
|
151
|
-
p(id=
|
152
|
-
}
|
153
|
-
|
154
|
-
assert_html '<p id="The letter aThe letter a">Test it</p>', source
|
155
|
-
end
|
156
|
-
|
157
|
-
def test_hash_call_in_delimited_attribute_with_ruby_evaluation_4
|
158
|
-
source = %q{
|
159
|
-
p(id=[@hash()['a'] + @hash()['a']] class=[@hash()['a']]) Test it
|
143
|
+
p(id=(@hash()['a'] + @hash()['a']) class=@hash()['a']) Test it
|
160
144
|
}
|
161
145
|
|
162
146
|
assert_html '<p class="The letter a" id="The letter aThe letter a">Test it</p>', source
|
163
147
|
end
|
164
148
|
|
165
|
-
def
|
149
|
+
def test_hash_call_in_delimited_attribute_with_ruby_evaluation_4_
|
166
150
|
source = %q{
|
167
|
-
p(id=@hash()['a'] class
|
151
|
+
p(id=@hash()['a'] class=@hash()['a']) Test it
|
168
152
|
}
|
169
153
|
|
170
154
|
assert_html '<p class="The letter a" id="The letter a">Test it</p>', source
|
@@ -185,101 +169,4 @@ p = @output_number()
|
|
185
169
|
|
186
170
|
assert_html '<p>1337</p>', source
|
187
171
|
end
|
188
|
-
|
189
|
-
def test_ternary_operation_in_attribute
|
190
|
-
source = %q{
|
191
|
-
p id="#{(if false then 'notshown' else 'shown')}" = @output_number()
|
192
|
-
}
|
193
|
-
|
194
|
-
assert_html '<p id="shown">1337</p>', source
|
195
|
-
end
|
196
|
-
|
197
|
-
def test_class_attribute_merging
|
198
|
-
source = %{
|
199
|
-
.alpha class="beta" Test it
|
200
|
-
}
|
201
|
-
assert_html '<div class="alpha beta">Test it</div>', source
|
202
|
-
end
|
203
|
-
|
204
|
-
def test_class_attribute_merging_with_null
|
205
|
-
skip "pending"
|
206
|
-
|
207
|
-
source = %{
|
208
|
-
.alpha class="beta" class=null class="gamma" Test it
|
209
|
-
}
|
210
|
-
assert_html '<div class="alpha beta gamma">Test it</div>', source
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_id_attribute_merging
|
214
|
-
source = %{
|
215
|
-
#alpha id="beta" Test it
|
216
|
-
}
|
217
|
-
assert_html '<div id="alpha_beta">Test it</div>', source, :attr_delimiter => {'class' => ' ', 'id' => '_' }
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_id_attribute_merging2
|
221
|
-
source = %{
|
222
|
-
#alpha id="beta" Test it
|
223
|
-
}
|
224
|
-
assert_html '<div id="alpha-beta">Test it</div>', source, :attr_delimiter => {'class' => ' ', 'id' => '-' }
|
225
|
-
end
|
226
|
-
|
227
|
-
def test_boolean_attribute_false
|
228
|
-
source = %{
|
229
|
-
option selected=false Text
|
230
|
-
}
|
231
|
-
|
232
|
-
assert_html '<option>Text</option>', source
|
233
|
-
end
|
234
|
-
|
235
|
-
def test_boolean_attribute_true
|
236
|
-
source = %{
|
237
|
-
option selected=true Text
|
238
|
-
}
|
239
|
-
|
240
|
-
assert_html '<option selected="selected">Text</option>', source
|
241
|
-
end
|
242
|
-
|
243
|
-
def test_boolean_attribute_dynamic
|
244
|
-
source = %{
|
245
|
-
option selected=@method_which_returns_true() Text
|
246
|
-
}
|
247
|
-
|
248
|
-
assert_html '<option selected="selected">Text</option>', source
|
249
|
-
end
|
250
|
-
|
251
|
-
def test_boolean_attribute_null
|
252
|
-
source = %{
|
253
|
-
option selected=null Text
|
254
|
-
}
|
255
|
-
|
256
|
-
assert_html '<option>Text</option>', source
|
257
|
-
end
|
258
|
-
|
259
|
-
def test_boolean_attribute_string2
|
260
|
-
source = %{
|
261
|
-
option selected="selected" Text
|
262
|
-
}
|
263
|
-
|
264
|
-
assert_html '<option selected="selected">Text</option>', source
|
265
|
-
end
|
266
|
-
|
267
|
-
def test_boolean_attribute_shortcut
|
268
|
-
source = %{
|
269
|
-
option(class="clazz" selected) Text
|
270
|
-
option(selected class="clazz") Text
|
271
|
-
}
|
272
|
-
|
273
|
-
assert_html '<option class="clazz" selected="selected">Text</option><option class="clazz" selected="selected">Text</option>', source
|
274
|
-
end
|
275
|
-
|
276
|
-
def test_array_attribute
|
277
|
-
skip "pending"
|
278
|
-
|
279
|
-
source = %{
|
280
|
-
.alpha class="beta" class=['gamma', null, 'delta', [true, false]]
|
281
|
-
}
|
282
|
-
|
283
|
-
assert_html '<div class="alpha beta gamma delta true false"></div>', source
|
284
|
-
end
|
285
172
|
end
|
data/test/test_html_structure.rb
CHANGED
@@ -15,7 +15,6 @@ html
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_html_tag_with_text_and_empty_line
|
18
|
-
# Keep the trailing space behind "body "!
|
19
18
|
source = %q{
|
20
19
|
p Hello
|
21
20
|
|
@@ -74,10 +73,21 @@ h1#title This is my title
|
|
74
73
|
def test_render_with_overwritten_default_tag
|
75
74
|
source = %q{
|
76
75
|
#notice.hello.world
|
76
|
+
= @hello_world()
|
77
|
+
}
|
78
|
+
|
79
|
+
assert_html '<section class="hello world" id="notice">Hello World from @env</section>', source, :default_tag => 'section'
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_render_with_custom_shortcut
|
83
|
+
source = %q{
|
84
|
+
#notice.hello.world@test
|
85
|
+
= @hello_world()
|
86
|
+
@abc
|
77
87
|
= @hello_world()
|
78
88
|
}
|
79
89
|
|
80
|
-
assert_html '<
|
90
|
+
assert_html '<div class="hello world" id="notice" role="test">Hello World from @env</div><section role="abc">Hello World from @env</section>', source, :shortcut => {'#' => {:attr => 'id'}, '.' => {:attr => 'class'}, '@' => {:tag => 'section', :attr => 'role'}}
|
81
91
|
end
|
82
92
|
|
83
93
|
def test_render_with_text_block
|
@@ -215,7 +225,7 @@ p class='underscored_class_name' = @output_number()
|
|
215
225
|
}
|
216
226
|
|
217
227
|
assert_html '<p class="underscored_class_name">1337</p>', source
|
218
|
-
|
228
|
+
end
|
219
229
|
|
220
230
|
def test_nonstandard_attributes
|
221
231
|
source = %q{
|
@@ -273,24 +283,6 @@ p(id="marvin" class="martian" data-info="Illudium Q-36")= @output_number()
|
|
273
283
|
assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">1337</p>', source
|
274
284
|
end
|
275
285
|
|
276
|
-
def test_static_empty_attribute
|
277
|
-
source = %q{
|
278
|
-
p(id="marvin" class="" data-info="Illudium Q-36")= @output_number()
|
279
|
-
}
|
280
|
-
|
281
|
-
assert_html '<p class="" data-info="Illudium Q-36" id="marvin">1337</p>', source
|
282
|
-
end
|
283
|
-
|
284
|
-
def test_dynamic_empty_attribute
|
285
|
-
skip "pending"
|
286
|
-
|
287
|
-
source = %q{
|
288
|
-
p(id="marvin" class=null other_empty=("") data-info="Illudium Q-36")= @output_number()
|
289
|
-
}
|
290
|
-
|
291
|
-
assert_html '<p data-info="Illudium Q-36" id="marvin">1337</p>', source
|
292
|
-
end
|
293
|
-
|
294
286
|
def test_closed_tag
|
295
287
|
source = %q{
|
296
288
|
closed/
|
@@ -354,7 +346,7 @@ p World
|
|
354
346
|
def test_render_with_html_conditional_and_method_output
|
355
347
|
source = %q{
|
356
348
|
/[ if IE ]
|
357
|
-
= @message
|
349
|
+
= @message('hello')
|
358
350
|
}
|
359
351
|
|
360
352
|
assert_html "<!--[if IE]>hello<![endif]-->", source
|
@@ -366,7 +358,7 @@ p<id="marvin"
|
|
366
358
|
class="martian"
|
367
359
|
data-info="Illudium Q-36"> = @output_number()
|
368
360
|
}
|
369
|
-
Slim::Parser::
|
361
|
+
Slim::Parser::DELIMS.each do |k,v|
|
370
362
|
str = source.sub('<',k).sub('>',v)
|
371
363
|
assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">1337</p>', str
|
372
364
|
end
|
@@ -378,7 +370,7 @@ p<id="marvin"
|
|
378
370
|
class="martian"
|
379
371
|
data-info="Illudium Q-36"> THE space modulator
|
380
372
|
}
|
381
|
-
Slim::Parser::
|
373
|
+
Slim::Parser::DELIMS.each do |k,v|
|
382
374
|
str = source.sub('<',k).sub('>',v)
|
383
375
|
assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">THE space modulator</p>', str
|
384
376
|
end
|
@@ -391,7 +383,7 @@ p<id="marvin"
|
|
391
383
|
data-info="Illudium Q-36">
|
392
384
|
| THE space modulator
|
393
385
|
}
|
394
|
-
Slim::Parser::
|
386
|
+
Slim::Parser::DELIMS.each do |k,v|
|
395
387
|
str = source.sub('<',k).sub('>',v)
|
396
388
|
assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">THE space modulator</p>', str
|
397
389
|
end
|
@@ -404,7 +396,7 @@ p<id=@id_helper()
|
|
404
396
|
data-info="Illudium Q-36">
|
405
397
|
| THE space modulator
|
406
398
|
}
|
407
|
-
Slim::Parser::
|
399
|
+
Slim::Parser::DELIMS.each do |k,v|
|
408
400
|
str = source.sub('<',k).sub('>',v)
|
409
401
|
assert_html '<p class="martian" data-info="Illudium Q-36" id="notice">THE space modulator</p>', str
|
410
402
|
end
|
@@ -418,7 +410,7 @@ p<id=@id_helper()
|
|
418
410
|
span.emphasis THE
|
419
411
|
| space modulator
|
420
412
|
}
|
421
|
-
Slim::Parser::
|
413
|
+
Slim::Parser::DELIMS.each do |k,v|
|
422
414
|
str = source.sub('<',k).sub('>',v)
|
423
415
|
assert_html '<p class="martian" data-info="Illudium Q-36" id="notice"><span class="emphasis">THE</span> space modulator</p>', str
|
424
416
|
end
|
@@ -431,7 +423,7 @@ li< id="myid"
|
|
431
423
|
data-info="myinfo">
|
432
424
|
a href="link" My Link
|
433
425
|
}
|
434
|
-
Slim::Parser::
|
426
|
+
Slim::Parser::DELIMS.each do |k,v|
|
435
427
|
str = source.sub('<',k).sub('>',v)
|
436
428
|
assert_html '<li class="myclass" data-info="myinfo" id="myid"><a href="link">My Link</a></li>', str
|
437
429
|
end
|
@@ -470,4 +462,17 @@ input[value=@succ_x()]
|
|
470
462
|
assert_html %{<input value="1" /><input value="2" />}, source
|
471
463
|
end
|
472
464
|
|
465
|
+
def test_html_line_indicator
|
466
|
+
source = %q{
|
467
|
+
<html>
|
468
|
+
head
|
469
|
+
meta name="keywords" content=@hello_world()
|
470
|
+
- if true
|
471
|
+
<p>#{@hello_world()}</p>
|
472
|
+
span = @hello_world()
|
473
|
+
</html>
|
474
|
+
}
|
475
|
+
|
476
|
+
assert_html '<html><head><meta content="Hello World from @env" name="keywords" /></head><p>Hello World from @env</p><span>Hello World from @env</span></html>', source
|
477
|
+
end
|
473
478
|
end
|
@@ -40,9 +40,10 @@ p #{@hello_world()}
|
|
40
40
|
def test_escape_interpolation
|
41
41
|
source = %q{
|
42
42
|
p \\#{@hello_world()}
|
43
|
+
p text1 \\#{@hello_world()} text2
|
43
44
|
}
|
44
45
|
|
45
|
-
assert_html '<p>#{@hello_world()}</p>', source
|
46
|
+
assert_html '<p>#{@hello_world()}</p><p>text1 #{@hello_world()} text2</p>', source
|
46
47
|
end
|
47
48
|
|
48
49
|
def test_complex_interpolation
|
@@ -58,7 +59,7 @@ p Message: #{@message('hello', "user #{@output_number()}")}
|
|
58
59
|
| #{@evil_method()}
|
59
60
|
}
|
60
61
|
|
61
|
-
assert_html '<script>do_something_evil();<
|
62
|
+
assert_html '<script>do_something_evil();</script>', source
|
62
63
|
end
|
63
64
|
|
64
65
|
def test_interpolation_without_escaping
|
@@ -73,6 +74,6 @@ p Message: #{@message('hello', "user #{@output_number()}")}
|
|
73
74
|
source = %q{
|
74
75
|
| #{(@evil_method())}
|
75
76
|
}
|
76
|
-
assert_html '<script>do_something_evil();<
|
77
|
+
assert_html '<script>do_something_evil();</script>', source
|
77
78
|
end
|
78
79
|
end
|
@@ -22,6 +22,17 @@ this.Skim =
|
|
22
22
|
result.skimSafe = true
|
23
23
|
result
|
24
24
|
|
25
|
+
context.isArray = Array.isArray || ( value ) -> return {}.toString.call( value ) is '[object Array]'
|
26
|
+
|
27
|
+
context.flatten = flatten = (array) ->
|
28
|
+
flattened = []
|
29
|
+
for element in array
|
30
|
+
if element instanceof Array
|
31
|
+
flattened = flattened.concat flatten element
|
32
|
+
else
|
33
|
+
flattened.push element
|
34
|
+
flattened
|
35
|
+
|
25
36
|
context.escape ||= @escape || (string) ->
|
26
37
|
return '' unless string?
|
27
38
|
return string if string.skimSafe
|
@@ -30,6 +41,5 @@ this.Skim =
|
|
30
41
|
.replace(/</g, '<')
|
31
42
|
.replace(/>/g, '>')
|
32
43
|
.replace(/"/g, '"')
|
33
|
-
.replace(/\//g,'/')
|
34
44
|
|
35
45
|
block.call(context)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,40 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-06-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: slim
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 1.2.2
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - <=
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 1.2.2
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: temple
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - <=
|
19
|
+
- - ~>
|
36
20
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.
|
21
|
+
version: 2.0.0
|
38
22
|
type: :runtime
|
39
23
|
prerelease: false
|
40
24
|
version_requirements: !ruby/object:Gem::Requirement
|
41
25
|
none: false
|
42
26
|
requirements:
|
43
|
-
- -
|
27
|
+
- - ~>
|
44
28
|
- !ruby/object:Gem::Version
|
45
|
-
version: 0.
|
29
|
+
version: 2.0.0
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: coffee-script
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,22 +59,6 @@ dependencies:
|
|
75
59
|
- - ! '>='
|
76
60
|
- !ruby/object:Gem::Version
|
77
61
|
version: 1.2.0
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: multi_json
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :runtime
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
62
|
- !ruby/object:Gem::Dependency
|
95
63
|
name: sprockets
|
96
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,6 +139,22 @@ dependencies:
|
|
171
139
|
- - ! '>='
|
172
140
|
- !ruby/object:Gem::Version
|
173
141
|
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: libv8
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - '='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 3.11.8.3
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - '='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 3.11.8.3
|
174
158
|
description: Fat-free client-side templates with Slim and CoffeeScript
|
175
159
|
email:
|
176
160
|
- john.firebaugh@gmail.com
|
@@ -186,10 +170,11 @@ files:
|
|
186
170
|
- README.md
|
187
171
|
- Rakefile
|
188
172
|
- lib/skim.rb
|
189
|
-
- lib/skim/
|
173
|
+
- lib/skim/code_attributes.rb
|
174
|
+
- lib/skim/controls.rb
|
190
175
|
- lib/skim/engine.rb
|
176
|
+
- lib/skim/interpolation.rb
|
191
177
|
- lib/skim/rails.rb
|
192
|
-
- lib/skim/sections.rb
|
193
178
|
- lib/skim/template.rb
|
194
179
|
- lib/skim/version.rb
|
195
180
|
- lib/temple/coffee_script.rb
|
@@ -213,7 +198,6 @@ files:
|
|
213
198
|
- test/test_code_structure.rb
|
214
199
|
- test/test_html_escaping.rb
|
215
200
|
- test/test_html_structure.rb
|
216
|
-
- test/test_sections.rb
|
217
201
|
- test/test_skim_template.rb
|
218
202
|
- test/test_text_interpolation.rb
|
219
203
|
- vendor/assets/javascripts/skim.js.coffee
|
@@ -229,21 +213,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
229
213
|
- - ! '>='
|
230
214
|
- !ruby/object:Gem::Version
|
231
215
|
version: '0'
|
232
|
-
segments:
|
233
|
-
- 0
|
234
|
-
hash: -2623561313365634861
|
235
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
236
217
|
none: false
|
237
218
|
requirements:
|
238
219
|
- - ! '>='
|
239
220
|
- !ruby/object:Gem::Version
|
240
221
|
version: '0'
|
241
|
-
segments:
|
242
|
-
- 0
|
243
|
-
hash: -2623561313365634861
|
244
222
|
requirements: []
|
245
223
|
rubyforge_project:
|
246
|
-
rubygems_version: 1.8.
|
224
|
+
rubygems_version: 1.8.23
|
247
225
|
signing_key:
|
248
226
|
specification_version: 3
|
249
227
|
summary: Take the fat out of your client-side templates with Skim. Skim is the Slim
|
@@ -262,6 +240,5 @@ test_files:
|
|
262
240
|
- test/test_code_structure.rb
|
263
241
|
- test/test_html_escaping.rb
|
264
242
|
- test/test_html_structure.rb
|
265
|
-
- test/test_sections.rb
|
266
243
|
- test/test_skim_template.rb
|
267
244
|
- test/test_text_interpolation.rb
|
data/lib/skim/compiler.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module Skim
|
2
|
-
class Compiler < Slim::Compiler
|
3
|
-
def on_slim_control(code, content)
|
4
|
-
[:multi,
|
5
|
-
[:code, code],
|
6
|
-
[:indent, compile(content)]]
|
7
|
-
end
|
8
|
-
|
9
|
-
def on_slim_attr(name, escape, code)
|
10
|
-
value = case code
|
11
|
-
when 'true'
|
12
|
-
escape = false
|
13
|
-
[:static, name]
|
14
|
-
when 'false', 'null'
|
15
|
-
escape = false
|
16
|
-
[:multi]
|
17
|
-
else
|
18
|
-
tmp = unique_name
|
19
|
-
[:multi,
|
20
|
-
[:code, "#{tmp} = #{code}"],
|
21
|
-
[:case, tmp,
|
22
|
-
['true', [:static, name]],
|
23
|
-
['false, null', [:multi]],
|
24
|
-
[:else,
|
25
|
-
[:dynamic,
|
26
|
-
#if delimiter = options[:attr_delimiter][name]
|
27
|
-
# "#{tmp}.respond_to?(:join) ? #{tmp}.flatten.compact.join(#{delimiter.inspect}) : #{tmp}"
|
28
|
-
#else
|
29
|
-
tmp
|
30
|
-
#end
|
31
|
-
]]]]
|
32
|
-
end
|
33
|
-
[:html, :attr, name, [:escape, escape, value]]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/skim/sections.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require "multi_json"
|
2
|
-
|
3
|
-
module Skim
|
4
|
-
class Sections < Slim::Sections
|
5
|
-
def call(exp)
|
6
|
-
if options[:sections]
|
7
|
-
compile(exp)
|
8
|
-
else
|
9
|
-
exp
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
protected
|
14
|
-
|
15
|
-
def on_slim_inverted_section(name, content)
|
16
|
-
[:if, "not #{access(name)}", compile(content)]
|
17
|
-
end
|
18
|
-
|
19
|
-
def on_slim_section(name, content)
|
20
|
-
tmp1, tmp2 = unique_name, unique_name
|
21
|
-
[:if, "#{tmp1} = #{access(name)}",
|
22
|
-
[:block, "for #{tmp2} in #{tmp1}",
|
23
|
-
[:block, "Skim.withContext.call @, #{tmp2}, ->", compile(content)]]]
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def access(name)
|
29
|
-
"Skim.access.call(@, #{MultiJson.encode(name.to_s)})"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/test/test_sections.rb
DELETED
@@ -1,157 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestSkimLogicLess < TestSkim
|
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, :context => hash, :sections => true
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_flag_section
|
22
|
-
source = %q{
|
23
|
-
p
|
24
|
-
- show_person
|
25
|
-
- person
|
26
|
-
.name = name
|
27
|
-
- show_person
|
28
|
-
| shown
|
29
|
-
}
|
30
|
-
|
31
|
-
hash = {
|
32
|
-
:show_person => true,
|
33
|
-
:person => [
|
34
|
-
{ :name => 'Joe', },
|
35
|
-
{ :name => 'Jack', }
|
36
|
-
]
|
37
|
-
}
|
38
|
-
|
39
|
-
assert_html '<p><div class="name">Joe</div><div class="name">Jack</div>shown</p>', source, :context => hash, :sections => true
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_inverted_section
|
43
|
-
source = %q{
|
44
|
-
p
|
45
|
-
- person
|
46
|
-
.name = name
|
47
|
-
-! person
|
48
|
-
| No person
|
49
|
-
- !person
|
50
|
-
| No person 2
|
51
|
-
}
|
52
|
-
|
53
|
-
hash = {}
|
54
|
-
|
55
|
-
assert_html '<p>No person No person 2</p>', source, :context => hash, :sections => true
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_output_with_content
|
59
|
-
source = %{
|
60
|
-
p = method_with_block do
|
61
|
-
block
|
62
|
-
}
|
63
|
-
assert_runtime_error 'Output statements with content are forbidden in sections mode', source, :sections => true
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_sections2
|
67
|
-
source = %q{
|
68
|
-
p
|
69
|
-
- person
|
70
|
-
.name = name
|
71
|
-
}
|
72
|
-
assert_html '<p><div class="name">Joe</div><div class="name">Jack</div></p>', source, :sections => true
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_with_array
|
76
|
-
source = %q{
|
77
|
-
ul
|
78
|
-
- people_with_locations
|
79
|
-
li = name
|
80
|
-
li = city
|
81
|
-
}
|
82
|
-
assert_html '<ul><li>Andy</li><li>Atlanta</li><li>Fred</li><li>Melbourne</li><li>Daniel</li><li>Karlsruhe</li></ul>', source, :sections => true
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_method
|
86
|
-
source = %q{
|
87
|
-
a href=output_number Link
|
88
|
-
}
|
89
|
-
assert_html '<a href="1337">Link</a>', source, :sections => true
|
90
|
-
end
|
91
|
-
|
92
|
-
SECTION = <<-SRC
|
93
|
-
- test
|
94
|
-
| Test
|
95
|
-
SRC
|
96
|
-
|
97
|
-
INVERTED_SECTION = <<-SRC
|
98
|
-
-! test
|
99
|
-
| Test
|
100
|
-
SRC
|
101
|
-
|
102
|
-
def test_undefined_section
|
103
|
-
assert_html "", SECTION, :context => {}, :sections => true
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_null_section
|
107
|
-
assert_html "", SECTION, :context => {:test => nil}, :sections => true
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_false_section
|
111
|
-
assert_html "", SECTION, :context => {:test => false}, :sections => true
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_empty_string_section
|
115
|
-
assert_html "Test", SECTION, :context => {:test => ""}, :sections => true
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_empty_array_section
|
119
|
-
assert_html "", SECTION, :context => {:test => []}, :sections => true
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_empty_object_section
|
123
|
-
assert_html "Test", SECTION, :context => {:test => {}}, :sections => true
|
124
|
-
end
|
125
|
-
|
126
|
-
def test_undefined_inverted_section
|
127
|
-
assert_html "Test", INVERTED_SECTION, :context => {}, :sections => true
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_null_inverted_section
|
131
|
-
assert_html "Test", INVERTED_SECTION, :context => {:test => nil}, :sections => true
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_false_inverted_section
|
135
|
-
assert_html "Test", INVERTED_SECTION, :context => {:test => false}, :sections => true
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_empty_string_inverted_section
|
139
|
-
assert_html "", INVERTED_SECTION, :context => {:test => ""}, :sections => true
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_empty_array_inverted_section
|
143
|
-
assert_html "Test", INVERTED_SECTION, :context => {:test => []}, :sections => true
|
144
|
-
end
|
145
|
-
|
146
|
-
def test_empty_object_inverted_section
|
147
|
-
assert_html "", INVERTED_SECTION, :context => {:test => {}}, :sections => true
|
148
|
-
end
|
149
|
-
|
150
|
-
def test_doesnt_modify_context
|
151
|
-
source = %q{
|
152
|
-
- constant_object
|
153
|
-
= constant_object_size
|
154
|
-
}
|
155
|
-
assert_html '2', source, :sections => true
|
156
|
-
end
|
157
|
-
end
|