Last active
February 2, 2024 17:10
-
-
Save pre63/cb7217f01342cdbcec5c873448be798a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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