mirror of
https://github.com/dillonkearns/elm-pages.git
synced 2024-09-11 09:05:28 +03:00
Add route example with unit test.
This commit is contained in:
parent
da62ada1b9
commit
5365e4b7dd
8
examples/routing/.gitignore
vendored
Normal file
8
examples/routing/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
node_modules/
|
||||
elm-stuff/
|
||||
dist/
|
||||
.cache/
|
||||
gen/
|
||||
functions/render/elm-pages-cli.js
|
||||
browser-elm.js
|
||||
|
1
examples/routing/README.md
Normal file
1
examples/routing/README.md
Normal file
@ -0,0 +1 @@
|
||||
# README
|
8
examples/routing/elm-application.json
Normal file
8
examples/routing/elm-application.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "dmy/elm-doc-preview",
|
||||
"summary": "Offline documentation previewer",
|
||||
"version": "5.0.0",
|
||||
"exposed-modules": [
|
||||
"Page"
|
||||
]
|
||||
}
|
8
examples/routing/elm-tooling.json
Normal file
8
examples/routing/elm-tooling.json
Normal 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"
|
||||
}
|
||||
}
|
67
examples/routing/elm.json
Normal file
67
examples/routing/elm.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"type": "application",
|
||||
"source-directories": [
|
||||
"src",
|
||||
"../../src",
|
||||
"gen",
|
||||
"../../plugins"
|
||||
],
|
||||
"elm-version": "0.19.1",
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"ThinkAlexandria/elm-html-in-elm": "1.0.1",
|
||||
"avh4/elm-color": "1.0.0",
|
||||
"billstclair/elm-xml-eeue56": "1.0.1",
|
||||
"danyx23/elm-mimetype": "4.0.1",
|
||||
"dillonkearns/elm-bcp47-language-tag": "1.0.1",
|
||||
"dillonkearns/elm-markdown": "6.0.1",
|
||||
"dillonkearns/elm-oembed": "1.0.0",
|
||||
"dillonkearns/elm-rss": "1.0.1",
|
||||
"dillonkearns/elm-sitemap": "1.0.1",
|
||||
"dmy/elm-imf-date-time": "1.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/svg": "1.0.1",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2",
|
||||
"elm-community/dict-extra": "2.4.0",
|
||||
"elm-community/list-extra": "8.3.0",
|
||||
"elm-community/result-extra": "2.4.0",
|
||||
"elm-community/string-extra": "4.0.1",
|
||||
"elm-explorations/markdown": "1.0.0",
|
||||
"justinmimbs/date": "3.2.0",
|
||||
"lukewestby/elm-string-interpolate": "1.0.4",
|
||||
"matheus23/elm-default-tailwind-modules": "1.0.0",
|
||||
"mdgriffith/elm-ui": "1.1.8",
|
||||
"miniBill/elm-codec": "1.2.0",
|
||||
"noahzgordon/elm-color-extra": "1.0.2",
|
||||
"pablohirafuji/elm-syntax-highlight": "3.3.0",
|
||||
"rtfeldman/elm-css": "16.1.1",
|
||||
"rtfeldman/elm-hex": "1.0.0",
|
||||
"tripokey/elm-fuzzy": "5.2.1",
|
||||
"zwilias/json-decode-exploration": "6.0.0"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/parser": "1.1.0",
|
||||
"elm/random": "1.0.0",
|
||||
"fredcy/elm-parseint": "2.0.1",
|
||||
"justinmimbs/time-extra": "1.1.0",
|
||||
"lazamar/dict-parser": "1.0.2",
|
||||
"mgold/elm-nonempty-list": "4.1.0",
|
||||
"ryannhg/date-format": "2.3.0"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
"direct": {
|
||||
"elm-explorations/test": "1.2.2"
|
||||
},
|
||||
"indirect": {}
|
||||
}
|
||||
}
|
68
examples/routing/index.md
Normal file
68
examples/routing/index.md
Normal file
@ -0,0 +1,68 @@
|
||||
<Banner>A **statically typed** site generator</Banner>
|
||||
|
||||
<Boxes>
|
||||
<Box>
|
||||
### Pure Elm Configuration
|
||||
|
||||
Layouts, styles, even a full-fledged elm application.
|
||||
|
||||
### 📄 Type-Safe Content
|
||||
|
||||
Configuration, errors for broken links
|
||||
</Box>
|
||||
<Box>
|
||||
|
||||
### 🚀 `elm-pages build`
|
||||
|
||||
No `elm make` or `webpack` setup needed! Just one simple command.
|
||||
|
||||
</Box>
|
||||
<Box>
|
||||
|
||||
### 📦 Optimized Elm Progressive Web App
|
||||
|
||||
Layouts, styles, even a full-fledged elm application.
|
||||
|
||||
### Deploy anywhere
|
||||
|
||||
Ship to Netlify, Github Pages, or any host that will serve up static files!
|
||||
</Box>
|
||||
</Boxes>
|
||||
|
||||
<Values>
|
||||
<Value>
|
||||
# No magic, just types
|
||||
|
||||
The magic is in how the pieces snap together. The basic platform provided is simple, letting you compose exactly what you need with types to support you.
|
||||
</Value>
|
||||
|
||||
<Value>
|
||||
# Extensible through pure elm
|
||||
|
||||
Behavior is shared through packages exposing simple helper functions to help you build up your data.
|
||||
</Value>
|
||||
|
||||
<Value>
|
||||
# If it compiles, it works
|
||||
|
||||
`elm-pages` just makes more of the things you do in your static site feel like elm. Did you misspell the name of an image asset or a link to a blog post? `elm-pages` will give you a friendly error message and some helpful suggestions.
|
||||
</Value>
|
||||
|
||||
<Value>
|
||||
# An extended elm platform
|
||||
|
||||
`elm-pages` is just elm, but with a broader set of primitives for declaring meta tags to improve SEO, or generate RSS feeds and other files based on your static content.
|
||||
</Value>
|
||||
|
||||
<Value>
|
||||
# Blazing fast
|
||||
|
||||
All you have to do is create your content and choose how to present it. Optimized images, pre-rendered pages, and a snappy lightweight single-page app all come for free.
|
||||
</Value>
|
||||
|
||||
<Value>
|
||||
# Simple
|
||||
|
||||
`elm-pages` gives you the smallest set of core concepts possible, and a type system to make sure all the pieces fit together just right. The rest is up to you. Rather than remember a lot of magic and special cases, you can just rely on your elm types to build what you need with a set of simple primitives.
|
||||
</Value>
|
||||
</Values>
|
2555
examples/routing/package-lock.json
generated
Normal file
2555
examples/routing/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
examples/routing/package.json
Normal file
18
examples/routing/package.json
Normal 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"
|
||||
}
|
||||
}
|
37
examples/routing/slides.md
Normal file
37
examples/routing/slides.md
Normal file
@ -0,0 +1,37 @@
|
||||
## elm-pages 2.0
|
||||
|
||||
```
|
||||
elm-pages generate Projects.Username_.Repo_
|
||||
```
|
||||
|
||||
```elm
|
||||
type alias RouteParams =
|
||||
{ username : String, repo : String }
|
||||
|
||||
template : Template RouteParams StaticData
|
||||
template =
|
||||
Template.noStaticData
|
||||
{ head = head
|
||||
, staticRoutes = StaticHttp.succeed []
|
||||
}
|
||||
|> Template.buildNoState { view = view }
|
||||
|
||||
|
||||
view :
|
||||
StaticPayload StaticData RouteParams
|
||||
-> Document Msg
|
||||
view static =
|
||||
{ title = "TODO title"
|
||||
, body = []
|
||||
}
|
||||
```
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- Page Templates (`Template.*.elm`)
|
||||
- `DataSource`s
|
||||
- `Shared.elm`, `Site.elm`
|
||||
|
||||
## Page Templates
|
||||
|
||||
Here's another body
|
23
examples/routing/src/Document.elm
Normal file
23
examples/routing/src/Document.elm
Normal file
@ -0,0 +1,23 @@
|
||||
module Document exposing (Document, map, placeholder)
|
||||
|
||||
import Html.Styled exposing (text)
|
||||
|
||||
|
||||
type alias Document msg =
|
||||
{ title : String
|
||||
, body : List (Html.Styled.Html msg)
|
||||
}
|
||||
|
||||
|
||||
map : (msg1 -> msg2) -> Document msg1 -> Document msg2
|
||||
map fn doc =
|
||||
{ title = doc.title
|
||||
, body = List.map (Html.Styled.map fn) doc.body
|
||||
}
|
||||
|
||||
|
||||
placeholder : String -> Document msg
|
||||
placeholder moduleName =
|
||||
{ title = "Placeholder - " ++ moduleName
|
||||
, body = [ text moduleName ]
|
||||
}
|
233
examples/routing/src/MarkdownRenderer.elm
Normal file
233
examples/routing/src/MarkdownRenderer.elm
Normal 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 ] ])
|
83
examples/routing/src/Page/Cats/Name__.elm
Normal file
83
examples/routing/src/Page/Cats/Name__.elm
Normal file
@ -0,0 +1,83 @@
|
||||
module Page.Cats.Name__ exposing (Data, Model, Msg, page)
|
||||
|
||||
import DataSource
|
||||
import Document exposing (Document)
|
||||
import Element exposing (Element)
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
import Html.Styled exposing (text)
|
||||
import Page exposing (Page, PageWithState, StaticPayload)
|
||||
import Pages.ImagePath as ImagePath
|
||||
import Shared
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type alias Msg =
|
||||
Never
|
||||
|
||||
|
||||
type alias RouteParams =
|
||||
{ name : Maybe String }
|
||||
|
||||
|
||||
page : Page RouteParams Data
|
||||
page =
|
||||
Page.prerenderedRoute
|
||||
{ head = head
|
||||
, routes = routes
|
||||
, data = data
|
||||
}
|
||||
|> Page.buildNoState { view = view }
|
||||
|
||||
|
||||
routes : DataSource.DataSource (List RouteParams)
|
||||
routes =
|
||||
DataSource.succeed
|
||||
[ { name = Just "larry"
|
||||
}
|
||||
, { name = Nothing
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
data : RouteParams -> DataSource.DataSource Data
|
||||
data routeParams =
|
||||
DataSource.succeed ()
|
||||
|
||||
|
||||
head :
|
||||
StaticPayload Data RouteParams
|
||||
-> List Head.Tag
|
||||
head static =
|
||||
Seo.summary
|
||||
{ canonicalUrlOverride = Nothing
|
||||
, siteName = "elm-pages"
|
||||
, image =
|
||||
{ url = ImagePath.build [ "TODO" ]
|
||||
, alt = "elm-pages logo"
|
||||
, dimensions = Nothing
|
||||
, mimeType = Nothing
|
||||
}
|
||||
, description = "TODO"
|
||||
, locale = Nothing
|
||||
, title = "TODO title" -- metadata.title -- TODO
|
||||
}
|
||||
|> Seo.website
|
||||
|
||||
|
||||
type alias Data =
|
||||
()
|
||||
|
||||
|
||||
view :
|
||||
StaticPayload Data RouteParams
|
||||
-> Document Msg
|
||||
view static =
|
||||
{ body =
|
||||
[ text (static.routeParams.name |> Maybe.withDefault "NOTHING")
|
||||
]
|
||||
, title = ""
|
||||
}
|
63
examples/routing/src/Page/Slide.elm
Normal file
63
examples/routing/src/Page/Slide.elm
Normal file
@ -0,0 +1,63 @@
|
||||
module Page.Slide exposing (Data, Model, Msg, page)
|
||||
|
||||
import DataSource
|
||||
import Document exposing (Document)
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
import Page exposing (Page, PageWithState, StaticPayload)
|
||||
import Pages.ImagePath as ImagePath
|
||||
import Shared
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type alias Msg =
|
||||
Never
|
||||
|
||||
|
||||
type alias RouteParams =
|
||||
{}
|
||||
|
||||
|
||||
page : Page RouteParams Data
|
||||
page =
|
||||
Page.singleRoute
|
||||
{ head = head
|
||||
, data = DataSource.succeed ()
|
||||
}
|
||||
|> Page.buildNoState { view = view }
|
||||
|
||||
|
||||
head :
|
||||
StaticPayload Data RouteParams
|
||||
-> List Head.Tag
|
||||
head static =
|
||||
Seo.summary
|
||||
{ canonicalUrlOverride = Nothing
|
||||
, siteName = "elm-pages"
|
||||
, image =
|
||||
{ url = ImagePath.build [ "TODO" ]
|
||||
, alt = "elm-pages logo"
|
||||
, dimensions = Nothing
|
||||
, mimeType = Nothing
|
||||
}
|
||||
, description = "TODO"
|
||||
, locale = Nothing
|
||||
, title = "TODO title" -- metadata.title -- TODO
|
||||
}
|
||||
|> Seo.website
|
||||
|
||||
|
||||
type alias Data =
|
||||
()
|
||||
|
||||
|
||||
view :
|
||||
StaticPayload Data RouteParams
|
||||
-> Document Msg
|
||||
view static =
|
||||
{ title = "TODO title"
|
||||
, body = []
|
||||
}
|
256
examples/routing/src/Page/Slide/Number_.elm
Normal file
256
examples/routing/src/Page/Slide/Number_.elm
Normal file
@ -0,0 +1,256 @@
|
||||
module Page.Slide.Number_ exposing (Data, Model, Msg, page)
|
||||
|
||||
import Browser.Events
|
||||
import Browser.Navigation
|
||||
import DataSource
|
||||
import DataSource.File
|
||||
import Document exposing (Document)
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
import Html.Styled as Html
|
||||
import Html.Styled.Attributes exposing (css)
|
||||
import Json.Decode as Decode
|
||||
import Markdown.Block
|
||||
import Markdown.Parser
|
||||
import Markdown.Renderer
|
||||
import MarkdownRenderer
|
||||
import OptimizedDecoder
|
||||
import Page exposing (Page, StaticPayload)
|
||||
import Pages.ImagePath as ImagePath
|
||||
import Shared
|
||||
import Tailwind.Utilities as Tw
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type Msg
|
||||
= OnKeyPress (Maybe Direction)
|
||||
|
||||
|
||||
type alias RouteParams =
|
||||
{ number : String }
|
||||
|
||||
|
||||
page : Page.PageWithState RouteParams Data Model Msg
|
||||
page =
|
||||
Page.prerenderedRoute
|
||||
{ head = head
|
||||
, routes =
|
||||
slideCount
|
||||
|> DataSource.map
|
||||
(\count ->
|
||||
List.range 1 count
|
||||
|> List.map String.fromInt
|
||||
|> List.map RouteParams
|
||||
)
|
||||
, data = data
|
||||
}
|
||||
|> Page.buildWithLocalState
|
||||
{ view = view
|
||||
, init = \staticPayload -> ( (), Cmd.none )
|
||||
, update =
|
||||
\sharedModel static msg model ->
|
||||
case msg of
|
||||
OnKeyPress (Just direction) ->
|
||||
let
|
||||
currentSlide =
|
||||
String.toInt static.routeParams.number |> Maybe.withDefault 0
|
||||
|
||||
nextSlide =
|
||||
clamp
|
||||
1
|
||||
static.static.totalCount
|
||||
(case direction of
|
||||
Right ->
|
||||
currentSlide + 1
|
||||
|
||||
Left ->
|
||||
currentSlide - 1
|
||||
)
|
||||
in
|
||||
( model
|
||||
, sharedModel.navigationKey
|
||||
|> Maybe.map
|
||||
(\navKey ->
|
||||
Browser.Navigation.pushUrl navKey
|
||||
("/slide/"
|
||||
++ String.fromInt
|
||||
nextSlide
|
||||
)
|
||||
)
|
||||
|> Maybe.withDefault Cmd.none
|
||||
)
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
, subscriptions =
|
||||
\routeParams path model ->
|
||||
Browser.Events.onKeyDown keyDecoder |> Sub.map OnKeyPress
|
||||
}
|
||||
|
||||
|
||||
type Direction
|
||||
= Left
|
||||
| Right
|
||||
|
||||
|
||||
keyDecoder : Decode.Decoder (Maybe Direction)
|
||||
keyDecoder =
|
||||
Decode.map toDirection (Decode.field "key" Decode.string)
|
||||
|
||||
|
||||
toDirection : String -> Maybe Direction
|
||||
toDirection string =
|
||||
case string of
|
||||
"ArrowLeft" ->
|
||||
Just Left
|
||||
|
||||
"ArrowRight" ->
|
||||
Just Right
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
data : RouteParams -> DataSource.DataSource Data
|
||||
data routeParams =
|
||||
DataSource.map2 Data
|
||||
(slideBody routeParams)
|
||||
slideCount
|
||||
|
||||
|
||||
slideBody : RouteParams -> DataSource.DataSource (List (Html.Html Msg))
|
||||
slideBody route =
|
||||
DataSource.File.request
|
||||
"slides.md"
|
||||
(DataSource.File.body
|
||||
|> OptimizedDecoder.andThen
|
||||
(\rawBody ->
|
||||
case rawBody |> Markdown.Parser.parse of
|
||||
Ok okBlocks ->
|
||||
case
|
||||
okBlocks
|
||||
|> markdownIndexedByHeading (route.number |> String.toInt |> Maybe.withDefault 1)
|
||||
|> Markdown.Renderer.render MarkdownRenderer.renderer
|
||||
of
|
||||
Ok renderedBody ->
|
||||
OptimizedDecoder.succeed renderedBody
|
||||
|
||||
Err error ->
|
||||
OptimizedDecoder.fail error
|
||||
|
||||
Err _ ->
|
||||
OptimizedDecoder.fail ""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
slideCount : DataSource.DataSource Int
|
||||
slideCount =
|
||||
DataSource.File.request "slides.md"
|
||||
(DataSource.File.body
|
||||
|> OptimizedDecoder.andThen
|
||||
(\rawBody ->
|
||||
case rawBody |> Markdown.Parser.parse of
|
||||
Ok okBlocks ->
|
||||
okBlocks
|
||||
|> Markdown.Block.foldl
|
||||
(\block h2CountSoFar ->
|
||||
case block of
|
||||
Markdown.Block.Heading Markdown.Block.H2 _ ->
|
||||
h2CountSoFar + 1
|
||||
|
||||
_ ->
|
||||
h2CountSoFar
|
||||
)
|
||||
0
|
||||
|> OptimizedDecoder.succeed
|
||||
|
||||
Err _ ->
|
||||
OptimizedDecoder.fail ""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
markdownIndexedByHeading :
|
||||
Int
|
||||
-> List Markdown.Block.Block
|
||||
-> List Markdown.Block.Block
|
||||
markdownIndexedByHeading index markdownBlocks =
|
||||
Markdown.Block.foldl
|
||||
(\block ( currentIndex, markdownToKeep ) ->
|
||||
case block of
|
||||
Markdown.Block.Heading Markdown.Block.H2 _ ->
|
||||
let
|
||||
newIndex =
|
||||
currentIndex + 1
|
||||
in
|
||||
--_ ->
|
||||
if newIndex == index then
|
||||
( newIndex, block :: markdownToKeep )
|
||||
|
||||
else
|
||||
( newIndex, markdownToKeep )
|
||||
|
||||
_ ->
|
||||
if currentIndex == index then
|
||||
( currentIndex, block :: markdownToKeep )
|
||||
|
||||
else
|
||||
( currentIndex, markdownToKeep )
|
||||
)
|
||||
( 0, [] )
|
||||
markdownBlocks
|
||||
|> Tuple.second
|
||||
|> List.reverse
|
||||
|
||||
|
||||
head :
|
||||
StaticPayload Data RouteParams
|
||||
-> List Head.Tag
|
||||
head static =
|
||||
Seo.summary
|
||||
{ canonicalUrlOverride = Nothing
|
||||
, siteName = "elm-pages"
|
||||
, image =
|
||||
{ url = ImagePath.build [ "TODO" ]
|
||||
, alt = "elm-pages logo"
|
||||
, dimensions = Nothing
|
||||
, mimeType = Nothing
|
||||
}
|
||||
, description = "TODO"
|
||||
, locale = Nothing
|
||||
, title = "TODO title" -- metadata.title -- TODO
|
||||
}
|
||||
|> Seo.website
|
||||
|
||||
|
||||
type alias Data =
|
||||
{ body : List (Html.Html Msg)
|
||||
, totalCount : Int
|
||||
}
|
||||
|
||||
|
||||
view :
|
||||
Model
|
||||
-> Shared.Model
|
||||
-> StaticPayload Data RouteParams
|
||||
-> Document Msg
|
||||
view model sharedModel static =
|
||||
{ title = "TODO title"
|
||||
, body =
|
||||
[ Html.div
|
||||
[ css
|
||||
[ Tw.prose
|
||||
, Tw.max_w_lg
|
||||
, Tw.px_8
|
||||
, Tw.py_6
|
||||
]
|
||||
]
|
||||
(static.static.body
|
||||
++ [ Html.text static.routeParams.number ]
|
||||
)
|
||||
]
|
||||
}
|
108
examples/routing/src/Shared.elm
Normal file
108
examples/routing/src/Shared.elm
Normal file
@ -0,0 +1,108 @@
|
||||
module Shared exposing (Data, Model, Msg(..), SharedMsg(..), template)
|
||||
|
||||
import Browser.Navigation
|
||||
import Css.Global
|
||||
import DataSource
|
||||
import DataSource.Http
|
||||
import Document exposing (Document)
|
||||
import Html exposing (Html)
|
||||
import Html.Styled
|
||||
import OptimizedDecoder as D
|
||||
import Pages.PagePath exposing (PagePath)
|
||||
import Secrets
|
||||
import SharedTemplate exposing (SharedTemplate)
|
||||
import Tailwind.Utilities
|
||||
|
||||
|
||||
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 : PagePath
|
||||
, query : Maybe String
|
||||
, fragment : Maybe String
|
||||
}
|
||||
| SharedMsg SharedMsg
|
||||
|
||||
|
||||
type alias Data =
|
||||
Int
|
||||
|
||||
|
||||
type SharedMsg
|
||||
= NoOp
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ showMobileMenu : Bool
|
||||
}
|
||||
|
||||
|
||||
init :
|
||||
Maybe Browser.Navigation.Key
|
||||
->
|
||||
Maybe
|
||||
{ path :
|
||||
{ path : PagePath
|
||||
, query : Maybe String
|
||||
, fragment : Maybe String
|
||||
}
|
||||
, metadata : route
|
||||
}
|
||||
-> ( Model, Cmd Msg )
|
||||
init _ 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 : PagePath -> Model -> Sub Msg
|
||||
subscriptions _ _ =
|
||||
Sub.none
|
||||
|
||||
|
||||
data : DataSource.DataSource Data
|
||||
data =
|
||||
DataSource.Http.get (Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages")
|
||||
(D.field "stargazers_count" D.int)
|
||||
|
||||
|
||||
view :
|
||||
Data
|
||||
->
|
||||
{ path : PagePath
|
||||
, frontmatter : route
|
||||
}
|
||||
-> Model
|
||||
-> (Msg -> msg)
|
||||
-> Document msg
|
||||
-> { body : Html msg, title : String }
|
||||
view stars page model toMsg pageView =
|
||||
{ body =
|
||||
Html.Styled.div []
|
||||
(Css.Global.global Tailwind.Utilities.globalStyles
|
||||
:: pageView.body
|
||||
)
|
||||
|> Html.Styled.toUnstyled
|
||||
, title = pageView.title
|
||||
}
|
46
examples/routing/src/SharedTemplate.elm
Normal file
46
examples/routing/src/SharedTemplate.elm
Normal file
@ -0,0 +1,46 @@
|
||||
module SharedTemplate exposing (..)
|
||||
|
||||
import Browser.Navigation
|
||||
import DataSource
|
||||
import Document exposing (Document)
|
||||
import Html exposing (Html)
|
||||
import Pages.PagePath exposing (PagePath)
|
||||
import Route exposing (Route)
|
||||
|
||||
|
||||
type alias SharedTemplate msg sharedModel sharedData sharedMsg mappedMsg =
|
||||
{ init :
|
||||
Maybe Browser.Navigation.Key
|
||||
->
|
||||
Maybe
|
||||
{ path :
|
||||
{ path : PagePath
|
||||
, query : Maybe String
|
||||
, fragment : Maybe String
|
||||
}
|
||||
, metadata : Maybe Route
|
||||
}
|
||||
-> ( sharedModel, Cmd msg )
|
||||
, update : msg -> sharedModel -> ( sharedModel, Cmd msg )
|
||||
, view :
|
||||
sharedData
|
||||
->
|
||||
{ path : PagePath
|
||||
, frontmatter : Maybe Route
|
||||
}
|
||||
-> sharedModel
|
||||
-> (msg -> mappedMsg)
|
||||
-> Document mappedMsg
|
||||
-> { body : Html mappedMsg, title : String }
|
||||
, data : DataSource.DataSource sharedData
|
||||
, subscriptions : PagePath -> sharedModel -> Sub msg
|
||||
, onPageChange :
|
||||
Maybe
|
||||
({ path : PagePath
|
||||
, query : Maybe String
|
||||
, fragment : Maybe String
|
||||
}
|
||||
-> msg
|
||||
)
|
||||
, sharedMsg : sharedMsg -> msg
|
||||
}
|
132
examples/routing/src/Site.elm
Normal file
132
examples/routing/src/Site.elm
Normal file
@ -0,0 +1,132 @@
|
||||
module Site exposing (config)
|
||||
|
||||
import Cloudinary
|
||||
import Color
|
||||
import DataSource
|
||||
import Head
|
||||
import MimeType
|
||||
import Pages.ImagePath as ImagePath exposing (ImagePath)
|
||||
import Pages.Manifest as Manifest
|
||||
import Pages.Manifest.Category
|
||||
import Pages.PagePath as PagePath
|
||||
import Route exposing (Route)
|
||||
import SiteConfig exposing (SiteConfig)
|
||||
import Sitemap
|
||||
|
||||
|
||||
config : SiteConfig Data
|
||||
config =
|
||||
\routes ->
|
||||
{ data = data
|
||||
, canonicalUrl = canonicalUrl
|
||||
, manifest = manifest
|
||||
, head = head
|
||||
, generateFiles = generateFiles routes
|
||||
}
|
||||
|
||||
|
||||
generateFiles :
|
||||
List (Maybe Route)
|
||||
->
|
||||
DataSource.DataSource
|
||||
(List
|
||||
(Result
|
||||
String
|
||||
{ path : List String
|
||||
, content : String
|
||||
}
|
||||
)
|
||||
)
|
||||
generateFiles allRoutes =
|
||||
DataSource.succeed
|
||||
[ siteMap allRoutes |> Ok
|
||||
]
|
||||
|
||||
|
||||
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 = PagePath.build []
|
||||
, 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
|
||||
-> ImagePath
|
||||
cloudinaryIcon mimeType width =
|
||||
Cloudinary.urlSquare "v1603234028/elm-pages/elm-pages-icon" (Just mimeType) width
|
||||
|
||||
|
||||
siteMap :
|
||||
List (Maybe Route)
|
||||
-> { path : List String, content : String }
|
||||
siteMap allRoutes =
|
||||
allRoutes
|
||||
|> List.filterMap identity
|
||||
|> List.map
|
||||
(\route ->
|
||||
{ path = Route.routeToPath (Just route) |> String.join "/"
|
||||
, lastMod = Nothing
|
||||
}
|
||||
)
|
||||
|> Sitemap.build { siteUrl = "https://elm-pages.com" }
|
||||
|> (\sitemapXmlString -> { path = [ "sitemap.xml" ], content = sitemapXmlString })
|
8
examples/routing/src/SiteConfig.elm
Normal file
8
examples/routing/src/SiteConfig.elm
Normal file
@ -0,0 +1,8 @@
|
||||
module SiteConfig exposing (SiteConfig)
|
||||
|
||||
import Pages.SiteConfig
|
||||
import Route exposing (Route)
|
||||
|
||||
|
||||
type alias SiteConfig data =
|
||||
Pages.SiteConfig.SiteConfig (Maybe Route) data
|
39
examples/routing/static/images/elm-logo.svg
Normal file
39
examples/routing/static/images/elm-logo.svg
Normal 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 |
1
examples/routing/static/images/github.svg
Normal file
1
examples/routing/static/images/github.svg
Normal 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 |
BIN
examples/routing/static/images/icon-png.png
Normal file
BIN
examples/routing/static/images/icon-png.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 976 B |
2
examples/routing/static/images/icon.svg
Normal file
2
examples/routing/static/images/icon.svg
Normal 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 |
1
examples/routing/static/index.js
Normal file
1
examples/routing/static/index.js
Normal file
@ -0,0 +1 @@
|
||||
export default function (elmLoaded) {}
|
79
examples/routing/static/style.css
Normal file
79
examples/routing/static/style.css
Normal 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;
|
||||
}
|
43
examples/routing/static/syntax.css
Normal file
43
examples/routing/static/syntax.css
Normal 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;}
|
||||
|
53
examples/routing/tests/RouteTest.elm
Normal file
53
examples/routing/tests/RouteTest.elm
Normal file
@ -0,0 +1,53 @@
|
||||
module RouteTest exposing (..)
|
||||
|
||||
import Expect
|
||||
import Route
|
||||
import Test exposing (Test, describe, test)
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
describe "routes"
|
||||
[ test "test 1" <|
|
||||
\() ->
|
||||
--{ path = "/cats/larry" }
|
||||
--{ path = "/slide" }
|
||||
{ path = "/cats/larry" }
|
||||
|> Route.urlToRoute
|
||||
|> Expect.equal
|
||||
(Route.Cats__Name__
|
||||
{ name = Just "larry" }
|
||||
|> Just
|
||||
)
|
||||
|
||||
--, test "test 2" <|
|
||||
-- \() ->
|
||||
-- "/cats"
|
||||
-- |> tryMatch
|
||||
-- { pattern = "^cats(?:\\/([^/]+))?$"
|
||||
-- , toRoute =
|
||||
-- \matches ->
|
||||
-- case matches of
|
||||
-- [ name ] ->
|
||||
-- Cats__Name__ { name = name } |> Just
|
||||
--
|
||||
-- _ ->
|
||||
-- Nothing
|
||||
-- }
|
||||
-- |> Expect.equal (Cats__Name__ { name = Nothing } |> Just)
|
||||
--, test "multiple matchers" <|
|
||||
-- \() ->
|
||||
-- "/slide/123"
|
||||
-- |> firstMatch exampleMatchers
|
||||
-- |> Expect.equal (Slide__Number_ { number = "123" } |> Just)
|
||||
--, test "hardcoded routes have precedence over dynamic segments" <|
|
||||
-- \() ->
|
||||
-- "/post/create"
|
||||
-- |> firstMatch postPrecedenceExample
|
||||
-- |> Expect.equal (Post__Create {} |> Just)
|
||||
--, test "dynamic segments match when they are not overshadowed by a hardcoded route" <|
|
||||
-- \() ->
|
||||
-- "/post/update"
|
||||
-- |> firstMatch postPrecedenceExample
|
||||
-- |> Expect.equal (Post__Slug_ { slug = "update" } |> Just)
|
||||
]
|
Loading…
Reference in New Issue
Block a user