cutaneous 0.1.7 → 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
  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