Include latest markdown parser.

This commit is contained in:
Dillon Kearns 2019-08-27 18:14:28 +05:30
parent 96c9484be3
commit 3aae520e14
5 changed files with 226 additions and 19 deletions

View File

@ -8,6 +8,18 @@ type: doc
As a general rule, `elm-pages` strives to be unopinionated about how you organize
your files (both code and content).
```shell
.
├── content/
├── elm.json
├── images/
├── static/
├── index.js
├── package.json
└── src/
└── Main.elm
```
## `content` folder
Each file in the `content` folder will result in a new route for your static site.

View File

@ -0,0 +1,114 @@
module Main exposing (main)
import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (..)
import Markdown.Parser as Markdown
import Url
main : Program () Model Msg
main =
Browser.document
{ init = init
, view = view
, update = update
, subscriptions = \_ -> Sub.none
}
type alias Model =
()
init : () -> ( Model, Cmd Msg )
init flags =
( (), Cmd.none )
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
( model, Cmd.none )
view : Model -> Browser.Document Msg
view model =
{ title = "elm-markdown-parser"
, body = [ mainView ]
}
markdown =
"""# Hello 👋
Welcome to this document!
## Features
Let me tell you why I built this...
<Red>
# Is this red? 😺
It seems to be! 👌
<Blue>
This should be blue in red!
</Blue>
</Red>
This should be plain markdown text.
<Blue>
# Is this blue? 😺
It seems to be! 👌
</Blue>
"""
mainView : Html msg
mainView =
markdown
|> Markdown.render
{ heading = \level content -> Html.h1 [] [ Html.text content ]
, raw =
\styledList ->
styledList
|> List.map
(\{ string, style } ->
-- TODO use style here
Html.text string
)
|> Html.p []
, todo = Html.text "TODO"
, htmlDecoder =
Markdown.htmlOneOf
[ Markdown.htmlTag "Red"
(\children ->
Html.div [ style "background-color" "red" ]
children
)
, Markdown.htmlTag "Blue"
(\children ->
Html.div [ style "background-color" "blue" ]
children
)
]
}
|> Result.map (Html.div [])
|> (\result ->
case result of
Ok content ->
content
Err error ->
error
|> Debug.toString
|> Html.text
)

View File

@ -0,0 +1,47 @@
module Markdown.CodeBlock exposing (..)
import Parser
import Parser.Advanced as Advanced exposing (..)
type alias Parser a =
Advanced.Parser String Parser.Problem a
parser : Parser CodeBlock
parser =
oneOf
[ parserHelp "```"
, parserHelp "~~~"
]
parserHelp : String -> Parser CodeBlock
parserHelp delimeter =
succeed
(\language body ->
{ body = body
, language =
if language == "" then
Nothing
else
Just language
}
)
|. Advanced.symbol (Advanced.Token delimeter (Parser.ExpectingSymbol delimeter))
|= getChompedString (chompUntil (Advanced.Token "\n" (Parser.Problem "Expecting newline")))
|. Advanced.symbol (Advanced.Token "\n" (Parser.ExpectingSymbol "\n"))
|= getChompedString (Advanced.chompUntilEndOr ("\n" ++ delimeter))
|. Advanced.symbol (Advanced.Token ("\n" ++ delimeter) (Parser.ExpectingSymbol delimeter))
-- |. Advanced.symbol (Advanced.Token "\n" (Parser.ExpectingSymbol "\n"))
-- |. Advanced.symbol (Advanced.Token delimeter (Parser.ExpectingSymbol delimeter))
type alias CodeBlock =
{ body : String
, language : Maybe String
}

View File

@ -1,5 +1,6 @@
module Markdown.Parser exposing (..)
import Markdown.CodeBlock
import Markdown.Inlines as Inlines exposing (StyledString)
import Markdown.List
import Parser
@ -71,6 +72,7 @@ type alias Renderer view =
-- TODO make this a `Result` so users can validate links
, link : { title : Maybe String, destination : String } -> String -> view
, list : List view -> view
, codeBlock : { body : String, language : Maybe String } -> view
}
@ -131,6 +133,11 @@ renderHelper renderer blocks =
|> List.map renderer.raw
|> renderer.list
|> Ok
CodeBlock codeBlock ->
codeBlock
|> renderer.codeBlock
|> Ok
)
blocks
@ -244,13 +251,14 @@ type Block
| Body (List StyledString)
| Html String (List Attribute) (List Block)
| ListBlock (List (List Inlines.StyledString))
| CodeBlock Markdown.CodeBlock.CodeBlock
type alias Attribute =
{ name : String, value : String }
plainLine : Parser (List StyledString)
plainLine : Parser (List Block)
plainLine =
succeed identity
|= Advanced.getChompedString (Advanced.chompUntilEndOr "\n")
@ -263,17 +271,8 @@ plainLine =
Err error ->
problem (Parser.Expecting "....??? TODO")
)
lineParser : Parser Block
lineParser =
oneOf
[ listBlock
, blankLine
, heading
, htmlParser
, plainLine |> Advanced.map Body
]
|> Advanced.map Body
|> Advanced.map List.singleton
listBlock : Parser Block
@ -377,36 +376,53 @@ childToParser node =
multiParser : Parser (List Block)
multiParser =
loop [] statementsHelp
loop [ [] ] statementsHelp
|. succeed Advanced.end
-- TODO find a more elegant way to exclude empty blocks for each blank lines
|> map (List.filter (\item -> item /= Body []))
statementsHelp : List Block -> Parser (Step (List Block) (List Block))
statementsHelp : List (List Block) -> Parser (Step (List (List Block)) (List Block))
statementsHelp revStmts =
oneOf
[ succeed
(\offsetBefore stmt offsetAfter ->
(\offsetBefore stmts offsetAfter ->
let
madeProgress =
offsetAfter > offsetBefore
in
if madeProgress then
Loop (stmt :: revStmts)
Loop (stmts :: revStmts)
else
Done (List.reverse (stmt :: revStmts))
Done
(List.reverse (stmts :: revStmts)
|> List.concat
)
)
|= Advanced.getOffset
|= lineParser
|= oneOf
[ listBlock |> map List.singleton
, blankLine |> map List.singleton
, heading |> map List.singleton
, Markdown.CodeBlock.parser |> map CodeBlock |> map List.singleton
, htmlParser |> map List.singleton
, htmlParser |> map List.singleton
, plainLine
]
|= Advanced.getOffset
-- TODO this is causing files to require newlines
-- at the end... how do I avoid this?
-- |. symbol (Advanced.Token "\n" (Parser.Expecting "newline"))
, succeed ()
|> map (\_ -> Done (List.reverse revStmts))
|> map
(\_ ->
Done
(List.reverse revStmts
|> List.concat
)
)
]

View File

@ -12,6 +12,7 @@ import Element.Region
import Head
import Head.OpenGraph as OpenGraph
import Html exposing (Html)
import Html.Attributes
import Json.Decode
import Mark
import MarkParser
@ -132,6 +133,7 @@ renderMarkdown markdown =
[ Element.text "", itemBlocks ]
)
)
, codeBlock = codeBlock
}
@ -170,6 +172,22 @@ code snippet =
(Element.text snippet)
codeBlock : { body : String, language : Maybe String } -> Element msg
codeBlock details =
Element.column
[ Element.Background.color
(Element.rgba 0 0 0 0.04)
, Element.Border.rounded 2
, Element.padding 20
, Font.color (Element.rgba255 0 0 0 1)
, Font.family [ Font.monospace ]
, Element.width Element.fill
, Element.htmlAttribute (Html.Attributes.style "line-height" "1.4em")
, Element.htmlAttribute (Html.Attributes.style "white-space" "pre")
]
[ Element.text details.body ]
type alias Model =
{}