syro-tilt 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c344875f1c37067ea3ede68552941eda515bf0d3e0b66e9b3335c5e5b15900f
4
- data.tar.gz: a2d4cec3221689f8b5f7c221c9e09f2e22f5c148266aacdb73c8cf41716e245d
3
+ metadata.gz: 1cfe3eed8f52da21ccc32308b4ec07c7992fb4a4cc378685a62760bb1d3e1496
4
+ data.tar.gz: 750a5807d161a85b49882fb2ada1ab1ce425688dd8346a7fd1724c98ff196a5e
5
5
  SHA512:
6
- metadata.gz: 67f316b8d950eb1fcf8409883c47a000c1959c1ab208593681012d70b74642d6bce3b7df77e10bf6ff87975f121cb632da015704104c35774582a67df494e211
7
- data.tar.gz: 03711476cdca8eb7867d3ab041e349f4d0cd57d464393753a46ab3319db766169054d97b4cefd694cca88f27a6e805b8747e8117724f987f78c27664a9ebbe7a
6
+ metadata.gz: 27d77ed0f98427523090cae24cf2e301adf305a27e78b4c41251eb0f4e8e9faa5d10a0f181df589312ada9cdd483cc8453e017e702f963677bc2e3af4f5e8bc4
7
+ data.tar.gz: 756805dbea57d98b914b755f8765ce5b55176917928698cf750cd566762c66489c36c0e1efbd94a1b0609baa432aea6f224086b96d13e452626ae7628be1ff16
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@ AllCops:
4
4
  DisplayCopNames: true
5
5
  DisplayStyleGuide: true
6
6
  ExtraDetails: true
7
- TargetRubyVersion: 2.5
7
+ TargetRubyVersion: 2.3
8
8
 
9
9
 
10
10
  Performance:
@@ -57,4 +57,3 @@ Style/IfUnlessModifier:
57
57
 
58
58
  Style/Next:
59
59
  MinBodyLength: 8
60
-
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.6
4
+ - 2.5
5
+ - 2.4
6
+ - 2.3
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Syro::Tilt
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/syro-tilt.svg)](https://badge.fury.io/rb/syro-tilt)
4
+ [![Build Status](https://secure.travis-ci.org/evanleck/syro-tilt.svg)](https://travis-ci.org/evanleck/syro-tilt)
5
+
3
6
  Render [Tilt][tilt] templates in [Syro][syro] routes.
4
7
 
5
8
 
@@ -75,6 +78,38 @@ end
75
78
  `content_for`: capture content for use later.
76
79
 
77
80
 
81
+ ## Template File Naming
82
+
83
+ For templates that will be passed to `render`, it's important that you name your
84
+ templates following the pattern `#{ identifier }.#{ mime_type }.#{
85
+ template_engine }`. For example `home.html.erb` would be returned with the MIME
86
+ type `text/html` (derived from the `.html` extension) and rendered by Tilt using
87
+ the preferred mapping for `.erb` extensions.
88
+
89
+ Templates that are only ever used by the `partial` method do not require the
90
+ same naming because `partial` does not set the response's content type.
91
+
92
+
93
+ ## Caching
94
+
95
+ There's an optional in-memory cache included that will cache calls to `template`
96
+ and `template_path`. You probably don't want to use the cache during development
97
+ since you'll have to restart your server to see updated templates, but it will
98
+ likely be useful in production. To use it, require `syro/tilt/cache`.
99
+
100
+ ```ruby
101
+ require 'syro'
102
+ require 'syro/tilt'
103
+ require 'syro/tilt/cache'
104
+
105
+ app = Syro.new do
106
+ get do
107
+ render 'home'
108
+ end
109
+ end
110
+ ```
111
+
112
+
78
113
  ## Installation
79
114
 
80
115
  Add this line to your application's Gemfile:
data/lib/syro/tilt.rb CHANGED
@@ -51,23 +51,22 @@ class Syro # :nodoc:
51
51
  #
52
52
  # @return [String]
53
53
  # The path to the template file.
54
- def template_path(path, from = nil)
54
+ def template_path(path, from = nil, accept = nil)
55
55
  from ||= templates_directory
56
56
  path = File.join(from, path)
57
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
58
+ # Taken from Rack::Request#parse_http_accept_header (which is a private
59
+ # method).
60
+ accepts = (accept || env.fetch(HTTP_ACCEPT) { EMPTY }).to_s.split(ACCEPT_SPLIT_MULTIPLES).map do |part|
61
+ attribute, parameters = part.split(ACCEPT_SPLIT_PARTS, 2)
62
+ quality =
63
+ if parameters =~ ACCEPT_CAPTURE_QUALITY
64
+ ACCEPT_CAPTURE_QUALITY.match(parameters)[1].to_f
65
+ else
66
+ 1.0
67
67
  end
68
68
 
69
- [attribute, quality]
70
- end
69
+ [attribute, quality]
71
70
  end
72
71
 
73
72
  # Reject "*/*" because it will always match the first thing it is compared
@@ -76,7 +75,7 @@ class Syro # :nodoc:
76
75
 
77
76
  # Find all potential templates e.g. ones with the same name but different
78
77
  # template engines or MIME types.
79
- potentials = Dir.glob(File.join(from, '**', '*')).filter do |potential|
78
+ potentials = Dir.glob(File.join(from, '**', '*')).select do |potential|
80
79
  potential.start_with?(path)
81
80
  end.sort
82
81
 
@@ -116,7 +115,10 @@ class Syro # :nodoc:
116
115
  #
117
116
  # @return [String]
118
117
  def partial(path, locals = {})
119
- template(template_path(path, locals.delete(:from))).render(self, locals) { yield if block_given? }
118
+ accept = env.fetch(HTTP_ACCEPT) { EMPTY }
119
+ from = locals.delete(:from) { templates_directory }
120
+
121
+ template(template_path(path, from, accept)).render(self, locals) { yield if block_given? }
120
122
  end
121
123
 
122
124
  # Set or get the current layout. A layout is just another template to wrap
@@ -141,10 +143,13 @@ class Syro # :nodoc:
141
143
  # @option locals [String] :from
142
144
  # The directory to look for templates within.
143
145
  def render(path, locals = {})
146
+ accept = env.fetch(HTTP_ACCEPT) { EMPTY }
147
+ from = locals.delete(:from) { templates_directory }
148
+
144
149
  content = partial(path, locals.dup) { yield if block_given? }
145
150
  content = partial(layout, locals.dup) { content } if layout
146
151
 
147
- res.headers[Rack::CONTENT_TYPE] = template_mime_type(template_path(path, locals[:from]))
152
+ res.headers[Rack::CONTENT_TYPE] = template_mime_type(template_path(path, from, accept))
148
153
  res.write content
149
154
  end
150
155
 
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ require_relative '../tilt'
3
+
4
+ class Syro # :nodoc:
5
+ module Tilt
6
+ # Add template and path caching to Syro::Tilt.
7
+ module Cache
8
+ # A very thin wrapper around Hash, with a Mutex.
9
+ class MemoryStore
10
+ def initialize
11
+ @cache = {}
12
+ @mutex = Mutex.new
13
+ end
14
+
15
+ def fetch(*key)
16
+ @mutex.synchronize do
17
+ @cache.fetch(key) do
18
+ @cache[key] = yield
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ @template_cache = MemoryStore.new
25
+ @template_path_cache = MemoryStore.new
26
+
27
+ # @return [MemoryStore]
28
+ def self.template_cache
29
+ @template_cache
30
+ end
31
+
32
+ # @return [MemoryStore]
33
+ def self.template_path_cache
34
+ @template_path_cache
35
+ end
36
+
37
+ # Cache calls to Syro::Tilt#template.
38
+ def template(path)
39
+ Cache.template_cache.fetch(path) do
40
+ super(path)
41
+ end
42
+ end
43
+
44
+ # Cache calls to Syro::Tilt#template_path.
45
+ def template_path(path, from, accept)
46
+ Cache.template_path_cache.fetch(path, from, accept) do
47
+ super(path, from, accept)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ Tilt.prepend(Tilt::Cache)
54
+ end
data/syro-tilt.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  Gem::Specification.new do |spec|
3
3
  spec.name = 'syro-tilt'
4
- spec.version = '0.1.0'
4
+ spec.version = '0.2.0'
5
5
  spec.authors = ['Evan Lecklider']
6
6
  spec.email = ['evan@lecklider.com']
7
7
  spec.summary = 'Render Tilt templates in Syro routes.'
@@ -9,12 +9,14 @@ Gem::Specification.new do |spec|
9
9
  spec.homepage = 'https://github.com/evanleck/syro-tilt'
10
10
  spec.license = 'MIT'
11
11
  spec.files = `git ls-files`.split("\n")
12
+ spec.required_ruby_version = '>= 2.3.0'
12
13
  spec.require_paths = ['lib']
13
14
 
14
15
  spec.add_dependency 'syro', '~> 3.0'
15
16
  spec.add_dependency 'tilt', '~> 2.0'
16
17
 
17
- spec.add_development_dependency 'bundler', '~> 2.0'
18
+ spec.add_development_dependency 'bundler', '>= 1.7'
19
+ spec.add_development_dependency 'erubi', '>= 1.8'
18
20
  spec.add_development_dependency 'minitest', '~> 5.0'
19
21
  spec.add_development_dependency 'rake', '~> 10.0'
20
22
  end
@@ -24,7 +24,7 @@ describe Syro::Tilt do
24
24
  end
25
25
 
26
26
  it 'finds the first match for an ambiguous file' do
27
- assert_equal 'test/views/plain.txt.erb', template_path('plain')
27
+ assert_equal 'test/views/plain.anope.erb', template_path('plain')
28
28
  end
29
29
 
30
30
  it "returns nil for files that don't exist" do
@@ -46,7 +46,7 @@ describe Syro::Tilt do
46
46
 
47
47
  describe '#partial' do
48
48
  it 'returns the contents of a template' do
49
- assert_equal "Plain text.\n", partial('plain')
49
+ assert_equal "First plain text.\n", partial('plain')
50
50
  end
51
51
 
52
52
  it 'accepts local variables' do
@@ -93,7 +93,7 @@ describe Syro::Tilt do
93
93
  render('plain')
94
94
 
95
95
  assert_equal 'text/plain', res.headers['Content-Type']
96
- assert_equal ["Plain text.\n"], res.body
96
+ assert_equal ["First plain text.\n"], res.body
97
97
  end
98
98
 
99
99
  it 'writes html text to the response' do
@@ -146,4 +146,34 @@ describe Syro::Tilt do
146
146
  refute content_for?(:notthere)
147
147
  end
148
148
  end
149
+
150
+ describe '#template' do
151
+ it 'returns a Tilt template' do
152
+ assert_instance_of Tilt::ErubiTemplate, template('test/views/typed.html.erb')
153
+ end
154
+
155
+ it "raises an error on missing files (Tilt's default behavior)" do
156
+ assert_raises(Errno::ENOENT) do
157
+ template('test/views/notthere.txt.erb')
158
+ end
159
+ end
160
+ end
161
+
162
+ describe 'Syro::Tilt::Cache' do
163
+ require_relative '../lib/syro/tilt/cache'
164
+
165
+ prepend Syro::Tilt::Cache
166
+
167
+ it 'caches templates' do
168
+ initial = template('test/views/typed.html.erb')
169
+
170
+ assert_equal initial, Syro::Tilt::Cache.template_cache.fetch('test/views/typed.html.erb')
171
+ end
172
+
173
+ it 'caches template paths' do
174
+ initial = template_path('typed.html', 'test/views', 'html')
175
+
176
+ assert_equal initial, Syro::Tilt::Cache.template_path_cache.fetch('typed.html', 'test/views', 'html')
177
+ end
178
+ end
149
179
  end
@@ -0,0 +1 @@
1
+ First plain text.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syro-tilt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Lecklider
@@ -42,16 +42,30 @@ dependencies:
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '2.0'
47
+ version: '1.7'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '2.0'
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: erubi
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.8'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.8'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: minitest
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -89,16 +103,19 @@ extra_rdoc_files: []
89
103
  files:
90
104
  - ".gitignore"
91
105
  - ".rubocop.yml"
106
+ - ".travis.yml"
92
107
  - Gemfile
93
108
  - LICENSE.txt
94
109
  - README.md
95
110
  - Rakefile
96
111
  - lib/syro/tilt.rb
112
+ - lib/syro/tilt/cache.rb
97
113
  - syro-tilt.gemspec
98
114
  - test/syro_tilt_test.rb
99
115
  - test/views/layout.erb
100
116
  - test/views/locals.erb
101
117
  - test/views/notsoplain.html.erb
118
+ - test/views/plain.anope.erb
102
119
  - test/views/plain.txt.erb
103
120
  - test/views/typed.anope.erb
104
121
  - test/views/typed.html.erb
@@ -115,7 +132,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
132
  requirements:
116
133
  - - ">="
117
134
  - !ruby/object:Gem::Version
118
- version: '0'
135
+ version: 2.3.0
119
136
  required_rubygems_version: !ruby/object:Gem::Requirement
120
137
  requirements:
121
138
  - - ">="