cutaneous 0.1.7 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 012024660b2cd0de6db4295f59f2dd7f627280a4
4
- data.tar.gz: ae08e8b3fcdc18c3060104beb02acb4f7e77b3f6
3
+ metadata.gz: d90ff3764cf47bc3c932b85e5d9833adbb86edcb
4
+ data.tar.gz: a996afd411cb3e846cd1237c13b49a9ef4e99e17
5
5
  SHA512:
6
- metadata.gz: 034dc2af99470678f14e0e687c09d946cd52545fc1b515a59c53b379b90d5a01920572db4d28c1bd1d3ae169840b8a9d0aa04ac75e6b94a119c27e6a749ebeaf
7
- data.tar.gz: 0e083ff19ecab0be7f48e40a23a2166c188ab41521c0b0c784584369b2a098457f69b34e32bc69fd9733660952d79c5236766b3818823449188a978928df1099
6
+ metadata.gz: a01dd50c0274e1fd17d7913d48b0e52913842fbc8ed479442356ff17e83aec31112ae93041b68e47c3c6e4d268f7f33d69c5d4c7975ec6305ee2a5f54abec298
7
+ data.tar.gz: 8e94956de888f9b8a12a5494245dfc3e242ef33e5ebdf0fd4c61dd443c59a2eb90163fd2890a3fe4e7e188d6a2bda97fd5e664ed7cc4a4d7da0263dbcb660868
data/cutaneous.gemspec CHANGED
@@ -8,14 +8,14 @@ Gem::Specification.new do |s|
8
8
  s.specification_version = 2 if s.respond_to? :specification_version=
9
9
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
10
  s.rubygems_version = '1.3.5'
11
- s.required_ruby_version = ">= 1.9.2"
11
+ s.required_ruby_version = ">= 1.9.3"
12
12
 
13
13
  ## Leave these as is they will be modified for you by the rake gemspec task.
14
14
  ## If your rubyforge_project name is different, then edit it and comment out
15
15
  ## the sub! line in the Rakefile
16
16
  s.name = 'cutaneous'
17
- s.version = '0.1.7'
18
- s.date = '2013-11-14'
17
+ s.version = '0.2.0'
18
+ s.date = '2014-01-29'
19
19
  s.rubyforge_project = 'cutaneous'
20
20
 
21
21
  ## Make sure your summary is short. The description may be as long
@@ -18,8 +18,11 @@ module Cutaneous
18
18
 
19
19
  alias_method :render, :render_file
20
20
 
21
+ # need an explicit #render_string method so it's possible to distinguish
22
+ # between a String which is a path to a template & a String which is a
23
+ # template itself.
21
24
  def render_string(template_string, context, format = default_format)
22
- string_loader(format).render(template_string, context)
25
+ render_file(proc_template(template_string), context, format)
23
26
  end
24
27
 
25
28
  # Create and cache a file loader on a per-format basis
@@ -29,14 +32,24 @@ module Cutaneous
29
32
  end
30
33
  end
31
34
 
32
- # Not worth caching string templates as they are most likely to be one-off
33
- # instances & not repeated in the lifetime of the engine.
34
- def string_loader(format)
35
- StringLoader.new(file_loader(format))
35
+ def template_exists?(relative_path, format)
36
+ @roots.each do |root|
37
+ return true if file_loader(format).exists?(root, relative_path)
38
+ end
39
+ false
40
+ end
41
+
42
+ def template_location(relative_path, format)
43
+ @roots.each do |root|
44
+ if (path = file_loader(format).location(root, relative_path))
45
+ return path
46
+ end
47
+ end
48
+ nil
36
49
  end
37
50
 
38
- def template_exists?(root, relative_path, format)
39
- file_loader(format).exists?(root, relative_path)
51
+ def dynamic_template?(template_string)
52
+ @syntax.is_dynamic?(template_string)
40
53
  end
41
54
 
42
55
  def convert(template, to_syntax, format = default_format)
@@ -44,7 +57,11 @@ module Cutaneous
44
57
  end
45
58
 
46
59
  def convert_string(template_string, to_syntax, format = default_format)
47
- string_loader(format).convert(template_string, to_syntax)
60
+ convert(proc_template(template_string), to_syntax, format)
61
+ end
62
+
63
+ def proc_template(template_string)
64
+ Proc.new { template_string }
48
65
  end
49
66
 
50
67
  protected
@@ -24,10 +24,6 @@ module Cutaneous
24
24
  template
25
25
  end
26
26
 
27
- # def script
28
- # @script ||= compile
29
- # end
30
-
31
27
  protected
32
28
 
33
29
  BRACES ||= /\{|\}/
@@ -35,7 +31,7 @@ module Cutaneous
35
31
 
36
32
  def parse
37
33
  tokens = []
38
- scanner = StringScanner.new(@template.to_s)
34
+ scanner = StringScanner.new(template_string)
39
35
  tag_start = syntax.tag_start_pattern
40
36
  tags = syntax.tags
41
37
  token_map = syntax.token_map
@@ -84,5 +80,17 @@ module Cutaneous
84
80
  expression.gsub!(ESCAPE_STRING, '\\\\\&')
85
81
  [:text, expression]
86
82
  end
83
+
84
+ def template_string
85
+ return read_file_template if @template.respond_to?(:read)
86
+ return @template.call if @template.respond_to?(:call)
87
+ @template.to_s
88
+ end
89
+
90
+ def read_file_template
91
+ source = @template.read
92
+ @template.close if @template.respond_to?(:close)
93
+ source
94
+ end
87
95
  end
88
96
  end
@@ -19,26 +19,22 @@ module Cutaneous
19
19
  end
20
20
 
21
21
  def template(template)
22
- return proc_template(template) if template.is_a?(Proc)
23
- template_path = path(template)
24
- raise UnknownTemplateError.new(@roots, filename(template)) if template_path.nil?
25
-
26
- @template_class.new(file_lexer(template_path)).tap do |template|
27
- template.path = template_path
28
- template.loader = self
29
- end
30
- end
31
-
32
- def proc_template(lmda)
33
- StringLoader.new(self).template(lmda.call)
22
+ template = open_template(template) if String === template
23
+ instance = @template_class.new(lexer(template))
24
+ instance.path = template.path if template.respond_to?(:path)
25
+ instance.loader = self
26
+ instance
34
27
  end
35
28
 
36
- def file_lexer(template_path)
37
- lexer(SourceFile.new(template_path))
29
+ def open_template(template)
30
+ template_path = path(template)
31
+ raise UnknownTemplateError.new(@roots, filename(template)) if template_path.nil?
32
+ # TODO: Make the encoding configurable?
33
+ TemplateReader.new(template_path, Encoding::UTF_8)
38
34
  end
39
35
 
40
- def lexer(template_string)
41
- Lexer.new(template_string, syntax)
36
+ def lexer(template)
37
+ Lexer.new(template, syntax)
42
38
  end
43
39
 
44
40
  def path(template_name)
@@ -52,40 +48,29 @@ module Cutaneous
52
48
  end
53
49
 
54
50
  def exists?(template_root, template_name)
55
- File.exists?(File.join(template_root, filename(template_name)))
56
- end
57
- end
58
-
59
- # Converts a template string into a Template instance.
60
- #
61
- # Because a string template can only come from the engine instance
62
- # we need a FileLoader to delegate all future template loading to.
63
- class StringLoader < FileLoader
64
- def initialize(file_loader)
65
- @file_loader = file_loader
51
+ path = ::File.join(template_root, filename(template_name))
52
+ ::File.exists?(path)
66
53
  end
67
54
 
68
- def syntax
69
- @file_loader.syntax
55
+ def location(template_root, template_name)
56
+ return ::File.join(template_root, template_name) if exists?(template_root, template_name)
57
+ nil
70
58
  end
71
59
 
72
- def template(template_string)
73
- Template.new(lexer(template_string)).tap do |template|
74
- template.loader = @file_loader
60
+ # An IO-like interface that provides #read and #path methods
61
+ class TemplateReader
62
+ def initialize(path, encoding)
63
+ @path = path
64
+ @encoding = encoding
75
65
  end
76
- end
77
- end
78
66
 
79
- # Converts a filepath to a template string as and when necessary
80
- class SourceFile
81
- attr_reader :path
82
-
83
- def initialize(filepath)
84
- @path = filepath
85
- end
67
+ def read(*args)
68
+ ::File.open(@path, 'r', external_encoding: @encoding) { |f| f.read }
69
+ end
86
70
 
87
- def to_s
88
- File.read(@path)
71
+ def path
72
+ @path
73
+ end
89
74
  end
90
75
  end
91
76
 
@@ -119,13 +104,13 @@ module Cutaneous
119
104
  class CachedTemplate < Template
120
105
 
121
106
  def script
122
- if cached?
123
- script = File.read(script_path)
107
+ script = nil
108
+ path = script_path
109
+ if path && cached?
110
+ script = File.read(path)
124
111
  else
125
112
  script = super
126
- File.open(script_path, "w") do |f|
127
- f.write(script)
128
- end
113
+ write_cached_script(script, path) unless path.nil?
129
114
  end
130
115
  script
131
116
  end
@@ -135,7 +120,7 @@ module Cutaneous
135
120
  end
136
121
 
137
122
  def template_path
138
- lexer.template.path
123
+ path
139
124
  end
140
125
 
141
126
  def script_path
@@ -144,8 +129,15 @@ module Cutaneous
144
129
 
145
130
  def generate_script_path
146
131
  path = template_path
132
+ return nil if path.nil?
147
133
  ext = File.extname path
148
134
  path.gsub(/#{ext}$/, ".rb")
149
135
  end
136
+
137
+ def write_cached_script(script, path)
138
+ File.open(script_path, "w") do |f|
139
+ f.write(script)
140
+ end
141
+ end
150
142
  end
151
143
  end
data/lib/cutaneous.rb CHANGED
@@ -7,7 +7,7 @@ require 'cutaneous/lexer'
7
7
  require 'cutaneous/compiler'
8
8
 
9
9
  module Cutaneous
10
- VERSION = "0.1.7"
10
+ VERSION = "0.2.0"
11
11
 
12
12
  class CompilationError < Exception; end
13
13
 
data/test/helper.rb CHANGED
@@ -5,6 +5,8 @@ require 'minitest/autorun'
5
5
 
6
6
  require 'cutaneous'
7
7
 
8
+ require 'stringio'
9
+
8
10
  class TestContext < Cutaneous::Context
9
11
  end
10
12
 
data/test/test_cache.rb CHANGED
@@ -101,4 +101,9 @@ describe Cutaneous do
101
101
  script_path = template_path("c", "html", "rb")
102
102
  refute ::File.exists?(script_path), "Template cache should not have created '#{script_path}'"
103
103
  end
104
+
105
+ it "doesn't attempt to write a cached script for Proc templates" do
106
+ context = ContextHash(right: "right")
107
+ result1 = engine.render(Proc.new { "This is ${right}"}, context)
108
+ end
104
109
  end
data/test/test_core.rb CHANGED
@@ -35,6 +35,14 @@ describe "Parsers" do
35
35
  result.must_equal expected
36
36
  end
37
37
 
38
+ it "will render an object that responds to #read" do
39
+ template = StringIO.new("This is ${ right }")
40
+ context = ContextHash(right: "right")
41
+ result = subject.render(template, context)
42
+ result.must_equal "This is right"
43
+ end
44
+
45
+
38
46
  it "can convert a template to another syntax" do
39
47
  result = subject.convert('statements1', Cutaneous::SecondPassSyntax)
40
48
  result.must_equal read_template('statements2.html.cut')
@@ -194,6 +202,17 @@ describe Cutaneous do
194
202
  result.must_equal "right"
195
203
  end
196
204
 
205
+ it "calls #close on any IO instances passed to it" do
206
+ context = ContextHash(right: "correct")
207
+ template = MiniTest::Mock.new
208
+ template.expect(:close, nil)
209
+ template.expect(:read, "${ right }")
210
+ template.expect(:path, "/path/to/template.html.cut")
211
+ result = engine.render(template, context, "rss")
212
+ template.verify
213
+ result.must_equal "correct"
214
+ end
215
+
197
216
  it "Allows for configuration of the engine's default format" do
198
217
  engine.default_format = "rss"
199
218
  context = ContextHash(right: "right")
@@ -208,10 +227,20 @@ describe Cutaneous do
208
227
  end
209
228
 
210
229
  it "Tests for the existence of a template file for a certain format" do
211
- assert engine.template_exists?(template_root, "expressions1", "html")
212
- assert engine.template_exists?(template_root, "other/error", "html")
213
- assert engine.template_exists?(template_root, "include", "rss")
214
- refute engine.template_exists?(template_root, "missing", "rss")
230
+ assert engine.template_exists?("expressions1", "html")
231
+ assert engine.template_exists?("other/error", "html")
232
+ assert engine.template_exists?("include", "rss")
233
+ refute engine.template_exists?("missing", "rss")
234
+ end
235
+
236
+ it "returns the full path to a template if found" do
237
+ assert_equal "#{template_root}/expressions1", engine.template_location("expressions1", "html")
238
+ assert_equal nil, engine.template_location("missing", "rss")
239
+ end
240
+
241
+ it "can determine if a template contains tags for its syntax" do
242
+ assert engine.dynamic_template?("i am ${dynamic}")
243
+ refute engine.dynamic_template?("i am not dynamic")
215
244
  end
216
245
 
217
246
  it "Passes any instance variables & locals between contexts" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cutaneous
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garry Hill
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-14 00:00:00.000000000 Z
11
+ date: 2014-01-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Cutaneous is the Ruby templating language designed for use with Spontaneous
14
14
  CMS. It has a simple syntax but powerful features such as Djano style template inheritance
@@ -78,7 +78,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - '>='
80
80
  - !ruby/object:Gem::Version
81
- version: 1.9.2
81
+ version: 1.9.3
82
82
  required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  requirements:
84
84
  - - '>='
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  version: '0'
87
87
  requirements: []
88
88
  rubyforge_project: cutaneous
89
- rubygems_version: 2.0.3
89
+ rubygems_version: 2.2.1
90
90
  signing_key:
91
91
  specification_version: 2
92
92
  summary: A Ruby templating language with Django style template inheritance