elm-pages 3.0.0-beta.40 → 3.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/codegen/elm-pages-codegen.cjs +204 -262
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
- package/generator/src/RouteBuilder.elm +9 -8
- package/generator/src/SharedTemplate.elm +5 -5
- package/generator/src/compatibility-key.js +2 -2
- package/package.json +1 -1
- package/src/BackendTask.elm +18 -24
- package/src/Head/Seo.elm +4 -4
- package/src/Pages/ConcurrentSubmission.elm +127 -0
- package/src/Pages/Form.elm +151 -40
- package/src/Pages/FormData.elm +18 -0
- package/src/Pages/Internal/NotFoundReason.elm +4 -4
- package/src/Pages/Internal/Platform/Cli.elm +15 -15
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +1 -1
- package/src/Pages/Internal/Platform.elm +39 -38
- package/src/Pages/Internal/ResponseSketch.elm +2 -2
- package/src/Pages/Manifest.elm +23 -7
- package/src/Pages/Navigation.elm +87 -0
- package/src/Pages/PageUrl.elm +3 -3
- package/src/Pages/ProgramConfig.elm +10 -9
- package/src/Pages/Script.elm +64 -7
- package/src/Pages/Url.elm +3 -3
- package/src/PagesMsg.elm +9 -3
- package/src/RenderRequest.elm +7 -7
- package/src/Scaffold/Form.elm +28 -5
- package/src/Scaffold/Route.elm +12 -3
- package/src/Server/Request.elm +2 -1
- package/src/Server/Session.elm +1 -1
- package/src/Server/SetCookie.elm +71 -31
- package/src/{Path.elm → UrlPath.elm} +21 -21
- package/src/Pages/Transition.elm +0 -79
package/src/RenderRequest.elm
CHANGED
|
@@ -13,15 +13,15 @@ import Internal.ApiRoute
|
|
|
13
13
|
import Json.Decode as Decode
|
|
14
14
|
import Json.Encode as Encode
|
|
15
15
|
import Pages.ProgramConfig exposing (ProgramConfig)
|
|
16
|
-
import Path exposing (Path)
|
|
17
16
|
import Regex
|
|
18
17
|
import Url exposing (Url)
|
|
18
|
+
import UrlPath exposing (UrlPath)
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
type RequestPayload route
|
|
22
|
-
= Page { path :
|
|
22
|
+
= Page { path : UrlPath, frontmatter : route }
|
|
23
23
|
| Api ( String, ApiRoute.ApiRoute ApiRoute.Response )
|
|
24
|
-
| NotFound
|
|
24
|
+
| NotFound UrlPath
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
type RenderRequest route
|
|
@@ -32,7 +32,7 @@ default : RenderRequest route
|
|
|
32
32
|
default =
|
|
33
33
|
SinglePage
|
|
34
34
|
HtmlAndJson
|
|
35
|
-
(NotFound (
|
|
35
|
+
(NotFound (UrlPath.fromString "/error"))
|
|
36
36
|
Encode.null
|
|
37
37
|
|
|
38
38
|
|
|
@@ -119,12 +119,12 @@ requestPayloadDecoder config =
|
|
|
119
119
|
( path, justApi ) |> Api
|
|
120
120
|
|
|
121
121
|
Nothing ->
|
|
122
|
-
NotFound (
|
|
122
|
+
NotFound (UrlPath.fromString path)
|
|
123
123
|
|
|
124
124
|
else
|
|
125
125
|
Page
|
|
126
126
|
{ frontmatter = route
|
|
127
|
-
, path = config.routeToPath route |>
|
|
127
|
+
, path = config.routeToPath route |> UrlPath.join
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
Nothing ->
|
|
@@ -133,7 +133,7 @@ requestPayloadDecoder config =
|
|
|
133
133
|
( path, justApi ) |> Api
|
|
134
134
|
|
|
135
135
|
Nothing ->
|
|
136
|
-
NotFound (
|
|
136
|
+
NotFound (UrlPath.fromString path)
|
|
137
137
|
)
|
|
138
138
|
)
|
|
139
139
|
|> Decode.field "path"
|
package/src/Scaffold/Form.elm
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
module Scaffold.Form exposing
|
|
2
2
|
( Kind(..), provide, restArgsParser
|
|
3
3
|
, Context
|
|
4
|
-
,
|
|
4
|
+
, recordEncoder, fieldEncoder
|
|
5
5
|
)
|
|
6
6
|
|
|
7
|
-
{-|
|
|
7
|
+
{-| This module helps you with scaffolding a form in `elm-pages`, similar to how rails generators are used to scaffold out forms to
|
|
8
|
+
get up and running quickly with the starting point for a form with different field types. See also [`Scaffold.Route`](Scaffold-Route).
|
|
9
|
+
|
|
10
|
+
See the `AddRoute` script in the starter template for an example. It's usually easiest to modify that script as a starting
|
|
11
|
+
point rather than using this API from scratch.
|
|
12
|
+
|
|
13
|
+
Using the `AddRoute` script from the default starter template, you can run a command like this:
|
|
14
|
+
|
|
15
|
+
`npx elm-pages run AddRoute Profile.Username_.Edit first last bio:textarea dob:date` to generate a Route module `app/Route/Profile/Username_/Edit.elm`
|
|
16
|
+
with the wiring form a `Form`.
|
|
17
|
+
|
|
18
|
+
[Learn more about writing and running elm-pages Scripts for scaffolding](https://elm-pages-v3.netlify.app/docs/elm-pages-scripts#scaffolding-a-route-module).
|
|
8
19
|
|
|
9
20
|
@docs Kind, provide, restArgsParser
|
|
10
21
|
|
|
11
22
|
@docs Context
|
|
12
23
|
|
|
13
|
-
@docs
|
|
24
|
+
@docs recordEncoder, fieldEncoder
|
|
14
25
|
|
|
15
26
|
-}
|
|
16
27
|
|
|
@@ -159,7 +170,18 @@ fieldToParam ( name, _ ) =
|
|
|
159
170
|
( name, Nothing )
|
|
160
171
|
|
|
161
172
|
|
|
162
|
-
{-|
|
|
173
|
+
{-| This parser handles the following field types (or `text` if none is provided):
|
|
174
|
+
|
|
175
|
+
- `text`
|
|
176
|
+
- `textarea`
|
|
177
|
+
- `checkbox`
|
|
178
|
+
- `time`
|
|
179
|
+
- `date`
|
|
180
|
+
|
|
181
|
+
The naming convention follows the same naming as the HTML form field elements or attributes that are used to represent them.
|
|
182
|
+
In addition to using the appropriate field type, this will also give you an Elm type with the corresponding base type (like `Date` for `date` or `Bool` for `checkbox`).
|
|
183
|
+
|
|
184
|
+
-}
|
|
163
185
|
restArgsParser : Cli.Option.Option (List String) (List ( String, Kind )) Cli.Option.RestArgsOption
|
|
164
186
|
restArgsParser =
|
|
165
187
|
Cli.Option.restArgs "formFields"
|
|
@@ -506,7 +528,8 @@ recordEncoder record fields =
|
|
|
506
528
|
)
|
|
507
529
|
|
|
508
530
|
|
|
509
|
-
{-| -
|
|
531
|
+
{-| A lower-level, more granular version of `recordEncoder` - lets you generate a JSON Encoder `Expression` for an individual Field rather than a group of Fields.
|
|
532
|
+
-}
|
|
510
533
|
fieldEncoder : Elm.Expression -> String -> Kind -> Elm.Expression
|
|
511
534
|
fieldEncoder record name kind =
|
|
512
535
|
Elm.apply
|
package/src/Scaffold/Route.elm
CHANGED
|
@@ -9,12 +9,17 @@ module Scaffold.Route exposing
|
|
|
9
9
|
|
|
10
10
|
{-| This module provides some functions for scaffolding code for a new Route Module. It uses [`elm-codegen`'s API](https://package.elm-lang.org/packages/mdgriffith/elm-codegen/latest/) for generating code.
|
|
11
11
|
|
|
12
|
-
Typically you'll want to use this via the `elm-pages
|
|
13
|
-
Learn more about
|
|
12
|
+
Typically you'll want to use this via the `elm-pages run` CLI command. The default starter template includes a Script that uses these functions, which you can tweak to customize your scaffolding commands.
|
|
13
|
+
[Learn more about writing and running elm-pages Scripts for scaffolding](https://elm-pages-v3.netlify.app/docs/elm-pages-scripts#scaffolding-a-route-module).
|
|
14
|
+
|
|
15
|
+
It's typically easiest to modify the `AddRoute` script from the starter template and adjust it to your needs rather than writing one from scratch.
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
## Initializing the Generator Builder
|
|
17
19
|
|
|
20
|
+
These functions mirror the `RouteBuilder` API that you use in your Route modules to define your route. The difference is that
|
|
21
|
+
instead of defining a route, this is defining a code generator for a Route module.
|
|
22
|
+
|
|
18
23
|
@docs buildWithLocalState, buildWithSharedState, buildNoState, Builder
|
|
19
24
|
|
|
20
25
|
@docs Type
|
|
@@ -214,7 +219,11 @@ buildNoState definitions builder_ =
|
|
|
214
219
|
}
|
|
215
220
|
|
|
216
221
|
|
|
217
|
-
{-|
|
|
222
|
+
{-| The helpers in this module help you generate a Route module file with the core boilerplate abstracted away.
|
|
223
|
+
|
|
224
|
+
You can also define additional top-level declarations in the generated Route module using this helper.
|
|
225
|
+
|
|
226
|
+
-}
|
|
218
227
|
addDeclarations : List Elm.Declaration -> Builder -> Builder
|
|
219
228
|
addDeclarations declarations builder =
|
|
220
229
|
case builder of
|
package/src/Server/Request.elm
CHANGED
|
@@ -98,6 +98,7 @@ import Internal.Request
|
|
|
98
98
|
import Json.Decode
|
|
99
99
|
import Json.Encode
|
|
100
100
|
import List.NonEmpty
|
|
101
|
+
import Pages.Form
|
|
101
102
|
import QueryParams
|
|
102
103
|
import Time
|
|
103
104
|
import Url
|
|
@@ -891,7 +892,7 @@ runForm validation =
|
|
|
891
892
|
|
|
892
893
|
{-| -}
|
|
893
894
|
formDataWithServerValidation :
|
|
894
|
-
Form.Handler
|
|
895
|
+
Pages.Form.Handler error combined
|
|
895
896
|
-> Parser (BackendTask FatalError (Result (Form.ServerResponse error) ( Form.ServerResponse error, combined )))
|
|
896
897
|
formDataWithServerValidation formParsers =
|
|
897
898
|
rawFormData
|
package/src/Server/Session.elm
CHANGED
|
@@ -318,7 +318,7 @@ encodeSessionUpdate config toRequest userRequestData sessionResult =
|
|
|
318
318
|
(\encoded ->
|
|
319
319
|
response
|
|
320
320
|
|> Server.Response.withSetCookieHeader
|
|
321
|
-
(SetCookie.setCookie config.name encoded (config.options |> Maybe.withDefault SetCookie.
|
|
321
|
+
(SetCookie.setCookie config.name encoded (config.options |> Maybe.withDefault SetCookie.options))
|
|
322
322
|
)
|
|
323
323
|
(sign config.secrets
|
|
324
324
|
(encodeNonExpiringPairs sessionUpdate)
|
package/src/Server/SetCookie.elm
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module Server.SetCookie exposing
|
|
2
|
-
( SetCookie
|
|
3
|
-
,
|
|
4
|
-
,
|
|
5
|
-
, withImmediateExpiration, makeVisibleToJavaScript, nonSecure,
|
|
2
|
+
( SetCookie, setCookie
|
|
3
|
+
, Options, options
|
|
4
|
+
, SameSite(..), withSameSite
|
|
5
|
+
, withImmediateExpiration, makeVisibleToJavaScript, nonSecure, withDomain, withExpiration, withMaxAge, withPath, withoutPath
|
|
6
6
|
, toString
|
|
7
7
|
)
|
|
8
8
|
|
|
@@ -20,16 +20,29 @@ You can learn more about the basics of cookies in the Web Platform in these help
|
|
|
20
20
|
- <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie>
|
|
21
21
|
- <https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies>
|
|
22
22
|
|
|
23
|
-
@docs SetCookie
|
|
23
|
+
@docs SetCookie, setCookie
|
|
24
24
|
|
|
25
|
-
@docs SameSite
|
|
26
25
|
|
|
26
|
+
## Building Options
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Usually you'll want to start by creating default `Options` with `options` and then overriding defaults using the `with...` helpers.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
import Server.SetCookie as SetCookie
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
options : SetCookie.Options
|
|
33
|
+
options =
|
|
34
|
+
SetCookie.options
|
|
35
|
+
|> SetCookie.nonSecure
|
|
36
|
+
|> SetCookie.withMaxAge 123
|
|
37
|
+
|> SetCookie.makeVisibleToJavaScript
|
|
38
|
+
|> SetCookie.withoutPath
|
|
39
|
+
|> SetCookie.setCookie "id" "a3fWa"
|
|
40
|
+
|
|
41
|
+
@docs Options, options
|
|
42
|
+
|
|
43
|
+
@docs SameSite, withSameSite
|
|
44
|
+
|
|
45
|
+
@docs withImmediateExpiration, makeVisibleToJavaScript, nonSecure, withDomain, withExpiration, withMaxAge, withPath, withoutPath
|
|
33
46
|
|
|
34
47
|
|
|
35
48
|
## Internal
|
|
@@ -51,7 +64,8 @@ type alias SetCookie =
|
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
|
|
54
|
-
{-|
|
|
67
|
+
{-| The set of possible configuration options. You can configure this record directly, or use the `with...` helpers.
|
|
68
|
+
-}
|
|
55
69
|
type alias Options =
|
|
56
70
|
{ expiration : Maybe Time.Posix
|
|
57
71
|
, visibleToJavaScript : Bool
|
|
@@ -63,7 +77,15 @@ type alias Options =
|
|
|
63
77
|
}
|
|
64
78
|
|
|
65
79
|
|
|
66
|
-
{-| -
|
|
80
|
+
{-| Possible values for [the cookie's same-site value](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value).
|
|
81
|
+
|
|
82
|
+
The default option is [`Lax`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#lax) (Lax does not send
|
|
83
|
+
cookies in cross-origin requests so it is a good default for most cases, but [`Strict`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#strict)
|
|
84
|
+
is even more restrictive).
|
|
85
|
+
|
|
86
|
+
Override the default option using [`withSameSite`](#withSameSite).
|
|
87
|
+
|
|
88
|
+
-}
|
|
67
89
|
type SameSite
|
|
68
90
|
= Strict
|
|
69
91
|
| Lax
|
|
@@ -95,24 +117,24 @@ toString builder =
|
|
|
95
117
|
else
|
|
96
118
|
""
|
|
97
119
|
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
options_ : Options
|
|
121
|
+
options_ =
|
|
100
122
|
builder.options
|
|
101
123
|
|
|
102
124
|
httpOnly : Bool
|
|
103
125
|
httpOnly =
|
|
104
|
-
not
|
|
126
|
+
not options_.visibleToJavaScript
|
|
105
127
|
in
|
|
106
128
|
builder.name
|
|
107
129
|
++ "="
|
|
108
130
|
++ Url.percentEncode builder.value
|
|
109
|
-
++ option "Expires" (
|
|
110
|
-
++ option "Max-Age" (
|
|
111
|
-
++ option "Path"
|
|
112
|
-
++ option "Domain"
|
|
113
|
-
++ option "SameSite" (
|
|
131
|
+
++ option "Expires" (options_.expiration |> Maybe.map Utc.fromTime)
|
|
132
|
+
++ option "Max-Age" (options_.maxAge |> Maybe.map String.fromInt)
|
|
133
|
+
++ option "Path" options_.path
|
|
134
|
+
++ option "Domain" options_.domain
|
|
135
|
+
++ option "SameSite" (options_.sameSite |> Maybe.map sameSiteToString)
|
|
114
136
|
++ boolOption "HttpOnly" httpOnly
|
|
115
|
-
++ boolOption "Secure"
|
|
137
|
+
++ boolOption "Secure" options_.secure
|
|
116
138
|
|
|
117
139
|
|
|
118
140
|
sameSiteToString : SameSite -> String
|
|
@@ -128,18 +150,22 @@ sameSiteToString sameSite =
|
|
|
128
150
|
"None"
|
|
129
151
|
|
|
130
152
|
|
|
131
|
-
{-| -
|
|
153
|
+
{-| Create a `SetCookie` record with the given name, value, and [`Options`](Options]. To add a `Set-Cookie` header, you can
|
|
154
|
+
pass this value with [`Server.Response.withSetCookieHeader`](Server-Response#withSetCookieHeader). Or for more low-level
|
|
155
|
+
uses you can stringify the value manually with [`toString`](#toString).
|
|
156
|
+
-}
|
|
132
157
|
setCookie : String -> String -> Options -> SetCookie
|
|
133
|
-
setCookie name value
|
|
158
|
+
setCookie name value options_ =
|
|
134
159
|
{ name = name
|
|
135
160
|
, value = value
|
|
136
|
-
, options =
|
|
161
|
+
, options = options_
|
|
137
162
|
}
|
|
138
163
|
|
|
139
164
|
|
|
140
|
-
{-|
|
|
141
|
-
|
|
142
|
-
|
|
165
|
+
{-| Initialize the default `SetCookie` `Options`. Can be configured directly through a record update, or with `withExpiration`, etc.
|
|
166
|
+
-}
|
|
167
|
+
options : Options
|
|
168
|
+
options =
|
|
143
169
|
{ expiration = Nothing
|
|
144
170
|
, visibleToJavaScript = False
|
|
145
171
|
, maxAge = Nothing
|
|
@@ -158,7 +184,9 @@ withExpiration time builder =
|
|
|
158
184
|
}
|
|
159
185
|
|
|
160
186
|
|
|
161
|
-
{-| -
|
|
187
|
+
{-| Sets [`Expires`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#expiresdate) to `Time.millisToPosix 0`,
|
|
188
|
+
which effectively tells the browser to delete the cookie immediately (by giving it an expiration date in the past).
|
|
189
|
+
-}
|
|
162
190
|
withImmediateExpiration : Options -> Options
|
|
163
191
|
withImmediateExpiration builder =
|
|
164
192
|
{ builder
|
|
@@ -184,7 +212,8 @@ makeVisibleToJavaScript builder =
|
|
|
184
212
|
}
|
|
185
213
|
|
|
186
214
|
|
|
187
|
-
{-| -
|
|
215
|
+
{-| Sets the `Set-Cookie`'s [`Max-Age`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#max-agenumber).
|
|
216
|
+
-}
|
|
188
217
|
withMaxAge : Int -> Options -> Options
|
|
189
218
|
withMaxAge maxAge builder =
|
|
190
219
|
{ builder
|
|
@@ -192,7 +221,11 @@ withMaxAge maxAge builder =
|
|
|
192
221
|
}
|
|
193
222
|
|
|
194
223
|
|
|
195
|
-
{-| -
|
|
224
|
+
{-| Sets the `Set-Cookie`'s [`Path`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value).
|
|
225
|
+
|
|
226
|
+
The default value is `/`, which will match any sub-directories or the root directory. See also [\`withoutPath](#withoutPath)
|
|
227
|
+
|
|
228
|
+
-}
|
|
196
229
|
withPath : String -> Options -> Options
|
|
197
230
|
withPath path builder =
|
|
198
231
|
{ builder
|
|
@@ -200,7 +233,13 @@ withPath path builder =
|
|
|
200
233
|
}
|
|
201
234
|
|
|
202
235
|
|
|
203
|
-
{-|
|
|
236
|
+
{-|
|
|
237
|
+
|
|
238
|
+
> If the server omits the Path attribute, the user agent will use the "directory" of the request-uri's path component as the default value.
|
|
239
|
+
|
|
240
|
+
Source: <https://www.rfc-editor.org/rfc/rfc6265>. See <https://stackoverflow.com/a/43336097>.
|
|
241
|
+
|
|
242
|
+
-}
|
|
204
243
|
withoutPath : Options -> Options
|
|
205
244
|
withoutPath builder =
|
|
206
245
|
{ builder
|
|
@@ -208,7 +247,8 @@ withoutPath builder =
|
|
|
208
247
|
}
|
|
209
248
|
|
|
210
249
|
|
|
211
|
-
{-| -
|
|
250
|
+
{-| Sets the `Set-Cookie`'s [`Domain`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#domaindomain-value).
|
|
251
|
+
-}
|
|
212
252
|
withDomain : String -> Options -> Options
|
|
213
253
|
withDomain domain builder =
|
|
214
254
|
{ builder
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
module
|
|
2
|
-
(
|
|
1
|
+
module UrlPath exposing
|
|
2
|
+
( UrlPath, join, fromString
|
|
3
3
|
, toAbsolute, toRelative, toSegments
|
|
4
4
|
)
|
|
5
5
|
|
|
@@ -9,27 +9,27 @@ This helper lets you combine together path parts without worrying about having t
|
|
|
9
9
|
These two examples will result in the same URL, even though the first example has trailing and leading slashes, and the
|
|
10
10
|
second does not.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|>
|
|
12
|
+
UrlPath.join [ "/blog/", "/post-1/" ]
|
|
13
|
+
|> UrlPath.toAbsolute
|
|
14
14
|
--> "/blog/post-1"
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|>
|
|
16
|
+
UrlPath.join [ "blog", "post-1" ]
|
|
17
|
+
|> UrlPath.toAbsolute
|
|
18
18
|
--> "/blog/post-1"
|
|
19
19
|
|
|
20
20
|
We can also safely join Strings that include multiple path parts, a single path part per string, or a mix of the two:
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|>
|
|
22
|
+
UrlPath.join [ "/articles/archive/", "1977", "06", "10", "post-1" ]
|
|
23
|
+
|> UrlPath.toAbsolute
|
|
24
24
|
--> "/articles/archive/1977/06/10/post-1"
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
## Creating
|
|
27
|
+
## Creating UrlPaths
|
|
28
28
|
|
|
29
|
-
@docs
|
|
29
|
+
@docs UrlPath, join, fromString
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
## Turning
|
|
32
|
+
## Turning UrlPaths to String
|
|
33
33
|
|
|
34
34
|
@docs toAbsolute, toRelative, toSegments
|
|
35
35
|
|
|
@@ -40,35 +40,35 @@ import Pages.Internal.String exposing (chopEnd, chopStart)
|
|
|
40
40
|
|
|
41
41
|
{-| The path portion of the URL, normalized to ensure that path segments are joined with `/`s in the right places (no doubled up or missing slashes).
|
|
42
42
|
-}
|
|
43
|
-
type alias
|
|
43
|
+
type alias UrlPath =
|
|
44
44
|
List String
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
{-| Turn a Path to a relative URL.
|
|
48
48
|
-}
|
|
49
|
-
join :
|
|
49
|
+
join : UrlPath -> UrlPath
|
|
50
50
|
join parts =
|
|
51
51
|
parts
|
|
52
52
|
|> List.filter (\segment -> segment /= "/")
|
|
53
53
|
|> List.map normalize
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
{-| Turn a
|
|
56
|
+
{-| Turn a UrlPath to a relative URL.
|
|
57
57
|
-}
|
|
58
|
-
toRelative :
|
|
58
|
+
toRelative : UrlPath -> String
|
|
59
59
|
toRelative parts =
|
|
60
60
|
join parts
|
|
61
61
|
|> String.join "/"
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
{-| Create a
|
|
64
|
+
{-| Create a UrlPath from a path String.
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|>
|
|
66
|
+
UrlPath.fromString "blog/post-1/"
|
|
67
|
+
|> UrlPath.toAbsolute
|
|
68
68
|
|> Expect.equal "/blog/post-1"
|
|
69
69
|
|
|
70
70
|
-}
|
|
71
|
-
fromString : String ->
|
|
71
|
+
fromString : String -> UrlPath
|
|
72
72
|
fromString path =
|
|
73
73
|
path
|
|
74
74
|
|> toSegments
|
|
@@ -80,9 +80,9 @@ toSegments path =
|
|
|
80
80
|
path |> String.split "/" |> List.filter ((/=) "")
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
{-| Turn a
|
|
83
|
+
{-| Turn a UrlPath to an absolute URL (with no trailing slash).
|
|
84
84
|
-}
|
|
85
|
-
toAbsolute :
|
|
85
|
+
toAbsolute : UrlPath -> String
|
|
86
86
|
toAbsolute path =
|
|
87
87
|
"/" ++ toRelative path
|
|
88
88
|
|
package/src/Pages/Transition.elm
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
module Pages.Transition exposing
|
|
2
|
-
( Transition(..), LoadingState(..), map, FormData
|
|
3
|
-
, FetcherState, FetcherSubmitStatus(..)
|
|
4
|
-
)
|
|
5
|
-
|
|
6
|
-
{-|
|
|
7
|
-
|
|
8
|
-
@docs Transition, LoadingState, map, FormData
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Fetchers
|
|
12
|
-
|
|
13
|
-
@docs FetcherState, FetcherSubmitStatus
|
|
14
|
-
|
|
15
|
-
-}
|
|
16
|
-
|
|
17
|
-
import Form
|
|
18
|
-
import Path exposing (Path)
|
|
19
|
-
import Time
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
{-| -}
|
|
23
|
-
type alias FormData =
|
|
24
|
-
{ fields : List ( String, String )
|
|
25
|
-
, method : Form.Method
|
|
26
|
-
, action : String
|
|
27
|
-
, id : Maybe String
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{-| -}
|
|
32
|
-
type Transition
|
|
33
|
-
= Submitting FormData
|
|
34
|
-
| LoadAfterSubmit FormData Path LoadingState
|
|
35
|
-
| Loading Path LoadingState
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{-| -}
|
|
39
|
-
type LoadingState
|
|
40
|
-
= Redirecting
|
|
41
|
-
| Load
|
|
42
|
-
| ActionRedirect
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
{-| -}
|
|
46
|
-
type alias FetcherState actionData =
|
|
47
|
-
{ status : FetcherSubmitStatus actionData
|
|
48
|
-
, payload : FormData
|
|
49
|
-
, initiatedAt : Time.Posix
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{-| -}
|
|
54
|
-
type FetcherSubmitStatus actionData
|
|
55
|
-
= FetcherSubmitting
|
|
56
|
-
| FetcherReloading actionData
|
|
57
|
-
| FetcherComplete actionData
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
{-| -}
|
|
61
|
-
map : (a -> b) -> FetcherState a -> FetcherState b
|
|
62
|
-
map mapFn fetcherState =
|
|
63
|
-
{ status = mapStatus mapFn fetcherState.status
|
|
64
|
-
, payload = fetcherState.payload
|
|
65
|
-
, initiatedAt = fetcherState.initiatedAt
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
mapStatus : (a -> b) -> FetcherSubmitStatus a -> FetcherSubmitStatus b
|
|
70
|
-
mapStatus mapFn fetcherSubmitStatus =
|
|
71
|
-
case fetcherSubmitStatus of
|
|
72
|
-
FetcherSubmitting ->
|
|
73
|
-
FetcherSubmitting
|
|
74
|
-
|
|
75
|
-
FetcherReloading value ->
|
|
76
|
-
FetcherReloading (mapFn value)
|
|
77
|
-
|
|
78
|
-
FetcherComplete value ->
|
|
79
|
-
FetcherComplete (mapFn value)
|