Gumbo.Attribute (gumbo v0.3.0)

Copy Markdown View Source

An attribute on an element node, identified by its index into the element's attribute vector.

An attribute is only meaningful together with the Gumbo.Node it came from: the node's output handle owns the tree and validates both indices. A hand-built struct can carry an out-of-range node or attribute index; that is a programmer error, so the scalar accessors raise ArgumentError on one and details/1 returns {:error, :invalid_node} or {:error, :invalid_attribute}. Nothing dereferences a bad index.

Summary

Functions

Every field at once, in one NIF crossing.

The attribute's name, case-normalized by the tokenizer.

The source position just after the attribute name.

The source position where the attribute name starts.

The attribute's namespace.

The attribute name as written in the source.

The attribute value as written in the source, including any surrounding quotes; the empty binary when the attribute has no value.

The attribute's value after entity decoding, without surrounding quotes.

The source position just after the attribute value.

The source position where the attribute value starts.

Types

t()

@opaque t()

Functions

details(attribute)

@spec details(t()) :: {:ok, map()} | {:error, :invalid_node | :invalid_attribute}

Every field at once, in one NIF crossing.

The map keys are the accessor names above, so details(attribute)[:name] == name(attribute) for every key. The deliberate exception to the ArgumentError contract, matching Gumbo.Node.details/1: a caller asking for a whole attribute branches on {:error, :invalid_node} or {:error, :invalid_attribute} rather than rescues.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> {:ok, details} = p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.details()
iex> details[:value]
"a"

name(attribute)

@spec name(t()) :: binary()

The attribute's name, case-normalized by the tokenizer.

In HTML content this is lowercased; foreign-content attributes are adjusted per the HTML spec, so e.g. xlink:href in SVG becomes "href" here with namespace/1 :xlink — original_name/1 keeps the source spelling.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.name()
"class"

name_end(attribute)

@spec name_end(t()) :: Gumbo.Position.t()

The source position just after the attribute name.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.name_end()
%Gumbo.Position{line: 1, column: 9, offset: 8}

name_start(attribute)

@spec name_start(t()) :: Gumbo.Position.t()

The source position where the attribute name starts.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.name_start()
%Gumbo.Position{line: 1, column: 4, offset: 3}

namespace(attribute)

@spec namespace(t()) :: Gumbo.Types.attribute_namespace()

The attribute's namespace.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.namespace()
:none

original_name(attribute)

@spec original_name(t()) :: binary()

The attribute name as written in the source.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.original_name()
"class"

original_value(attribute)

@spec original_value(t()) :: binary()

The attribute value as written in the source, including any surrounding quotes; the empty binary when the attribute has no value.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.original_value()
"\"a\""

value(attribute)

@spec value(t()) :: binary()

The attribute's value after entity decoding, without surrounding quotes.

Attributes with no value yield the empty binary.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.value()
"a"

value_end(attribute)

@spec value_end(t()) :: Gumbo.Position.t()

The source position just after the attribute value.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.value_end()
%Gumbo.Position{line: 1, column: 13, offset: 12}

value_start(attribute)

@spec value_start(t()) :: Gumbo.Position.t()

The source position where the attribute value starts.

Examples

iex> {:ok, output} = Gumbo.parse(~s(<p class="a">x</p>))
iex> p = output |> Gumbo.Output.root() |> Gumbo.Node.descendants() |> Enum.find(&(Gumbo.Node.tag_name(&1) == "p"))
iex> p |> Gumbo.Node.attributes() |> Enum.at(0) |> Gumbo.Attribute.value_start()
%Gumbo.Position{line: 1, column: 10, offset: 9}