feather 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Scott Tadman
1
+ Copyright (c) 2011-2013 Scott Tadman, The Working Group Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # feather
2
2
 
3
- A simple text template system for generating output for a variety of uses
4
- including plain-text, HTML, and JavaScript.
3
+ A simple text template system inspired by Mustache for generating output for a
4
+ variety of uses including plain-text, HTML, and JavaScript.
5
5
 
6
6
  ## Examples
7
7
 
@@ -0,0 +1,19 @@
1
+ 0.4.0
2
+ - Made more compatible with the Mustache template library semantics.
3
+ - Added support for {{#...}} section definitions.
4
+ - Added support for {{^...}} negative definitions.
5
+ - Added support for {{!...}} comments.
6
+ 0.3.1
7
+ - Template names can be supplied as either Strings or Symbols.
8
+ - Variables can be defined with either String or Symbol keys.
9
+ 0.3.0
10
+ - Renaming library to Feather.
11
+ 0.2.2
12
+ - Handling nil template arguments and empty template substitutions.
13
+ 0.2.1
14
+ - Adding support for Hash-compatible objects to be passed in, responding to
15
+ the [] method is sufficient.
16
+ 0.2.0
17
+ - Adding ? and ?! conditional tests.
18
+ 0.1.0
19
+ - Initial thin prototype.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "feather"
8
- s.version = "0.3.1"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Scott Tadman"]
12
- s.date = "2013-01-25"
12
+ s.date = "2013-04-09"
13
13
  s.description = "A simple light-weight text templating system"
14
14
  s.email = "github@tadman.ca"
15
15
  s.extra_rdoc_files = [
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
  "Gemfile",
22
22
  "LICENSE.txt",
23
23
  "README.md",
24
+ "RELEASES.txt",
24
25
  "Rakefile",
25
26
  "VERSION",
26
27
  "feather.gemspec",
@@ -36,7 +37,7 @@ Gem::Specification.new do |s|
36
37
  s.homepage = "http://github.com/twg/feather"
37
38
  s.licenses = ["MIT"]
38
39
  s.require_paths = ["lib"]
39
- s.rubygems_version = "1.8.24"
40
+ s.rubygems_version = "1.8.25"
40
41
  s.summary = "Light-weight text tempating system"
41
42
 
42
43
  if s.respond_to? :specification_version then
@@ -6,12 +6,14 @@ module Feather
6
6
 
7
7
  # == Module Methods =======================================================
8
8
 
9
+ # Returns the current library version
9
10
  def self.version
10
11
  @version ||= File.readlines(
11
12
  File.expand_path('../VERSION', File.dirname(__FILE__))
12
13
  ).first.chomp
13
14
  end
14
15
 
16
+ # Create a new template with a supplied template body and optional options.
15
17
  def self.new(*args)
16
18
  template = Feather::Template.new(*args)
17
19
 
@@ -1,7 +1,7 @@
1
1
  class Feather::Template
2
2
  # == Constants ============================================================
3
3
 
4
- TOKEN_REGEXP = /((?:[^\{]|\{[^\{]|\{\{\{)+)|\{\{\s*([\&\%\$\.\:\*\/\=]|\?\!?)?([^\}]*)\}\}/.freeze
4
+ TOKEN_REGEXP = /((?:[^\{]|\{[^\{]|\{\{\{)+)|\{\{\s*([\&\%\$\.\:\#\^\*\/\=\!]|\?\!?)?([^\}]*)\}\}/.freeze
5
5
  TOKEN_TRIGGER = /\{\{/.freeze
6
6
 
7
7
  TO_YAML_PROPERTIES = %w[ @content @escape_method ].freeze
@@ -29,6 +29,9 @@ class Feather::Template
29
29
 
30
30
  # == Instance Methods =====================================================
31
31
 
32
+ # Creates a new template with the supplied contens. Options may be specified:
33
+ # * :html - Automatically escape fields for HTML
34
+ # * :text - Default mode, render all fields literally
32
35
  def initialize(content, options = nil)
33
36
  if (options)
34
37
  if (source = options[:escape])
@@ -54,6 +57,7 @@ class Feather::Template
54
57
  yield(self) if (block_given?)
55
58
  end
56
59
 
60
+ # Returns a function that can be used to evaluate the template.
57
61
  def to_proc
58
62
  @_proc ||= begin
59
63
  source = ''
@@ -64,6 +68,10 @@ class Feather::Template
64
68
  end
65
69
  end
66
70
 
71
+ # Render the template with the given variables, templates, and parent chain.
72
+ # The variables are specified in a Hash, Array, or object that supports
73
+ # [](key). templates must be a Hash or [](key) accessible object. The parents
74
+ # chain is defined as an array.
67
75
  def render(variables = nil, templates = nil, parents = nil)
68
76
  variables = Feather::Support.variable_stack(variables, true)
69
77
 
@@ -138,6 +146,12 @@ class Feather::Template
138
146
  end
139
147
  alias_method :call, :render
140
148
 
149
+ # Compiles a template and manipulates the options strucutre passed in. Keys
150
+ # supported are:
151
+ # * :escape_method - Defines the default escape method for this template.
152
+ # * :templates - Hash to capture the templates referenced in this template.
153
+ # * :variables - Hash to capture the variables referenced in this template.
154
+ # * :source - String to capture the Ruby equivalent of this template.
141
155
  def compile(options)
142
156
  escape_method = options[:escape_method]
143
157
  sections = options[:sections]
@@ -165,7 +179,6 @@ class Feather::Template
165
179
  source and source << "v&&r<<h.html_escape(v[#{tag.inspect}].to_s);"
166
180
 
167
181
  variables and variables[tag] = true
168
-
169
182
  when '%'
170
183
  # URI escaped
171
184
  index = stack[-1][2][tag.inspect]
@@ -187,8 +200,8 @@ class Feather::Template
187
200
  source and source << "v&&r<<h.css_escape(v.is_a?(Array)?v[#{index}]:v[#{tag.inspect}]);"
188
201
 
189
202
  variables and variables[tag] = true
190
- when ':'
191
- # Defines start of a :section
203
+ when ':', '#'
204
+ # Defines start of a :section or #section
192
205
  index = stack[-1][2][tag.inspect]
193
206
 
194
207
  stack_variables ||= 's=[];'
@@ -198,6 +211,16 @@ class Feather::Template
198
211
  source and source << "h.iterate(v){|v|;v=h.cast_as_vars(v, s);"
199
212
 
200
213
  sections and sections[tag] = true
214
+ when '^'
215
+ # Displays if referenced variable is undefined or empty
216
+ index = stack[-1][2][tag.inspect]
217
+
218
+ stack_variables ||= 's=[];'
219
+ stack << [ :empty_section, tag, stack[-1][2] ]
220
+
221
+ source and source << "t=v.is_a?(Array)?v[#{index}]:(v.is_a?(Hash)&&v[#{tag.inspect}]);if(!t||t.respond_to?(:empty?)&&t.empty?);"
222
+
223
+ variables and variables[tag] = true
201
224
  when '?', '?!'
202
225
  # Defines start of a ?conditional
203
226
 
@@ -222,6 +245,8 @@ class Feather::Template
222
245
  end
223
246
 
224
247
  source and source << "};v=s.pop;end;"
248
+ when :empty_section
249
+ source and source << "end;"
225
250
  when :conditional
226
251
  source and source << "end;"
227
252
  when :base
@@ -269,10 +294,12 @@ class Feather::Template
269
294
  true
270
295
  end
271
296
 
297
+ # For compatibility with YAML.dump
272
298
  def to_yaml_properties
273
299
  TO_YAML_PROPERTIES
274
300
  end
275
301
 
302
+ # For compatibility with the Psych YAML library
276
303
  def psych_to_yaml(dump)
277
304
  # Avoid serializing the generated proc by moving it to a temporary
278
305
  # variable for the duration of this operation.
@@ -285,10 +312,12 @@ class Feather::Template
285
312
  dump
286
313
  end
287
314
 
315
+ # For compatibility with Marshal.dump
288
316
  def marshal_dump
289
317
  [ @content, { :escape => @escape_method } ]
290
318
  end
291
319
 
320
+ # For compatibility with Marshal.load
292
321
  def marshal_load(dump)
293
322
  @content, options = dump
294
323
 
@@ -1,5 +1,4 @@
1
1
  require 'rubygems'
2
-
3
2
  require 'test/unit'
4
3
 
5
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
@@ -14,7 +13,7 @@ class Test::Unit::TestCase
14
13
  rescue exception_class
15
14
  # Expected
16
15
  else
17
- flunk message || "Did not raise #{exception_class}"
16
+ flunk(message || "Did not raise #{exception_class}")
18
17
  end
19
18
  end
20
19
  end
@@ -79,6 +79,25 @@ class TestFeatherTemplate < Test::Unit::TestCase
79
79
  assert_equal '<div></div>', template.render(:link => nil)
80
80
  assert_equal '<div></div>', template.render(:link => [ ])
81
81
  end
82
+
83
+ def test_empty_section
84
+ template = Feather::Template.new('<head>{{:head}}{{tag}}{{/head}}{{^head}}<title></title>{{/head}}</head>')
85
+
86
+ assert_equal '<head><title></title></head>', template.render
87
+ assert_equal '<head><title></title></head>', template.render(:head => nil)
88
+ assert_equal '<head><title></title></head>', template.render(:head => '')
89
+ assert_equal '<head><title></title></head>', template.render(:head => [ ])
90
+ assert_equal '<head><title></title></head>', template.render(:head => { })
91
+ assert_equal '<head>0</head>', template.render(:head => 0)
92
+ assert_equal '<head><test><tags></head>', template.render(:head => %w[ <test> <tags> ])
93
+ end
94
+
95
+ def test_comment
96
+ template = Feather::Template.new('<test>{{!commment with all kinds of <markup>}}</test>')
97
+
98
+ assert_equal '<test></test>', template.render
99
+ assert_equal '<test></test>', template.render(:comment => 'test')
100
+ end
82
101
 
83
102
  def test_template_with_context
84
103
  template = Feather::Template.new('{{example}}', :escape => :html)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feather
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-25 00:00:00.000000000 Z
12
+ date: 2013-04-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jeweler
@@ -39,6 +39,7 @@ files:
39
39
  - Gemfile
40
40
  - LICENSE.txt
41
41
  - README.md
42
+ - RELEASES.txt
42
43
  - Rakefile
43
44
  - VERSION
44
45
  - feather.gemspec
@@ -71,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
72
  version: '0'
72
73
  requirements: []
73
74
  rubyforge_project:
74
- rubygems_version: 1.8.24
75
+ rubygems_version: 1.8.25
75
76
  signing_key:
76
77
  specification_version: 3
77
78
  summary: Light-weight text tempating system