zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

markdown.ex (3115B)


      1 defmodule ExDoc.Markdown do
      2   @moduledoc """
      3   Adapter behaviour and conveniences for converting Markdown to HTML.
      4 
      5   ExDoc is compatible with any markdown processor that implements the
      6   functions defined in this module. The markdown processor can be changed
      7   via the `:markdown_processor` option in your `mix.exs`.
      8 
      9   ExDoc supports the following Markdown parsers out of the box:
     10 
     11     * [EarmarkParser](https://github.com/robertdober/earmark_parser)
     12 
     13   ExDoc uses EarmarkParser by default.
     14   """
     15 
     16   @doc """
     17   Converts markdown into HTML.
     18   """
     19   @callback to_ast(String.t(), Keyword.t()) :: term()
     20 
     21   @doc """
     22   Returns true if all dependencies necessary are available.
     23   """
     24   @callback available?() :: boolean()
     25 
     26   @markdown_processors [
     27     ExDoc.Markdown.Earmark
     28   ]
     29 
     30   @markdown_processor_key :markdown_processor
     31 
     32   @doc """
     33   Converts the given markdown document to HTML AST.
     34   """
     35   def to_ast(text, opts \\ []) when is_binary(text) do
     36     {processor, options} = get_markdown_processor()
     37     processor.to_ast(text, options |> Keyword.merge(opts))
     38   end
     39 
     40   @doc """
     41   Gets the current markdown processor set globally.
     42   """
     43   def get_markdown_processor do
     44     case Application.fetch_env(:ex_doc, @markdown_processor_key) do
     45       {:ok, {processor, options}} ->
     46         {processor, options}
     47 
     48       :error ->
     49         processor = find_markdown_processor() || raise_no_markdown_processor()
     50         put_markdown_processor({processor, []})
     51         {processor, []}
     52     end
     53   end
     54 
     55   @doc """
     56   Changes the markdown processor globally.
     57   """
     58   def put_markdown_processor(processor) when is_atom(processor) do
     59     put_markdown_processor({processor, []})
     60   end
     61 
     62   def put_markdown_processor({processor, options}) do
     63     Application.put_env(:ex_doc, @markdown_processor_key, {processor, options})
     64   end
     65 
     66   defp find_markdown_processor do
     67     Enum.find(@markdown_processors, fn module ->
     68       Code.ensure_loaded?(module) && module.available?
     69     end)
     70   end
     71 
     72   defp raise_no_markdown_processor do
     73     raise """
     74     Could not find a markdown processor to be used by ex_doc.
     75     You can either:
     76 
     77     * Add {:earmark, ">= 0.0.0"} to your mix.exs deps
     78       to use an Elixir-based markdown processor
     79     """
     80   end
     81 
     82   @doc """
     83   Wraps the desired tags in HTML in sections.
     84   """
     85   def sectionize(list, matcher), do: sectionize(list, matcher, [])
     86 
     87   defp sectionize(list, matcher, acc) do
     88     case pivot(list, acc, matcher) do
     89       {acc, {header_tag, header_attrs, _, _} = header, rest} ->
     90         {inner, rest} = Enum.split_while(rest, &not_tag?(&1, header_tag))
     91         class = String.trim_trailing("#{header_tag} #{header_attrs[:class]}")
     92         section = {:section, [class: class], [header | sectionize(inner, matcher, [])], %{}}
     93         sectionize(rest, matcher, [section | acc])
     94 
     95       acc ->
     96         acc
     97     end
     98   end
     99 
    100   defp not_tag?({tag, _, _, _}, tag), do: false
    101   defp not_tag?(_, _tag), do: true
    102 
    103   defp pivot([head | tail], acc, fun) do
    104     case fun.(head) do
    105       true -> {acc, head, tail}
    106       false -> pivot(tail, [head | acc], fun)
    107     end
    108   end
    109 
    110   defp pivot([], acc, _fun), do: Enum.reverse(acc)
    111 end