scribble 1.0.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.
- 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
         |