7

ERB とマークダウン テンプレートを使用する Ruby 1.9.3 で実行されている非常に単純な Sinatra アプリがあります。問題を示すために、それを削除しました。

これは、Mac OS X Snow Leopard で Sinatra 1.3.2 を実行しています。マークダウンには、rdiscount 1.6.8 を使用しています。

メインの Ruby ファイルには次のものが含まれます。

get '/services' do
  erb :services
end

services.erb ファイルには次の内容が含まれています。

<%= markdown :'content/service1' %>
£

マークダウンファイル内には、1行しかありません

£

Sinatra アプリを実行して「サービス」ページをロードするEncoding::CompatibilityError at /services incompatible character encodings: UTF-8 and ASCII-8BITと、ERB ファイルの 2 行目 (「£」のみを含む行) で例外が発生します。

私は多くのグーグルを行ってきましたが、なぜこれが起こっているのかを理解することはできません。ERB とマークダウン ファイルは私のローカル ディスクでは UTF-8 ですが、明らかにそれらは Sinatra によって読み込まれ、文字列に変換されており、それらの文字列がどのようなエンコーディングであるかを知る方法がわかりません。

Sinatra に ASCII-8BIT の使用を強制すると (settings.default_encoding = 'ASCII-8BIT'メインの Sinatra Ruby ファイルの先頭に追加することによって)、例外はスローされませんが、「£」文字が正しく表示されません。

ポインタはありますか?

4

1 に答える 1

14

これは、Sinatra が使用している (Rails 用に検討されている) テンプレート システムであるTiltの問題です。issue #75#107を見てください。

問題は基本的に、Tiltがディスクからテンプレート ファイルを読み取るbinread方法にあり、 . これは、実際のテンプレート エンジンに渡されるソース文字列に のエンコーディングが関連付けられていることを意味しますASCII-8BIT。これは、基本的に不明であることを示しています。

RDiscount には、入力と一致するように出力のエンコーディングを設定するコードがありますASCII-8BITが、入力エンコーディングが;の場合、これはあまり役に立ちません。結果には同じエンコーディングが与えられます。Kramdown でも同じこと (または同様のこと) が発生するため、単純に切り替えるだけでは解決しません。

これは、テンプレートに非 ASCII 文字 (つまり£) が含まれていて、その結果を他の utf-8 でエンコードされた文字列と結合しようとした場合に問題を引き起こします。テンプレートに ASCII 文字のみが含まれている場合、utf-8 と互換性があり、Ruby は 2 つの文字列を組み合わせることができます。そうでない場合は、表示されているものを取得CompatibilityErrorします。

考えられる回避策は、テンプレート ファイルを自分で読み取り、結果の文字列を正しいエンコーディングで Tilt に渡すことです。

<%= markdown File.read './views/pound.md' %>
£

readの代わりに を使用してファイルを自分で読み取ることにより、ファイルbinreadのエンコーディングが正しく、ファイルの残りの部分と互換性があることを確認できerbます。これを試す場合は、一度ファイルを読み込んで、その内容をどこかにキャッシュすることをお勧めします。

markdown別の回避策は、メソッドの出力をキャプチャして使用force_encodingすることです。

<%= markdown(:pound).force_encoding('utf-8') %>
£

これが可能なのは、エンコーディングがASCII-8BITであるにもかかわらず、文字列内のバイトが実際には utf-8 でエンコードされていることがわかっているため、エンコーディングを変更するだけでよいからです。

于 2012-04-27T01:50:53.297 に答える