From a7179c898ae3d38dfcbfe78d4093a6e7c1809425 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Sun, 23 Aug 2026 11:28:50 +0900 Subject: [PATCH] Fix `Encoding::InvalidByteSequenceError` in Aliki on non-UTF-8 locales `RDoc::Generator::Darkfish` reads template files with `Encoding.default_external`. As a result, Aliki's templates, which contain non-ASCII characters such as emojis, raised `Encoding::InvalidByteSequenceError` when the external encoding was UTF-8, such as with `LANG=C`. This adds a `#template_encoding` hook to `Generator::Darkfish` with a default value of `nil`, and lets `Generator::Aliki` override the hook with `Encoding::UTF_8`. As a result, Aliki template files are always read with UTF-8. Fixes #1574 --- lib/rdoc/generator/aliki.rb | 4 ++++ lib/rdoc/generator/darkfish.rb | 10 +++++++--- test/rdoc/generator/aliki_test.rb | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/rdoc/generator/aliki.rb b/lib/rdoc/generator/aliki.rb index 439c0bf915..bb8628c56a 100644 --- a/lib/rdoc/generator/aliki.rb +++ b/lib/rdoc/generator/aliki.rb @@ -151,6 +151,10 @@ def resolve_url(rel_prefix, url) private + def template_encoding + Encoding::UTF_8 + end + def build_class_module_entry(klass) type = case klass when RDoc::NormalClass then 'class' diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb index 8e63f5bd23..3fa935d198 100644 --- a/lib/rdoc/generator/darkfish.rb +++ b/lib/rdoc/generator/darkfish.rb @@ -599,7 +599,7 @@ def refresh_store_data # used directly. def assemble_template(body_file) - body = body_file.read + body = body_file.read(encoding: template_encoding) return body if body =~ / -#{head_file.read} +#{head_file.read(encoding: template_encoding)} #{body} TEMPLATE @@ -693,7 +693,7 @@ def template_for(file, page = true, klass = ERB) template = assemble_template file erbout = 'io' else - template = file.read + template = file.read(encoding: template_encoding) template = template.encode @options.encoding file_var = File.basename(file).sub(/\..*/, '') @@ -805,6 +805,10 @@ def group_classes_by_namespace_for_sidebar(classes) private + def template_encoding + nil + end + def nesting_namespaces_to_class_modules(klass) tree = {} diff --git a/test/rdoc/generator/aliki_test.rb b/test/rdoc/generator/aliki_test.rb index 081cd19588..00054a5a90 100644 --- a/test/rdoc/generator/aliki_test.rb +++ b/test/rdoc/generator/aliki_test.rb @@ -266,4 +266,20 @@ def test_html_lang_from_locale content = File.binread('index.html') assert_include content, '' end + + def test_generate_with_non_utf8_default_external_encoding + original_encoding = Encoding.default_external + begin + Encoding.default_external = Encoding::US_ASCII + @g.generate + ensure + Encoding.default_external = original_encoding + end + + assert_file 'index.html' + + content = File.read('index.html', encoding: Encoding::UTF_8) + assert content.valid_encoding?, 'index.html should be valid UTF-8' + refute content.ascii_only?, 'non-ASCII characters in the template should be kept' + end end