Packages
html_to_markdown
2.23.0
3.9.0
3.8.3
3.8.2
3.8.1
3.8.0
3.8.0-rc.2
3.8.0-rc.1
3.7.2
3.7.1
3.7.0
3.6.21
3.6.20
3.6.19
3.6.18
3.6.17
3.6.16
3.6.15
3.6.14
3.6.13
3.6.11
3.6.10
3.6.9
3.6.8
3.6.3
3.6.1
3.6.0
3.6.0-rc.25
3.6.0-rc.23
3.6.0-rc.22
3.6.0-rc.21
3.6.0-rc.20
3.6.0-rc.17
3.6.0-rc.16
3.6.0-rc.14
3.6.0-rc.13
3.6.0-rc.12
3.6.0-rc.11
3.6.0-rc.10
3.6.0-rc.9
3.6.0-rc.7
3.6.0-rc.3
3.6.0-rc.2
3.6.0-rc.1
3.5.7
3.5.5
3.5.3
3.5.2
3.5.1
3.5.0
3.5.0-rc.1
3.4.0
3.4.0-rc.45
3.4.0-rc.44
3.4.0-rc.42
3.4.0-rc.41
3.4.0-rc.40
3.4.0-rc.25
3.4.0-rc.24
3.4.0-rc.23
3.4.0-rc.21
3.4.0-rc.20
3.4.0-rc.18
3.4.0-rc.16
3.4.0-rc.15
3.4.0-rc.14
3.4.0-rc.13
3.4.0-rc.12
3.4.0-rc.11
3.4.0-rc.9
3.4.0-rc.8
3.4.0-rc.2
3.4.0-rc.1
3.3.2
3.2.4
3.2.2
3.2.1
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
2.30.0
2.29.0
2.28.6
2.28.5
2.28.4
2.28.3
2.28.2
2.28.1
2.28.0
2.27.3
2.27.2
2.27.1
2.27.0
2.26.3
2.26.2
2.26.1
2.25.1
2.25.0
2.24.6
2.24.5
2.24.4
2.24.3
2.24.1
2.23.4
2.23.3
2.23.2
2.23.1
2.23.0
2.22.5
2.22.2
2.22.1
2.22.0
2.21.1
2.20.0
2.19.8
2.19.7
2.19.6
2.19.5
2.19.4
2.19.3
2.19.2
2.19.1
2.19.0
2.18.0
2.16.1
2.16.0
2.15.0
2.14.11
2.14.10
2.14.9
2.14.8
2.14.7
2.14.6
2.14.3
2.14.2
2.14.1
2.14.0
2.13.0
2.12.1
2.12.0
2.11.4
2.11.3
2.11.1
2.10.1
2.9.2
2.9.1
2.9.0
2.8.3
High-performance HTML to Markdown converter
Current section
Files
Jump to
Current section
Files
lib/html_to_markdown/inline_image_config.ex
defmodule HtmlToMarkdown.InlineImageConfig do
@moduledoc """
Configuration for inline image extraction.
"""
@default_limit 5 * 1_024 * 1_024
defstruct max_decoded_size_bytes: @default_limit,
filename_prefix: nil,
capture_svg: true,
infer_dimensions: false
@type t :: %__MODULE__{
max_decoded_size_bytes: pos_integer(),
filename_prefix: String.t() | nil,
capture_svg: boolean(),
infer_dimensions: boolean()
}
@doc """
Build a configuration struct from a map, keyword list, or another struct.
"""
@spec new(t() | map() | keyword() | nil) :: t()
def new(nil), do: %__MODULE__{}
def new(%__MODULE__{} = cfg), do: cfg
def new(attrs) when is_list(attrs) or is_map(attrs) do
attrs =
attrs
|> Map.new()
|> Enum.reduce(%{}, fn {key, value}, acc ->
case normalize_key(key) do
nil -> acc
normalized -> Map.put(acc, normalized, value)
end
end)
struct(%__MODULE__{}, attrs)
end
defp normalize_key(key) when is_atom(key) do
if key in [:max_decoded_size_bytes, :filename_prefix, :capture_svg, :infer_dimensions],
do: key,
else: nil
end
defp normalize_key(key) when is_binary(key) do
key
|> String.trim()
|> String.replace("-", "_")
|> case do
"max_decoded_size_bytes" -> :max_decoded_size_bytes
"filename_prefix" -> :filename_prefix
"capture_svg" -> :capture_svg
"infer_dimensions" -> :infer_dimensions
_ -> nil
end
end
defp normalize_key(_), do: nil
@doc false
@spec to_map(t() | map() | keyword() | nil) :: map()
def to_map(input) do
case to_map_result(input) do
{:ok, cfg} -> cfg
{:error, reason} -> raise ArgumentError, reason
end
end
@doc false
@spec to_map_result(t() | map() | keyword() | nil) :: {:ok, map()} | {:error, String.t()}
def to_map_result(nil), do: to_map_result(%__MODULE__{})
def to_map_result(%__MODULE__{} = cfg), do: config_to_map(cfg)
def to_map_result(attrs) when is_list(attrs) or is_map(attrs),
do: attrs |> new() |> config_to_map()
defp config_to_map(%__MODULE__{} = cfg) do
with {:ok, max_bytes} <- positive_integer(cfg.max_decoded_size_bytes, :max_decoded_size_bytes),
{:ok, capture_svg} <- ensure_boolean(cfg.capture_svg, :capture_svg),
{:ok, infer_dimensions} <- ensure_boolean(cfg.infer_dimensions, :infer_dimensions),
{:ok, prefix} <- normalize_prefix(cfg.filename_prefix) do
base = %{
"max_decoded_size_bytes" => max_bytes,
"capture_svg" => capture_svg,
"infer_dimensions" => infer_dimensions
}
map =
if prefix do
Map.put(base, "filename_prefix", prefix)
else
base
end
{:ok, map}
end
end
defp positive_integer(value, _field) when is_integer(value) and value > 0, do: {:ok, value}
defp positive_integer(value, field) when is_binary(value) do
value
|> String.trim()
|> Integer.parse()
|> case do
{parsed, ""} when parsed > 0 -> {:ok, parsed}
_ -> {:error, error_message(field, "must be a positive integer")}
end
end
defp positive_integer(_value, field),
do: {:error, error_message(field, "must be a positive integer")}
defp ensure_boolean(value, _field) when is_boolean(value), do: {:ok, value}
defp ensure_boolean(_value, field), do: {:error, error_message(field, "must be a boolean")}
defp normalize_prefix(nil), do: {:ok, nil}
defp normalize_prefix(value) when is_binary(value) do
trimmed = String.trim(value)
if trimmed == "" do
{:ok, nil}
else
{:ok, trimmed}
end
end
defp normalize_prefix(_value), do: {:error, error_message(:filename_prefix, "must be a string")}
defp error_message(field, message) when is_atom(field) do
"#{field}: #{message}"
end
defp error_message(field, message), do: "#{field}: #{message}"
end