skim 0.8.6 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 [  ](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
|