Type spec fixes: - duct_usable_* return boolean→float (delegate to duct_usable_for_band) - sanitize/1 spec includes :unicode error tuples - match_delete/1 broadened from :ets.match_spec() - telemetry_event local type replaces :telemetry.event/0 - wgrib2 parse_lon_val_segment corrected to tuple spec - preloaded Ecto assoc types in get_mission/get_contact! specs Unmatched returns: - _ = prefix on Task.start, Oban.insert, Repo.query!, PubSub.subscribe, :ets.new, and if-expression returns across 18 files Pattern match fixes: - markdown: restructure acc!=[] guard as direct pattern match - path_compute/pskr/skewt_location_resolver: remove dead clauses - calibrate.aprs_144: remove unreachable format_float catch-all - unused.ex: suppress MapSet.union no_opaque Also: remove unused unicode_util_compat from mix.lock
52 lines
1.8 KiB
Elixir
52 lines
1.8 KiB
Elixir
defmodule Microwaveprop.Radio.TextSanitizer do
|
|
@moduledoc """
|
|
Strip non-printable characters from user-uploaded log text. Removes BOM,
|
|
zero-width spaces/joiners, C0 control bytes (except CR/LF/TAB), and DEL;
|
|
collapses non-breaking and other unicode whitespace into a regular space.
|
|
|
|
Used by CSV and ADIF importers because field values frequently arrive
|
|
with stray NBSPs from website copy-paste, BOM markers from Windows
|
|
exports, etc.
|
|
"""
|
|
|
|
@spec sanitize(nil) :: nil
|
|
@spec sanitize(String.t()) :: String.t() | {:error, String.t(), String.t()} | {:incomplete, String.t(), String.t()}
|
|
def sanitize(nil), do: nil
|
|
def sanitize(""), do: ""
|
|
|
|
def sanitize(string) when is_binary(string) do
|
|
string
|
|
|> :unicode.characters_to_list()
|
|
|> Enum.reduce([], fn cp, acc ->
|
|
case sanitize_codepoint(cp) do
|
|
:strip -> acc
|
|
replacement -> [replacement | acc]
|
|
end
|
|
end)
|
|
|> Enum.reverse()
|
|
|> :unicode.characters_to_binary()
|
|
end
|
|
|
|
defp sanitize_codepoint(?\t), do: ?\t
|
|
defp sanitize_codepoint(?\n), do: ?\n
|
|
defp sanitize_codepoint(?\r), do: ?\r
|
|
|
|
# C0 control characters and DEL — strip.
|
|
defp sanitize_codepoint(cp) when cp < 0x20 or cp == 0x7F, do: :strip
|
|
|
|
# NBSP and other unicode whitespace → regular space.
|
|
defp sanitize_codepoint(0x00A0), do: ?\s
|
|
defp sanitize_codepoint(cp) when cp >= 0x2000 and cp <= 0x200A, do: ?\s
|
|
defp sanitize_codepoint(0x202F), do: ?\s
|
|
defp sanitize_codepoint(0x205F), do: ?\s
|
|
defp sanitize_codepoint(0x3000), do: ?\s
|
|
|
|
# Zero-width characters (ZWSP, ZWNJ, ZWJ, word-joiner, BOM) — strip.
|
|
defp sanitize_codepoint(0x200B), do: :strip
|
|
defp sanitize_codepoint(0x200C), do: :strip
|
|
defp sanitize_codepoint(0x200D), do: :strip
|
|
defp sanitize_codepoint(0x2060), do: :strip
|
|
defp sanitize_codepoint(0xFEFF), do: :strip
|
|
|
|
defp sanitize_codepoint(cp), do: cp
|
|
end
|