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

View File

@ -1,16 +1,16 @@
module Document exposing (Document, map) module Document exposing (Document, map)
import Element exposing (Element) import Html.Styled
type alias Document msg = type alias Document msg =
{ title : String { title : String
, body : List (Element msg) , body : List (Html.Styled.Html msg)
} }
map : (msg1 -> msg2) -> Document msg1 -> Document msg2 map : (msg1 -> msg2) -> Document msg1 -> Document msg2
map fn doc = map fn doc =
{ title = doc.title { 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) module MarkdownRenderer exposing (renderer)
import Element exposing (Element) import Html.Styled as Html
import Element.Background import Html.Styled.Attributes as Attr exposing (css)
import Element.Border
import Element.Font as Font
import Element.Input
import Element.Region
import Html
import Html.Attributes
import Markdown.Block as Block exposing (ListItem(..), Task(..)) import Markdown.Block as Block exposing (ListItem(..), Task(..))
import Markdown.Html import Markdown.Html
import Markdown.Renderer import Markdown.Renderer
import Palette import Tailwind.Utilities as Tw
renderer : Markdown.Renderer.Renderer (Element msg) renderer : Markdown.Renderer.Renderer (Html.Html msg)
renderer = renderer =
{ heading = heading { heading = heading
, paragraph = , paragraph = Html.p []
Element.paragraph , thematicBreak = Html.hr [] []
[ Element.spacing 15 ] , text = Html.text
, thematicBreak = Element.none , strong = \content -> Html.strong [ css [ Tw.font_bold ] ] content
, text = \value -> Element.paragraph [] [ Element.text value ] , emphasis = \content -> Html.em [ css [ Tw.italic ] ] content
, strong = \content -> Element.paragraph [ Font.bold ] content , blockQuote = Html.blockquote []
, emphasis = \content -> Element.paragraph [ Font.italic ] content , codeSpan =
, codeSpan = code \content -> Html.code [] [ Html.text content ]
--, codeSpan = code
, link = , link =
\{ destination } body -> \{ destination } body ->
Element.newTabLink [] Html.a
{ url = destination [ Attr.href destination
, label = ]
Element.paragraph body
[ Font.color (Element.rgb255 0 0 255) , hardLineBreak = Html.br [] []
, Element.htmlAttribute (Html.Attributes.style "overflow-wrap" "break-word")
, Element.htmlAttribute (Html.Attributes.style "word-break" "break-word")
]
body
}
, hardLineBreak = Html.br [] [] |> Element.html
, image = , image =
\image -> \image ->
case image.title of case image.title of
Just _ -> Just _ ->
Element.image [ Element.width Element.fill ] { src = image.src, description = image.alt } Html.img [ Attr.src image.src, Attr.alt image.alt ] []
Nothing -> Nothing ->
Element.image [ Element.width Element.fill ] { src = image.src, description = image.alt } Html.img [ Attr.src image.src, Attr.alt 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
, unorderedList = , unorderedList =
\items -> \items ->
Element.column [ Element.spacing 15 ] Html.ul []
(items (items
|> List.map |> List.map
(\(ListItem task children) -> (\item ->
Element.paragraph [ Element.spacing 5 ] case item of
[ Element.row Block.ListItem task children ->
[ Element.alignTop ] let
((case task of checkbox =
IncompleteTask -> case task of
Element.Input.defaultCheckbox False Block.NoTask ->
Html.text ""
CompletedTask -> Block.IncompleteTask ->
Element.Input.defaultCheckbox True Html.input
[ Attr.disabled True
, Attr.checked False
, Attr.type_ "checkbox"
]
[]
NoTask -> Block.CompletedTask ->
Element.text "" Html.input
) [ Attr.disabled True
:: Element.text " " , Attr.checked True
:: children , Attr.type_ "checkbox"
) ]
] []
in
Html.li [] (checkbox :: children)
) )
) )
, orderedList = , orderedList =
\startingIndex items -> \startingIndex items ->
Element.column [ Element.spacing 15 ] Html.ol
(case startingIndex of
1 ->
[ Attr.start startingIndex ]
_ ->
[]
)
(items (items
|> List.indexedMap |> List.map
(\index itemBlocks -> (\itemBlocks ->
Element.row [ Element.spacing 5 ] Html.li []
[ Element.row [ Element.alignTop ] itemBlocks
(Element.text (String.fromInt (index + startingIndex) ++ " ") :: itemBlocks)
]
) )
) )
, codeBlock = codeBlock , html = Markdown.Html.oneOf []
, table = Element.column [] , codeBlock =
, tableHeader = Element.column [] \{ body, language } ->
, tableBody = Element.column [] let
, tableRow = Element.row [] 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 = , tableHeaderCell =
\_ children -> \maybeAlignment ->
Element.paragraph [] children let
, tableCell = Element.paragraph [] attrs =
, html = maybeAlignment
Markdown.Html.oneOf |> Maybe.map
[ Markdown.Html.tag "banner" (\alignment ->
(\children -> case alignment of
Element.paragraph Block.AlignLeft ->
[ Font.center "left"
, Font.size 47
, Font.family [ Font.typeface "Montserrat" ] Block.AlignCenter ->
, Font.color Palette.color.primary "center"
]
children Block.AlignRight ->
) "right"
, Markdown.Html.tag "values" )
(\children -> |> Maybe.map Attr.align
Element.row |> Maybe.map List.singleton
[ Element.spacing 30 |> Maybe.withDefault []
, Element.htmlAttribute (Html.Attributes.style "flex-wrap" "wrap") in
] Html.th attrs
children , tableCell =
) \maybeAlignment ->
, Markdown.Html.tag "value" let
(\children -> attrs =
Element.column maybeAlignment
[ Element.width Element.fill |> Maybe.map
, Element.padding 20 (\alignment ->
, Element.spacing 20 case alignment of
, Element.height Element.fill Block.AlignLeft ->
, Element.centerX "left"
]
children 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 |> 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 } = heading { level, rawText, children } =
Element.paragraph (case level of
[ Font.size Block.H1 ->
(case level of Html.h1
Block.H1 ->
36
Block.H2 -> Block.H2 ->
24 Html.h2
_ -> Block.H3 ->
20 Html.h3
)
, Font.bold Block.H4 ->
, Font.family [ Font.typeface "Montserrat" ] Html.h4
, Element.Region.heading (Block.headingLevelToInt level)
, Element.htmlAttribute Block.H5 ->
(Html.Attributes.attribute "name" (rawTextToId rawText)) Html.h5
, Element.htmlAttribute
(Html.Attributes.id (rawTextToId rawText)) Block.H6 ->
Html.h6
)
[ Attr.id (rawTextToId rawText)
, Attr.attribute "name" (rawTextToId rawText)
, css [ Tw.font_bold ]
] ]
children 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 -- TODO turn this back on - it's off for now to get more accurate performance benchmarks
--SyntaxHighlight.elm details.body --SyntaxHighlight.elm details.body
-- |> Result.map (SyntaxHighlight.toBlockHtml (Just 1)) -- |> 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 Document exposing (Document)
import Html exposing (Html) import Html exposing (Html)
import Html.Styled
import OptimizedDecoder as D import OptimizedDecoder as D
import Pages.PagePath exposing (PagePath) import Pages.PagePath exposing (PagePath)
import Pages.StaticHttp as StaticHttp import Pages.StaticHttp as StaticHttp
@ -92,6 +93,7 @@ view :
-> { body : Html msg, title : String } -> { body : Html msg, title : String }
view stars page model toMsg pageView = view stars page model toMsg pageView =
{ body = { body =
Html.text "Hi" Html.Styled.div [] pageView.body
|> Html.Styled.toUnstyled
, title = pageView.title , title = pageView.title
} }

View File

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