Add an end-to-end test example folder.

This commit is contained in:
Dillon Kearns 2021-07-21 13:29:45 -07:00
parent 6762719367
commit d81c5ad0d3
22 changed files with 3459 additions and 0 deletions

6
examples/end-to-end/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
node_modules/
elm-stuff/
dist/
.cache/
.elm-pages/
functions/render/elm-pages-cli.js

View File

@ -0,0 +1 @@
# README

View File

@ -0,0 +1,8 @@
{
"name": "dmy/elm-doc-preview",
"summary": "Offline documentation previewer",
"version": "5.0.0",
"exposed-modules": [
"Page"
]
}

View File

@ -0,0 +1,8 @@
{
"tools": {
"elm": "0.19.1",
"elm-format": "0.8.4",
"elm-json": "0.2.10",
"elm-test-rs": "1.0.0"
}
}

View File

@ -0,0 +1,56 @@
{
"type": "application",
"source-directories": [
"src",
"../../src",
".elm-pages",
"../../plugins"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"MartinSStewart/elm-serialize": "1.2.5",
"avh4/elm-color": "1.0.0",
"danyx23/elm-mimetype": "4.0.1",
"dillonkearns/elm-bcp47-language-tag": "1.0.1",
"dillonkearns/elm-markdown": "6.0.1",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/json": "1.1.3",
"elm/regex": "1.0.0",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm-community/dict-extra": "2.4.0",
"elm-community/list-extra": "8.3.0",
"matheus23/elm-default-tailwind-modules": "2.0.1",
"miniBill/elm-codec": "2.0.0",
"noahzgordon/elm-color-extra": "1.0.2",
"pablohirafuji/elm-syntax-highlight": "3.4.0",
"robinheghan/murmur3": "1.0.0",
"rtfeldman/elm-css": "16.1.1",
"tripokey/elm-fuzzy": "5.2.1",
"vito/elm-ansi": "10.0.1",
"zwilias/json-decode-exploration": "6.0.0"
},
"indirect": {
"bburdette/toop": "1.0.1",
"danfishgold/base64-bytes": "1.1.0",
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/parser": "1.1.0",
"elm/random": "1.0.0",
"elm/virtual-dom": "1.0.2",
"fredcy/elm-parseint": "2.0.1",
"mgold/elm-nonempty-list": "4.2.0",
"rtfeldman/elm-hex": "1.0.0"
}
},
"test-dependencies": {
"direct": {
"elm-explorations/test": "1.2.2"
},
"indirect": {}
}
}

View File

@ -0,0 +1,3 @@
{
"greeting": "Hello, World!"
}

2562
examples/end-to-end/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
{
"name": "elm-pages-example",
"version": "1.0.0",
"description": "Example site built with elm-pages.",
"scripts": {
"start": "elm-pages dev",
"serve": "npm run build && http-server ./dist -a localhost -p 3000 -c-1",
"build": "elm-pages build"
},
"author": "Dillon Kearns",
"license": "BSD-3",
"devDependencies": {
"elm-oembed": "0.0.6",
"elm-pages": "file:../..",
"elm-tooling": "^1.3.0",
"http-server": "^0.11.1"
}
}

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 323.141 322.95" enable-background="new 0 0 323.141 322.95" xml:space="preserve">
<g>
<polygon
fill="#F0AD00"
points="161.649,152.782 231.514,82.916 91.783,82.916"/>
<polygon
fill="#7FD13B"
points="8.867,0 79.241,70.375 232.213,70.375 161.838,0"/>
<rect
fill="#7FD13B"
x="192.99"
y="107.392"
transform="matrix(0.7071 0.7071 -0.7071 0.7071 186.4727 -127.2386)"
width="107.676"
height="108.167"/>
<polygon
fill="#60B5CC"
points="323.298,143.724 323.298,0 179.573,0"/>
<polygon
fill="#5A6378"
points="152.781,161.649 0,8.868 0,314.432"/>
<polygon
fill="#F0AD00"
points="255.522,246.655 323.298,314.432 323.298,178.879"/>
<polygon
fill="#60B5CC"
points="161.649,170.517 8.869,323.298 314.43,323.298"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub icon</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

View File

@ -0,0 +1,2 @@
<svg version="1.1" viewBox="251.0485 144.52063 56.114286 74.5" width="50px" height="74.5"><defs><linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="10%" style="stop-color:rgba(1.96%,45.88%,90.2%,1);stop-opacity:1"></stop><stop offset="100%" style="stop-color:rgba(0%,94.9%,37.65%,1);stop-opacity:1"></stop></linearGradient></defs><metadata></metadata><g id="Canvas_11" stroke="none" fill="url(#grad1)" stroke-opacity="1" fill-opacity="1" stroke-dasharray="none"><g id="Canvas_11: Layer 1"><g id="Group_38"><g id="Graphic_32"><path d="M 252.5485 146.02063 L 252.5485 217.52063 L 305.66277 217.52063 L 305.66277 161.68254 L 290.00087 146.02063 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"></path></g><g id="Line_34"><line x1="266.07286" y1="182.8279" x2="290.75465" y2="183.00997" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line></g><g id="Line_35"><line x1="266.07286" y1="191.84156" x2="290.75465" y2="192.02363" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line></g><g id="Line_36"><line x1="266.07286" y1="200.85522" x2="290.75465" y2="201.0373" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line></g><g id="Line_37"><line x1="266.07286" y1="164.80058" x2="278.3874" y2="164.94049" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,6 @@
export default {
load: function (elmLoaded) {},
flags: function () {
return null;
},
};

View File

@ -0,0 +1,79 @@
@import url("https://rsms.me/inter/inter.css");
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&display=swap");
body {
font-family: "Inter var" !important;
}
pre.elmsh {
padding: 10px;
margin: 0;
text-align: left;
overflow: auto;
height: 100%;
width: 500px;
font-size: 14px;
font-family: "IBM Plex Mono" !important;
}
code.elmsh {
padding: 0;
}
.elmsh-line:before {
content: attr(data-elmsh-lc);
display: inline-block;
text-align: right;
width: 40px;
padding: 0 20px 0 0;
opacity: 0.3;
}
.elmsh {
color: #f8f8f2;
background: #1e1e1e;
}
.elmsh-hl {
background: #4864aa;
}
.elmsh-add {
background: #003800;
}
.elmsh-del {
background: #380000;
}
.elmsh-comm {
color: #d4d4d4;
}
.elmsh1 {
color: #74b0df;
}
.elmsh2 {
color: #ce9178;
}
.elmsh3 {
color: #ff00ff;
}
.elmsh4 {
color: #4f76ac;
}
.elmsh5 {
color: #3dc9b0;
}
.elmsh6 {
color: #74b0df;
}
.elmsh7 {
color: #ce9178;
}
.elmsh-elm-ts,
.elmsh-js-dk,
.elmsh-css-p {
font-style: italic;
color: #4f76ac;
}
.elmsh-js-ce {
font-style: italic;
color: #5bb498;
}
.elmsh-css-ar-i {
font-weight: bold;
color: #ff0000;
}

View File

@ -0,0 +1,43 @@
pre.elmsh {
padding: 10px;
margin: 0;
text-align: left;
overflow: auto;
padding: 20px !important;
}
code.elmsh {
padding: 0;
}
code {
font-family: 'Roboto Mono' !important;
font-size: 20px !important;
line-height: 28px;
}
.elmsh-line:before {
/* content: attr(data-elmsh-lc); */
display: inline-block;
text-align: right;
width: 40px;
padding: 0 20px 0 0;
opacity: 0.3;
}
.elmsh {
color: #f8f8f2;
background: #000;
}
.elmsh-hl {background: #343434;}
.elmsh-add {background: #003800;}
.elmsh-del {background: #380000;}
.elmsh-comm {color: #75715e;}
.elmsh1 {color: #ae81ff;}
.elmsh2 {color: #e6db74;}
.elmsh3 {color: #66d9ef;}
.elmsh4 {color: #f92672;}
.elmsh5 {color: #a6e22e;}
.elmsh6 {color: #ae81ff;}
.elmsh7 {color: #fd971f;}

View File

@ -0,0 +1,18 @@
module Api exposing (routes)
import ApiRoute
import DataSource exposing (DataSource)
import DataSource.Http
import Html exposing (Html)
import Json.Encode
import OptimizedDecoder as Decode
import Route exposing (Route)
import Secrets
routes :
DataSource (List Route)
-> (Html Never -> String)
-> List (ApiRoute.Done ApiRoute.Response)
routes getStaticRoutes htmlToString =
[]

View File

@ -0,0 +1,233 @@
module MarkdownRenderer exposing (renderer)
import Html.Styled as Html
import Html.Styled.Attributes as Attr exposing (css)
import Markdown.Block as Block exposing (ListItem(..), Task(..))
import Markdown.Html
import Markdown.Renderer
import SyntaxHighlight
import Tailwind.Utilities as Tw
renderer : Markdown.Renderer.Renderer (Html.Html msg)
renderer =
{ heading = heading
, paragraph = Html.p []
, thematicBreak = Html.hr [] []
, text = Html.text
, strong = \content -> Html.strong [ css [ Tw.font_bold ] ] content
, emphasis = \content -> Html.em [ css [ Tw.italic ] ] content
, blockQuote = Html.blockquote []
, codeSpan =
\content ->
Html.code
[ css
[ Tw.font_semibold
, Tw.font_medium
]
]
[ Html.text content ]
--, codeSpan = code
, link =
\{ destination } body ->
Html.a
[ Attr.href destination
, css
[ Tw.underline
]
]
body
, hardLineBreak = Html.br [] []
, image =
\image ->
case image.title of
Just _ ->
Html.img [ Attr.src image.src, Attr.alt image.alt ] []
Nothing ->
Html.img [ Attr.src image.src, Attr.alt image.alt ] []
, unorderedList =
\items ->
Html.ul []
(items
|> List.map
(\item ->
case item of
Block.ListItem task children ->
let
checkbox =
case task of
Block.NoTask ->
Html.text ""
Block.IncompleteTask ->
Html.input
[ Attr.disabled True
, Attr.checked False
, Attr.type_ "checkbox"
]
[]
Block.CompletedTask ->
Html.input
[ Attr.disabled True
, Attr.checked True
, Attr.type_ "checkbox"
]
[]
in
Html.li [] (checkbox :: children)
)
)
, orderedList =
\startingIndex items ->
Html.ol
(case startingIndex of
1 ->
[ Attr.start startingIndex ]
_ ->
[]
)
(items
|> List.map
(\itemBlocks ->
Html.li []
itemBlocks
)
)
, html = Markdown.Html.oneOf []
, codeBlock = codeBlock
--\{ body, language } ->
-- let
-- classes =
-- -- Only the first word is used in the class
-- case Maybe.map String.words language of
-- Just (actualLanguage :: _) ->
-- [ Attr.class <| "language-" ++ actualLanguage ]
--
-- _ ->
-- []
-- in
-- Html.pre []
-- [ Html.code classes
-- [ Html.text body
-- ]
-- ]
, table = Html.table []
, tableHeader = Html.thead []
, tableBody = Html.tbody []
, tableRow = Html.tr []
, strikethrough =
\children -> Html.del [] children
, tableHeaderCell =
\maybeAlignment ->
let
attrs =
maybeAlignment
|> Maybe.map
(\alignment ->
case alignment of
Block.AlignLeft ->
"left"
Block.AlignCenter ->
"center"
Block.AlignRight ->
"right"
)
|> Maybe.map Attr.align
|> Maybe.map List.singleton
|> Maybe.withDefault []
in
Html.th attrs
, tableCell =
\maybeAlignment ->
let
attrs =
maybeAlignment
|> Maybe.map
(\alignment ->
case alignment of
Block.AlignLeft ->
"left"
Block.AlignCenter ->
"center"
Block.AlignRight ->
"right"
)
|> Maybe.map Attr.align
|> Maybe.map List.singleton
|> Maybe.withDefault []
in
Html.td attrs
}
rawTextToId : String -> String
rawTextToId rawText =
rawText
|> String.split " "
|> String.join "-"
|> String.toLower
heading : { level : Block.HeadingLevel, rawText : String, children : List (Html.Html msg) } -> Html.Html msg
heading { level, rawText, children } =
(case level of
Block.H1 ->
Html.h1
Block.H2 ->
Html.h2
Block.H3 ->
Html.h3
Block.H4 ->
Html.h4
Block.H5 ->
Html.h5
Block.H6 ->
Html.h6
)
[ Attr.id (rawTextToId rawText)
, Attr.attribute "name" (rawTextToId rawText)
, css
[ Tw.font_bold
, Tw.text_2xl
, Tw.mt_8
, Tw.mb_4
]
]
children
--code : String -> Element msg
--code snippet =
-- Element.el
-- [ Element.Background.color
-- (Element.rgba255 50 50 50 0.07)
-- , Element.Border.rounded 2
-- , Element.paddingXY 5 3
-- , Font.family [ Font.typeface "Roboto Mono", Font.monospace ]
-- ]
-- (Element.text snippet)
--
--
codeBlock : { body : String, language : Maybe String } -> Html.Html msg
codeBlock details =
SyntaxHighlight.elm details.body
|> Result.map (SyntaxHighlight.toBlockHtml (Just 1))
|> Result.map Html.fromUnstyled
|> Result.withDefault (Html.pre [] [ Html.code [] [ Html.text details.body ] ])

View File

@ -0,0 +1,79 @@
module Page.FileData exposing (Data, Model, Msg, page)
import DataSource exposing (DataSource)
import DataSource.File
import Head
import Head.Seo as Seo
import Html.Styled exposing (text)
import OptimizedDecoder as Decode
import Page exposing (Page, PageWithState, StaticPayload)
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Shared
import View exposing (View)
type alias Model =
()
type alias Msg =
Never
type alias RouteParams =
{}
page : Page RouteParams Data
page =
Page.single
{ head = head
, data = data
}
|> Page.buildNoState { view = view }
type alias Data =
{ greeting : String
}
data : DataSource Data
data =
"my-json-data.json"
|> DataSource.File.jsonFile (Decode.field "greeting" Decode.string)
|> DataSource.map Data
head :
StaticPayload Data RouteParams
-> List Head.Tag
head static =
Seo.summary
{ canonicalUrlOverride = Nothing
, siteName = "elm-pages"
, image =
{ url = Pages.Url.external "TODO"
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "TODO"
, locale = Nothing
, title = "TODO title" -- metadata.title -- TODO
}
|> Seo.website
view :
Maybe PageUrl
-> Shared.Model
-> StaticPayload Data RouteParams
-> View Msg
view maybeUrl sharedModel static =
{ title = "Index page"
, body =
[ text <| "Greeting: " ++ static.data.greeting
]
}

View File

@ -0,0 +1,72 @@
module Page.Index exposing (Data, Model, Msg, page)
import DataSource exposing (DataSource)
import Head
import Head.Seo as Seo
import Html.Styled exposing (text)
import Page exposing (Page, PageWithState, StaticPayload)
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Shared
import View exposing (View)
type alias Model =
()
type alias Msg =
Never
type alias RouteParams =
{}
page : Page RouteParams Data
page =
Page.single
{ head = head
, data = data
}
|> Page.buildNoState { view = view }
type alias Data =
()
data : DataSource Data
data =
DataSource.succeed ()
head :
StaticPayload Data RouteParams
-> List Head.Tag
head static =
Seo.summary
{ canonicalUrlOverride = Nothing
, siteName = "elm-pages"
, image =
{ url = Pages.Url.external "TODO"
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "TODO"
, locale = Nothing
, title = "TODO title" -- metadata.title -- TODO
}
|> Seo.website
view :
Maybe PageUrl
-> Shared.Model
-> StaticPayload Data RouteParams
-> View Msg
view maybeUrl sharedModel static =
{ title = "Index page"
, body = [ text "This is the index page" ]
}

View File

@ -0,0 +1,109 @@
module Shared exposing (Data, Model, Msg(..), SharedMsg(..), template)
import Browser.Navigation
import Css.Global
import DataSource
import DataSource.Http
import Html exposing (Html)
import Html.Styled
import OptimizedDecoder as D
import Pages.Flags
import Pages.PageUrl exposing (PageUrl)
import Path exposing (Path)
import Secrets
import SharedTemplate exposing (SharedTemplate)
import Tailwind.Utilities
import View exposing (View)
template : SharedTemplate Msg Model Data SharedMsg msg
template =
{ init = init
, update = update
, view = view
, data = data
, subscriptions = subscriptions
, onPageChange = Just OnPageChange
, sharedMsg = SharedMsg
}
type Msg
= OnPageChange
{ path : Path
, query : Maybe String
, fragment : Maybe String
}
| SharedMsg SharedMsg
type alias Data =
()
type SharedMsg
= NoOp
type alias Model =
{ showMobileMenu : Bool
}
init :
Maybe Browser.Navigation.Key
-> Pages.Flags.Flags
->
Maybe
{ path :
{ path : Path
, query : Maybe String
, fragment : Maybe String
}
, metadata : route
, pageUrl : Maybe PageUrl
}
-> ( Model, Cmd Msg )
init _ flags maybePagePath =
( { showMobileMenu = False }
, Cmd.none
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
OnPageChange _ ->
( { model | showMobileMenu = False }, Cmd.none )
SharedMsg globalMsg ->
( model, Cmd.none )
subscriptions : Path -> Model -> Sub Msg
subscriptions _ _ =
Sub.none
data : DataSource.DataSource Data
data =
DataSource.succeed ()
view :
Data
->
{ path : Path
, frontmatter : route
}
-> Model
-> (Msg -> msg)
-> View msg
-> { body : Html msg, title : String }
view stars page model toMsg pageView =
{ body =
Html.Styled.div []
pageView.body
|> Html.Styled.toUnstyled
, title = pageView.title
}

View File

@ -0,0 +1,93 @@
module Site exposing (config)
import Cloudinary
import DataSource
import Head
import MimeType
import Pages.Manifest as Manifest
import Pages.Url
import Route exposing (Route)
import SiteConfig exposing (SiteConfig)
config : SiteConfig Data
config =
\routes ->
{ data = data
, canonicalUrl = canonicalUrl
, manifest = manifest
, head = head
}
type alias Data =
{ siteName : String
}
data : DataSource.DataSource Data
data =
DataSource.map Data
--(StaticFile.request "site-name.txt" StaticFile.body)
(DataSource.succeed "site-name")
head : Data -> List Head.Tag
head static =
[ Head.icon [ ( 32, 32 ) ] MimeType.Png (cloudinaryIcon MimeType.Png 32)
, Head.icon [ ( 16, 16 ) ] MimeType.Png (cloudinaryIcon MimeType.Png 16)
, Head.appleTouchIcon (Just 180) (cloudinaryIcon MimeType.Png 180)
, Head.appleTouchIcon (Just 192) (cloudinaryIcon MimeType.Png 192)
, Head.sitemapLink "/sitemap.xml"
]
canonicalUrl : String
canonicalUrl =
"https://elm-pages.com"
manifest : Data -> Manifest.Config
manifest static =
Manifest.init
{ name = static.siteName
, description = "elm-pages - " ++ tagline
, startUrl = Route.Slide__Number_ { number = "1" } |> Route.toPath
, icons =
[ icon webp 192
, icon webp 512
, icon MimeType.Png 192
, icon MimeType.Png 512
]
}
|> Manifest.withShortName "elm-pages"
tagline : String
tagline =
"A statically typed site generator"
webp : MimeType.MimeImage
webp =
MimeType.OtherImage "webp"
icon :
MimeType.MimeImage
-> Int
-> Manifest.Icon
icon format width =
{ src = cloudinaryIcon format width
, sizes = [ ( width, width ) ]
, mimeType = format |> Just
, purposes = [ Manifest.IconPurposeAny, Manifest.IconPurposeMaskable ]
}
cloudinaryIcon :
MimeType.MimeImage
-> Int
-> Pages.Url.Url
cloudinaryIcon mimeType width =
Cloudinary.urlSquare "v1603234028/elm-pages/elm-pages-icon" (Just mimeType) width

View File

@ -0,0 +1,23 @@
module View exposing (View, map, placeholder)
import Html.Styled exposing (text)
type alias View msg =
{ title : String
, body : List (Html.Styled.Html msg)
}
map : (msg1 -> msg2) -> View msg1 -> View msg2
map fn doc =
{ title = doc.title
, body = List.map (Html.Styled.map fn) doc.body
}
placeholder : String -> View msg
placeholder moduleName =
{ title = "Placeholder - " ++ moduleName
, body = [ text moduleName ]
}