Use a tailwind renderer.

This commit is contained in:
Dillon Kearns 2021-04-14 08:32:46 -07:00
parent c6d09e3bdf
commit 55711852ea
5 changed files with 174 additions and 155 deletions

View File

@ -13,7 +13,7 @@
"avh4/elm-color": "1.0.0",
"billstclair/elm-xml-eeue56": "1.0.1",
"danyx23/elm-mimetype": "4.0.1",
"dillonkearns/elm-markdown": "4.0.2",
"dillonkearns/elm-markdown": "6.0.1",
"dillonkearns/elm-oembed": "1.0.0",
"dillonkearns/elm-rss": "1.0.1",
"dillonkearns/elm-sitemap": "1.0.1",
@ -35,10 +35,12 @@
"elm-explorations/markdown": "1.0.0",
"justinmimbs/date": "3.2.0",
"lukewestby/elm-string-interpolate": "1.0.4",
"matheus23/elm-default-tailwind-modules": "1.0.0",
"mdgriffith/elm-ui": "1.1.8",
"miniBill/elm-codec": "1.2.0",
"noahzgordon/elm-color-extra": "1.0.2",
"pablohirafuji/elm-syntax-highlight": "3.3.0",
"rtfeldman/elm-css": "16.1.1",
"rtfeldman/elm-hex": "1.0.0",
"tripokey/elm-fuzzy": "5.2.1",
"zwilias/json-decode-exploration": "6.0.0"
@ -61,4 +63,4 @@
},
"indirect": {}
}
}
}

View File

@ -1,16 +1,16 @@
module Document exposing (Document, map)
import Element exposing (Element)
import Html.Styled
type alias Document msg =
{ title : String
, body : List (Element msg)
, body : List (Html.Styled.Html msg)
}
map : (msg1 -> msg2) -> Document msg1 -> Document msg2
map fn doc =
{ title = doc.title
, body = List.map (Element.map fn) doc.body
, body = List.map (Html.Styled.map fn) doc.body
}

View File

@ -1,138 +1,159 @@
module MarkdownRenderer exposing (renderer)
import Element exposing (Element)
import Element.Background
import Element.Border
import Element.Font as Font
import Element.Input
import Element.Region
import Html
import Html.Attributes
import Html.Styled as Html
import Html.Styled.Attributes as Attr exposing (css)
import Markdown.Block as Block exposing (ListItem(..), Task(..))
import Markdown.Html
import Markdown.Renderer
import Palette
import Tailwind.Utilities as Tw
renderer : Markdown.Renderer.Renderer (Element msg)
renderer : Markdown.Renderer.Renderer (Html.Html msg)
renderer =
{ heading = heading
, paragraph =
Element.paragraph
[ Element.spacing 15 ]
, thematicBreak = Element.none
, text = \value -> Element.paragraph [] [ Element.text value ]
, strong = \content -> Element.paragraph [ Font.bold ] content
, emphasis = \content -> Element.paragraph [ Font.italic ] content
, codeSpan = code
, paragraph = Html.p []
, thematicBreak = Html.hr [] []
, text = Html.text
, strong = \content -> Html.strong [ css [ Tw.font_bold ] ] content
, emphasis = \content -> Html.em [ css [ Tw.italic ] ] content
, blockQuote = Html.blockquote []
, codeSpan =
\content -> Html.code [] [ Html.text content ]
--, codeSpan = code
, link =
\{ destination } body ->
Element.newTabLink []
{ url = destination
, label =
Element.paragraph
[ Font.color (Element.rgb255 0 0 255)
, Element.htmlAttribute (Html.Attributes.style "overflow-wrap" "break-word")
, Element.htmlAttribute (Html.Attributes.style "word-break" "break-word")
]
body
}
, hardLineBreak = Html.br [] [] |> Element.html
Html.a
[ Attr.href destination
]
body
, hardLineBreak = Html.br [] []
, image =
\image ->
case image.title of
Just _ ->
Element.image [ Element.width Element.fill ] { src = image.src, description = image.alt }
Html.img [ Attr.src image.src, Attr.alt image.alt ] []
Nothing ->
Element.image [ Element.width Element.fill ] { src = image.src, description = image.alt }
, blockQuote =
\children ->
Element.column
[ Element.Border.widthEach { top = 0, right = 0, bottom = 0, left = 10 }
, Element.padding 10
, Element.Border.color (Element.rgb255 145 145 145)
, Element.Background.color (Element.rgb255 245 245 245)
]
children
Html.img [ Attr.src image.src, Attr.alt image.alt ] []
, unorderedList =
\items ->
Element.column [ Element.spacing 15 ]
Html.ul []
(items
|> List.map
(\(ListItem task children) ->
Element.paragraph [ Element.spacing 5 ]
[ Element.row
[ Element.alignTop ]
((case task of
IncompleteTask ->
Element.Input.defaultCheckbox False
(\item ->
case item of
Block.ListItem task children ->
let
checkbox =
case task of
Block.NoTask ->
Html.text ""
CompletedTask ->
Element.Input.defaultCheckbox True
Block.IncompleteTask ->
Html.input
[ Attr.disabled True
, Attr.checked False
, Attr.type_ "checkbox"
]
[]
NoTask ->
Element.text ""
)
:: Element.text " "
:: children
)
]
Block.CompletedTask ->
Html.input
[ Attr.disabled True
, Attr.checked True
, Attr.type_ "checkbox"
]
[]
in
Html.li [] (checkbox :: children)
)
)
, orderedList =
\startingIndex items ->
Element.column [ Element.spacing 15 ]
Html.ol
(case startingIndex of
1 ->
[ Attr.start startingIndex ]
_ ->
[]
)
(items
|> List.indexedMap
(\index itemBlocks ->
Element.row [ Element.spacing 5 ]
[ Element.row [ Element.alignTop ]
(Element.text (String.fromInt (index + startingIndex) ++ " ") :: itemBlocks)
]
|> List.map
(\itemBlocks ->
Html.li []
itemBlocks
)
)
, codeBlock = codeBlock
, table = Element.column []
, tableHeader = Element.column []
, tableBody = Element.column []
, tableRow = Element.row []
, html = Markdown.Html.oneOf []
, codeBlock =
\{ body, language } ->
let
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
]
]
, table = Html.table []
, tableHeader = Html.thead []
, tableBody = Html.tbody []
, tableRow = Html.tr []
, strikethrough =
\children -> Html.del [] children
, tableHeaderCell =
\_ children ->
Element.paragraph [] children
, tableCell = Element.paragraph []
, html =
Markdown.Html.oneOf
[ Markdown.Html.tag "banner"
(\children ->
Element.paragraph
[ Font.center
, Font.size 47
, Font.family [ Font.typeface "Montserrat" ]
, Font.color Palette.color.primary
]
children
)
, Markdown.Html.tag "values"
(\children ->
Element.row
[ Element.spacing 30
, Element.htmlAttribute (Html.Attributes.style "flex-wrap" "wrap")
]
children
)
, Markdown.Html.tag "value"
(\children ->
Element.column
[ Element.width Element.fill
, Element.padding 20
, Element.spacing 20
, Element.height Element.fill
, Element.centerX
]
children
)
]
\maybeAlignment ->
let
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 =
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
}
@ -144,49 +165,50 @@ rawTextToId rawText =
|> String.toLower
heading : { level : Block.HeadingLevel, rawText : String, children : List (Element msg) } -> Element msg
heading : { level : Block.HeadingLevel, rawText : String, children : List (Html.Html msg) } -> Html.Html msg
heading { level, rawText, children } =
Element.paragraph
[ Font.size
(case level of
Block.H1 ->
36
(case level of
Block.H1 ->
Html.h1
Block.H2 ->
24
Block.H2 ->
Html.h2
_ ->
20
)
, Font.bold
, Font.family [ Font.typeface "Montserrat" ]
, Element.Region.heading (Block.headingLevelToInt level)
, Element.htmlAttribute
(Html.Attributes.attribute "name" (rawTextToId rawText))
, Element.htmlAttribute
(Html.Attributes.id (rawTextToId rawText))
Block.H3 ->
Html.h3
Block.H4 ->
Html.h4
Block.H5 ->
Html.h5
Block.H6 ->
Html.h6
)
[ Attr.id (rawTextToId rawText)
, Attr.attribute "name" (rawTextToId rawText)
, css [ Tw.font_bold ]
]
children
code : String -> Element msg
code snippet =
Element.el
[ Element.Background.color
(Element.rgba255 50 50 50 0.07)
, Element.Border.rounded 2
, Element.paddingXY 5 3
, Font.family [ Font.typeface "Roboto Mono", Font.monospace ]
]
(Element.text snippet)
codeBlock : { body : String, language : Maybe String } -> Element msg
codeBlock details =
Element.paragraph [] [ Element.text details.body ]
--code : String -> Element msg
--code snippet =
-- Element.el
-- [ Element.Background.color
-- (Element.rgba255 50 50 50 0.07)
-- , Element.Border.rounded 2
-- , Element.paddingXY 5 3
-- , Font.family [ Font.typeface "Roboto Mono", Font.monospace ]
-- ]
-- (Element.text snippet)
--
--
--codeBlock : { body : String, language : Maybe String } -> Element msg
--codeBlock details =
-- Element.paragraph [] [ Element.text details.body ]
-- TODO turn this back on - it's off for now to get more accurate performance benchmarks
--SyntaxHighlight.elm details.body
-- |> Result.map (SyntaxHighlight.toBlockHtml (Just 1))

View File

@ -2,6 +2,7 @@ module Shared exposing (Model, Msg(..), SharedMsg(..), StaticData, template)
import Document exposing (Document)
import Html exposing (Html)
import Html.Styled
import OptimizedDecoder as D
import Pages.PagePath exposing (PagePath)
import Pages.StaticHttp as StaticHttp
@ -92,6 +93,7 @@ view :
-> { body : Html msg, title : String }
view stars page model toMsg pageView =
{ body =
Html.text "Hi"
Html.Styled.div [] pageView.body
|> Html.Styled.toUnstyled
, title = pageView.title
}

View File

@ -4,6 +4,7 @@ import Document exposing (Document)
import Element exposing (Element)
import Head
import Head.Seo as Seo
import Html.Styled
import Markdown.Block
import Markdown.Parser
import Markdown.Renderer
@ -117,7 +118,7 @@ head static =
type alias StaticData =
List (Element Msg)
List (Html.Styled.Html Msg)
view :
@ -125,13 +126,5 @@ view :
-> Document Msg
view static =
{ title = "TODO title"
, body =
[ Element.column
[ Element.padding 40
]
[ Element.text static.routeParams.number
, Element.column []
static.static
]
]
, body = static.static
}