feather 0.3.1 → 0.4.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.
@@ -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