And I also want to take the time to thank the many contributors adding value and fixing bugs.
Not having much time for Earmark right now it is just so rewarding to get help from the community.
Check the Kudos for more information
And I also want to take the time to thank the many contributors adding value and fixing bugs.
Not having much time for Earmark right now it is just so rewarding to get help from the community.
Check the Kudos for more information
Just release bugfix release for broken strike througs
And here is the accompaning release for Earmark
EarmarkParser
1.4.29As we all hate compiler warnings
line
and footnote_offset
)Thanks for Earmark! Happy user
In case anyone else has a need to walk and modify the AST (and if I’m reading the changelog so far correctly, that is not yet a built-in part of Earmark), I wrote a function for that which is public domain. Written for Earmark 1.4.19 and tested only with that version so far:
@doc """
Walks an AST and allows you to process it (storing details in acc) and/or
modify it as it is walked.
The process_item_fn function is required. It takes two parameters, the
single item to process (which will either be a string or a 4-tuple) and
the accumulator, and returns a tuple {processed_item, updated_acc}.
Returning the empty list for processed_item will remove the item processed
the AST.
The process_list_fn function is optional and defaults to no modification of
items or accumulator. It takes two parameters, the list of items that
are the sub-items of a given element in the AST (or the top-level list of
items), and the accumulator, and returns a tuple
{processed_items_list, updated_acc}.
This function ends up returning {ast, acc}.
"""
def walk_and_modify_ast(items, acc, process_item_fn, process_list_fn \\ &({&1, &2}))
when is_list(items) and is_function(process_item_fn) and is_function(process_list_fn)
do
{items, acc} = process_list_fn.(items, acc)
{ast, acc} = Enum.map_reduce(items, acc, fn (item, acc) ->
{_item, _acc} = walk_and_modify_ast_item(item, acc, process_item_fn, process_list_fn)
end)
{List.flatten(ast), acc}
end
def walk_and_modify_ast_item(item, acc, process_item_fn, process_list_fn)
when is_function(process_item_fn) and is_function(process_list_fn) do
case process_item_fn.(item, acc) do
{{type, attribs, items, annotations}, acc}
when is_binary(type) and is_list(attribs) and is_list(items) and is_map(annotations) ->
{items, acc} = walk_and_modify_ast(items, acc, process_item_fn, process_list_fn)
{{type, attribs, List.flatten(items), annotations}, acc}
{item_or_items, acc} when is_binary(item_or_items) or is_list(item_or_items) ->
{item_or_items, acc}
end
end
You would use it something like follows, this example is from my own code where I’m fixing up a non-standard markdown format that uses * and / for strong and italic):
def parse(some_markdown):
{:ok, ast, _} = EarmarkParser.as_ast(some_markdown)
ast
|> handle_bold()
|> handle_italics()
end
# We process the ast to replace "em" with "strong" (because "Bear *boldly* goes
# where no bear has gone before", and to find matching pairs of word-adjacent
# slashes and change to italic (because "Bear has a certain /je ne c'est quoi/
# to it").
def handle_italics(ast) do
ast
|> walk_and_modify_ast("", &handle_italics_impl/2)
|> elem(0)
end
def handle_italics_impl(item, "a"), do: {item, ""}
def handle_italics_impl(item, acc) when is_binary(item) do
new_item = text_to_ast_list_splitting_regex(
item,
~r/\/([[:graph:]].*?[[:graph:]]|[[:graph:]])\//,
fn [_, content] ->
{"em", [], [content], %{}}
end
)
{new_item, acc}
end
def handle_italics_impl({name, _, _, _} = item, _acc) do
# Store the last seen element name so we can skip handling
# italics within <a> elements.
{item, name}
end
def handle_bold(ast) do
ast
|> walk_and_modify_ast(0, &handle_bold_impl/2)
|> elem(0)
end
def handle_bold_impl({"em", attribs, items, annotations}, acc) do
{{"strong", attribs, items, annotations}, acc}
end
def handle_bold_impl(item, acc), do: {item, acc}
Thank you I will have a look at it (in the PR if you do not mind) when I find some time
I just released a new version of Earmark
this one exposes a quite general AST transformation function allowing for structural modification. This is a contribution from Jói Sigurðsson
No updates on the parser version.
I just released new versions of EarmarkParser and Earmark
Fixed a problem with headers that close with # but have a # inside too
Kudos to Alex Martsinovich
Adding a non regression test for ~
inside links (was broken earlier)
Kudos to Faried Nawaz
Just updating to use EarmarkParser v1.4.30
I just released a new version of
PR Fix catastrophic backtracking in IAL regex
Special Kudos for spotting and fixing this Alex Martsinovich
Bugfix for Strikethrough not working if option breaks: true
Kudos to Mayel de Borniol for providing tests
and the accompagning
updating EarmarkParser to v1.4.31
I just released new versions
PR-460 Avoid trailing slash on void elements
Kudos to Jaime Iniesta
updating EarmarkParser to v1.4.32
A little late annoncement for the last EarmarkParser release, but it only removed warnings in Elixir 1.16
PR Avoid warnings in String#slice/2 with Elixir 1.16
Kudos to José Valim
And …
updated EarmarkParser’s version to 1.4.33 to avoid warnings in Elixir 1.16
I just released
EarmarkParser.as_ast
and also
Exposing all relevant Earmark.Options
to the command line
Updated EarmarkParser
version to 1.4.35
I have just released, what I consider my last release of
Isolate from EarmarkParser
in order to prevent conflicts with indirect dependencies
on EarmarkParser
via ExDoc
.
This shall mark the end of my role as maintainer of Earmark.
Removing the dependency on EarmarkParser
allows to
Earmark
decide how to parse markdownEarmark
→ EarmarkParser
and ex_doc
→ EarmarkParser
as has occurred hereJust released a quickfix for Earmark 1.4.42
hopefully I can get ~> 1.4.42
stable soon, please stick to 1.4.40
for the time being in case of problems (but of course bug requests in GH are welcome)
@RobertDober thanks for all your work on Earmark, its a critical part of the ecosystem and you’ve made it better through your efforts.
Very minor changes here
Correting deprection version for smarty_pants
Checking for result type EarmarkParser.t
of EarmarkParser.as_ast
In the case you use Earmark and EarmarkParser, I just released
Kudos to José Valim (do you really need a link here )for an important renaming task I had forgotten, this is only
important for users of both, Earmark
and EarmarkParser
More work from José to cleanup my sloppy last releases. So greatful.
This one might be interesting for everyone
These are for people using Earmark
and EarmarkParser
. As they address a potential naming conflict concerning compiled yecc or leex file however, a version update might be useful for all users. All work was done again by José, thank you so much.
Here are the release notes: