From 3aae520e1457ef02c80cf993322799fe0ecb8077 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Tue, 27 Aug 2019 18:14:28 +0530 Subject: [PATCH] Include latest markdown parser. --- examples/docs/content/docs/file-structure.md | 12 ++ examples/docs/elm-markdown-parser/Main.elm | 114 ++++++++++++++++++ .../Markdown/CodeBlock.elm | 47 ++++++++ .../elm-markdown-parser/Markdown/Parser.elm | 54 ++++++--- examples/docs/src/Main.elm | 18 +++ 5 files changed, 226 insertions(+), 19 deletions(-) create mode 100644 examples/docs/elm-markdown-parser/Main.elm create mode 100644 examples/docs/elm-markdown-parser/Markdown/CodeBlock.elm diff --git a/examples/docs/content/docs/file-structure.md b/examples/docs/content/docs/file-structure.md index 57eb19ce..7e6b7704 100644 --- a/examples/docs/content/docs/file-structure.md +++ b/examples/docs/content/docs/file-structure.md @@ -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. diff --git a/examples/docs/elm-markdown-parser/Main.elm b/examples/docs/elm-markdown-parser/Main.elm new file mode 100644 index 00000000..5b1fcce3 --- /dev/null +++ b/examples/docs/elm-markdown-parser/Main.elm @@ -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... + + +# Is this red? 😺 + +It seems to be! 👌 + +This should be blue in red! + + + +This should be plain markdown text. + + +# Is this blue? 😺 + +It seems to be! 👌 + +""" + + +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 + ) diff --git a/examples/docs/elm-markdown-parser/Markdown/CodeBlock.elm b/examples/docs/elm-markdown-parser/Markdown/CodeBlock.elm new file mode 100644 index 00000000..61c23b80 --- /dev/null +++ b/examples/docs/elm-markdown-parser/Markdown/CodeBlock.elm @@ -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 + } diff --git a/examples/docs/elm-markdown-parser/Markdown/Parser.elm b/examples/docs/elm-markdown-parser/Markdown/Parser.elm index 7d3e8ee5..3ae941df 100644 --- a/examples/docs/elm-markdown-parser/Markdown/Parser.elm +++ b/examples/docs/elm-markdown-parser/Markdown/Parser.elm @@ -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 + ) + ) ] diff --git a/examples/docs/src/Main.elm b/examples/docs/src/Main.elm index f1470be5..52f785a9 100644 --- a/examples/docs/src/Main.elm +++ b/examples/docs/src/Main.elm @@ -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 = {}