Exoplanet.Filters (Exoplanet v0.5.0)

Copy Markdown View Source

Per-feed content filters: HTML sanitization, category allow/block lists, image stripping, and summary truncation. The sanitizer removes dangerous tags and style attributes but the default configuration does not filter attribute-based injection vectors such as on* event handlers or javascript: URIs.

Category filters

allow_categories accepts a list of strings or :all (no allowlist constraint). block_categories accepts a list of strings or :none (no blocklist constraint). The empty list [] is equivalent to :all / :none respectively and remains supported. Atoms are normalized to [] internally; see normalize_categories/1. The inverses (allow_categories: :none, block_categories: :all) raise ArgumentError — drop the feed entirely if you want zero posts.

Summary

Functions

Applies the merged filter map to a list of Exoplanet.Post structs.

Built-in default filter map. Used by Exoplanet.Config as the baseline for default_filters and as the starting point that user-supplied default_filters are merged onto.

Merges a per-feed filter map onto a default filter map.

Normalizes the category-filter atoms in a filter map.

Types

t()

@type t() :: %{
  allow_categories: [String.t()] | :all,
  block_categories: [String.t()] | :none,
  strip_images: boolean(),
  excerpt_length: pos_integer() | nil,
  sanitize_html: boolean(),
  drop_tags: [String.t()],
  drop_attrs: [String.t()]
}

Functions

apply(posts, filters)

@spec apply([Exoplanet.Post.t()], t()) :: [Exoplanet.Post.t()]

Applies the merged filter map to a list of Exoplanet.Post structs.

Returns the filtered list. Posts dropped by category filters are removed entirely. The sanitize_html and strip_images filters modify each post's :body and :summary. The excerpt_length filter modifies only :summary. Sanitization runs first, then image stripping, then excerpt generation. When both HTML filters are enabled they share a single tree walk.

defaults()

@spec defaults() :: t()

Built-in default filter map. Used by Exoplanet.Config as the baseline for default_filters and as the starting point that user-supplied default_filters are merged onto.

merge(defaults, per_feed)

@spec merge(t(), map() | nil) :: t()

Merges a per-feed filter map onto a default filter map.

allow_categories and block_categories REPLACE the default value when the per-feed map sets them to a list. Other keys override field-by-field. Per-feed keys set to nil leave the default in place.

Defaults are normalized first, then the merged result is normalized, so callers may use allow_categories: :all or block_categories: :none on either side. Invalid atoms (allow_categories: :none, block_categories: :all, or any unrecognized atom) raise ArgumentError.

normalize_categories(filters)

@spec normalize_categories(map()) :: map()

Normalizes the category-filter atoms in a filter map.

Replaces allow_categories: :all with [] and block_categories: :none with []. Lists pass through unchanged. Keys that are missing stay missing (no defaults are inserted). Raises ArgumentError for any other atom value, including allow_categories: :none and block_categories: :all (both nonsensical — drop the feed instead).

Called automatically by merge/2 and Exoplanet.Config.from_file/1, so consumers rarely need to invoke it directly.