Packages

Earmark is a pure-Elixir Markdown converter. It is intended to be used as a library (just call Earmark.as_html), but can also be used as a command-line tool (run mix escript.build first). Output generation is pluggable.

Retired package: Deprecated - Earmark is no longer maintained. Migrate to a replacement, for example MDEx (https://hex.pm/packages/mdex).
Security advisory: This version has known vulnerabilities. View advisories

Current section

Files

Jump to
earmark lib earmark_parser helpers ast_helpers.ex
Raw

lib/earmark_parser/helpers/ast_helpers.ex

defmodule Earmark.Parser.Helpers.AstHelpers do
@moduledoc false
import Earmark.Parser.Ast.Emitter
import Earmark.Parser.Helpers
alias Earmark.Parser.Block
@doc false
def annotate(node, from_block)
def annotate(node, %{annotation: nil}), do: node
def annotate({tag, atts, children, meta}, %{annotation: annotation}),
do: {tag, atts, children, Map.put(meta, :annotation, annotation)}
def annotate({tag, atts, children, meta}, annotation),
do: {tag, atts, children, Map.put(meta, :annotation, annotation)}
@doc false
def attrs_to_string_keys(key_value_pair)
def attrs_to_string_keys({k, vs}) when is_list(vs) do
{to_string(k), Enum.join(vs, " ")}
end
def attrs_to_string_keys({k, vs}) do
{to_string(k),to_string(vs)}
end
@doc false
def augment_tag_with_ial(tags, ial)
def augment_tag_with_ial([{t, a, c, m}|tags], atts) do
[{t, merge_attrs(a, atts), c, m}|tags]
end
def augment_tag_with_ial([], _atts) do
[]
end
@doc false
def code_classes(language, prefix) do
classes =
["" | String.split(prefix || "")]
|> Enum.map(fn pfx -> "#{pfx}#{language}" end)
{"class", classes |> Enum.join(" ")}
end
@doc false
def codespan(text) do
emit("code", text, class: "inline")
end
@doc false
def render_footnote_link(ref, backref, number) do
emit("a", to_string(number), href: "##{ref}", id: backref, class: "footnote", title: "see footnote")
end
@doc false
def render_code(%Block.Code{lines: lines}) do
lines |> Enum.join("\n")
end
@remove_escapes ~r{ \\ (?! \\ ) }x
@doc false
def render_image(text, href, title) do
alt = text |> escape() |> String.replace(@remove_escapes, "")
if title do
emit("img", [], src: href, alt: alt, title: title)
else
emit("img", [], src: href, alt: alt)
end
end
@doc false
def render_link(url, text) do
emit("a", text, href: _encode(url))
end
##############################################
# add attributes to the outer tag in a block #
##############################################
@verbatims ~r<%[\da-f]{2}>i
defp _encode(url) do
url
|> String.split(@verbatims, include_captures: true)
|> Enum.chunk_every(2)
|> Enum.map(&_encode_chunk/1)
|> IO.chardata_to_string
end
defp _encode_chunk([encodable, verbatim]), do: [URI.encode(encodable), verbatim]
defp _encode_chunk([encodable]), do: URI.encode(encodable)
@doc false
def merge_attrs(maybe_atts, new_atts)
def merge_attrs(nil, new_atts), do: new_atts
def merge_attrs(atts, new) when is_list(atts) do
atts
|> Enum.into(%{})
|> merge_attrs(new)
end
def merge_attrs(atts, new) do
atts
|> Map.merge(new, &_value_merger/3)
|> Enum.into([])
|> Enum.map(&attrs_to_string_keys/1)
end
defp _value_merger(key, val1, val2)
defp _value_merger(_, val1, val2) when is_list(val1) do
val1 ++ [val2]
end
defp _value_merger(_, val1, val2) do
[val1, val2]
end
end
# SPDX-License-Identifier: Apache-2.0