syro-tilt 0.1.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 +10 -0
- data/.rubocop.yml +60 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +102 -0
- data/Rakefile +11 -0
- data/lib/syro/tilt.rb +191 -0
- data/syro-tilt.gemspec +20 -0
- data/test/syro_tilt_test.rb +149 -0
- data/test/views/layout.erb +3 -0
- data/test/views/locals.erb +1 -0
- data/test/views/notsoplain.html.erb +1 -0
- data/test/views/plain.txt.erb +1 -0
- data/test/views/typed.anope.erb +1 -0
- data/test/views/typed.html.erb +1 -0
- data/test/views/typed.json.erb +1 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0c344875f1c37067ea3ede68552941eda515bf0d3e0b66e9b3335c5e5b15900f
|
4
|
+
data.tar.gz: a2d4cec3221689f8b5f7c221c9e09f2e22f5c148266aacdb73c8cf41716e245d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 67f316b8d950eb1fcf8409883c47a000c1959c1ab208593681012d70b74642d6bce3b7df77e10bf6ff87975f121cb632da015704104c35774582a67df494e211
|
7
|
+
data.tar.gz: 03711476cdca8eb7867d3ab041e349f4d0cd57d464393753a46ab3319db766169054d97b4cefd694cca88f27a6e805b8747e8117724f987f78c27664a9ebbe7a
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# http://rubocop.readthedocs.io
|
2
|
+
# https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml
|
3
|
+
AllCops:
|
4
|
+
DisplayCopNames: true
|
5
|
+
DisplayStyleGuide: true
|
6
|
+
ExtraDetails: true
|
7
|
+
TargetRubyVersion: 2.5
|
8
|
+
|
9
|
+
|
10
|
+
Performance:
|
11
|
+
enabled: true
|
12
|
+
|
13
|
+
Layout/AlignParameters:
|
14
|
+
EnforcedStyle: with_fixed_indentation
|
15
|
+
|
16
|
+
Layout/EmptyLineAfterMagicComment:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Layout/IndentHash:
|
20
|
+
EnforcedStyle: consistent
|
21
|
+
|
22
|
+
Layout/MultilineOperationIndentation:
|
23
|
+
EnforcedStyle: indented
|
24
|
+
|
25
|
+
Layout/SpaceInsideStringInterpolation:
|
26
|
+
EnforcedStyle: space
|
27
|
+
|
28
|
+
Metrics/AbcSize:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Metrics/BlockLength:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Metrics/ClassLength:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Metrics/CyclomaticComplexity:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Metrics/LineLength:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
Metrics/MethodLength:
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
Metrics/ModuleLength:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
Metrics/PerceivedComplexity:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
Style/FormatStringToken:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
Style/IfUnlessModifier:
|
56
|
+
Enabled: false
|
57
|
+
|
58
|
+
Style/Next:
|
59
|
+
MinBodyLength: 8
|
60
|
+
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Evan Lecklider
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Syro::Tilt
|
2
|
+
|
3
|
+
Render [Tilt][tilt] templates in [Syro][syro] routes.
|
4
|
+
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
An example Syro app using Syro::Tilt would look like this:
|
9
|
+
|
10
|
+
```erb
|
11
|
+
<%# 'html.html.erb' %>
|
12
|
+
<% greeting = 'Hey there!' %>
|
13
|
+
|
14
|
+
<p>
|
15
|
+
<%= greeting %>
|
16
|
+
</p>
|
17
|
+
```
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'syro'
|
21
|
+
require 'syro/tilt'
|
22
|
+
|
23
|
+
app = Syro.new do
|
24
|
+
get do
|
25
|
+
render 'home'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
Calling `render` will look for a template file (e.g. "views/home.html.erb"),
|
31
|
+
render it in the context of the route, write the content to Syro's response, and
|
32
|
+
set the `Content-Type` header based on the file extension (i.e. the ".html"
|
33
|
+
means that it's a `text/html` response).
|
34
|
+
|
35
|
+
|
36
|
+
## API
|
37
|
+
|
38
|
+
`partial`: render a template from Tilt into a string, optionally passing in
|
39
|
+
local variables and yielding to a block.
|
40
|
+
|
41
|
+
`render`: render a Tilt template to a string (using `partial`), write the
|
42
|
+
contents to Syro's response, and set the content type.
|
43
|
+
|
44
|
+
`layout`: set (or get) a layout file to be used to wrap calls to `render`.
|
45
|
+
|
46
|
+
`templates_directory`: the default directory to look for template files in.
|
47
|
+
Overwriting this method is the recommended way to configure your template
|
48
|
+
location. For example:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
def templates_directory
|
52
|
+
'app/views'
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
`template_options`: a hash of options passed to `Tilt.new`. The class of the
|
57
|
+
template being instantiated is passed so you can customize the options for each
|
58
|
+
template engine. Overwriting this method is the recommended way to configure
|
59
|
+
template options per engine. For example:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
def template_options(templ)
|
63
|
+
if templ == Hamlit::Block::Engine
|
64
|
+
{ escape_html: true }
|
65
|
+
elsif templ == Tilt::ErubiTemplate
|
66
|
+
{ engine_class: Erubi::CaptureEndEngine, escape: true, escape_capture: false, freeze: true, yield_returns_buffer: true }
|
67
|
+
else
|
68
|
+
{}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
`template`: create a new `Tilt` instance from a path to a template.
|
74
|
+
|
75
|
+
`content_for`: capture content for use later.
|
76
|
+
|
77
|
+
|
78
|
+
## Installation
|
79
|
+
|
80
|
+
Add this line to your application's Gemfile:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
gem 'syro-tilt', require: 'syro/tilt'
|
84
|
+
```
|
85
|
+
|
86
|
+
And then execute:
|
87
|
+
|
88
|
+
$ bundle
|
89
|
+
|
90
|
+
Or install it yourself as:
|
91
|
+
|
92
|
+
$ gem install syro-tilt
|
93
|
+
|
94
|
+
|
95
|
+
## License
|
96
|
+
|
97
|
+
The gem is available as open source under the terms of the [MIT License][mit].
|
98
|
+
|
99
|
+
|
100
|
+
[mit]: https://opensource.org/licenses/MIT
|
101
|
+
[syro]: https://github.com/soveran/syro
|
102
|
+
[tilt]: https://github.com/rtomayko/tilt
|
data/Rakefile
ADDED
data/lib/syro/tilt.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'syro'
|
3
|
+
require 'tilt'
|
4
|
+
|
5
|
+
class Syro # :nodoc:
|
6
|
+
# Render Tilt templates in Syro routes.
|
7
|
+
module Tilt
|
8
|
+
DEFAULT_MIME_TYPE = 'text/plain'
|
9
|
+
DOT = '.'
|
10
|
+
EMPTY = ''
|
11
|
+
HTTP_ACCEPT = 'HTTP_ACCEPT'
|
12
|
+
MIME_TYPE_ANY = '*/*'
|
13
|
+
|
14
|
+
ACCEPT_CAPTURE_QUALITY = /\Aq=([\d.]+)/.freeze
|
15
|
+
ACCEPT_SPLIT_MULTIPLES = /\s*,\s*/.freeze
|
16
|
+
ACCEPT_SPLIT_PARTS = /\s*;\s*/.freeze
|
17
|
+
|
18
|
+
# A Tilt template for the file path passed in.
|
19
|
+
#
|
20
|
+
# @return [Tilt::Template]
|
21
|
+
def template(path)
|
22
|
+
::Tilt.new(path, template_options(::Tilt.template_for(path)))
|
23
|
+
end
|
24
|
+
|
25
|
+
# Options passed to Tilt.new.
|
26
|
+
#
|
27
|
+
# @param templ [Class]
|
28
|
+
# The class of the template engine being used e.g. "Tilt::ErubiTemplate".
|
29
|
+
#
|
30
|
+
# @return [Hash]
|
31
|
+
def template_options(_templ = nil)
|
32
|
+
{}
|
33
|
+
end
|
34
|
+
|
35
|
+
# The default directory to look for templates within.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
def templates_directory
|
39
|
+
'views'
|
40
|
+
end
|
41
|
+
|
42
|
+
# Find a template's file path based on a "fuzzy" name like "posts/show". The
|
43
|
+
# HTTP Accept header will be checked and the first template found that
|
44
|
+
# matches the MIME type of the Accept header will be used, otherwise the
|
45
|
+
# first matching template file will be used.
|
46
|
+
#
|
47
|
+
# @param path [String]
|
48
|
+
# A "fuzzy" file path like "posts/show".
|
49
|
+
# @param from [String]
|
50
|
+
# The directory to look for templates within.
|
51
|
+
#
|
52
|
+
# @return [String]
|
53
|
+
# The path to the template file.
|
54
|
+
def template_path(path, from = nil)
|
55
|
+
from ||= templates_directory
|
56
|
+
path = File.join(from, path)
|
57
|
+
|
58
|
+
accepts = env.fetch(HTTP_ACCEPT) { EMPTY }.to_s.then do |header|
|
59
|
+
# Taken from Rack::Request#parse_http_accept_header (which is a private
|
60
|
+
# method).
|
61
|
+
header.split(ACCEPT_SPLIT_MULTIPLES).map do |part|
|
62
|
+
attribute, parameters = part.split(ACCEPT_SPLIT_PARTS, 2)
|
63
|
+
quality = 1.0
|
64
|
+
|
65
|
+
if parameters && ACCEPT_CAPTURE_QUALITY.match?(parameters)
|
66
|
+
quality = ACCEPT_CAPTURE_QUALITY.match(parameters)[1].to_f
|
67
|
+
end
|
68
|
+
|
69
|
+
[attribute, quality]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Reject "*/*" because it will always match the first thing it is compared
|
74
|
+
# to, regardless of wether there's a better match coming up.
|
75
|
+
accepts.reject! { |acc, _q| acc == MIME_TYPE_ANY }
|
76
|
+
|
77
|
+
# Find all potential templates e.g. ones with the same name but different
|
78
|
+
# template engines or MIME types.
|
79
|
+
potentials = Dir.glob(File.join(from, '**', '*')).filter do |potential|
|
80
|
+
potential.start_with?(path)
|
81
|
+
end.sort
|
82
|
+
|
83
|
+
# Select the best potential template match based on MIME type and HTTP
|
84
|
+
# Accept header.
|
85
|
+
potentials.find do |potential|
|
86
|
+
content_type = template_mime_type(potential)
|
87
|
+
|
88
|
+
accepts.any? do |acc, _quality|
|
89
|
+
Rack::Mime.match?(content_type, acc)
|
90
|
+
end
|
91
|
+
end || potentials.first
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get the MIME type of a template file. The MIME type is looked up from
|
95
|
+
# Rack's MIME type list.
|
96
|
+
#
|
97
|
+
# @return [String]
|
98
|
+
def template_mime_type(path)
|
99
|
+
File.basename(path).split(DOT).reverse.map do |ext|
|
100
|
+
Rack::Mime::MIME_TYPES[".#{ ext.downcase }"]
|
101
|
+
end.compact.first || DEFAULT_MIME_TYPE
|
102
|
+
end
|
103
|
+
|
104
|
+
# Generate a string by rendering the Tilt template in the context of `self`
|
105
|
+
# with the locals that were passed in.
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
# partial('posts/show') # => "OMG look at this page!"
|
109
|
+
#
|
110
|
+
# @param path [String]
|
111
|
+
# The path to the view template you'd like to render.
|
112
|
+
# @param locals [Hash]
|
113
|
+
# The local variables to pass to the template.
|
114
|
+
# @option locals [String] :from
|
115
|
+
# The directory to look for templates within.
|
116
|
+
#
|
117
|
+
# @return [String]
|
118
|
+
def partial(path, locals = {})
|
119
|
+
template(template_path(path, locals.delete(:from))).render(self, locals) { yield if block_given? }
|
120
|
+
end
|
121
|
+
|
122
|
+
# Set or get the current layout. A layout is just another template to wrap
|
123
|
+
# other templates in. If set, it'll be used by #render.
|
124
|
+
#
|
125
|
+
# @param path [String]
|
126
|
+
# A path to a template file.
|
127
|
+
#
|
128
|
+
# @return [String, nil]
|
129
|
+
def layout(templ = nil)
|
130
|
+
inbox[:tilt_layout] = templ if templ
|
131
|
+
inbox[:tilt_layout]
|
132
|
+
end
|
133
|
+
|
134
|
+
# Render a template to Syro's #res object and write the appropriate MIME
|
135
|
+
# type based on the rendered template.
|
136
|
+
#
|
137
|
+
# @param path [String]
|
138
|
+
# The path to a view file.
|
139
|
+
# @param locals [Hash]
|
140
|
+
# Local variables that should be accessible to the view.
|
141
|
+
# @option locals [String] :from
|
142
|
+
# The directory to look for templates within.
|
143
|
+
def render(path, locals = {})
|
144
|
+
content = partial(path, locals.dup) { yield if block_given? }
|
145
|
+
content = partial(layout, locals.dup) { content } if layout
|
146
|
+
|
147
|
+
res.headers[Rack::CONTENT_TYPE] = template_mime_type(template_path(path, locals[:from]))
|
148
|
+
res.write content
|
149
|
+
end
|
150
|
+
|
151
|
+
# Capture content from a block for use later. Note that capturing the block
|
152
|
+
# is not implemented here due to the differences in varying template
|
153
|
+
# languages. Erubi::CaptureEndEngine and Hamlit::Block::Engine work well
|
154
|
+
# with this method.
|
155
|
+
#
|
156
|
+
# @param key [Symbol]
|
157
|
+
# The content key name.
|
158
|
+
#
|
159
|
+
# @return [String]
|
160
|
+
# An empty string if content is provided, otherwise the joined contents of
|
161
|
+
# the provided key.
|
162
|
+
def content_for(key)
|
163
|
+
inbox[:tilt_content_for] ||= {}
|
164
|
+
inbox[:tilt_content_for][key] ||= []
|
165
|
+
|
166
|
+
if block_given?
|
167
|
+
inbox[:tilt_content_for][key].push yield
|
168
|
+
|
169
|
+
EMPTY # Returned to prevent the result of #push from displaying.
|
170
|
+
else
|
171
|
+
inbox[:tilt_content_for].delete(key).join
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Determine if there's content to display.
|
176
|
+
#
|
177
|
+
# @param key [Symbol]
|
178
|
+
# The key to check for captured content for.
|
179
|
+
#
|
180
|
+
# @return [Boolean]
|
181
|
+
# Have we captured any content for this key?
|
182
|
+
def content_for?(key)
|
183
|
+
inbox[:tilt_content_for] ||= {}
|
184
|
+
inbox[:tilt_content_for][key] ||= []
|
185
|
+
|
186
|
+
!inbox[:tilt_content_for][key].empty?
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
Deck.include Tilt
|
191
|
+
end
|
data/syro-tilt.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
spec.name = 'syro-tilt'
|
4
|
+
spec.version = '0.1.0'
|
5
|
+
spec.authors = ['Evan Lecklider']
|
6
|
+
spec.email = ['evan@lecklider.com']
|
7
|
+
spec.summary = 'Render Tilt templates in Syro routes.'
|
8
|
+
spec.description = 'Render Tilt templates in Syro routes.'
|
9
|
+
spec.homepage = 'https://github.com/evanleck/syro-tilt'
|
10
|
+
spec.license = 'MIT'
|
11
|
+
spec.files = `git ls-files`.split("\n")
|
12
|
+
spec.require_paths = ['lib']
|
13
|
+
|
14
|
+
spec.add_dependency 'syro', '~> 3.0'
|
15
|
+
spec.add_dependency 'tilt', '~> 2.0'
|
16
|
+
|
17
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
18
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
19
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
20
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../lib/syro/tilt'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'syro'
|
5
|
+
|
6
|
+
describe Syro::Tilt do
|
7
|
+
include Syro::Tilt
|
8
|
+
|
9
|
+
let(:inbox) do
|
10
|
+
{}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:templates_directory) do
|
14
|
+
'test/views'
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:env) do
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#template_path' do
|
22
|
+
it 'returns the path for an existing file' do
|
23
|
+
assert_equal 'test/views/plain.txt.erb', template_path('plain.txt.erb')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'finds the first match for an ambiguous file' do
|
27
|
+
assert_equal 'test/views/plain.txt.erb', template_path('plain')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns nil for files that don't exist" do
|
31
|
+
assert_nil template_path('nah.txt')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#layout' do
|
36
|
+
it 'is nil by default' do
|
37
|
+
assert_nil layout
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can be set' do
|
41
|
+
layout('something')
|
42
|
+
|
43
|
+
assert_equal 'something', layout
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#partial' do
|
48
|
+
it 'returns the contents of a template' do
|
49
|
+
assert_equal "Plain text.\n", partial('plain')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'accepts local variables' do
|
53
|
+
assert_equal "Locals rule!\n", partial('locals', what: 'rule')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'accepts a block' do
|
57
|
+
assert_equal "Layout!\n\nNot so plain!\n\n", partial('layout') { partial('notsoplain') }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'template disambiguation' do
|
61
|
+
it 'picks the first one found without clear accepts' do
|
62
|
+
assert_equal "This is the first.\n", partial('typed')
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'disambiguation by HTTP Accept' do
|
66
|
+
let(:env) do
|
67
|
+
{ 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' }
|
68
|
+
end
|
69
|
+
|
70
|
+
it "checks the environment's 'Accept' header when present" do
|
71
|
+
assert_equal "This is HTML.\n", partial('typed')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'disambiguation by HTTP Accept' do
|
76
|
+
let(:env) do
|
77
|
+
{ 'HTTP_ACCEPT' => 'application/json' }
|
78
|
+
end
|
79
|
+
|
80
|
+
it "checks the environment's 'Accept' header when present" do
|
81
|
+
assert_equal %({ "thisis": "json" }\n), partial('typed')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#render' do
|
88
|
+
let(:res) do
|
89
|
+
Syro::Response.new
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'writes plain text to the response' do
|
93
|
+
render('plain')
|
94
|
+
|
95
|
+
assert_equal 'text/plain', res.headers['Content-Type']
|
96
|
+
assert_equal ["Plain text.\n"], res.body
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'writes html text to the response' do
|
100
|
+
render('notsoplain')
|
101
|
+
|
102
|
+
assert_equal 'text/html', res.headers['Content-Type']
|
103
|
+
assert_equal ["Not so plain!\n"], res.body
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'accepts local variables' do
|
107
|
+
render('locals', what: 'rule')
|
108
|
+
|
109
|
+
assert_equal ["Locals rule!\n"], res.body
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'uses the layout when present' do
|
113
|
+
layout('layout')
|
114
|
+
render('notsoplain')
|
115
|
+
|
116
|
+
assert_equal ["Layout!\n\nNot so plain!\n\n"], res.body
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#content_for' do
|
121
|
+
it 'captures content from a block' do
|
122
|
+
content_for(:capture) do
|
123
|
+
'This is a capture.'
|
124
|
+
end
|
125
|
+
|
126
|
+
assert_equal 'This is a capture.', content_for(:capture)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'deletes content once output' do
|
130
|
+
content_for(:capture) do
|
131
|
+
'This is a capture.'
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_equal 'This is a capture.', content_for(:capture)
|
135
|
+
assert_equal '', content_for(:capture)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe '#content_for?' do
|
140
|
+
it 'reports captured content' do
|
141
|
+
content_for(:capture) do
|
142
|
+
'This is a capture.'
|
143
|
+
end
|
144
|
+
|
145
|
+
assert content_for?(:capture)
|
146
|
+
refute content_for?(:notthere)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Locals <%= what %>!
|
@@ -0,0 +1 @@
|
|
1
|
+
Not so plain!
|
@@ -0,0 +1 @@
|
|
1
|
+
Plain text.
|
@@ -0,0 +1 @@
|
|
1
|
+
This is the first.
|
@@ -0,0 +1 @@
|
|
1
|
+
This is HTML.
|
@@ -0,0 +1 @@
|
|
1
|
+
{ "thisis": "json" }
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: syro-tilt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Evan Lecklider
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: syro
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tilt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
description: Render Tilt templates in Syro routes.
|
84
|
+
email:
|
85
|
+
- evan@lecklider.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rubocop.yml"
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- lib/syro/tilt.rb
|
97
|
+
- syro-tilt.gemspec
|
98
|
+
- test/syro_tilt_test.rb
|
99
|
+
- test/views/layout.erb
|
100
|
+
- test/views/locals.erb
|
101
|
+
- test/views/notsoplain.html.erb
|
102
|
+
- test/views/plain.txt.erb
|
103
|
+
- test/views/typed.anope.erb
|
104
|
+
- test/views/typed.html.erb
|
105
|
+
- test/views/typed.json.erb
|
106
|
+
homepage: https://github.com/evanleck/syro-tilt
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
metadata: {}
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubygems_version: 3.0.3
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Render Tilt templates in Syro routes.
|
129
|
+
test_files: []
|