mirror of
https://github.com/ryannhg/elm-spa.git
synced 2024-11-22 17:52:33 +03:00
reorganize docs site, simplify type alias with 6.0.8--beta
This commit is contained in:
parent
19df55bd85
commit
c2c77e9abf
@ -1,4 +1,4 @@
|
||||
# [![elm-spa](https://v6-elm-spa.netlify.app/images/outlined-to-edge.png)](https://elm-spa.dev)
|
||||
# [![elm-spa](https://elm-spa.dev/images/outlined-to-edge.png)](https://elm-spa.dev)
|
||||
|
||||
# **Installation**
|
||||
|
||||
|
@ -2,6 +2,13 @@
|
||||
publish = "public"
|
||||
command = "npm i elm-spa@beta && node scripts/generate-index.js && npx elm-spa build"
|
||||
|
||||
# Prevents missing markdown files from redirecting to index.html
|
||||
[[redirects]]
|
||||
from = "/content/*"
|
||||
to = "/content/:splat"
|
||||
status = 200
|
||||
force = true
|
||||
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Guide
|
||||
# Docs
|
||||
|
||||
Welcome to __elm-spa__, a framework for building web applications with [Elm](https://elm-lang.org)!
|
||||
If you are new to Elm, you should check out [the official guide](https://guide.elm-lang.org), which
|
||||
@ -44,7 +44,7 @@ npx elm-spa server
|
||||
So far, we've used [npx](https://www.npmjs.com/package/npx) so we don't need to install __elm-spa__ directly. If you'd like to run commands from the terminal, without the `npx` prefix, you can install __elm-spa__ like this:
|
||||
|
||||
```terminal
|
||||
npm install -g elm-spa@next
|
||||
npm install -g elm-spa@latest
|
||||
```
|
||||
|
||||
You can verify the install succeeded by running `elm-spa help` from your terminal:
|
||||
@ -61,11 +61,11 @@ elm-spa build . . . . . one-time production build
|
||||
elm-spa watch . . . . . . runs build as you code
|
||||
elm-spa server . . . . . start a live dev server
|
||||
|
||||
Visit https://next.elm-spa.dev for more!
|
||||
Visit https://elm-spa.dev for more!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
__Ready for more?__
|
||||
|
||||
Let's check out [the CLI](/guide/cli) to learn more about those five commands!
|
||||
Let's check out [the CLI](/docs/cli) to learn more about those five commands!
|
@ -3,16 +3,16 @@
|
||||
At the end of the last section, we installed the __elm-spa__ CLI using [npm](https://npmjs.org) like this:
|
||||
|
||||
```terminal
|
||||
npm install -g elm-spa@next
|
||||
npm install -g elm-spa@latest
|
||||
```
|
||||
|
||||
This gave us the ability to run a few commands:
|
||||
|
||||
1. __[`elm-spa new`](#elm-spa-new)__ - creates a new project
|
||||
1. __[`elm-spa server`](#elm-spa-server)__ - runs a dev server as you code
|
||||
1. __[`elm-spa watch`](#elm-spa-watch)__ - builds as you code
|
||||
1. __[`elm-spa build`](#elm-spa-build)__ - one-time production build
|
||||
1. __[`elm-spa add`](#elm-spa-add)__ - adds a page to an existing project
|
||||
1. [__elm-spa new__](#elm-spa-new) - creates a new project
|
||||
1. [__elm-spa server__](#elm-spa-server) - runs a dev server as you code
|
||||
1. [__elm-spa watch__](#elm-spa-watch) - builds as you code
|
||||
1. [__elm-spa build__](#elm-spa-build) - one-time production build
|
||||
1. [__elm-spa add__](#elm-spa-add) - adds a page to an existing project
|
||||
|
||||
What do these do? This section of the guide dives into more detail on each command!
|
||||
|
||||
@ -57,7 +57,7 @@ If you want the automatic compilation on change, but don't need a HTTP server, y
|
||||
elm-spa watch
|
||||
```
|
||||
|
||||
This will automatically generate and compile on save, but without the server. This is a great choice when combining __elm-spa__ with another tool like [Parcel](https://parceljs.org/elm.html)
|
||||
This will automatically generate code and compile your Elm files on save, but without the server. This is a great command to combine __elm-spa__ with another tool like [Parcel](https://parceljs.org/elm.html).
|
||||
|
||||
|
||||
## elm-spa build
|
@ -13,11 +13,11 @@ view =
|
||||
}
|
||||
```
|
||||
|
||||
This homepage renders the tab `title`, and a HTML `body` onto the page. This is great when you have a static page that just needs to render some elements.
|
||||
This homepage renders the tab `title`, and a HTML `body` onto the page. This is great when you have a static page that just needs to render some HTML.
|
||||
|
||||
Because the file is named `Home_.elm`, we know it's the homepage. These 8 lines of code are all we need to tell __elm-spa__ we'd like to render this when users visit the homepage.
|
||||
|
||||
For real world applications, we'll need pages that can do more. That's where the `Page` module comes in handy.
|
||||
For real world applications, our pages will need to do more than print "Hello, world!". Let's upgrade!
|
||||
|
||||
### Upgrading "Hello World!"
|
||||
|
||||
@ -26,13 +26,12 @@ Let's start by introducing the `page` function, marking the start of our journey
|
||||
```elm
|
||||
module Pages.Home_ exposing (page)
|
||||
|
||||
-- our other imports
|
||||
import Html
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
|
||||
page :
|
||||
Shared.Model
|
||||
-> Request Params
|
||||
-> Page () Never
|
||||
page : Shared.Model -> Request -> Page
|
||||
page shared req =
|
||||
Page.static
|
||||
{ view = view
|
||||
@ -46,13 +45,13 @@ view =
|
||||
|
||||
Here, our code hasn't changed very much- except now we have this new `page` function that:
|
||||
|
||||
1. Takes in two inputs: `Shared.Model` and `Request Params`
|
||||
2. Returns a `Page () Never` value.
|
||||
3. Is exposed at the top of our `Pages.Home_` module.
|
||||
1. Accepts two inputs: `Shared.Model` and `Request`
|
||||
2. Returns a `Page` value
|
||||
3. Has been __exposed__ at the top of the file
|
||||
|
||||
> Without exposing `page`, __elm-spa__ will not understand how to compile your application. Make sure to _always_ expose `page` from modules within the `src/Pages` folder.
|
||||
> Exposing `page` from this module lets __elm-spa__ know to use it instead of the plain `view` function from before.
|
||||
|
||||
This new `page` will always get the latest `Shared.Model` and URL information, which means you don't have to worry about tracking that stuff yourself.
|
||||
This new `page` will always get the latest `Shared.Model` and a `Request` value (that contains URL information).
|
||||
|
||||
This is great, but there is still more that our `page` function can do other than render a view!
|
||||
|
||||
@ -152,28 +151,50 @@ Notice how the type annotations of `init` and `update` changed to accept their i
|
||||
|
||||
## Page.static
|
||||
|
||||
```elm
|
||||
module Pages.Example exposing (page)
|
||||
```
|
||||
|
||||
```elm
|
||||
Page.static
|
||||
{ view : View Never
|
||||
{ view = view
|
||||
}
|
||||
```
|
||||
|
||||
```elm
|
||||
view : View Never
|
||||
```
|
||||
|
||||
( video introducing concept )
|
||||
|
||||
## Page.sandbox
|
||||
|
||||
```elm
|
||||
module Pages.Example exposing (Model, Msg, page)
|
||||
```
|
||||
|
||||
```elm
|
||||
Page.sandbox
|
||||
{ init : Model
|
||||
, update : Msg -> Model -> Model
|
||||
, view : Model -> View Msg
|
||||
{ init = init
|
||||
, update = update
|
||||
, view = view
|
||||
}
|
||||
```
|
||||
|
||||
```elm
|
||||
init : Model
|
||||
update : Msg -> Model -> Model
|
||||
view : Model -> View Msg
|
||||
```
|
||||
|
||||
( video introducing concept )
|
||||
|
||||
## Page.element
|
||||
|
||||
```elm
|
||||
module Pages.Example exposing (Model, Msg, page)
|
||||
```
|
||||
|
||||
```elm
|
||||
Page.element
|
||||
{ init : ( Model, Cmd Msg )
|
||||
@ -187,6 +208,10 @@ Page.element
|
||||
|
||||
## Page.advanced
|
||||
|
||||
```elm
|
||||
module Pages.Example exposing (Model, Msg, page)
|
||||
```
|
||||
|
||||
```elm
|
||||
Page.advanced
|
||||
{ init : ( Model, Effect Msg )
|
@ -1,6 +1,6 @@
|
||||
# Requests
|
||||
|
||||
Every URL that a user visits in your application contains useful information. When __elm-spa__ gets an updated URL, it passes that information to every [Page](/guide/pages) as a `Request` value.
|
||||
Every URL that a user visits in your application contains useful information. When __elm-spa__ gets an updated URL, it passes that information to every [Page](/docs/pages) as a `Request` value.
|
||||
|
||||
|
||||
This section of the guide breaks down the [Request](https://package.elm-lang.org/packages/ryannhg/elm-spa/latest/ElmSpa-Request) type exposed by the official Elm package:
|
||||
@ -17,7 +17,7 @@ type alias Request params =
|
||||
|
||||
## URL Parameters
|
||||
|
||||
Every request has parameters that you can rely on. If you are on a [dynamic route](/guide/routing#dynamic-routes), you have access to that route's URL parameters:
|
||||
Every request has parameters that you can rely on. If you are on a [dynamic route](/docs/routing#dynamic-routes), you have access to that route's URL parameters:
|
||||
|
||||
URL | Params
|
||||
--- | ---
|
||||
@ -36,7 +36,7 @@ greet req =
|
||||
"Hello, " ++ req.params.name ++ "!"
|
||||
```
|
||||
|
||||
__Note:__ When working with [shared state](/guide/shared-state), all requests are `Request ()`.
|
||||
__Note:__ When working with [shared state](/docs/shared-state), all requests are `Request ()`.
|
||||
|
||||
## Query Parameters
|
||||
|
@ -16,7 +16,7 @@ In this section, we'll cover the 3 kinds of routes you can find in an __elm-spa_
|
||||
|
||||
## The homepage
|
||||
|
||||
The `src/Pages/Home_.elm` is a reserved filename that handles requests to /. The easiest way to make a new homepage is with the [`add` command](/guide/cli#adding-a-homepage) covered in the CLI section:
|
||||
The `src/Pages/Home_.elm` is a reserved filename that handles requests to /. The easiest way to make a new homepage is with the [`add` command](/docs/cli#adding-a-homepage) covered in the CLI section:
|
||||
|
||||
```terminal
|
||||
elm-spa add /
|
||||
@ -78,7 +78,7 @@ The __trailing underscore__ at the end of the filename (`Name_.elm`) indicates t
|
||||
|
||||
The name of the route parameter variable (`name` in this example) is determined by the name of the file! If we named the file `Id_.elm`, the dynamic value would be available at `params.id` instead.
|
||||
|
||||
Every page gets access to these dynamic parameters, via the [`Request params`](/guide/pages#requests) value passed in. We'll cover that in the next section!
|
||||
Every page gets access to these dynamic parameters, via the [`Request params`](/docs/pages#requests) value passed in. We'll cover that in the next section!
|
||||
|
||||
### Nested dynamic routes
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Shared State
|
||||
# Shared state
|
||||
|
||||
With __elm-spa__, every time you navigate from one page to another, the `init` function for that page is called. This means that the `Model` for the page you we're previously looking at has been cleared out. Most of the time, that's a good thing!
|
||||
|
||||
@ -22,7 +22,7 @@ init : Flags -> Request () -> Model -> ( Model, Effect Msg )
|
||||
The `init` function is called when your page loads for the first time. It takes in two inputs:
|
||||
|
||||
- `Flags` - initial JSON value passed in from `public/main.js
|
||||
- `Request ()` - a [Request](/guide/request) value with the current URL information
|
||||
- `Request ()` - a [Request](/docs/request) value with the current URL information
|
||||
|
||||
The `init` function returns the initial `Model`, as well as any `Effect`s you'd like to run (like initial HTTP requests, etc)
|
||||
|
@ -1 +1,7 @@
|
||||
# Examples
|
||||
# Examples
|
||||
|
||||
Here are real-world applications using __elm-spa__:
|
||||
|
||||
- This site
|
||||
- Realworld example app
|
||||
- User featured projects
|
@ -1 +0,0 @@
|
||||
# User Authentication
|
1
docs/public/content/guides.md
Normal file
1
docs/public/content/guides.md
Normal file
@ -0,0 +1 @@
|
||||
# Guides
|
1
docs/public/content/guides/01-getting-started.md
Normal file
1
docs/public/content/guides/01-getting-started.md
Normal file
@ -0,0 +1 @@
|
||||
# Getting started
|
1
docs/public/content/guides/02-page-transitions.md
Normal file
1
docs/public/content/guides/02-page-transitions.md
Normal file
@ -0,0 +1 @@
|
||||
# Page transitions
|
3
docs/public/content/guides/03-local-storage.md
Normal file
3
docs/public/content/guides/03-local-storage.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Local storage
|
||||
|
||||
TODO
|
3
docs/public/content/guides/04-authentication.md
Normal file
3
docs/public/content/guides/04-authentication.md
Normal file
@ -0,0 +1,3 @@
|
||||
# User authentication
|
||||
|
||||
TODO
|
1
docs/public/content/guides/05-elm-ui.md
Normal file
1
docs/public/content/guides/05-elm-ui.md
Normal file
@ -0,0 +1 @@
|
||||
# Using Elm UI
|
1
docs/public/content/guides/06-testing.md
Normal file
1
docs/public/content/guides/06-testing.md
Normal file
@ -0,0 +1 @@
|
||||
# Testing
|
@ -16,7 +16,7 @@
|
||||
--color--green: #407742;
|
||||
--color--green-light: #d7ead8;
|
||||
|
||||
--size--h1: 4em;
|
||||
--size--h1: 3em;
|
||||
--size--h2: 2em;
|
||||
--size--h3: 1.5em;
|
||||
--size--h4: 1.2em;
|
||||
@ -64,6 +64,16 @@ pre {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.aside {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table-of-contents {
|
||||
min-width: 14em;
|
||||
max-width: 14em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
main {
|
||||
animation: fadeIn 200ms 400ms ease-in forwards;
|
||||
opacity: 0;
|
||||
@ -163,12 +173,14 @@ hr { border: 0; }
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.markdown p code {
|
||||
.markdown p code,
|
||||
.markdown li code {
|
||||
font-size: 0.92em;
|
||||
color: var(--color--green);
|
||||
}
|
||||
|
||||
.markdown p code::before { content: '`'; opacity: 0.75; pointer-events: none; user-select: none; }
|
||||
.markdown p code::after { content: '`'; opacity: 0.75; pointer-events: none; user-select: none; }
|
||||
.markdown p code::before, .markdown li code::before { content: '`'; opacity: 0.75; pointer-events: none; user-select: none; }
|
||||
.markdown p code::after, .markdown li code::after { content: '`'; opacity: 0.75; pointer-events: none; user-select: none; }
|
||||
|
||||
.markdown blockquote {
|
||||
padding-left: 1rem;
|
||||
@ -243,9 +255,7 @@ hr { border: 0; }
|
||||
}
|
||||
|
||||
.markdown th,
|
||||
.markdown td {
|
||||
padding: 0.75em;
|
||||
}
|
||||
.markdown td { padding: 0.75em }
|
||||
|
||||
.markdown tbody tr:nth-child(2n + 1) {
|
||||
background-color: var(--color--grey-100);
|
||||
|
@ -6,6 +6,10 @@ const config = {
|
||||
output: path.join(__dirname, '..', 'public', 'dist')
|
||||
}
|
||||
|
||||
// Terminal color output
|
||||
const green = ``
|
||||
const reset = ``
|
||||
|
||||
// Recursively lists all files in the given folder
|
||||
const listContainedFiles = async (folder) => {
|
||||
let files = []
|
||||
@ -54,7 +58,7 @@ const main = () =>
|
||||
await fs.mkdir(config.output, { recursive: true })
|
||||
return fs.writeFile(path.join(config.output, 'flags.js'), contents, { encoding: 'utf-8' })
|
||||
})
|
||||
.then(_ => console.info(`\n ✓ Indexed the content folder\n`))
|
||||
.then(_ => console.info(`\n ${green}✓${reset} Indexed the content folder\n`))
|
||||
.catch(console.error)
|
||||
|
||||
// Run the program
|
||||
|
@ -106,7 +106,8 @@ sections : Index -> List Section
|
||||
sections index =
|
||||
let
|
||||
sectionOrder =
|
||||
[ "Guide"
|
||||
[ "Docs"
|
||||
, "Guides"
|
||||
, "Examples"
|
||||
]
|
||||
|
||||
|
@ -145,6 +145,6 @@ subscriptions model =
|
||||
-- REQUESTS
|
||||
|
||||
|
||||
request : { model | url : Url, key : Key } -> Request ()
|
||||
request : { model | url : Url, key : Key } -> Request
|
||||
request model =
|
||||
Request.create () model.url model.key
|
||||
|
19
docs/src/Pages/Docs.elm
Normal file
19
docs/src/Pages/Docs.elm
Normal file
@ -0,0 +1,19 @@
|
||||
module Pages.Docs exposing (Model, Msg, page)
|
||||
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
19
docs/src/Pages/Docs/Section_.elm
Normal file
19
docs/src/Pages/Docs/Section_.elm
Normal file
@ -0,0 +1,19 @@
|
||||
module Pages.Docs.Section_ exposing (Model, Msg, page)
|
||||
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
@ -1,12 +1,12 @@
|
||||
module Pages.Examples exposing (Model, Msg, page)
|
||||
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
module Pages.Examples.Section_ exposing (Model, Msg, page)
|
||||
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request params -> Page Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
@ -1,19 +0,0 @@
|
||||
module Pages.Guide exposing (Model, Msg, page)
|
||||
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request params -> Page Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
@ -1,19 +0,0 @@
|
||||
module Pages.Guide.Section_ exposing (Model, Msg, page)
|
||||
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request params -> Page Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
19
docs/src/Pages/Guides.elm
Normal file
19
docs/src/Pages/Guides.elm
Normal file
@ -0,0 +1,19 @@
|
||||
module Pages.Guides exposing (Model, Msg, page)
|
||||
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
19
docs/src/Pages/Guides/Section_.elm
Normal file
19
docs/src/Pages/Guides/Section_.elm
Normal file
@ -0,0 +1,19 @@
|
||||
module Pages.Guides.Section_ exposing (Model, Msg, page)
|
||||
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI.Docs
|
||||
|
||||
|
||||
page : Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Docs.page
|
||||
|
||||
|
||||
type alias Model =
|
||||
UI.Docs.Model
|
||||
|
||||
|
||||
type alias Msg =
|
||||
UI.Docs.Msg
|
@ -1,15 +1,15 @@
|
||||
module Pages.Home_ exposing (Model, Msg, page)
|
||||
|
||||
import Gen.Params.Home_ exposing (Params)
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI
|
||||
import UI.Layout
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request Params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With Params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Layout.page
|
||||
{ view = view
|
||||
@ -36,7 +36,7 @@ view =
|
||||
## Build reliable applications.
|
||||
|
||||
I need to verify that the line height for paragraphs is reasonable, because if it isn't then I'll need to tweak it a bit until it's actually readable.
|
||||
Only the most readable lines should be included in the __official__ [guide](/guide), ya dig?
|
||||
Only the most readable lines should be included in the __official__ [guide](/docs), ya dig?
|
||||
|
||||
Bippity boppity, my guy.
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
module Pages.NotFound exposing (Model, Msg, page)
|
||||
|
||||
import Gen.Params.NotFound exposing (Params)
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI
|
||||
import UI.Layout
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request Params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With Params -> Page.With Model Msg
|
||||
page =
|
||||
UI.Layout.page
|
||||
{ view = view
|
||||
|
@ -36,7 +36,7 @@ type Msg
|
||||
-- INIT
|
||||
|
||||
|
||||
init : Request () -> Flags -> ( Model, Cmd Msg )
|
||||
init : Request -> Flags -> ( Model, Cmd Msg )
|
||||
init _ flags =
|
||||
( Model
|
||||
(flags
|
||||
@ -51,7 +51,7 @@ init _ flags =
|
||||
-- UPDATE
|
||||
|
||||
|
||||
update : Request () -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update : Request -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update request msg model =
|
||||
case msg of
|
||||
NoOp ->
|
||||
@ -62,6 +62,6 @@ update request msg model =
|
||||
-- SUBSCRIPTIONS
|
||||
|
||||
|
||||
subscriptions : Request () -> Model -> Sub Msg
|
||||
subscriptions : Request -> Model -> Sub Msg
|
||||
subscriptions request model =
|
||||
Sub.none
|
||||
|
@ -1,8 +1,8 @@
|
||||
module UI.Docs exposing (Model, Msg, page)
|
||||
|
||||
import Http
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import UI
|
||||
import UI.Layout
|
||||
@ -10,7 +10,7 @@ import Url exposing (Url)
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page shared req =
|
||||
Page.element
|
||||
{ init = init req.url
|
||||
|
@ -13,6 +13,7 @@ module UI.Layout exposing
|
||||
|
||||
-}
|
||||
|
||||
import Gen.Route as Route exposing (Route)
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes as Attr
|
||||
import Page exposing (Page)
|
||||
@ -72,9 +73,9 @@ viewDocumentation :
|
||||
-> List (Html msg)
|
||||
viewDocumentation options markdownContent view =
|
||||
[ navbar options
|
||||
, Html.div [ Attr.class "container pad-lg" ]
|
||||
[ UI.row.lg [ UI.align.top, UI.padY.lg ]
|
||||
[ Html.aside [ Attr.class "only-desktop sticky pad-y-lg", Attr.style "width" "13em" ]
|
||||
, Html.div [ Attr.class "container pad-md" ]
|
||||
[ UI.row.xl [ UI.align.top, UI.padY.lg ]
|
||||
[ Html.aside [ Attr.class "only-desktop sticky pad-y-lg aside" ]
|
||||
[ UI.Sidebar.viewSidebar
|
||||
{ index = options.shared.index
|
||||
, url = options.url
|
||||
@ -83,7 +84,7 @@ viewDocumentation options markdownContent view =
|
||||
, Html.main_ [ Attr.class "flex" ]
|
||||
[ UI.row.lg [ UI.align.top ]
|
||||
[ Html.div [ Attr.class "col flex" ] view
|
||||
, Html.div [ Attr.class "hidden-mobile sticky pad-y-lg", Attr.style "width" "16em" ]
|
||||
, Html.div [ Attr.class "hidden-mobile sticky pad-y-lg table-of-contents" ]
|
||||
[ UI.Sidebar.viewTableOfContents
|
||||
{ content = markdownContent
|
||||
, url = options.url
|
||||
@ -105,12 +106,12 @@ navbar :
|
||||
-> Html msg
|
||||
navbar { onMsg, model, shared, url } =
|
||||
let
|
||||
navLink : { text : String, url : String } -> Html msg
|
||||
navLink : { text : String, route : Route } -> Html msg
|
||||
navLink options =
|
||||
Html.a
|
||||
[ Attr.class "link"
|
||||
, Attr.href options.url
|
||||
, Attr.classList [ ( "bold text-blue", String.startsWith options.url url.path ) ]
|
||||
, Attr.href (Route.toHref options.route)
|
||||
, Attr.classList [ ( "bold text-blue", String.startsWith (Route.toHref options.route) url.path ) ]
|
||||
]
|
||||
[ Html.text options.text ]
|
||||
in
|
||||
@ -119,9 +120,9 @@ navbar { onMsg, model, shared, url } =
|
||||
[ Html.div [ Attr.class "row align-center gap-md" ]
|
||||
[ Html.a [ Attr.href "/" ] [ UI.logo ]
|
||||
, Html.nav [ Attr.class "row gap-md hidden-mobile pad-left-xs" ]
|
||||
[ navLink { text = "guide", url = "/guide" }
|
||||
, navLink { text = "docs", url = "/docs" }
|
||||
, navLink { text = "examples", url = "/examples" }
|
||||
[ navLink { text = "docs", route = Route.Docs }
|
||||
, navLink { text = "guides ", route = Route.Guides }
|
||||
, navLink { text = "examples", route = Route.Examples }
|
||||
]
|
||||
]
|
||||
, Html.div [ Attr.class "row gap-md spread" ]
|
||||
@ -144,7 +145,7 @@ navbar { onMsg, model, shared, url } =
|
||||
-- PAGE
|
||||
|
||||
|
||||
page : { view : View Msg } -> Shared.Model -> Request params -> Page Model Msg
|
||||
page : { view : View Msg } -> Shared.Model -> Request.With params -> Page.With Model Msg
|
||||
page options shared req =
|
||||
Page.sandbox
|
||||
{ init = init
|
||||
|
@ -6,7 +6,7 @@
|
||||
This project requires the latest LTS version of [Node.js](https://nodejs.org/)
|
||||
|
||||
```bash
|
||||
npm install -g elm elm-spa
|
||||
npm install -g elm-spa@latest
|
||||
```
|
||||
|
||||
## running locally
|
||||
|
@ -9,7 +9,7 @@ module ElmSpa.Page exposing
|
||||
# **( These docs are for CLI contributors )**
|
||||
|
||||
|
||||
### If you are using **elm-spa**, check out [the official guide](https://v6.elm-spa.dev/guide) instead!
|
||||
### If you are using **elm-spa**, check out [the official guide](https://elm-spa.dev/guide) instead!
|
||||
|
||||
---
|
||||
|
||||
|
@ -6,7 +6,7 @@ module ElmSpa.Request exposing (Request, create)
|
||||
# **( These docs are for CLI contributors )**
|
||||
|
||||
|
||||
### If you are using **elm-spa**, check out [the official guide](https://v6.elm-spa.dev/guide) instead!
|
||||
### If you are using **elm-spa**, check out [the official guide](https://elm-spa.dev/guide) instead!
|
||||
|
||||
---
|
||||
|
||||
|
7373
src/cli/package-lock.json
generated
7373
src/cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "elm-spa",
|
||||
"version": "6.0.7--beta",
|
||||
"version": "6.0.8--beta",
|
||||
"description": "single page apps made easy",
|
||||
"bin": "dist/src/index.js",
|
||||
"scripts": {
|
||||
@ -45,4 +45,4 @@
|
||||
"terser": "5.3.8",
|
||||
"websocket": "1.0.32"
|
||||
}
|
||||
}
|
||||
}
|
@ -19,5 +19,5 @@ ${bold(`elm-spa ${cyan(`build`)}`)} . . . . . . one-time production build
|
||||
${bold(`elm-spa ${cyan(`watch`)}`)} . . . . . . . runs build as you code
|
||||
${bold(`elm-spa ${cyan(`server`)}`)} . . . . . . start a live dev server
|
||||
|
||||
Visit ${green(`https://next.elm-spa.dev`)} for more!
|
||||
Visit ${green(`https://elm-spa.dev`)} for more!
|
||||
`
|
@ -1,13 +1,14 @@
|
||||
module Page exposing
|
||||
( Page
|
||||
( Page, With
|
||||
, static, sandbox, element, advanced
|
||||
, protected
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Page
|
||||
@docs Page, With
|
||||
@docs static, sandbox, element, advanced
|
||||
@docs protected
|
||||
|
||||
-}
|
||||
|
||||
@ -20,6 +21,58 @@ import View exposing (View)
|
||||
|
||||
|
||||
|
||||
-- PAGES
|
||||
|
||||
|
||||
type alias Page =
|
||||
With () Never
|
||||
|
||||
|
||||
type alias With model msg =
|
||||
ElmSpa.Page Shared.Model Route (Effect msg) (View msg) model msg
|
||||
|
||||
|
||||
static :
|
||||
{ view : View Never
|
||||
}
|
||||
-> Page
|
||||
static =
|
||||
ElmSpa.static Effect.none
|
||||
|
||||
|
||||
sandbox :
|
||||
{ init : model
|
||||
, update : msg -> model -> model
|
||||
, view : model -> View msg
|
||||
}
|
||||
-> With model msg
|
||||
sandbox =
|
||||
ElmSpa.sandbox Effect.none
|
||||
|
||||
|
||||
element :
|
||||
{ init : ( model, Cmd msg )
|
||||
, update : msg -> model -> ( model, Cmd msg )
|
||||
, view : model -> View msg
|
||||
, subscriptions : model -> Sub msg
|
||||
}
|
||||
-> With model msg
|
||||
element =
|
||||
ElmSpa.element Effect.fromCmd
|
||||
|
||||
|
||||
advanced :
|
||||
{ init : ( model, Effect msg )
|
||||
, update : msg -> model -> ( model, Effect msg )
|
||||
, view : model -> View msg
|
||||
, subscriptions : model -> Sub msg
|
||||
}
|
||||
-> With model msg
|
||||
advanced =
|
||||
ElmSpa.advanced
|
||||
|
||||
|
||||
|
||||
-- PROTECTED PAGES
|
||||
|
||||
|
||||
@ -41,84 +94,36 @@ Here, you can provide logic on where to redirect if a user is not signed in. Her
|
||||
ElmSpa.RedirectTo Gen.Route.SignIn
|
||||
|
||||
-}
|
||||
beforeProtectedInit : Shared.Model -> Request () -> ElmSpa.Protected User Route
|
||||
beforeProtectedInit : Shared.Model -> Request -> ElmSpa.Protected User Route
|
||||
beforeProtectedInit shared req =
|
||||
ElmSpa.RedirectTo Gen.Route.NotFound
|
||||
|
||||
|
||||
|
||||
-- PAGES
|
||||
|
||||
|
||||
type alias Page model msg =
|
||||
ElmSpa.Page Shared.Model Route (Effect msg) (View msg) model msg
|
||||
|
||||
|
||||
static :
|
||||
{ view : View Never
|
||||
}
|
||||
-> Page () Never
|
||||
static =
|
||||
ElmSpa.static Effect.none
|
||||
|
||||
|
||||
sandbox :
|
||||
{ init : model
|
||||
, update : msg -> model -> model
|
||||
, view : model -> View msg
|
||||
}
|
||||
-> Page model msg
|
||||
sandbox =
|
||||
ElmSpa.sandbox Effect.none
|
||||
|
||||
|
||||
element :
|
||||
{ init : ( model, Cmd msg )
|
||||
, update : msg -> model -> ( model, Cmd msg )
|
||||
, view : model -> View msg
|
||||
, subscriptions : model -> Sub msg
|
||||
}
|
||||
-> Page model msg
|
||||
element =
|
||||
ElmSpa.element Effect.fromCmd
|
||||
|
||||
|
||||
advanced :
|
||||
{ init : ( model, Effect msg )
|
||||
, update : msg -> model -> ( model, Effect msg )
|
||||
, view : model -> View msg
|
||||
, subscriptions : model -> Sub msg
|
||||
}
|
||||
-> Page model msg
|
||||
advanced =
|
||||
ElmSpa.advanced
|
||||
|
||||
|
||||
protected :
|
||||
{ static :
|
||||
{ view : User -> View msg
|
||||
}
|
||||
-> Page () msg
|
||||
-> With () msg
|
||||
, sandbox :
|
||||
{ init : User -> model
|
||||
, update : User -> msg -> model -> model
|
||||
, view : User -> model -> View msg
|
||||
}
|
||||
-> Page model msg
|
||||
-> With model msg
|
||||
, element :
|
||||
{ init : User -> ( model, Cmd msg )
|
||||
, update : User -> msg -> model -> ( model, Cmd msg )
|
||||
, view : User -> model -> View msg
|
||||
, subscriptions : User -> model -> Sub msg
|
||||
}
|
||||
-> Page model msg
|
||||
-> With model msg
|
||||
, advanced :
|
||||
{ init : User -> ( model, Effect msg )
|
||||
, update : User -> msg -> model -> ( model, Effect msg )
|
||||
, view : User -> model -> View msg
|
||||
, subscriptions : User -> model -> Sub msg
|
||||
}
|
||||
-> Page model msg
|
||||
-> With model msg
|
||||
}
|
||||
protected =
|
||||
ElmSpa.protected2
|
||||
|
@ -3,6 +3,6 @@ module Pages.NotFound exposing (view)
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
view : View Never
|
||||
view : View msg
|
||||
view =
|
||||
View.placeholder "Page not found."
|
||||
|
@ -1,4 +1,16 @@
|
||||
module Request exposing (Request, create, pushRoute, replaceRoute)
|
||||
module Request exposing
|
||||
( Request, With
|
||||
, create
|
||||
, pushRoute, replaceRoute
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Request, With
|
||||
@docs create
|
||||
@docs pushRoute, replaceRoute
|
||||
|
||||
-}
|
||||
|
||||
import Browser.Navigation exposing (Key)
|
||||
import ElmSpa.Request as ElmSpa
|
||||
@ -6,20 +18,24 @@ import Gen.Route as Route exposing (Route)
|
||||
import Url exposing (Url)
|
||||
|
||||
|
||||
type alias Request params =
|
||||
type alias Request =
|
||||
With ()
|
||||
|
||||
|
||||
type alias With params =
|
||||
ElmSpa.Request Route params
|
||||
|
||||
|
||||
create : params -> Url -> Key -> Request params
|
||||
create : params -> Url -> Key -> With params
|
||||
create params url key =
|
||||
ElmSpa.create (Route.fromUrl url) params url key
|
||||
|
||||
|
||||
pushRoute : Route -> Request params -> Cmd msg
|
||||
pushRoute : Route -> With params -> Cmd msg
|
||||
pushRoute route req =
|
||||
Browser.Navigation.pushUrl req.key (Route.toHref route)
|
||||
|
||||
|
||||
replaceRoute : Route -> Request params -> Cmd msg
|
||||
replaceRoute : Route -> With params -> Cmd msg
|
||||
replaceRoute route req =
|
||||
Browser.Navigation.replaceUrl req.key (Route.toHref route)
|
||||
|
@ -23,18 +23,18 @@ type Msg
|
||||
= NoOp
|
||||
|
||||
|
||||
init : Request () -> Flags -> ( Model, Cmd Msg )
|
||||
init : Request -> Flags -> ( Model, Cmd Msg )
|
||||
init _ _ =
|
||||
( {}, Cmd.none )
|
||||
|
||||
|
||||
update : Request () -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update : Request -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update _ msg model =
|
||||
case msg of
|
||||
NoOp ->
|
||||
( model, Cmd.none )
|
||||
|
||||
|
||||
subscriptions : Request () -> Model -> Sub Msg
|
||||
subscriptions : Request -> Model -> Sub Msg
|
||||
subscriptions _ _ =
|
||||
Sub.none
|
||||
|
@ -4,7 +4,7 @@ import Html
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
view : View Never
|
||||
view : View msg
|
||||
view =
|
||||
{ title = "Homepage"
|
||||
, body = [ Html.text "Hello, world!" ]
|
||||
|
@ -1,10 +1,10 @@
|
||||
export default (page : string[]) : string => `
|
||||
export default (page: string[]): string => `
|
||||
module Pages.${page.join('.')} exposing (view)
|
||||
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
view : View Never
|
||||
view : View msg
|
||||
view =
|
||||
View.placeholder "${page.join('.')}"
|
||||
|
||||
|
@ -2,13 +2,14 @@ module Pages.{{module}} exposing (Model, Msg, page)
|
||||
|
||||
import Effect exposing (Effect)
|
||||
import Gen.Params.{{module}} exposing (Params)
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
import Page
|
||||
|
||||
|
||||
page : Shared.Model -> Request Params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With Params -> Page.With Model Msg
|
||||
page shared req =
|
||||
Page.advanced
|
||||
{ init = init
|
||||
|
@ -1,13 +1,13 @@
|
||||
module Pages.{{module}} exposing (Model, Msg, page)
|
||||
|
||||
import Gen.Params.{{module}} exposing (Params)
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request Params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With Params -> Page.With Model Msg
|
||||
page shared req =
|
||||
Page.element
|
||||
{ init = init
|
||||
|
@ -1,13 +1,13 @@
|
||||
module Pages.{{module}} exposing (Model, Msg, page)
|
||||
|
||||
import Gen.Params.{{module}} exposing (Params)
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request Params -> Page Model Msg
|
||||
page : Shared.Model -> Request.With Params -> Page.With Model Msg
|
||||
page shared req =
|
||||
Page.sandbox
|
||||
{ init = init
|
||||
|
@ -2,18 +2,18 @@ module Pages.{{module}} exposing (page)
|
||||
|
||||
import Gen.Params.{{module}} exposing (Params)
|
||||
import Page exposing (Page)
|
||||
import Request exposing (Request)
|
||||
import Request
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request Params -> Page () Never
|
||||
page : Shared.Model -> Request.With Params -> Page
|
||||
page shared req =
|
||||
Page.static
|
||||
{ view = view
|
||||
}
|
||||
|
||||
|
||||
view : View Never
|
||||
view : View msg
|
||||
view =
|
||||
View.placeholder "{{module}}"
|
||||
|
@ -1,6 +1,31 @@
|
||||
import config from "../config"
|
||||
import { routeTypeDefinition, indent, routeParserList, paramsImports, Options, routeToHref } from "./utils"
|
||||
|
||||
export default (pages : string[][], _options : Options) : string => `
|
||||
const routeParserOrder = (pages: string[][]) =>
|
||||
[...pages].sort(sorter)
|
||||
|
||||
const isHomepage = (list: string[]) => list.join('.') === config.reserved.homepage
|
||||
const isDynamic = (piece: string) => piece.endsWith('_')
|
||||
const alphaSorter = (a: string, b: string) => a < b ? -1 : b < a ? 1 : 0
|
||||
|
||||
const sorter = (a: string[], b: string[]): (-1 | 1 | 0) => {
|
||||
if (isHomepage(a)) return -1
|
||||
if (isHomepage(b)) return 1
|
||||
|
||||
if (a.length < b.length) return -1
|
||||
if (a.length > b.length) return 1
|
||||
|
||||
for (let i in a) {
|
||||
const [isA, isB] = [isDynamic(a[i]), isDynamic(b[i])]
|
||||
if (isA && isB) return alphaSorter(a[i], b[i])
|
||||
if (isA) return 1
|
||||
if (isB) return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
export default (pages: string[][], _options: Options): string => `
|
||||
module Gen.Route exposing
|
||||
( Route(..)
|
||||
, fromUrl
|
||||
@ -22,7 +47,7 @@ fromUrl =
|
||||
|
||||
routes : List (Parser (Route -> a) a)
|
||||
routes =
|
||||
${indent(routeParserList(pages), 1)}
|
||||
${indent(routeParserList(routeParserOrder(pages)), 1)}
|
||||
|
||||
|
||||
toHref : Route -> String
|
||||
|
Loading…
Reference in New Issue
Block a user