scribble 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +455 -0
- data/Rakefile +2 -0
- data/lib/scribble.rb +44 -0
- data/lib/scribble/block.rb +25 -0
- data/lib/scribble/converter.rb +10 -0
- data/lib/scribble/errors.rb +24 -0
- data/lib/scribble/method.rb +91 -0
- data/lib/scribble/methods/if.rb +26 -0
- data/lib/scribble/methods/layout.rb +25 -0
- data/lib/scribble/methods/partial.rb +14 -0
- data/lib/scribble/methods/times.rb +11 -0
- data/lib/scribble/nodes/call.rb +55 -0
- data/lib/scribble/nodes/ending.rb +6 -0
- data/lib/scribble/nodes/node.rb +24 -0
- data/lib/scribble/nodes/value.rb +16 -0
- data/lib/scribble/objects/boolean.rb +33 -0
- data/lib/scribble/objects/fixnum.rb +53 -0
- data/lib/scribble/objects/nil.rb +21 -0
- data/lib/scribble/objects/string.rb +62 -0
- data/lib/scribble/parsing/nester.rb +49 -0
- data/lib/scribble/parsing/parser.rb +132 -0
- data/lib/scribble/parsing/reporter.rb +71 -0
- data/lib/scribble/parsing/transform.rb +87 -0
- data/lib/scribble/partial.rb +41 -0
- data/lib/scribble/registry.rb +95 -0
- data/lib/scribble/support/context.rb +98 -0
- data/lib/scribble/support/matcher.rb +74 -0
- data/lib/scribble/support/unmatched.rb +70 -0
- data/lib/scribble/support/utilities.rb +49 -0
- data/lib/scribble/template.rb +61 -0
- data/lib/scribble/version.rb +3 -0
- data/scribble.gemspec +22 -0
- data/test/all.rb +23 -0
- data/test/errors_test.rb +94 -0
- data/test/methods/if_test.rb +49 -0
- data/test/methods/layout_test.rb +71 -0
- data/test/methods/partial_test.rb +85 -0
- data/test/methods/times_test.rb +10 -0
- data/test/objects/boolean_test.rb +162 -0
- data/test/objects/fixnum_test.rb +236 -0
- data/test/objects/nil_test.rb +83 -0
- data/test/objects/string_test.rb +268 -0
- data/test/parsing/parsing_test.rb +234 -0
- data/test/registry_test.rb +264 -0
- data/test/template_test.rb +51 -0
- data/test/test_helper.rb +65 -0
- metadata +127 -0
data/scribble.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'scribble/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "scribble"
|
8
|
+
spec.version = Scribble::VERSION
|
9
|
+
spec.authors = ["Stefan Kroes"]
|
10
|
+
spec.email = ["stefan.kroes@lab01.nl"]
|
11
|
+
spec.summary = "Scribble is a client facing template language similar to Liquid build in Ruby"
|
12
|
+
spec.description = "Scribble is a client facing template language similar to Liquid. Scribble was written in Ruby and can be used in any Ruby or Ruby on Rails project. It takes a template file, consisting of text and Scribble tags and transforms it into text. Scribble can be used to transform any plain text format like HTML, Markdown, JSON, XML, etc. Client facing means that it is safe to use Scribble to run/evaluate user provided templates."
|
13
|
+
spec.homepage = "https://github.com/stefankroes/scribble"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "parslet", "~> 1.6"
|
22
|
+
end
|
data/test/all.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Parsing
|
2
|
+
|
3
|
+
require_relative 'parsing/parsing_test'
|
4
|
+
|
5
|
+
# Main components
|
6
|
+
|
7
|
+
require_relative 'registry_test'
|
8
|
+
require_relative 'template_test'
|
9
|
+
require_relative 'errors_test'
|
10
|
+
|
11
|
+
# Object registrations
|
12
|
+
|
13
|
+
require_relative 'objects/boolean_test'
|
14
|
+
require_relative 'objects/fixnum_test'
|
15
|
+
require_relative 'objects/nil_test'
|
16
|
+
require_relative 'objects/string_test'
|
17
|
+
|
18
|
+
# Method registrations
|
19
|
+
|
20
|
+
require_relative 'methods/if_test'
|
21
|
+
require_relative 'methods/layout_test'
|
22
|
+
require_relative 'methods/partial_test'
|
23
|
+
require_relative 'methods/times_test'
|
data/test/errors_test.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
describe Scribble do
|
4
|
+
it 'provides syntax errors' do
|
5
|
+
assert_scribble_raises '{{ + 1 }}', Scribble::Errors::Syntax, "Unexpected '+' at line 1 column 4, expected '(', 'end', '}}' or a value"
|
6
|
+
assert_scribble_raises '{{ 1 + }}', Scribble::Errors::Syntax, "Unexpected '}' at line 1 column 8, expected '(' or a value"
|
7
|
+
assert_scribble_raises '{{ 1 + ( ) }}', Scribble::Errors::Syntax, "Unexpected ')' at line 1 column 10, expected '(' or a value"
|
8
|
+
assert_scribble_raises '{{ if', Scribble::Errors::Syntax, "Unexpected end of template at line 1 column 6, expected '(', '}}' or an operator"
|
9
|
+
assert_scribble_raises '{{ if {{', Scribble::Errors::Syntax, "Unexpected '{' at line 1 column 7, expected '(', '}}', a value or an operator"
|
10
|
+
assert_scribble_raises '{{ \' }} ', Scribble::Errors::Syntax, "Unexpected end of template at line 1 column 9; unterminated string"
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'provides syntax errors for inproper block nesting' do
|
14
|
+
assert_scribble_raises '{{ if }}', Scribble::Errors::Syntax, "Unexpected end of template; unclosed 'if' block at line 1 column 4"
|
15
|
+
assert_scribble_raises '{{ end }}', Scribble::Errors::Syntax, "Unexpected 'end' at line 1 column 4; no block currently open"
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'provides syntax errors for unexpected split methods' do
|
19
|
+
assert_scribble_raises '{{ if false }}{{ else }}{{ else }}{{ end }}', Scribble::Errors::Syntax, "Unexpected 'else' at line 1 column 28"
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'provides syntax errors for unexpected block methods' do
|
23
|
+
assert_scribble_raises '{{ if if false }}{{ end }}', Scribble::Errors::Syntax, "Unexpected 'if' at line 1 column 7; block methods can't be arguments"
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'provides undefined errors' do
|
27
|
+
assert_scribble_raises '{{ foo }}', Scribble::Errors::Undefined, "Undefined variable or method 'foo' at line 1 column 4"
|
28
|
+
assert_scribble_raises '{{ partial foo }}', Scribble::Errors::Undefined, "Undefined variable or method 'foo' at line 1 column 12"
|
29
|
+
assert_scribble_raises '{{ foo() }}', Scribble::Errors::Undefined, "Undefined method 'foo' at line 1 column 4"
|
30
|
+
assert_scribble_raises '{{ foo 1 }}', Scribble::Errors::Undefined, "Undefined method 'foo' at line 1 column 4"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'provides arity errors' do
|
34
|
+
Scribble::Registry.reset do
|
35
|
+
Scribble::Registry.for Fixnum do
|
36
|
+
method :qux
|
37
|
+
method :qux, Fixnum, String, [String, 1]
|
38
|
+
method :qux, Fixnum, String, String, String, String, [Fixnum]
|
39
|
+
end
|
40
|
+
|
41
|
+
assert_scribble_raises '{{ partial }}', Scribble::Errors::Arity, "Wrong number of arguments (0 for 1-2) for 'partial' at line 1 column 4"
|
42
|
+
assert_scribble_raises '{{ 0.add }}', Scribble::Errors::Arity, "Wrong number of arguments (0 for 1) for 'add' at line 1 column 6"
|
43
|
+
assert_scribble_raises '{{ 0.qux 0 }}', Scribble::Errors::Arity, "Wrong number of arguments (1 for 0, 2-3 or 5+) for 'qux' at line 1 column 6"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'provides argument errors' do
|
48
|
+
Scribble::Registry.reset do
|
49
|
+
Scribble::Registry.for Fixnum do
|
50
|
+
method :qux, [Fixnum], String
|
51
|
+
end
|
52
|
+
|
53
|
+
assert_scribble_raises '{{ partial 1 }}', Scribble::Errors::Argument, "Expected string as 1st argument to 'partial', got number at line 1 column 12"
|
54
|
+
assert_scribble_raises '{{ 0.qux 1 }}', Scribble::Errors::Argument, "Expected string as 2nd argument to 'qux' at line 1 column 6"
|
55
|
+
assert_scribble_raises "{{ 0.qux '', 1 }}", Scribble::Errors::Argument, "Unexpected 2nd argument to 'qux', got number at line 1 column 14"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'provides specific argument errors with locations' do
|
60
|
+
assert_scribble_raises "{{ '' * -1 }}", Scribble::Errors::Argument, "Can't repeat string a negative number of times at line 1 column 7"
|
61
|
+
assert_scribble_raises "{{ ''.truncate(-1) }}", Scribble::Errors::Argument, "Can't truncate string with a negative length at line 1 column 7"
|
62
|
+
assert_scribble_raises "{{ 1 / 0 }}", Scribble::Errors::Argument, 'Division by zero at line 1 column 6'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'combines errors generated in nested contexts' do
|
66
|
+
Scribble::Registry.reset do
|
67
|
+
class SomeBlock < Scribble::Block
|
68
|
+
def foo; render; end; register :foo
|
69
|
+
method :bar, Fixnum, returns: 'bar'
|
70
|
+
method :baz, Fixnum, [Fixnum], returns: 'baz'
|
71
|
+
end
|
72
|
+
|
73
|
+
class SomeMethod < Scribble::Method
|
74
|
+
def baz string; 'baz'; end; register :baz, String
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_scribble_raises '{{ foo }}{{ bar }}{{ end }}', Scribble::Errors::Arity, "Wrong number of arguments (0 for 1) for 'bar' at line 1 column 13"
|
78
|
+
assert_scribble_raises '{{ foo }}{{ baz }}{{ end }}', Scribble::Errors::Arity, "Wrong number of arguments (0 for 1 or 1+) for 'baz' at line 1 column 13"
|
79
|
+
assert_scribble_raises '{{ foo }}{{ baz true }}{{ end }}', Scribble::Errors::Argument, "Expected string or number as 1st argument to 'baz', got boolean at line 1 column 17"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'does not call split methods from a nested context' do
|
84
|
+
Scribble::Registry.reset do
|
85
|
+
class SomeBlock < Scribble::Block
|
86
|
+
register :foo
|
87
|
+
def foo; render; end
|
88
|
+
method :bar, split: true
|
89
|
+
end
|
90
|
+
|
91
|
+
assert_scribble_raises '{{ foo }}{{ if true }}{{ bar }}{{ end }}{{ end }}', Scribble::Errors::Undefined, "Undefined variable or method 'bar' at line 1 column 26"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Scribble::Methods::If do
|
4
|
+
it 'renders according if-elsif-else semantics' do
|
5
|
+
assert_scribble_render '{{ if true }}Foo {{ end }}Bar', 'Foo Bar'
|
6
|
+
assert_scribble_render '{{ if false }}Foo {{ end }}Bar', 'Bar'
|
7
|
+
|
8
|
+
assert_scribble_render '{{ if true }}Foo {{ else }}Bar {{ end }}Baz', 'Foo Baz'
|
9
|
+
assert_scribble_render '{{ if false }}Foo {{ else }}Bar {{ end }}Baz', 'Bar Baz'
|
10
|
+
|
11
|
+
assert_scribble_render '{{ if true }}Foo {{ elsif true }}Bar {{ end }}Baz', 'Foo Baz'
|
12
|
+
assert_scribble_render '{{ if false }}Foo {{ elsif true }}Bar {{ end }}Baz', 'Bar Baz'
|
13
|
+
assert_scribble_render '{{ if true }}Foo {{ elsif false }}Bar {{ end }}Baz', 'Foo Baz'
|
14
|
+
assert_scribble_render '{{ if false }}Foo {{ elsif false }}Bar {{ end }}Baz', 'Baz'
|
15
|
+
|
16
|
+
assert_scribble_render '{{ if true }}Foo {{ elsif true }}Bar {{ else }}Qux {{ end }}Baz', 'Foo Baz'
|
17
|
+
assert_scribble_render '{{ if false }}Foo {{ elsif true }}Bar {{ else }}Qux {{ end }}Baz', 'Bar Baz'
|
18
|
+
assert_scribble_render '{{ if true }}Foo {{ elsif false }}Bar {{ else }}Qux {{ end }}Baz', 'Foo Baz'
|
19
|
+
assert_scribble_render '{{ if false }}Foo {{ elsif false }}Bar {{ else }}Qux {{ end }}Baz', 'Qux Baz'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'casts numbers to booleans' do
|
23
|
+
assert_scribble_render '{{ if 1 }}Foo {{ elsif 1 }}Bar {{ end }}Baz', 'Foo Baz'
|
24
|
+
assert_scribble_render '{{ if 0 }}Foo {{ elsif 1 }}Bar {{ end }}Baz', 'Bar Baz'
|
25
|
+
assert_scribble_render '{{ if 1 }}Foo {{ elsif 0 }}Bar {{ end }}Baz', 'Foo Baz'
|
26
|
+
assert_scribble_render '{{ if 0 }}Foo {{ elsif 0 }}Bar {{ end }}Baz', 'Baz'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'casts strings to booleans' do
|
30
|
+
assert_scribble_render '{{ if 1 }}Foo {{ elsif 1 }}Bar {{ end }}Baz', 'Foo Baz'
|
31
|
+
assert_scribble_render '{{ if 0 }}Foo {{ elsif 1 }}Bar {{ end }}Baz', 'Bar Baz'
|
32
|
+
assert_scribble_render '{{ if 1 }}Foo {{ elsif 0 }}Bar {{ end }}Baz', 'Foo Baz'
|
33
|
+
assert_scribble_render '{{ if 0 }}Foo {{ elsif 0 }}Bar {{ end }}Baz', 'Baz'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'works with boolean expressions' do
|
37
|
+
assert_scribble_render '{{ if 1 = 1 }}Foo {{ elsif 1 < 2 }}Bar {{ end }}Baz', 'Foo Baz'
|
38
|
+
assert_scribble_render '{{ if 3 > 10 }}Foo {{ elsif 5 <= 10 }}Bar {{ end }}Baz', 'Bar Baz'
|
39
|
+
assert_scribble_render '{{ if 5 != 3 }}Foo {{ elsif 1.zero }}Bar {{ end }}Baz', 'Foo Baz'
|
40
|
+
assert_scribble_render '{{ if (0.nonzero) }}Foo {{ elsif 5 < 0 }}Bar {{ end }}Baz', 'Baz'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'casts other expressions to booleans' do
|
44
|
+
assert_scribble_render "{{ if 1 + 1 }}Foo {{ elsif 'foo'.replace('foo', '') }}Bar {{ end }}Baz", 'Foo Baz'
|
45
|
+
assert_scribble_render "{{ if 1 - 1 }}Foo {{ elsif 3 * 'foo' }}Bar {{ end }}Baz", 'Bar Baz'
|
46
|
+
assert_scribble_render "{{ if ' ' }}Foo {{ elsif ' '.strip }}Bar {{ end }}Baz", 'Foo Baz'
|
47
|
+
assert_scribble_render "{{ if '' * 5 }}Foo {{ elsif 0.abs }}Bar {{ end }}Baz", 'Baz'
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Scribble::Methods::Layout do
|
4
|
+
it 'loads and renders a layout template' do
|
5
|
+
loader = MockLoader.new test: 'Foo {{ content }} Baz'
|
6
|
+
assert_scribble_render "{{ layout 'test' }}Bar{{end}}", 'Foo Bar Baz', template: {loader: loader}
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'evaluates expressions in the template' do
|
10
|
+
loader = MockLoader.new test: "{{ 'Foo' * 2 }} {{ content.repeat(2) }} Baz"
|
11
|
+
assert_scribble_render "{{ layout 'test' }}Bar{{end}}", 'FooFoo BarBar Baz', template: {loader: loader}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Access
|
15
|
+
|
16
|
+
it 'has access to template methods' do
|
17
|
+
loader = MockLoader.new test: 'Foo {{ if true }}{{ content }} {{ end }}Baz'
|
18
|
+
assert_scribble_render "{{ layout 'test' }}Bar{{end}}", 'Foo Bar Baz', template: {loader: loader}
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has access to template variables' do
|
22
|
+
loader = MockLoader.new test: 'Foo {{ content }} Baz {{ 12 }}'
|
23
|
+
assert_scribble_render "{{ layout 'test' }}Bar{{end}}", 'Foo Bar Baz 12', template: {loader: loader}, variables: {foo: 12}
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'has access to layout variables' do
|
27
|
+
skip # Implement var first
|
28
|
+
end
|
29
|
+
|
30
|
+
# Passing object and nesting
|
31
|
+
|
32
|
+
it 'exposes a second argument as a variable' do
|
33
|
+
loader = MockLoader.new test: '{{ test }} {{ content }}'
|
34
|
+
assert_scribble_render "{{ layout 'test', 'Foo' }}Bar {{end}}Baz", 'Foo Bar Baz', template: {loader: loader}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'exposes a second argument as a variable when nested' do
|
38
|
+
loader = MockLoader.new foo: "{{ foo }}{{ layout 'bar', content }}{{ foo }}{{ end }}{{ foo }}", bar: '{{ bar }}{{ content }}{{ bar }}'
|
39
|
+
assert_scribble_render "0{{ layout 'foo', 1 }}2{{end}}0", '0121210', template: {loader: loader}
|
40
|
+
end
|
41
|
+
|
42
|
+
# Formats
|
43
|
+
|
44
|
+
it 'adopts context format when no layout format is specified' do
|
45
|
+
loader = MockLoader.new foo: '{{ content }}'
|
46
|
+
assert_scribble_render "{{ layout 'foo' }}FOO{{ end }}", 'FOO', template: {loader: loader, format: :template_format}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "won't need converter to render a layout in template format" do
|
50
|
+
loader = MockLoader.new foo: ['{{ content }}', :template_format]
|
51
|
+
assert_scribble_render "{{ layout 'foo' }}FOO{{ end }}", 'FOO', template: {loader: loader, format: :template_format}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "can't render a layout with a format without suitable converters back and forth" do
|
55
|
+
loader = MockLoader.new foo: ['{{ content }}BAR', :layout_format]
|
56
|
+
c1 = MockConverter.new :layout_format, :template_format
|
57
|
+
c2 = MockConverter.new :template_format, :layout_format
|
58
|
+
|
59
|
+
assert_raises_message 'No suitable converter' do
|
60
|
+
Scribble::Template.new("{{ layout 'foo' }}FOO{{ end }}", loader: loader, format: :template_format, converters: [c1]).render
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_raises_message 'No suitable converter' do
|
64
|
+
Scribble::Template.new("{{ layout 'foo' }}FOO{{ end }}", loader: loader, format: :template_format, converters: [c2]).render
|
65
|
+
end
|
66
|
+
|
67
|
+
assert_scribble_render "{{ layout 'foo' }}FOO{{ end }}", 'layout_format > template_format(template_format > layout_format(FOO)BAR)',
|
68
|
+
template: {loader: loader, format: :template_format, converters: [c1, c2]}
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Scribble::Methods::Partial do
|
4
|
+
it 'loads and renders a partial template' do
|
5
|
+
loader = MockLoader.new test: 'Foo Bar Baz'
|
6
|
+
assert_scribble_render "{{ partial 'test' }}", 'Foo Bar Baz', template: {loader: loader}
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'evaluates expressions in the template' do
|
10
|
+
loader = MockLoader.new test: '{{ 1 + 2 }}'
|
11
|
+
assert_scribble_render "{{ partial 'test' }}", '3', template: {loader: loader}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Access
|
15
|
+
|
16
|
+
it 'has access to template methods' do
|
17
|
+
loader = MockLoader.new test: '{{ if true }}foo{{ else }}bar{{ end }}'
|
18
|
+
assert_scribble_render "{{ partial 'test' }}", 'foo', template: {loader: loader}
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has access to template variables' do
|
22
|
+
loader = MockLoader.new test: 'foo={{ foo }}, bar={{ bar }}, foo * bar={{ foo * bar }}'
|
23
|
+
assert_scribble_render "{{ partial 'test' }}", 'foo=3, bar=Foo, foo * bar=FooFooFoo', template: {loader: loader}, variables: {foo: 3, bar: 'Foo'}
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'has access to template variables when nested' do
|
27
|
+
loader = MockLoader.new test: "{{ partial 'nested' }}", nested: '{{ foo }}'
|
28
|
+
assert_scribble_render "foo={{ partial 'test' }}", 'foo=3', template: {loader: loader}, variables: {foo: 3}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Passing object
|
32
|
+
|
33
|
+
it 'exposes a second argument as a variable' do
|
34
|
+
loader = MockLoader.new test: '{{ test }}'
|
35
|
+
assert_scribble_render "{{ partial 'test', 'foo' }}", 'foo', template: {loader: loader}, variables: {foo: 3}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Formats
|
39
|
+
|
40
|
+
it 'ignores partial format if no render format is specified' do
|
41
|
+
loader = MockLoader.new foo: ['FOO', :partial_format]
|
42
|
+
assert_scribble_render "{{ partial 'foo' }}", 'FOO', template: {loader: loader}
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'adopts context format when no partial format is specified' do
|
46
|
+
loader = MockLoader.new foo: 'FOO'
|
47
|
+
assert_scribble_render "{{ partial 'foo' }}", 'FOO', template: {loader: loader, format: :template_format}
|
48
|
+
end
|
49
|
+
|
50
|
+
it "can't render a partial with format without a suitable converter" do
|
51
|
+
loader = MockLoader.new foo: ['FOO', :partial_format]
|
52
|
+
assert_raises_message 'No suitable converter' do
|
53
|
+
Scribble::Template.new("{{ partial 'foo' }}", loader: loader, format: :template_format).render
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "won't need converter to render a partial in template format" do
|
58
|
+
loader = MockLoader.new foo: ['FOO', :template_format]
|
59
|
+
assert_scribble_render "{{ partial 'foo' }}", 'FOO', template: {loader: loader, format: :template_format}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "converts a partial with format to the template format using a suitable converter" do
|
63
|
+
loader = MockLoader.new foo: ['FOO', :partial_format]
|
64
|
+
converter = MockConverter.new :partial_format, :template_format
|
65
|
+
assert_scribble_render "{{ partial 'foo' }}", 'partial_format > template_format(FOO)',
|
66
|
+
template: {loader: loader, format: :template_format, converters: [converter]}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Formats and nested partials
|
70
|
+
|
71
|
+
it "won't converted nested partials with the same format" do
|
72
|
+
loader = MockLoader.new test: ["{{ partial 'nested' }}", :partial_format], nested: ['NESTED', :partial_format]
|
73
|
+
converter = MockConverter.new :partial_format, :template_format
|
74
|
+
assert_scribble_render "{{ partial 'test' }}", 'partial_format > template_format(NESTED)',
|
75
|
+
template: {loader: loader, format: :template_format, converters: [converter]}
|
76
|
+
end
|
77
|
+
|
78
|
+
it "converts nested partials" do
|
79
|
+
loader = MockLoader.new test: ["{{ partial 'nested' }}", :partial_format], nested: ['NESTED', :nested_partial_format]
|
80
|
+
c1 = MockConverter.new :partial_format, :template_format
|
81
|
+
c2 = MockConverter.new :nested_partial_format, :partial_format
|
82
|
+
assert_scribble_render "{{ partial 'test' }}", 'partial_format > template_format(nested_partial_format > partial_format(NESTED))',
|
83
|
+
template: {loader: loader, format: :template_format, converters: [c1, c2]}
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Scribble::Methods::Times do
|
4
|
+
it 'repeats a block of content x times' do
|
5
|
+
assert_scribble_render "{{ 0.times }}Foo Bar {{ end }}", ''
|
6
|
+
assert_scribble_render "{{ 1.times }}Foo Bar {{ end }}", 'Foo Bar '
|
7
|
+
assert_scribble_render "{{ 3.times }}Foo Bar {{ end }}", 'Foo Bar Foo Bar Foo Bar '
|
8
|
+
assert_scribble_render "{{ 5.times }}Foo Bar {{ end }}", 'Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar '
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe 'scribble boolean' do
|
4
|
+
it 'can be used as a literal' do
|
5
|
+
assert_scribble_render '{{ true }}', 'true'
|
6
|
+
assert_scribble_render '{{ false }}', 'false'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'supports method and operator for logical or' do
|
10
|
+
assert_scribble_render '{{ false.or true }}', 'true'
|
11
|
+
assert_scribble_render '{{ true.or true }}', 'true'
|
12
|
+
assert_scribble_render '{{ false.or false }}', 'false'
|
13
|
+
assert_scribble_render '{{ true.or false }}', 'true'
|
14
|
+
assert_scribble_render '{{ false.or 2 }}', 'true'
|
15
|
+
assert_scribble_render '{{ true.or 2 }}', 'true'
|
16
|
+
assert_scribble_render '{{ false.or 0 }}', 'false'
|
17
|
+
assert_scribble_render '{{ true.or 0 }}', 'true'
|
18
|
+
assert_scribble_render "{{ false.or 'foo' }}", 'true'
|
19
|
+
assert_scribble_render "{{ true.or 'foo' }}", 'true'
|
20
|
+
assert_scribble_render "{{ false.or '' }}", 'false'
|
21
|
+
assert_scribble_render "{{ true.or '' }}", 'true'
|
22
|
+
assert_scribble_render '{{ false | true }}', 'true'
|
23
|
+
assert_scribble_render '{{ true | true }}', 'true'
|
24
|
+
assert_scribble_render '{{ false | false }}', 'false'
|
25
|
+
assert_scribble_render '{{ true | false }}', 'true'
|
26
|
+
assert_scribble_render '{{ false | 2 }}', 'true'
|
27
|
+
assert_scribble_render '{{ true | 2 }}', 'true'
|
28
|
+
assert_scribble_render '{{ false | 0 }}', 'false'
|
29
|
+
assert_scribble_render '{{ true | 0 }}', 'true'
|
30
|
+
assert_scribble_render "{{ false | 'foo' }}", 'true'
|
31
|
+
assert_scribble_render "{{ true | 'foo' }}", 'true'
|
32
|
+
assert_scribble_render "{{ false | '' }}", 'false'
|
33
|
+
assert_scribble_render "{{ true | '' }}", 'true'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'supports method and operator for logical and' do
|
37
|
+
assert_scribble_render '{{ false.and true }}', 'false'
|
38
|
+
assert_scribble_render '{{ true.and true }}', 'true'
|
39
|
+
assert_scribble_render '{{ false.and false }}', 'false'
|
40
|
+
assert_scribble_render '{{ true.and false }}', 'false'
|
41
|
+
assert_scribble_render '{{ false.and 2 }}', 'false'
|
42
|
+
assert_scribble_render '{{ true.and 2 }}', 'true'
|
43
|
+
assert_scribble_render '{{ false.and 0 }}', 'false'
|
44
|
+
assert_scribble_render '{{ true.and 0 }}', 'false'
|
45
|
+
assert_scribble_render "{{ false.and 'foo' }}", 'false'
|
46
|
+
assert_scribble_render "{{ true.and 'foo' }}", 'true'
|
47
|
+
assert_scribble_render "{{ false.and '' }}", 'false'
|
48
|
+
assert_scribble_render "{{ true.and '' }}", 'false'
|
49
|
+
assert_scribble_render '{{ false & true }}', 'false'
|
50
|
+
assert_scribble_render '{{ true & true }}', 'true'
|
51
|
+
assert_scribble_render '{{ false & false }}', 'false'
|
52
|
+
assert_scribble_render '{{ true & false }}', 'false'
|
53
|
+
assert_scribble_render '{{ false & 2 }}', 'false'
|
54
|
+
assert_scribble_render '{{ true & 2 }}', 'true'
|
55
|
+
assert_scribble_render '{{ false & 0 }}', 'false'
|
56
|
+
assert_scribble_render '{{ true & 0 }}', 'false'
|
57
|
+
assert_scribble_render "{{ false & 'foo' }}", 'false'
|
58
|
+
assert_scribble_render "{{ true & 'foo' }}", 'true'
|
59
|
+
assert_scribble_render "{{ false & '' }}", 'false'
|
60
|
+
assert_scribble_render "{{ true & '' }}", 'false'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can equal another boolean' do
|
64
|
+
assert_scribble_render '{{ true.equals true }}', 'true'
|
65
|
+
assert_scribble_render '{{ true.equals false }}', 'false'
|
66
|
+
assert_scribble_render '{{ true = true }}', 'true'
|
67
|
+
assert_scribble_render '{{ true = false }}', 'false'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'does not equal another type' do
|
71
|
+
assert_scribble_render '{{ true.equals 3 }}', 'false'
|
72
|
+
assert_scribble_render "{{ true.equals 'foo' }}", 'false'
|
73
|
+
assert_scribble_render '{{ true = 3 }}', 'false'
|
74
|
+
assert_scribble_render "{{ true = 'foo' }}", 'false'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'can differ from another boolean' do
|
78
|
+
assert_scribble_render '{{ true.differs true }}', 'false'
|
79
|
+
assert_scribble_render '{{ true.differs false }}', 'true'
|
80
|
+
assert_scribble_render '{{ true != true }}', 'false'
|
81
|
+
assert_scribble_render '{{ true != false }}', 'true'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'differs from another type' do
|
85
|
+
assert_scribble_render '{{ true.differs 3 }}', 'true'
|
86
|
+
assert_scribble_render "{{ true.differs 'foo' }}", 'true'
|
87
|
+
assert_scribble_render '{{ true != 3 }}', 'true'
|
88
|
+
assert_scribble_render "{{ true != 'foo' }}", 'true'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'can not be compared' do
|
92
|
+
assert_scribble_raises "{{ true.greater 'foo' }}"
|
93
|
+
assert_scribble_raises '{{ true.greater 3 }}'
|
94
|
+
assert_scribble_raises '{{ true.greater true }}'
|
95
|
+
assert_scribble_raises "{{ true > 'foo' }}"
|
96
|
+
assert_scribble_raises '{{ true > 3 }}'
|
97
|
+
assert_scribble_raises '{{ true > true }}'
|
98
|
+
assert_scribble_raises "{{ true.less 'foo' }}"
|
99
|
+
assert_scribble_raises '{{ true.less 3 }}'
|
100
|
+
assert_scribble_raises '{{ true.less true }}'
|
101
|
+
assert_scribble_raises "{{ true < 'foo' }}"
|
102
|
+
assert_scribble_raises '{{ true < 3 }}'
|
103
|
+
assert_scribble_raises '{{ true < true }}'
|
104
|
+
assert_scribble_raises "{{ true.greater_or_equal 'foo' }}"
|
105
|
+
assert_scribble_raises '{{ true.greater_or_equal 3 }}'
|
106
|
+
assert_scribble_raises '{{ true.greater_or_equal true }}'
|
107
|
+
assert_scribble_raises "{{ true >= 'foo' }}"
|
108
|
+
assert_scribble_raises '{{ true >= 3 }}'
|
109
|
+
assert_scribble_raises '{{ true >= true }}'
|
110
|
+
assert_scribble_raises "{{ true.less_or_equal 'foo' }}"
|
111
|
+
assert_scribble_raises '{{ true.less_or_equal 3 }}'
|
112
|
+
assert_scribble_raises '{{ true.less_or_equal true }}'
|
113
|
+
assert_scribble_raises "{{ true <= 'foo' }}"
|
114
|
+
assert_scribble_raises '{{ true <= 3 }}'
|
115
|
+
assert_scribble_raises '{{ true <= true }}'
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'does not support calculations' do
|
119
|
+
assert_scribble_raises '{{ true.add 3 }}'
|
120
|
+
assert_scribble_raises "{{ true.add 'foo' }}"
|
121
|
+
assert_scribble_raises '{{ true.add true }}'
|
122
|
+
assert_scribble_raises '{{ true + 3 }}'
|
123
|
+
assert_scribble_raises "{{ true + 'foo' }}"
|
124
|
+
assert_scribble_raises '{{ true + true }}'
|
125
|
+
assert_scribble_raises '{{ true.subtract 3 }}'
|
126
|
+
assert_scribble_raises "{{ true.subtract 'foo' }}"
|
127
|
+
assert_scribble_raises '{{ true.subtract true }}'
|
128
|
+
assert_scribble_raises '{{ true - 3 }}'
|
129
|
+
assert_scribble_raises "{{ true - 'foo' }}"
|
130
|
+
assert_scribble_raises '{{ true - true }}'
|
131
|
+
assert_scribble_raises '{{ true.multiply 3 }}'
|
132
|
+
assert_scribble_raises "{{ true.multiply 'foo' }}"
|
133
|
+
assert_scribble_raises '{{ true.multiply true }}'
|
134
|
+
assert_scribble_raises '{{ true * 3 }}'
|
135
|
+
assert_scribble_raises "{{ true * 'foo' }}"
|
136
|
+
assert_scribble_raises '{{ true * true }}'
|
137
|
+
assert_scribble_raises '{{ true.divide 3 }}'
|
138
|
+
assert_scribble_raises "{{ true.divide 'foo' }}"
|
139
|
+
assert_scribble_raises '{{ true.divide true }}'
|
140
|
+
assert_scribble_raises '{{ true / 3 }}'
|
141
|
+
assert_scribble_raises "{{ true / 'foo' }}"
|
142
|
+
assert_scribble_raises '{{ true / true }}'
|
143
|
+
assert_scribble_raises '{{ true.remainder 3 }}'
|
144
|
+
assert_scribble_raises "{{ true.remainder 'foo' }}"
|
145
|
+
assert_scribble_raises '{{ true.remainder true }}'
|
146
|
+
assert_scribble_raises '{{ true % 3 }}'
|
147
|
+
assert_scribble_raises "{{ true % 'foo' }}"
|
148
|
+
assert_scribble_raises '{{ true % true }}'
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'can not be negated' do
|
152
|
+
assert_scribble_raises '{{ true.negative }}'
|
153
|
+
assert_scribble_raises '{{ -true }}'
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'can be logically negated' do
|
157
|
+
assert_scribble_render '{{ true.not }}', 'false'
|
158
|
+
assert_scribble_render '{{ false.not }}', 'true'
|
159
|
+
assert_scribble_render '{{ !!true }}', 'true'
|
160
|
+
assert_scribble_render '{{ !!!true }}', 'false'
|
161
|
+
end
|
162
|
+
end
|