Set encoding for inline templates correctly.

* If Ruby version is not encoding aware, do nothing
* If file contains a magic comment in the first line, use that encoding
* Otherwise use settings.default_encoding

Allows one to use unicode characters without having to escape them and deploy
on Linux systems, like Heroku, on 1.9.2 (on OSX encodings always default to
UTF-8, which makes it hard to spot this issue before deployment).

Fixes #136.
This commit is contained in:
Konstantin Haase 2010-12-13 11:40:17 +01:00
parent 30de33861a
commit b23a6febc5
2 changed files with 26 additions and 9 deletions

View File

@ -921,15 +921,20 @@ module Sinatra
end
if data
if app and app.lines.first =~ /^\s*#\W*encoding\W*(\w[\w_\-\.\d]+)\W*$/
encoding = $1
else
encoding = settings.default_encoding
end
lines = app.count("\n") + 1
template = nil
data.each_line do |line|
lines += 1
if line =~ /^@@\s*(.*\S)\s*$/
template = ''
template = force_encoding('', encoding)
templates[$1.to_sym] = [template, file, lines]
elsif template
template << line
template << force_encoding(line, encoding)
end
end
end
@ -1231,20 +1236,22 @@ module Sinatra
#
# The latter might not be necessary if Rack handles it one day.
# Keep an eye on Rack's LH #100.
def force_encoding(*args) settings.force_encoding(*args) end
if defined? Encoding
def force_encoding(data)
return if data == self || data.is_a?(Tempfile)
def self.force_encoding(data, encoding = default_encoding)
return if data == settings || data.is_a?(Tempfile)
if data.respond_to? :force_encoding
data.force_encoding settings.default_encoding
data.force_encoding encoding
elsif data.respond_to? :each_value
data.each_value { |v| force_encoding(v) }
data.each_value { |v| force_encoding(v, encoding) }
elsif data.respond_to? :each
data.each { |v| force_encoding(v) }
data.each { |v| force_encoding(v, encoding) }
end
data
end
else
def force_encoding(*) end
end
def self.force_encoding(data, *) data end
end
reset!

View File

@ -1,3 +1,4 @@
# encoding: UTF-8
require File.dirname(__FILE__) + '/helper'
File.delete(File.dirname(__FILE__) + '/views/layout.test') rescue nil
@ -137,6 +138,12 @@ class TemplatesTest < Test::Unit::TestCase
assert @app.templates.empty?
end
it 'allows unicode in inline templates' do
mock_app { set :inline_templates, __FILE__ }
assert_equal "Den som tror at hemma det är där man bor har aldrig vart hos mig.\n\n",
@app.templates[:umlaut][0]
end
it 'loads templates from specified views directory' do
render_app { render :test, :hello, :views => options.views + '/foo' }
@ -216,6 +223,9 @@ There's a space after 'bar'!
@@ foo bar
this is not foo
@@ umlaut
Den som tror at hemma det är där man bor har aldrig vart hos mig.
@@ layout
X
= yield