Add markdown parsing with hardcoded RawContent file.

This commit is contained in:
Dillon Kearns 2019-08-02 05:29:31 -07:00
parent b02c3a8d0e
commit 34b29436fd
5 changed files with 172 additions and 19 deletions

View File

@ -15,9 +15,11 @@
"elm/url": "1.0.0",
"elm-community/list-extra": "8.2.0",
"elm-community/result-extra": "2.2.1",
"elm-explorations/markdown": "1.0.0",
"lukewestby/elm-string-interpolate": "1.0.3",
"mdgriffith/elm-markup": "3.0.1",
"mdgriffith/elm-ui": "1.1.2"
"mdgriffith/elm-ui": "1.1.2",
"terezka/yaml": "1.0.0"
},
"indirect": {
"elm/parser": "1.1.0",

View File

@ -1,14 +1,27 @@
module RawContent exposing (content)
import Pages.Content as Content exposing (Content)
import Dict exposing (Dict)
import Element exposing (Element)
import Pages.Content as Content exposing (Content)
content : List ( List String, String )
content : { markdown : List ( List String, { frontMatter : String, body : String } ), markup : List ( List String, String ) }
content =
[
( ["about"]
{ markdown = markdown, markup = markup }
markdown : List ( List String, { frontMatter : String, body : String } )
markdown =
[ ( [ "markdown" ], { frontMatter = """
title: This is a markdown article
""", body = """# Hey there 👋
Welcome to this markdown document!""" } )
]
markup : List ( List String, String )
markup =
[ ( [ "about" ]
, """|> Article
title = How I Learned /elm-markup/
description = How I learned to use elm-markup.
@ -50,8 +63,7 @@ What does a *list* look like?
With some content
"""
)
,( ["articles"]
, ( [ "articles" ]
, """|> Article
title = How I Learned /elm-markup/
description = How I learned to use elm-markup.
@ -62,8 +74,7 @@ Here are some articles. You can learn more at.....
posts = articles
"""
)
,( ["articles", "moving-faster-with-tiny-steps"]
, ( [ "articles", "moving-faster-with-tiny-steps" ]
, """|> Article
title = Moving Faster with Tiny Steps in Elm
description = How I learned to use elm-markup.
@ -221,5 +232,4 @@ You can sign up here for more tips on writing Elm code incrementally. When you s
Let me know how this technique goes! Ive gotten a lot of great feedback from my clients about this approach, and I love hearing success stories. Hit reply and let me know how it goes! Id love to hear how youre able to apply this in your day-to-day work!
"""
)
]

View File

@ -11,6 +11,7 @@ import List.Extra
import Mark
import Mark.Error
import MarkParser
import Markdown
import Metadata exposing (Metadata)
import Pages
import Pages.Content as Content exposing (Content)
@ -18,6 +19,7 @@ import Pages.HeadTag as HeadTag exposing (HeadTag)
import Pages.Parser exposing (PageOrPost)
import RawContent
import Url exposing (Url)
import Yaml.Decode
port toJsPort : Json.Encode.Value -> Cmd msg
@ -35,13 +37,35 @@ main =
, update = update
, subscriptions = subscriptions
, parser = MarkParser.document
, frontmatterParser = frontmatterParser
, content = RawContent.content
, markdownToHtml = markdownToHtml
, toJsPort = toJsPort
, headTags = headTags
, siteUrl = "https://incrementalelm.com"
}
markdownToHtml : String -> Element msg
markdownToHtml body =
Markdown.toHtmlWith
{ githubFlavored = Just { tables = True, breaks = False }
, defaultHighlighting = Nothing
, sanitize = True
, smartypants = False
}
[]
body
|> Element.html
frontmatterParser : Yaml.Decode.Decoder (Metadata.Metadata msg)
frontmatterParser =
Yaml.Decode.field "title" Yaml.Decode.string
|> Yaml.Decode.map Metadata.PageMetadata
|> Yaml.Decode.map Metadata.Page
type alias Model =
{}

View File

@ -1,4 +1,4 @@
module Metadata exposing (ArticleMetadata, Metadata(..), metadata)
module Metadata exposing (ArticleMetadata, Metadata(..), PageMetadata, metadata)
import Dict exposing (Dict)
import Element exposing (Element)
@ -8,10 +8,14 @@ import Pages.Parser
type Metadata msg
= Page { title : String }
= Page PageMetadata
| Article (ArticleMetadata msg)
type alias PageMetadata =
{ title : String }
type alias LearnMetadata =
{ title : String }

View File

@ -13,11 +13,13 @@ import Pages.Content as Content exposing (Content)
import Pages.HeadTag exposing (HeadTag)
import Pages.Parser exposing (PageOrPost)
import Platform.Sub exposing (Sub)
import Result.Extra
import Url exposing (Url)
import Yaml.Decode
type alias Content =
List ( List String, String )
{ markdown : List ( List String, { frontMatter : String, body : String } ), markup : List ( List String, String ) }
type alias Program userFlags userModel userMsg metadata view =
@ -93,8 +95,35 @@ type alias Flags userFlags =
}
splitMarkdownFrontmatter : String -> ( String, String )
splitMarkdownFrontmatter string =
( """title: This is markdown""", """
# Markdown Rendered Successfully!
Nice job, you did it! 😄
""" )
something :
List ( List String, Result error success )
-> Result error (List ( List String, success ))
something input =
input
|> List.map
(\( path, result ) ->
result
|> Result.map (\success -> ( path, success ))
)
|> Result.Extra.combine
-- Result.Extra.com
init :
String
(String -> view)
-> Yaml.Decode.Decoder metadata
-> String
-> (Json.Encode.Value -> Cmd (Msg userMsg))
-> (String -> metadata -> List HeadTag)
-> Parser metadata view
@ -104,7 +133,7 @@ init :
-> Url
-> Browser.Navigation.Key
-> ( Model userModel userMsg metadata view, Cmd (Msg userMsg) )
init siteUrl toJsPort headTags parser content initUserModel flags url key =
init markdownToHtml frontmatterParser siteUrl toJsPort headTags parser content initUserModel flags url key =
let
( userModel, userCmd ) =
initUserModel flags
@ -115,8 +144,46 @@ init siteUrl toJsPort headTags parser content initUserModel flags url key =
flags.imageAssets
|> Result.withDefault Dict.empty
parsedMarkdown =
-- markdown
-- |> splitMarkdownFrontmatter
content.markdown
-- """
-- title: This is markdown
-- """
|> List.map
(Tuple.mapSecond
(\{ frontMatter } ->
Yaml.Decode.fromString frontmatterParser frontMatter
|> Result.mapError
(\error ->
case error of
Yaml.Decode.Parsing string ->
Html.text string
Yaml.Decode.Decoding string ->
Html.text string
)
)
)
-- |> Yaml.Decode.fromString frontmatterParser
markdown =
"""---
title: This is markdown
---
# Markdown Rendered Successfully!
Nice job, you did it! 😄
"""
metadata =
Content.parseMetadata parser imageAssets content
[ Content.parseMetadata parser imageAssets content.markup
, parsedMarkdown
|> something
]
|> Result.Extra.combine
|> Result.map List.concat
in
case metadata of
Ok okMetadata ->
@ -129,7 +196,11 @@ init siteUrl toJsPort headTags parser content initUserModel flags url key =
metadata
|> Result.andThen
(\m ->
Content.buildAllData m parser imageAssets content
[ Content.buildAllData m parser imageAssets content.markup
, parseMarkdown markdownToHtml frontmatterParser content.markdown
]
|> Result.Extra.combine
|> Result.map List.concat
)
}
, Cmd.batch
@ -156,7 +227,7 @@ init siteUrl toJsPort headTags parser content initUserModel flags url key =
metadata
|> Result.andThen
(\m ->
Content.buildAllData m parser imageAssets content
Content.buildAllData m parser imageAssets content.markup
)
}
, Cmd.batch
@ -227,11 +298,13 @@ program :
, toJsPort : Json.Encode.Value -> Cmd (Msg userMsg)
, headTags : String -> metadata -> List HeadTag
, siteUrl : String
, frontmatterParser : Yaml.Decode.Decoder metadata
, markdownToHtml : String -> view
}
-> Program userFlags userModel userMsg metadata view
program config =
Browser.application
{ init = init config.siteUrl config.toJsPort config.headTags config.parser config.content config.init
{ init = init config.markdownToHtml config.frontmatterParser config.siteUrl config.toJsPort config.headTags config.parser config.content config.init
, view = view config.content config.parser config.view
, update = update config.update
, subscriptions =
@ -241,3 +314,43 @@ program config =
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}
-- Result (Html msg) (List ( List String, { metadata : metadata , view : List view }))
-- TODO pass in the parsed frontmatter
-- TODO let the user render the markdown however the want... just give them the markdown as a String,
-- the parsed metadata, and let them return the view (either Html, or Element, or anything else)
parseMarkdown :
(String -> view)
-> Yaml.Decode.Decoder metadata
-> List ( List String, { frontMatter : String, body : String } )
-> Result (Html msg) (Content.Content metadata view)
parseMarkdown markdownToHtml frontmatterParser markdownContent =
markdownContent
|> List.map
(Tuple.mapSecond
(\{ frontMatter, body } ->
Yaml.Decode.fromString frontmatterParser frontMatter
|> Result.mapError
(\error ->
case error of
Yaml.Decode.Parsing string ->
Html.text string
Yaml.Decode.Decoding string ->
Html.text string
)
|> Result.map
(\metadata ->
{ metadata = metadata
, view =
[ markdownToHtml body
]
}
)
)
)
|> something