pablohirafuji/elm-markdown/2.0.6

Markdown.Block

Block parsing, rendering and helpers.

Model

type Block b i
= BlankLine String
| ThematicBreak
| Heading String Int (List (Inline i))
| CodeBlock CodeBlock String
| Paragraph String (List (Inline i))
| BlockQuote (List (Block b i))
| List ListBlock (List (List (Block b i)))
| PlainInlines (List (Inline i))
| Custom b (List (Block b i))

The block type.

  • BlankLine | Text
  • ThematicBreak
  • Heading | Raw text | Level | Inlines
  • CodeBlock | CodeBlock | Code
  • Paragraph | Raw text | Inlines
  • BlockQuote | Blocks
  • List | ListBlock | Items
  • PlainInlines | Inlines
  • Custom | Custom type | Blocks
= Indented
| Fenced Bool Fence

CodeBlock type.

  • Indented
  • Fenced | Is fence open? | Fence
type alias Fence =
{ indentLength : Int
, fenceLength : Int
, fenceChar : String
, language : Maybe String
}

Code fence model.

type alias ListBlock =
{ type_ : ListType
, indentLength : Int
, delimiter : String
, isLoose : Bool
}

List model.

= Unordered
| Ordered Int

Types of list.

  • Unordered
  • Ordered | Start

Parsing

parse : Maybe Options -> String -> List (Block b i)

Turn a markdown string into a list of blocks.

blocks : List (Block b i)
blocks =
    parse Nothing "# Heading with *emphasis*"

It's the same of:

blocks : List (Block b i)
blocks =
    [ Heading "Heading with *emphasis*"
        1
        [ Text "Heading with "
        , Emphasis 1
            [ Text "emphasis" ]
        ]
    ]

Note: If Maybe Options is Nothing, Config.defaultOptions will be used.

Rendering

toHtml : Block b i -> List (Html msg)

Transform a Block into a list of Html using the default html elements.

import Html exposing (Html, div)
import Markdown.Block as Block


view : Html msg
view =
    myMarkdownString
        |> Block.parse Nothing
        -- using Config.defaultOptions
        |> List.map Block.toHtml
        |> List.concat
        |> div []
Maybe (Block b i -> List (Html msg))
-> Maybe (Inline i -> Html msg)
-> Block b i
-> List (Html msg)

If you want to customize the html output, this function will help you.

Transform a block into a list of Html, optionally using custom html elements to render inner blocks or/and inlines.

Example of rendering:

  • All blockquotes as a detail element;
  • Images using figure and figcaption;
  • Links not starting with http://elm-lang.org with a target="_blank" attribute.
import Html exposing (..)
import Html.Attributes exposing (..)
import Markdown.Block as Block exposing (Block(..))
import Markdown.Inline as Inline exposing (Inline(..))

view : Html msg
view =
    myMarkdownString
        |> Block.parse Nothing
        -- using Config.defaultOptions
        |> List.map customHtmlBlock
        |> List.concat
        |> article []

customHtmlBlock : Block b i -> List (Html msg)
customHtmlBlock block =
    case block of
        BlockQuote blocks ->
            List.map customHtmlBlock blocks
                |> List.concat
                |> details []
                |> (\a -> (::) a [])

        _ ->
            Block.defaultHtml
                (Just customHtmlBlock)
                (Just customHtmlInline)
                block

customHtmlInline : Inline i -> Html msg
customHtmlInline inline =
    case inline of
        Image url maybeTitle inlines ->
            figure []
                [ img
                    [ alt (Inline.extractText inlines)
                    , src url
                    , title (Maybe.withDefault "" maybeTitle)
                    ]
                    []
                , figcaption []
                    [ text (Inline.extractText inlines) ]
                ]

        Link url maybeTitle inlines ->
            if String.startsWith "http://elm-lang.org" url then
                a
                    [ href url
                    , title (Maybe.withDefault "" maybeTitle)
                    ]
                    (List.map customHtmlInline inlines)
            else
                a
                    [ href url
                    , title (Maybe.withDefault "" maybeTitle)
                    , target "_blank"
                    , rel "noopener noreferrer"
                    ]
                    (List.map customHtmlInline inlines)

        _ ->
            Inline.defaultHtml (Just customHtmlInline) inline

Note: If both Maybe arguments are Nothing, the default html elements will be used to render the inner blocks and inlines.

Helpers

walk : (Block b i -> Block b i) -> Block b i -> Block b i

Apply a function to every block whithin a block recursively.

Example of replacing all level 3+ heading to regular paragraphs:

import Html exposing (Html, section)
import Markdown.Block as Block exposing (Block(..))


view : Html msg
view =
    myMarkdownString
        |> Block.parse Nothing
        -- using Config.defaultOptions
        |> List.map (Block.walk modHeader)
        |> List.map Block.toHtml
        |> List.concat
        |> section []


modHeader : Block b i -> Block b i
modHeader block =
    case block of
        Heading rawText level inlines ->
            if level >= 3 then
                Paragraph rawText inlines
            else
                block


        _ ->
            block
walkInlines : (Inline i -> Inline i) -> Block b i -> Block b i

Apply a function to every block's inline recursively.

Example of converting all Text to UPPERCASE:

import Html exposing (Html, section)
import Markdown.Block as Block exposing (Block(..))
import Markdown.Inline exposing (Inline(..))


view : Html msg
view =
    myMarkdownString
        |> Block.parse Nothing
        |> List.map (Block.walkInlines upperText)
        |> List.map Block.toHtml
        |> List.concat
        |> section []


upperText : Inline i -> Inline i
upperText inline =
    case inline of
        Text str ->
            Text (String.toUpper str)


        _ ->
            inline
query : (Block b i -> List a) -> Block b i -> List a

Walks a block and applies a function for every block, appending the results.

Example of getting all headings of a list of blocks:

toc : List ( Int, String )
toc =
    myMarkdownString
        |> Block.parse Nothing
        |> List.map (Block.query getHeader)
        |> List.concat


getHeader : Block b i -> List ( Int, String )
getHeader block =
    case block of
        Heading _ lvl inlines ->
            [ ( lvl, Inline.extractText inlines ) ]


        _ ->
            []
queryInlines : (Inline i -> List a) -> Block b i -> List a

Walks a block and applies a function for every inline, appending the results.

Example of getting all links within a list of blocks:

links : List String
links =
    myMarkdownString
        |> Block.parse Nothing
        |> List.map (Block.queryInlines getLinks)
        |> List.concat


getLinks : Inline i -> List String
getLinks inline =
    case inline of
        Link url _ _ ->
            [ url ]


        _ ->
            []