EarmarkAstDsl (EarmarkAstDsl v0.3.2) View Source
EarmarkAstDsl is a toolset to generate EarmarkParser conformant AST Nodes version 1.4.6 and on, which is the always return quadruples version.
Its main purpose is to remove boilerplate code from Earmark and
EarmarkParser tests.
Documentation for EarmarkAstDsl
.
tag
The most general helper is the tag function:
iex(1)> tag("div", "Some content")
{"div", [], ["Some content"], %{}}
Content and attributes can be provided as arrays, ...
iex(2)> tag("p", ~w[Hello World], class: "hidden")
{"p", [{"class", "hidden"}], ["Hello", "World"], %{}}
... or maps:
iex(3)> tag("p", ~w[Hello World], %{class: "hidden"})
{"p", [{"class", "hidden"}], ["Hello", "World"], %{}}
Annotations (as implemented in EarmarkParser
>= v1.4.16)
In order to not overload tha API for tag/2
, tag/3
and tag/4
we offer the general
tag_annotated
function
iex(4)> tag_annotated("header", "content", "annotation")
{"header", [], ["content"], %{annotation: "annotation"}}
in this case atts come last
iex(5)> tag_annotated("header", "content", "annotation", class: "two")
{"header", [{"class", "two"}], ["content"], %{annotation: "annotation"}}
Shortcuts for common tags (a
, div
, li
, p
)
iex(6)> a("hello", href: "mylink")
{"a", [{"href", "mylink"}], ["hello"], %{}}
iex(7)> p("A para")
{"p", [], ["A para"], %{}}
iex(8)> div(tag("span", "content"))
{"div", [], [{"span", [], ["content"], %{}}], %{}}
iex(9)> li(p("hello"))
{"li", [], [{"p", [], ["hello"], %{}}], %{}}
More helpers, which are less common are described on their functiondocs
Link to this section Summary
Functions
iex(10)> div_annotated("content", "special", class: "special_class")
{"div", [{"class", "special_class"}], ["content"], %{annotation: "special"}}
iex(11)> div_annotated("content", "special")
{"div", [], ["content"], %{annotation: "special"}}
Creates a list of li
itmes
The ol
helper is different in respect to other helpers as it wraps content elements into li
tags if
necessary
iex(16)> p_annotated("text", "annotation")
{"p", [], ["text"], %{annotation: "annotation"}}
A convenient shortcut for the often occurring <pre><code>
tag chain
The annotation adding helper
Tables
Tables are probably the raison d'être ot this little lib, as their ast is quite verbose, as we will see here
This is the base helper which emits a tag with its content, attributes and metadata can be added at the user's convenience
A convience function for easy addition of an annotation to the meta map
The ul
helper is different in respect to other helpers as it wraps content elements into li
tags if
necessary
Void tags are just convenient shortcats for calls to tag
with the second argument
nil
or []
Again the annotated version is available
vtags are tags from verbatim html
Verbatim tags still can be annotated and therefore we have this helper
Link to this section Types
Link to this section Functions
Specs
a(content_t(), free_atts_t()) :: ast_t()
Specs
div(content_t(), free_atts_t()) :: ast_t()
Specs
div_annotated(content_t(), any(), free_atts_t()) :: ast_t()
iex(10)> div_annotated("content", "special", class: "special_class")
{"div", [{"class", "special_class"}], ["content"], %{annotation: "special"}}
iex(11)> div_annotated("content", "special")
{"div", [], ["content"], %{annotation: "special"}}
Specs
li(content_t(), free_atts_t()) :: ast_t()
Specs
Creates a list of li
itmes
iex(12)> lis(~W[alpha beta gamma])
[{"li", [], ["alpha"], %{}},
{"li", [], ["beta"], %{}},
{"li", [], ["gamma"], %{}}]
Which can typically be used in, well, a list
iex(13)> tag("ol", lis(["a", p("b")]))
{"ol", [], [{"li", [], ["a"], %{}}, {"li", [], [{"p", [], ["b"], %{}}], %{}}], %{}}
Specs
ol(content_t(), free_atts_t()) :: ast_t()
The ol
helper is different in respect to other helpers as it wraps content elements into li
tags if
necessary
iex(14)> ol(["hello", "world"])
{"ol", [], [{"li", [], ["hello"], %{}}, {"li", [], ["world"], %{}}], %{}}
but as mentioned only if necessary so that we can refine li
elements with attributes or meta if we want
iex(15)> ol(["hello", li("world", class: "global")])
{"ol", [], [{"li", [], ["hello"], %{}}, {"li", [{"class", "global"}], ["world"], %{}}], %{}}
Specs
p(content_t(), free_atts_t()) :: ast_t()
Specs
p_annotated(content_t(), any(), free_atts_t()) :: ast_t()
iex(16)> p_annotated("text", "annotation")
{"p", [], ["text"], %{annotation: "annotation"}}
Specs
pre_code(content_t(), free_atts_t()) :: ast_t()
A convenient shortcut for the often occurring <pre><code>
tag chain
iex(17)> pre_code("hello")
{"pre", [], [{"code", [], ["hello"], %{}}], %{}}
Specs
pre_code_annotated(content_t(), any(), free_atts_t()) :: ast_t()
The annotation adding helper
iex(18)> pre_code_annotated("code", "@@lang=elixir")
{"pre", [], [{"code", [], ["code"], %{annotation: "@@lang=elixir"}}], %{}}
Specs
table(table_t(), free_atts_t()) :: ast_t()
Tables
Tables are probably the raison d'être ot this little lib, as their ast is quite verbose, as we will see here:
iex(19)> table("one cell only") # and look at the output
{"table", [], [
{"tbody", [], [
{"tr", [], [
{"td", [{"style", "text-align: left;"}], ["one cell only"], %{}}
], %{}}
], %{}}
], %{}}
Now if we want a header and have some more data:
iex(20)> table([~w[1-1 1-2], ~w[2-1 2-2]], head: ~w[left right]) # This is quite verbose!
{"table", [], [
{"thead", [], [
{"tr", [], [
{"th", [{"style", "text-align: left;"}], ["left"], %{}},
{"th", [{"style", "text-align: left;"}], ["right"], %{}},
], %{}}
], %{}},
{"tbody", [], [
{"tr", [], [
{"td", [{"style", "text-align: left;"}], ["1-1"], %{}},
{"td", [{"style", "text-align: left;"}], ["1-2"], %{}},
], %{}},
{"tr", [], [
{"td", [{"style", "text-align: left;"}], ["2-1"], %{}},
{"td", [{"style", "text-align: left;"}], ["2-2"], %{}},
], %{}}
], %{}}
], %{}}
And tables can easily be aligned differently in Markdown, which makes some style helpers very useful
iex(21)> table([~w[1-1 1-2], ~w[2-1 2-2]],
...(21)> head: ~w[alpha beta],
...(21)> text_aligns: ~w[right center])
{"table", [], [
{"thead", [], [
{"tr", [], [
{"th", [{"style", "text-align: right;"}], ["alpha"], %{}},
{"th", [{"style", "text-align: center;"}], ["beta"], %{}},
], %{}}
], %{}},
{"tbody", [], [
{"tr", [], [
{"td", [{"style", "text-align: right;"}], ["1-1"], %{}},
{"td", [{"style", "text-align: center;"}], ["1-2"], %{}},
], %{}},
{"tr", [], [
{"td", [{"style", "text-align: right;"}], ["2-1"], %{}},
{"td", [{"style", "text-align: center;"}], ["2-2"], %{}},
], %{}}
], %{}}
], %{}}
Some leeway is given for the determination of the number of columns, bear in mind that Markdown only supports regularly shaped tables with a fixed number of columns.
Problems might arise when we have a table like the following
| alpha |
| beta *gamma* |
where the first cell contains one element, but the second two, we can hint that we only want one by grouping into tuples
iex(22)> table(["alpha", {"beta", tag("em", "gamma")}])
{"table", [], [
{"tbody", [], [
{"tr", [], [
{"td", [{"style", "text-align: left;"}], ["alpha"], %{}},
], %{}},
{"tr", [], [
{"td", [{"style", "text-align: left;"}], ["beta", {"em", [], ["gamma"], %{}}], %{}}
], %{}}
], %{}}
], %{}}
Specs
This is the base helper which emits a tag with its content, attributes and metadata can be added at the user's convenience
iex(23)> tag("div")
{"div", [], [], %{}}
With content,
iex(24)> tag("span", "hello")
{"span", [], ["hello"], %{}}
... and attributes,
iex(25)> tag("code", "let it(:be_light)", [class: "inline"])
{"code", [{"class", "inline"}], ["let it(:be_light)"], %{}}
... and metadata
iex(26)> tag("div", "content", [], %{verbatim: true})
{"div", [], ["content"], %{verbatim: true}}
Specs
A convience function for easy addition of an annotation to the meta map
Specs
ul(content_t(), free_atts_t()) :: ast_t()
The ul
helper is different in respect to other helpers as it wraps content elements into li
tags if
necessary
iex(14)> ul(["hello", "world"])
{"ul", [], [{"li", [], ["hello"], %{}}, {"li", [], ["world"], %{}}], %{}}
but as mentioned only if necessary so that we can refine li
elements with attributes or meta if we want
iex(15)> ul(["hello", li("world", class: "global")])
{"ul", [], [{"li", [], ["hello"], %{}}, {"li", [{"class", "global"}], ["world"], %{}}], %{}}
Specs
void_tag(binary(), free_atts_t()) :: ast_t()
Void tags are just convenient shortcats for calls to tag
with the second argument
nil
or []
One cannot pass metadata to a void_tag call
iex(27)> void_tag("hr")
{"hr", [], [], %{}}
iex(28)> void_tag("hr", class: "thin")
{"hr", [{"class", "thin"}], [], %{}}
Specs
void_tag_annotated(binary(), any(), free_atts_t()) :: ast_t()
Again the annotated version is available
iex(29)> void_tag_annotated("br", "// break")
{"br", [], [], %{annotation: "// break"}}
iex(30)> void_tag_annotated("wbr", "// for printer", class: "nine")
{"wbr", [{"class", "nine"}], [], %{annotation: "// for printer"}}
Specs
vtags are tags from verbatim html
iex(31)> vtag("div", "hello")
{"div", [], ["hello"], %{verbatim: true}}
Attributes can be provided, of course
iex(32)> vtag("div", ["some", "content"], [{"data-lang", "elixir"}])
{"div", [{"data-lang", "elixir"}], ["some", "content"], %{verbatim: true}}
Specs
Verbatim tags still can be annotated and therefore we have this helper
iex(33)> vtag_annotated("i", "emphasized", "-- verbatim", printer: "no")
{"i", [{"printer", "no"}], ["emphasized"], %{annotation: "-- verbatim", verbatim: true}}