Get description from first paragraph when there is no description frontmatter field.

This commit is contained in:
Dillon Kearns 2021-07-30 10:43:14 -07:00
parent 4a24a1c72a
commit c8ed2fb140
4 changed files with 163 additions and 54 deletions

View File

@ -1,7 +1,3 @@
---
description: TODO
---
# Getting Started
You can create a fresh `elm-pages` project with the `init` command.

View File

@ -1,7 +1,3 @@
---
description: TODO
---
# Ports and Flags
You can handle ports and flags similar to how you would in a regular Elm application.

View File

@ -70,7 +70,7 @@ routes =
data : RouteParams -> DataSource Data
data routeParams =
DataSource.map3 Data
DataSource.map4 Data
(pageBody routeParams)
(previousAndNextData routeParams)
(routeParams.section
@ -79,6 +79,7 @@ data routeParams =
|> Glob.expectUniqueMatch
|> DataSource.map filePathToEditUrl
)
(routeParams |> filePathDataSource |> DataSource.andThen MarkdownCodec.titleAndDescription)
filePathToEditUrl : String -> String
@ -175,7 +176,7 @@ head static =
, dimensions = Nothing
, mimeType = Nothing
}
, description = static.data.body.description
, description = static.data.metadata.description
, locale = Nothing
, title = static.data.titles.title ++ " | elm-pages docs"
}
@ -183,9 +184,10 @@ head static =
type alias Data =
{ body : { description : String, body : List (Html Msg) }
{ body : List (Html Msg)
, titles : { title : String, previousAndNext : ( Maybe NextPrevious.Item, Maybe NextPrevious.Item ) }
, editUrl : String
, metadata : { title : String, description : String }
}
@ -239,7 +241,7 @@ view maybeUrl sharedModel static =
, Bp.xl [ Tw.pr_36 ]
]
]
(static.data.body.body
(static.data.body
++ [ NextPrevious.view static.data.titles.previousAndNext
, Html.hr [] []
, Html.footer
@ -272,8 +274,8 @@ view maybeUrl sharedModel static =
}
pageBody : RouteParams -> DataSource { description : String, body : List (Html msg) }
pageBody routeParams =
filePathDataSource : RouteParams -> DataSource String
filePathDataSource routeParams =
let
slug : String
slug =
@ -281,11 +283,14 @@ pageBody routeParams =
|> Maybe.withDefault "what-is-elm-pages"
in
Glob.expectUniqueMatch (findBySlug slug)
pageBody : RouteParams -> DataSource (List (Html msg))
pageBody routeParams =
routeParams
|> filePathDataSource
|> DataSource.andThen
(MarkdownCodec.withFrontmatter (\description body -> { description = description, body = body })
(Decode.field "description" Decode.string)
TailwindMarkdownRenderer.renderer
)
(MarkdownCodec.withoutFrontmatter TailwindMarkdownRenderer.renderer)
findBySlug : String -> Glob String

View File

@ -1,7 +1,8 @@
module MarkdownCodec exposing (codec, withFrontmatter)
module MarkdownCodec exposing (noteTitle, titleAndDescription, withFrontmatter, withoutFrontmatter)
import DataSource
import DataSource exposing (DataSource)
import DataSource.File as StaticFile
import List.Extra
import Markdown.Block as Block exposing (Block)
import Markdown.Parser
import Markdown.Renderer
@ -9,12 +10,156 @@ import OptimizedDecoder exposing (Decoder)
import Serialize as S
noteTitle : String -> DataSource String
noteTitle filePath =
titleFromFrontmatter filePath
|> DataSource.andThen
(\maybeTitle ->
maybeTitle
|> Maybe.map DataSource.succeed
|> Maybe.withDefault
(StaticFile.bodyWithoutFrontmatter filePath
|> DataSource.andThen
(\rawContent ->
Markdown.Parser.parse rawContent
|> Result.mapError (\_ -> "Markdown error")
|> Result.map
(\blocks ->
List.Extra.findMap
(\block ->
case block of
Block.Heading Block.H1 inlines ->
Just (Block.extractInlineText inlines)
_ ->
Nothing
)
blocks
)
|> Result.andThen (Result.fromMaybe <| "Expected to find an H1 heading for page " ++ filePath)
|> DataSource.fromResult
)
)
)
|> DataSource.distillSerializeCodec ("note-title-" ++ filePath) S.string
titleAndDescription : String -> DataSource { title : String, description : String }
titleAndDescription filePath =
filePath
|> StaticFile.onlyFrontmatter
(OptimizedDecoder.map2 (\title description -> { title = title, description = description })
(OptimizedDecoder.optionalField "title" OptimizedDecoder.string)
(OptimizedDecoder.optionalField "description" OptimizedDecoder.string)
)
|> DataSource.andThen
(\metadata ->
Maybe.map2 (\title description -> { title = title, description = description })
metadata.title
metadata.description
|> Maybe.map DataSource.succeed
|> Maybe.withDefault
(StaticFile.bodyWithoutFrontmatter filePath
|> DataSource.andThen
(\rawContent ->
Markdown.Parser.parse rawContent
|> Result.mapError (\_ -> "Markdown error")
|> Result.map
(\blocks ->
Maybe.map
(\title ->
{ title = title
, description =
case metadata.description of
Just description ->
description
Nothing ->
findDescription blocks
}
)
(case metadata.title of
Just title ->
Just title
Nothing ->
findH1 blocks
)
)
|> Result.andThen (Result.fromMaybe <| "Expected to find an H1 heading for page " ++ filePath)
|> DataSource.fromResult
)
)
)
findH1 : List Block -> Maybe String
findH1 blocks =
List.Extra.findMap
(\block ->
case block of
Block.Heading Block.H1 inlines ->
Just (Block.extractInlineText inlines)
_ ->
Nothing
)
blocks
findDescription : List Block -> String
findDescription blocks =
blocks
|> List.Extra.findMap
(\block ->
case block of
Block.Paragraph inlines ->
Just (Block.extractInlineText inlines)
_ ->
Nothing
)
|> Maybe.withDefault ""
titleFromFrontmatter : String -> DataSource (Maybe String)
titleFromFrontmatter filePath =
StaticFile.onlyFrontmatter
(OptimizedDecoder.optionalField "title" OptimizedDecoder.string)
filePath
withoutFrontmatter :
Markdown.Renderer.Renderer view
-> String
-> DataSource (List view)
withoutFrontmatter renderer filePath =
(StaticFile.bodyWithoutFrontmatter
filePath
|> DataSource.andThen
(\rawBody ->
rawBody
|> Markdown.Parser.parse
|> Result.mapError (\_ -> "Couldn't parse markdown.")
|> DataSource.fromResult
)
)
|> DataSource.distillSerializeCodec ("markdown-blocks-" ++ filePath)
(S.list codec)
|> DataSource.andThen
(\blocks ->
blocks
|> Markdown.Renderer.render renderer
|> DataSource.fromResult
)
withFrontmatter :
(frontmatter -> List view -> value)
-> Decoder frontmatter
-> Markdown.Renderer.Renderer view
-> String
-> DataSource.DataSource value
-> DataSource value
withFrontmatter constructor frontmatterDecoder renderer filePath =
DataSource.map2 constructor
(StaticFile.onlyFrontmatter
@ -42,39 +187,6 @@ withFrontmatter constructor frontmatterDecoder renderer filePath =
)
withoutFrontmatter :
(frontmatter -> List view -> value)
-> Decoder frontmatter
-> Markdown.Renderer.Renderer view
-> String
-> DataSource.DataSource value
withoutFrontmatter constructor frontmatterDecoder renderer filePath =
DataSource.map2 constructor
(StaticFile.onlyFrontmatter
frontmatterDecoder
filePath
)
((StaticFile.bodyWithoutFrontmatter
filePath
|> DataSource.andThen
(\rawBody ->
rawBody
|> Markdown.Parser.parse
|> Result.mapError (\_ -> "Couldn't parse markdown.")
|> DataSource.fromResult
)
)
|> DataSource.distillSerializeCodec ("markdown-blocks-" ++ filePath)
(S.list codec)
|> DataSource.andThen
(\blocks ->
blocks
|> Markdown.Renderer.render renderer
|> DataSource.fromResult
)
)
codec : S.Codec Never Block
codec =
S.customType