Skip to content

Instantly share code, notes, and snippets.

@pre63
Last active February 2, 2024 17:10
Show Gist options
  • Save pre63/cb7217f01342cdbcec5c873448be798a to your computer and use it in GitHub Desktop.
Save pre63/cb7217f01342cdbcec5c873448be798a to your computer and use it in GitHub Desktop.
module Mark exposing (markit, view)
import Element
exposing
( Element
, column
, paragraph
, spacing
, text
, width
, fill
)
import Html exposing (Html)
import Html.Attributes as Attr
import Markdown.Block as Block
import Markdown.Html
import Markdown.Parser
import Markdown.Renderer
wf = width fill
markit : String -> Element msg
markit markdown =
column [ wf, spacing 10, Element.htmlAttribute <| Attr.class "learn-markdown" ] (mark markdown |> List.map (\e -> paragraph [ wf ] [ e ]))
view : String -> Result String (List (Element msg))
view markdown =
markdown
|> String.replace "<br>" "\n\n"
|> Markdown.Parser.parse
|> Result.mapError (\error -> error |> List.map Markdown.Parser.deadEndToString |> String.join "\n")
|> Result.andThen (Markdown.Renderer.render defaultHtmlRenderer)
|> Result.map (\html -> List.map Element.html html)
mark : String -> List (Element msg)
mark val =
case view val of
Ok rendered ->
rendered
Err err ->
[ oops, text err ]
defaultHtmlRenderer : Markdown.Renderer.Renderer (Html.Html msg)
defaultHtmlRenderer =
{ heading =
\{ level, children } ->
case level of
Block.H1 ->
Html.h1 [] children
Block.H2 ->
Html.h2 [] children
Block.H3 ->
Html.h3 [] children
Block.H4 ->
Html.h4 [] children
Block.H5 ->
Html.h5 [] children
Block.H6 ->
Html.h6 [] children
, paragraph = Html.p []
, hardLineBreak = Html.br [] []
, blockQuote = Html.blockquote []
, strong =
\children -> Html.strong [] children
, emphasis =
\children -> Html.em [] children
, strikethrough =
\children -> Html.del [] children
, codeSpan =
\content -> Html.code [] [ Html.text content ]
, link =
\link content ->
case link.title of
Just title ->
Html.a
[ Attr.href link.destination
, Attr.title title
, Attr.target "_blank"
]
content
Nothing ->
Html.a [ Attr.href link.destination, Attr.target "_blank" ] content
, image =
\imageInfo ->
case imageInfo.title of
Just title ->
Html.img
[ Attr.src imageInfo.src
, Attr.alt imageInfo.alt
, Attr.title title
]
[]
Nothing ->
Html.img
[ Attr.src imageInfo.src
, Attr.alt imageInfo.alt
]
[]
, text =
Html.text
, unorderedList =
\items ->
Html.ul []
(items
|> List.map
(\item ->
case item of
Block.ListItem task children ->
let
checkbox : Html msg
checkbox =
case task of
Block.NoTask ->
Html.text ""
Block.IncompleteTask ->
Html.input
[ Attr.disabled True
, Attr.checked False
, Attr.type_ "checkbox"
]
[]
Block.CompletedTask ->
Html.input
[ Attr.disabled True
, Attr.checked True
, Attr.type_ "checkbox"
]
[]
in
Html.li [] (checkbox :: children)
)
)
, orderedList =
\startingIndex items ->
Html.ol
(case startingIndex of
1 ->
[ Attr.start startingIndex ]
_ ->
[]
)
(items
|> List.map
(\itemBlocks ->
Html.li []
itemBlocks
)
)
, html = Markdown.Html.oneOf []
, codeBlock =
\{ body, language } ->
let
classes : List (Html.Attribute msg)
classes =
-- Only the first word is used in the class
case Maybe.map String.words language of
Just (actualLanguage :: _) ->
[ Attr.class <| "language-" ++ actualLanguage ]
_ ->
[]
in
Html.pre []
[ Html.code classes
[ Html.text body
]
]
, thematicBreak = Html.hr [] []
, table = Html.table []
, tableHeader = Html.thead []
, tableBody = Html.tbody []
, tableRow = Html.tr []
, tableHeaderCell =
\maybeAlignment ->
let
attrs : List (Html.Attribute msg)
attrs =
maybeAlignment
|> Maybe.map
(\alignment ->
case alignment of
Block.AlignLeft ->
"left"
Block.AlignCenter ->
"center"
Block.AlignRight ->
"right"
)
|> Maybe.map Attr.align
|> Maybe.map List.singleton
|> Maybe.withDefault []
in
Html.th attrs
, tableCell =
\maybeAlignment ->
let
attrs : List (Html.Attribute msg)
attrs =
maybeAlignment
|> Maybe.map
(\alignment ->
case alignment of
Block.AlignLeft ->
"left"
Block.AlignCenter ->
"center"
Block.AlignRight ->
"right"
)
|> Maybe.map Attr.align
|> Maybe.map List.singleton
|> Maybe.withDefault []
in
Html.td attrs
}
oops : Element msg
oops =
text "Oops can't render that!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment