recovery us-ascii encoding

This commit is contained in:
mmacia committed 2026-09-25 23:33:36 +00:00
1 parent 7200ef5215
commit d030408ab8
3 files changed
+16 -3

No files matched your search

+2 -2
View File
@@ -8,14 +8,14 @@ defmodule FeedReader.Recovery.Encoding do
to UTF-8, including declarations split across input chunks. to UTF-8, including declarations split across input chunks.
""" """
def transcode(input, :utf8), do: input def transcode(input, encoding) when encoding in [:utf8, :ascii], do: input
def transcode(input, :latin1), def transcode(input, :latin1),
do: Stream.map(input, &:unicode.characters_to_binary(&1, :latin1, :utf8)) do: Stream.map(input, &:unicode.characters_to_binary(&1, :latin1, :utf8))
def normalize_declaration(input, :utf8), do: input def normalize_declaration(input, :utf8), do: input
def normalize_declaration(input, :latin1) do def normalize_declaration(input, encoding) when encoding in [:latin1, :ascii] do
Stream.transform(input, fn -> {:prolog, <<>>} end, &rewrite_chunk/2, &flush/1) Stream.transform(input, fn -> {:prolog, <<>>} end, &rewrite_chunk/2, &flush/1)
end end
+2 -1
View File
@@ -10,7 +10,7 @@ defmodule FeedReader.Recovery do
""" """
@doc "Returns the encoding declared by an XML prefix, defaulting to UTF-8." @doc "Returns the encoding declared by an XML prefix, defaulting to UTF-8."
@spec declared_encoding(binary()) :: :utf8 | :latin1 @spec declared_encoding(binary()) :: :utf8 | :latin1 | :ascii
def declared_encoding(prefix) do def declared_encoding(prefix) do
case Regex.run(~r/<\?xml\b[^>]*\bencoding\s*=\s*["']([^"']+)["']/is, prefix, case Regex.run(~r/<\?xml\b[^>]*\bencoding\s*=\s*["']([^"']+)["']/is, prefix,
capture: :all_but_first capture: :all_but_first
@@ -34,6 +34,7 @@ defmodule FeedReader.Recovery do
defp normalize_encoding(encoding) do defp normalize_encoding(encoding) do
case String.downcase(encoding) do case String.downcase(encoding) do
value when value in ["iso-8859-1", "latin1", "latin-1"] -> :latin1 value when value in ["iso-8859-1", "latin1", "latin-1"] -> :latin1
"us-ascii" -> :ascii
_utf8 -> :utf8 _utf8 -> :utf8
end end
end end
@@ -2,6 +2,7 @@ defmodule FeedReader.Recovery.EncodingTest do
use ExUnit.Case, async: true use ExUnit.Case, async: true
alias FeedReader.Recovery.Encoding alias FeedReader.Recovery.Encoding
alias FeedReader.Recovery
test "passes UTF-8 input through unchanged" do test "passes UTF-8 input through unchanged" do
chunks = ["<title>", "café", "</title>"] chunks = ["<title>", "café", "</title>"]
@@ -29,4 +30,15 @@ defmodule FeedReader.Recovery.EncodingTest do
assert chunks |> Encoding.normalize_declaration(:latin1) |> Enum.join() == assert chunks |> Encoding.normalize_declaration(:latin1) |> Enum.join() ==
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><rss/>" "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rss/>"
end end
test "rewrites a US-ASCII declaration to UTF-8" do
chunks = ["<?xml version=\"1.0\" encoding=\"us-ascii\"?>", "<rss/>"]
assert chunks |> Encoding.normalize_declaration(:ascii) |> Enum.join() ==
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><rss/>"
end
test "recognizes US-ASCII declarations" do
assert Recovery.declared_encoding("<?xml encoding=\"us-ascii\"?>") == :ascii
end
end end