mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-12-30 23:47:42 +03:00
Include latest markdown parser.
This commit is contained in:
parent
96c9484be3
commit
3aae520e14
@ -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.
|
||||
|
114
examples/docs/elm-markdown-parser/Main.elm
Normal file
114
examples/docs/elm-markdown-parser/Main.elm
Normal 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
|
||||
)
|
47
examples/docs/elm-markdown-parser/Markdown/CodeBlock.elm
Normal file
47
examples/docs/elm-markdown-parser/Markdown/CodeBlock.elm
Normal 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
|
||||
}
|
@ -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
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
|
@ -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 =
|
||||
{}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user