defmodule PureHTML do @moduledoc """ A pure Elixir HTML5 parser with CSS selector querying. PureHTML parses HTML strings into a tree of nodes and provides functions to query, traverse, and serialize them back to HTML. ## Parsing iex> PureHTML.parse("
Hello
") [{"html", [], [{"head", [], []}, {"body", [], [{"p", [], ["Hello"]}]}]}] ## Querying iex> html = PureHTML.parse("Hello
Hello
" ## Node Format Nodes are represented as tuples compatible with [Floki](https://hex.pm/packages/floki): - `{tag, attrs, children}` - Element with tag name, attribute list, and children - `{:doctype, name, public_id, system_id}` - DOCTYPE declaration - `{:comment, text}` - HTML comment - `"text"` - Text content (binary string) Attributes are lists of `{name, value}` tuples, sorted alphabetically. """ alias PureHTML.{Query, Serializer, Tokenizer, TreeBuilder} @doc """ Parses an HTML string into a list of nodes. Returns a list of nodes where each node is one of: - `{:doctype, name, public_id, system_id}` - DOCTYPE declaration (if present, always first) - `{:comment, text}` - HTML comment - `{tag, attrs, children}` - Element with tag name, attributes list, and child nodes - `text` - Text content (binary) Attributes are represented as a list of `{name, value}` tuples, sorted alphabetically. ## Examples iex> PureHTML.parse("Hello
") [{"html", [], [{"head", [], []}, {"body", [], [{"p", [], ["Hello"]}]}]}] iex> PureHTML.parse("") [{:doctype, "html", nil, nil}, {"html", [], [{"head", [], []}, {"body", [], []}]}] """ @spec parse(String.t()) :: [term()] def parse(html) when is_binary(html) do html |> Tokenizer.new() |> TreeBuilder.build() end @doc """ Converts parsed HTML nodes back to an HTML string. ## Options - `:quote_char` - Force `"'"` or `"\""` for attribute quotes (default: smart quoting) - `:minimize_boolean_attributes` - Output `disabled` vs `disabled=disabled` (default: true) - `:use_trailing_solidus` - Output `Hello
") |> PureHTML.to_html() "Hello
" iex> PureHTML.to_html([{"div", [{"class", "foo"}], ["text"]}]) "Hello
World