summaryrefslogtreecommitdiff
path: root/lib/erb.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erb.rb')
-rw-r--r--lib/erb.rb51
1 files changed, 45 insertions, 6 deletions
diff --git a/lib/erb.rb b/lib/erb.rb
index c8799412842..c5194817bee 100644
--- a/lib/erb.rb
+++ b/lib/erb.rb
@@ -58,6 +58,24 @@
#
# See the ERB.new and ERB#result methods for more detail.
#
+# == Character encodings
+#
+# ERB (or ruby code generated by ERB) returns a string in the same
+# character encoding as the input string. When the input string has
+# a magic comment, however, it returns a string in the encoding specified
+# by the magic comment.
+#
+# # -*- coding: UTF-8 -*-
+# require 'erb'
+#
+# template = ERB.new <<EOF
+# <%#-*- coding: Big5 -*-%>
+# \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
+# EOF
+# puts template.result
+#
+# <em>Prints:</em> \_\_ENCODING\_\_ is Big5.
+#
#
# == Examples
#
@@ -517,10 +535,14 @@ class ERB
end
def compile(s)
- out = Buffer.new(self, s.encoding)
+ enc = s.encoding
+ raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
+ s = s.dup.force_encoding("ASCII-8BIT") # don't use constant Enoding::ASCII_8BIT for miniruby
+ enc = detect_magic_comment(s) || enc
+ out = Buffer.new(self, enc)
content = ''
- scanner = make_scanner(s.dup.force_encoding("ASCII-8BIT"))
+ scanner = make_scanner(s)
scanner.scan do |token|
if scanner.stag.nil?
case token
@@ -560,6 +582,7 @@ class ERB
when '<%='
out.push("#{@insert_cmd}((#{content}).to_s)")
when '<%#'
+ # content = content.force_encoding(@enc)
# out.push("# #{content.dump}")
end
scanner.stag = nil
@@ -573,7 +596,7 @@ class ERB
end
out.push("#{@put_cmd} #{content.dump}") if content.size > 0
out.close
- out.script
+ return out.script, enc
end
def prepare_trim_mode(mode)
@@ -613,6 +636,18 @@ class ERB
end
attr_reader :percent, :trim_mode
attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
+
+ private
+ def detect_magic_comment(s)
+ if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s)
+ comment = $1
+ comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
+ if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment
+ enc = $1.sub(/-(?:mac|dos|unix)/i, '')
+ enc = Encoding.find(enc)
+ end
+ end
+ end
end
end
@@ -688,7 +723,7 @@ class ERB
@safe_level = safe_level
compiler = ERB::Compiler.new(trim_mode)
set_eoutvar(compiler, eoutvar)
- @src = compiler.compile(str)
+ @src, @enc = *compiler.compile(str)
@filename = nil
end
@@ -714,7 +749,7 @@ class ERB
compiler.pre_cmd = cmd
cmd = []
- cmd.push(eoutvar)
+ cmd.push("#{eoutvar}.force_encoding(__ENCODING__)")
compiler.post_cmd = cmd
end
@@ -745,7 +780,11 @@ class ERB
end
def def_method(mod, methodname, fname='(ERB)') # :nodoc:
- mod.module_eval("def #{methodname}\n" + self.src + "\nend\n", fname, -1)
+ src = self.src
+ magic_comment = "#coding:#{@enc}\n"
+ mod.module_eval do
+ eval(magic_comment + "def #{methodname}\n" + src + "\nend\n", binding, fname, -2)
+ end
end
def def_module(methodname='erb') # :nodoc: