elm-pages 3.0.0-beta.3 → 3.0.0-beta.31
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 +10 -1
- package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2864 -2589
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
- 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/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16458 -13724
- 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 +4 -4
- package/generator/dead-code-review/elm.json +9 -7
- package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
- package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
- 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/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +24542 -21748
- 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 +4 -4
- package/generator/review/elm.json +10 -10
- package/generator/src/RouteBuilder.elm +113 -107
- package/generator/src/SharedTemplate.elm +3 -2
- package/generator/src/SiteConfig.elm +3 -2
- package/generator/src/basepath-middleware.js +3 -3
- package/generator/src/build.js +125 -88
- package/generator/src/cli.js +273 -88
- package/generator/src/codegen.js +29 -27
- package/generator/src/compatibility-key.js +3 -0
- package/generator/src/compile-elm.js +43 -26
- package/generator/src/config.js +39 -0
- package/generator/src/copy-dir.js +2 -2
- package/generator/src/dev-server.js +150 -133
- package/generator/src/dir-helpers.js +9 -26
- package/generator/src/elm-codegen.js +5 -4
- package/generator/src/elm-file-constants.js +2 -3
- package/generator/src/error-formatter.js +12 -11
- package/generator/src/file-helpers.js +3 -4
- package/generator/src/generate-template-module-connector.js +23 -22
- package/generator/src/init.js +9 -8
- package/generator/src/pre-render-html.js +39 -28
- package/generator/src/render-test.js +109 -0
- package/generator/src/render-worker.js +25 -28
- package/generator/src/render.js +320 -142
- package/generator/src/request-cache.js +252 -163
- package/generator/src/resolve-elm-module.js +63 -0
- package/generator/src/rewrite-client-elm-json.js +6 -5
- package/generator/src/rewrite-elm-json-help.js +56 -0
- package/generator/src/rewrite-elm-json.js +17 -7
- package/generator/src/route-codegen-helpers.js +16 -31
- package/generator/src/seo-renderer.js +12 -7
- package/generator/src/vite-utils.js +77 -0
- package/generator/static-code/hmr.js +79 -13
- package/generator/template/app/Api.elm +6 -5
- package/generator/template/app/Effect.elm +123 -0
- package/generator/template/app/ErrorPage.elm +37 -6
- package/generator/template/app/Route/Index.elm +17 -10
- package/generator/template/app/Shared.elm +24 -47
- package/generator/template/app/Site.elm +19 -6
- package/generator/template/app/View.elm +1 -8
- package/generator/template/elm-tooling.json +0 -3
- package/generator/template/elm.json +32 -24
- package/generator/template/package.json +10 -4
- package/package.json +29 -27
- package/src/ApiRoute.elm +199 -61
- package/src/BackendTask/Custom.elm +325 -0
- package/src/BackendTask/Env.elm +90 -0
- package/src/{DataSource → BackendTask}/File.elm +128 -43
- package/src/{DataSource → BackendTask}/Glob.elm +136 -125
- package/src/BackendTask/Http.elm +673 -0
- package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
- package/src/BackendTask/Internal/Request.elm +28 -0
- package/src/BackendTask/Random.elm +79 -0
- package/src/BackendTask/Time.elm +47 -0
- package/src/BackendTask.elm +537 -0
- package/src/FatalError.elm +89 -0
- package/src/Form/Field.elm +21 -9
- package/src/Form/FieldView.elm +94 -14
- package/src/Form.elm +275 -400
- package/src/Head.elm +237 -7
- package/src/HtmlPrinter.elm +7 -3
- package/src/Internal/ApiRoute.elm +7 -5
- package/src/PageServerResponse.elm +6 -1
- package/src/Pages/FormState.elm +6 -5
- package/src/Pages/GeneratorProgramConfig.elm +15 -0
- package/src/Pages/Internal/FatalError.elm +5 -0
- package/src/Pages/Internal/Form.elm +21 -1
- package/src/Pages/{Msg.elm → Internal/Msg.elm} +26 -16
- package/src/Pages/Internal/Platform/Cli.elm +598 -763
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
- package/src/Pages/Internal/Platform/Effect.elm +1 -2
- package/src/Pages/Internal/Platform/GeneratorApplication.elm +373 -0
- package/src/Pages/Internal/Platform/StaticResponses.elm +73 -270
- package/src/Pages/Internal/Platform/ToJsPayload.elm +4 -7
- package/src/Pages/Internal/Platform.elm +216 -102
- package/src/Pages/Internal/Script.elm +17 -0
- package/src/Pages/Internal/StaticHttpBody.elm +35 -1
- package/src/Pages/Manifest.elm +29 -4
- package/src/Pages/PageUrl.elm +23 -9
- package/src/Pages/ProgramConfig.elm +14 -10
- package/src/Pages/Script.elm +109 -0
- package/src/Pages/SiteConfig.elm +3 -2
- package/src/Pages/StaticHttp/Request.elm +2 -2
- package/src/Pages/StaticHttpRequest.elm +23 -98
- package/src/PagesMsg.elm +92 -0
- package/src/Path.elm +16 -19
- package/src/QueryParams.elm +21 -172
- package/src/RequestsAndPending.elm +8 -19
- package/src/Result/Extra.elm +26 -0
- package/src/Scaffold/Form.elm +560 -0
- package/src/Scaffold/Route.elm +1388 -0
- package/src/Server/Request.elm +43 -37
- package/src/Server/Session.elm +62 -42
- package/src/Server/SetCookie.elm +12 -4
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
- package/src/DataSource/Env.elm +0 -38
- package/src/DataSource/Http.elm +0 -446
- package/src/DataSource/Internal/Request.elm +0 -20
- package/src/DataSource/Port.elm +0 -90
- package/src/DataSource.elm +0 -538
- package/src/Pages/Generate.elm +0 -800
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module BackendTask.Glob exposing
|
|
2
2
|
( Glob
|
|
3
3
|
, capture, match
|
|
4
4
|
, captureFilePath
|
|
@@ -9,8 +9,8 @@ module DataSource.Glob exposing
|
|
|
9
9
|
, map, succeed
|
|
10
10
|
, oneOf
|
|
11
11
|
, zeroOrMore, atLeastOne
|
|
12
|
-
,
|
|
13
|
-
,
|
|
12
|
+
, toBackendTask
|
|
13
|
+
, toBackendTaskWithOptions
|
|
14
14
|
, defaultOptions, Options, Include(..)
|
|
15
15
|
)
|
|
16
16
|
|
|
@@ -18,23 +18,23 @@ module DataSource.Glob exposing
|
|
|
18
18
|
|
|
19
19
|
@docs Glob
|
|
20
20
|
|
|
21
|
-
This module helps you get a List of matching file paths from your local file system as a [`
|
|
22
|
-
for ways you can combine and map `
|
|
21
|
+
This module helps you get a List of matching file paths from your local file system as a [`BackendTask`](BackendTask#BackendTask). See the [`BackendTask`](BackendTask) module documentation
|
|
22
|
+
for ways you can combine and map `BackendTask`s.
|
|
23
23
|
|
|
24
24
|
A common example would be to find all the markdown files of your blog posts. If you have all your blog posts in `content/blog/*.md`
|
|
25
25
|
, then you could use that glob pattern in most shells to refer to each of those files.
|
|
26
26
|
|
|
27
|
-
With the `
|
|
27
|
+
With the `BackendTask.Glob` API, you could get all of those files like so:
|
|
28
28
|
|
|
29
|
-
import
|
|
29
|
+
import BackendTask exposing (BackendTask)
|
|
30
30
|
|
|
31
|
-
blogPostsGlob :
|
|
31
|
+
blogPostsGlob : BackendTask (List String)
|
|
32
32
|
blogPostsGlob =
|
|
33
33
|
Glob.succeed (\slug -> slug)
|
|
34
34
|
|> Glob.match (Glob.literal "content/blog/")
|
|
35
35
|
|> Glob.capture Glob.wildcard
|
|
36
36
|
|> Glob.match (Glob.literal ".md")
|
|
37
|
-
|> Glob.
|
|
37
|
+
|> Glob.toBackendTask
|
|
38
38
|
|
|
39
39
|
Let's say you have these files locally:
|
|
40
40
|
|
|
@@ -47,11 +47,11 @@ Let's say you have these files locally:
|
|
|
47
47
|
- second-post.md
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
We would end up with a `
|
|
50
|
+
We would end up with a `BackendTask` like this:
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
BackendTask.succeed [ "first-post", "second-post" ]
|
|
53
53
|
|
|
54
|
-
Of course, if you add or remove matching files, the
|
|
54
|
+
Of course, if you add or remove matching files, the BackendTask will get those new files (unlike `BackendTask.succeed`). That's why we have Glob!
|
|
55
55
|
|
|
56
56
|
You can even see the `elm-pages dev` server will automatically flow through any added/removed matching files with its hot module reloading.
|
|
57
57
|
|
|
@@ -66,10 +66,10 @@ There are two functions for building up a Glob pattern: `capture` and `match`.
|
|
|
66
66
|
`capture` and `match` both build up a `Glob` pattern that will match 0 or more files on your local file system.
|
|
67
67
|
There will be one argument for every `capture` in your pipeline, whereas `match` does not apply any arguments.
|
|
68
68
|
|
|
69
|
-
import
|
|
70
|
-
import
|
|
69
|
+
import BackendTask exposing (BackendTask)
|
|
70
|
+
import BackendTask.Glob as Glob
|
|
71
71
|
|
|
72
|
-
blogPostsGlob :
|
|
72
|
+
blogPostsGlob : BackendTask (List String)
|
|
73
73
|
blogPostsGlob =
|
|
74
74
|
Glob.succeed (\slug -> slug)
|
|
75
75
|
-- no argument from this, but we will only
|
|
@@ -81,7 +81,7 @@ There will be one argument for every `capture` in your pipeline, whereas `match`
|
|
|
81
81
|
-- no argument from this, but we will only
|
|
82
82
|
-- match files that end with `.md`
|
|
83
83
|
|> Glob.match (Glob.literal ".md")
|
|
84
|
-
|> Glob.
|
|
84
|
+
|> Glob.toBackendTask
|
|
85
85
|
|
|
86
86
|
So to understand _which_ files will match, you can ignore whether you are using `capture` or `match` and just read
|
|
87
87
|
the patterns you're using in order to understand what will match. To understand what Elm data type you will get
|
|
@@ -94,10 +94,10 @@ used in the function you use in `Glob.succeed`.
|
|
|
94
94
|
|
|
95
95
|
Let's try our blogPostsGlob from before, but change every `match` to `capture`.
|
|
96
96
|
|
|
97
|
-
import
|
|
97
|
+
import BackendTask exposing (BackendTask)
|
|
98
98
|
|
|
99
99
|
blogPostsGlob :
|
|
100
|
-
|
|
100
|
+
BackendTask
|
|
101
101
|
(List
|
|
102
102
|
{ filePath : String
|
|
103
103
|
, slug : String
|
|
@@ -113,15 +113,15 @@ Let's try our blogPostsGlob from before, but change every `match` to `capture`.
|
|
|
113
113
|
|> Glob.capture (Glob.literal "content/blog/")
|
|
114
114
|
|> Glob.capture Glob.wildcard
|
|
115
115
|
|> Glob.capture (Glob.literal ".md")
|
|
116
|
-
|> Glob.
|
|
116
|
+
|> Glob.toBackendTask
|
|
117
117
|
|
|
118
118
|
Notice that we now need 3 arguments at the start of our pipeline instead of 1. That's because
|
|
119
119
|
we apply 1 more argument every time we do a `Glob.capture`, much like `Json.Decode.Pipeline.required`, or other pipeline APIs.
|
|
120
120
|
|
|
121
121
|
Now we actually have the full file path of our files. But having that slug (like `first-post`) is also very helpful sometimes, so
|
|
122
|
-
we kept that in our record as well. So we'll now have the equivalent of this `
|
|
122
|
+
we kept that in our record as well. So we'll now have the equivalent of this `BackendTask` with the current `.md` files in our `blog` folder:
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
BackendTask.succeed
|
|
125
125
|
[ { filePath = "content/blog/first-post.md"
|
|
126
126
|
, slug = "first-post"
|
|
127
127
|
}
|
|
@@ -152,23 +152,23 @@ title: My First Post
|
|
|
152
152
|
This is my first post!
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
Then we could read that title for our blog post list page using our `blogPosts` `
|
|
155
|
+
Then we could read that title for our blog post list page using our `blogPosts` `BackendTask` that we defined above.
|
|
156
156
|
|
|
157
|
-
import
|
|
157
|
+
import BackendTask.File
|
|
158
158
|
import Json.Decode as Decode exposing (Decoder)
|
|
159
159
|
|
|
160
|
-
titles :
|
|
160
|
+
titles : BackendTask (List BlogPost)
|
|
161
161
|
titles =
|
|
162
162
|
blogPosts
|
|
163
|
-
|>
|
|
163
|
+
|> BackendTask.map
|
|
164
164
|
(List.map
|
|
165
165
|
(\blogPost ->
|
|
166
|
-
|
|
166
|
+
BackendTask.File.request
|
|
167
167
|
blogPost.filePath
|
|
168
|
-
(
|
|
168
|
+
(BackendTask.File.frontmatter blogFrontmatterDecoder)
|
|
169
169
|
)
|
|
170
170
|
)
|
|
171
|
-
|>
|
|
171
|
+
|> BackendTask.resolve
|
|
172
172
|
|
|
173
173
|
type alias BlogPost =
|
|
174
174
|
{ title : String }
|
|
@@ -180,7 +180,7 @@ Then we could read that title for our blog post list page using our `blogPosts`
|
|
|
180
180
|
|
|
181
181
|
That will give us
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
BackendTask.succeed
|
|
184
184
|
[ { title = "My First Post" }
|
|
185
185
|
, { title = "My Second Post" }
|
|
186
186
|
]
|
|
@@ -212,23 +212,24 @@ That will give us
|
|
|
212
212
|
@docs zeroOrMore, atLeastOne
|
|
213
213
|
|
|
214
214
|
|
|
215
|
-
## Getting Glob Data from a
|
|
215
|
+
## Getting Glob Data from a BackendTask
|
|
216
216
|
|
|
217
|
-
@docs
|
|
217
|
+
@docs toBackendTask
|
|
218
218
|
|
|
219
219
|
|
|
220
220
|
### With Custom Options
|
|
221
221
|
|
|
222
|
-
@docs
|
|
222
|
+
@docs toBackendTaskWithOptions
|
|
223
223
|
|
|
224
224
|
@docs defaultOptions, Options, Include
|
|
225
225
|
|
|
226
226
|
-}
|
|
227
227
|
|
|
228
|
-
import
|
|
229
|
-
import
|
|
230
|
-
import
|
|
231
|
-
import
|
|
228
|
+
import BackendTask exposing (BackendTask)
|
|
229
|
+
import BackendTask.Http
|
|
230
|
+
import BackendTask.Internal.Glob exposing (Glob(..))
|
|
231
|
+
import BackendTask.Internal.Request
|
|
232
|
+
import FatalError exposing (FatalError)
|
|
232
233
|
import Json.Decode as Decode
|
|
233
234
|
import Json.Encode as Encode
|
|
234
235
|
import List.Extra
|
|
@@ -237,7 +238,7 @@ import List.Extra
|
|
|
237
238
|
{-| A pattern to match local files and capture parts of the path into a nice Elm data type.
|
|
238
239
|
-}
|
|
239
240
|
type alias Glob a =
|
|
240
|
-
|
|
241
|
+
BackendTask.Internal.Glob.Glob a
|
|
241
242
|
|
|
242
243
|
|
|
243
244
|
{-| A `Glob` can be mapped. This can be useful for transforming a sub-match in-place.
|
|
@@ -245,26 +246,26 @@ type alias Glob a =
|
|
|
245
246
|
For example, if you wanted to take the slugs for a blog post and make sure they are normalized to be all lowercase, you
|
|
246
247
|
could use
|
|
247
248
|
|
|
248
|
-
import
|
|
249
|
-
import
|
|
249
|
+
import BackendTask exposing (BackendTask)
|
|
250
|
+
import BackendTask.Glob as Glob
|
|
250
251
|
|
|
251
|
-
blogPostsGlob :
|
|
252
|
+
blogPostsGlob : BackendTask (List String)
|
|
252
253
|
blogPostsGlob =
|
|
253
254
|
Glob.succeed (\slug -> slug)
|
|
254
255
|
|> Glob.match (Glob.literal "content/blog/")
|
|
255
256
|
|> Glob.capture (Glob.wildcard |> Glob.map String.toLower)
|
|
256
257
|
|> Glob.match (Glob.literal ".md")
|
|
257
|
-
|> Glob.
|
|
258
|
+
|> Glob.toBackendTask
|
|
258
259
|
|
|
259
|
-
If you want to validate file formats, you can combine that with some `
|
|
260
|
-
a `
|
|
260
|
+
If you want to validate file formats, you can combine that with some `BackendTask` helpers to turn a `Glob (Result String value)` into
|
|
261
|
+
a `BackendTask (List value)`.
|
|
261
262
|
|
|
262
263
|
For example, you could take a date and parse it.
|
|
263
264
|
|
|
264
|
-
import
|
|
265
|
-
import
|
|
265
|
+
import BackendTask exposing (BackendTask)
|
|
266
|
+
import BackendTask.Glob as Glob
|
|
266
267
|
|
|
267
|
-
example :
|
|
268
|
+
example : BackendTask (List ( String, String ))
|
|
268
269
|
example =
|
|
269
270
|
Glob.succeed
|
|
270
271
|
(\dateResult slug ->
|
|
@@ -276,9 +277,9 @@ For example, you could take a date and parse it.
|
|
|
276
277
|
|> Glob.match (Glob.literal "/")
|
|
277
278
|
|> Glob.capture Glob.wildcard
|
|
278
279
|
|> Glob.match (Glob.literal ".md")
|
|
279
|
-
|> Glob.
|
|
280
|
-
|>
|
|
281
|
-
|>
|
|
280
|
+
|> Glob.toBackendTask
|
|
281
|
+
|> BackendTask.map (List.map BackendTask.fromResult)
|
|
282
|
+
|> BackendTask.resolve
|
|
282
283
|
|
|
283
284
|
expectDateFormat : List String -> Result String String
|
|
284
285
|
expectDateFormat dateParts =
|
|
@@ -317,11 +318,11 @@ fullFilePath =
|
|
|
317
318
|
|
|
318
319
|
{-|
|
|
319
320
|
|
|
320
|
-
import
|
|
321
|
-
import
|
|
321
|
+
import BackendTask exposing (BackendTask)
|
|
322
|
+
import BackendTask.Glob as Glob
|
|
322
323
|
|
|
323
324
|
blogPosts :
|
|
324
|
-
|
|
325
|
+
BackendTask
|
|
325
326
|
(List
|
|
326
327
|
{ filePath : String
|
|
327
328
|
, slug : String
|
|
@@ -338,7 +339,7 @@ fullFilePath =
|
|
|
338
339
|
|> Glob.match (Glob.literal "content/blog/")
|
|
339
340
|
|> Glob.capture Glob.wildcard
|
|
340
341
|
|> Glob.match (Glob.literal ".md")
|
|
341
|
-
|> Glob.
|
|
342
|
+
|> Glob.toBackendTask
|
|
342
343
|
|
|
343
344
|
This function does not change which files will or will not match. It just gives you the full matching
|
|
344
345
|
file path in your `Glob` pipeline.
|
|
@@ -357,8 +358,8 @@ where you can run commands like `rm client/*.js` to remove all `.js` files in th
|
|
|
357
358
|
Just like a `*` glob pattern in bash, this `Glob.wildcard` function will only match within a path part. If you need to
|
|
358
359
|
match 0 or more path parts like, see `recursiveWildcard`.
|
|
359
360
|
|
|
360
|
-
import
|
|
361
|
-
import
|
|
361
|
+
import BackendTask exposing (BackendTask)
|
|
362
|
+
import BackendTask.Glob as Glob
|
|
362
363
|
|
|
363
364
|
type alias BlogPost =
|
|
364
365
|
{ year : String
|
|
@@ -367,7 +368,7 @@ match 0 or more path parts like, see `recursiveWildcard`.
|
|
|
367
368
|
, slug : String
|
|
368
369
|
}
|
|
369
370
|
|
|
370
|
-
example :
|
|
371
|
+
example : BackendTask (List BlogPost)
|
|
371
372
|
example =
|
|
372
373
|
Glob.succeed BlogPost
|
|
373
374
|
|> Glob.match (Glob.literal "blog/")
|
|
@@ -379,7 +380,7 @@ match 0 or more path parts like, see `recursiveWildcard`.
|
|
|
379
380
|
|> Glob.match (Glob.literal "/")
|
|
380
381
|
|> Glob.capture Glob.wildcard
|
|
381
382
|
|> Glob.match (Glob.literal ".md")
|
|
382
|
-
|> Glob.
|
|
383
|
+
|> Glob.toBackendTask
|
|
383
384
|
|
|
384
385
|
```shell
|
|
385
386
|
|
|
@@ -390,9 +391,9 @@ match 0 or more path parts like, see `recursiveWildcard`.
|
|
|
390
391
|
|
|
391
392
|
That will match to:
|
|
392
393
|
|
|
393
|
-
results :
|
|
394
|
+
results : BackendTask (List BlogPost)
|
|
394
395
|
results =
|
|
395
|
-
|
|
396
|
+
BackendTask.succeed
|
|
396
397
|
[ { year = "2021"
|
|
397
398
|
, month = "05"
|
|
398
399
|
, day = "27"
|
|
@@ -439,16 +440,16 @@ digits =
|
|
|
439
440
|
|
|
440
441
|
Leading 0's are ignored.
|
|
441
442
|
|
|
442
|
-
import
|
|
443
|
-
import
|
|
443
|
+
import BackendTask exposing (BackendTask)
|
|
444
|
+
import BackendTask.Glob as Glob
|
|
444
445
|
|
|
445
|
-
slides :
|
|
446
|
+
slides : BackendTask (List Int)
|
|
446
447
|
slides =
|
|
447
448
|
Glob.succeed identity
|
|
448
449
|
|> Glob.match (Glob.literal "slide-")
|
|
449
450
|
|> Glob.capture Glob.int
|
|
450
451
|
|> Glob.match (Glob.literal ".md")
|
|
451
|
-
|> Glob.
|
|
452
|
+
|> Glob.toBackendTask
|
|
452
453
|
|
|
453
454
|
With files
|
|
454
455
|
|
|
@@ -471,9 +472,9 @@ With files
|
|
|
471
472
|
|
|
472
473
|
Yields
|
|
473
474
|
|
|
474
|
-
matches :
|
|
475
|
+
matches : BackendTask (List Int)
|
|
475
476
|
matches =
|
|
476
|
-
|
|
477
|
+
BackendTask.succeed
|
|
477
478
|
[ 1
|
|
478
479
|
, 1
|
|
479
480
|
, 2
|
|
@@ -509,10 +510,10 @@ In contrast, `wildcard` will never match `/`, so it only matches within a single
|
|
|
509
510
|
|
|
510
511
|
This is the elm-pages equivalent of `**/*.txt` in standard shell syntax:
|
|
511
512
|
|
|
512
|
-
import
|
|
513
|
-
import
|
|
513
|
+
import BackendTask exposing (BackendTask)
|
|
514
|
+
import BackendTask.Glob as Glob
|
|
514
515
|
|
|
515
|
-
example :
|
|
516
|
+
example : BackendTask (List ( List String, String ))
|
|
516
517
|
example =
|
|
517
518
|
Glob.succeed Tuple.pair
|
|
518
519
|
|> Glob.match (Glob.literal "articles/")
|
|
@@ -520,7 +521,7 @@ This is the elm-pages equivalent of `**/*.txt` in standard shell syntax:
|
|
|
520
521
|
|> Glob.match (Glob.literal "/")
|
|
521
522
|
|> Glob.capture Glob.wildcard
|
|
522
523
|
|> Glob.match (Glob.literal ".txt")
|
|
523
|
-
|> Glob.
|
|
524
|
+
|> Glob.toBackendTask
|
|
524
525
|
|
|
525
526
|
With these files:
|
|
526
527
|
|
|
@@ -536,9 +537,9 @@ With these files:
|
|
|
536
537
|
|
|
537
538
|
We would get the following matches:
|
|
538
539
|
|
|
539
|
-
matches :
|
|
540
|
+
matches : BackendTask (List ( List String, String ))
|
|
540
541
|
matches =
|
|
541
|
-
|
|
542
|
+
BackendTask.succeed
|
|
542
543
|
[ ( [ "archive", "1977", "06", "10" ], "apple-2-announced" )
|
|
543
544
|
, ( [], "google-io-2021-recap" )
|
|
544
545
|
]
|
|
@@ -551,16 +552,16 @@ And also note that it matches 0 path parts into an empty list.
|
|
|
551
552
|
If we didn't include the `wildcard` after the `recursiveWildcard`, then we would only get
|
|
552
553
|
a single level of matches because it is followed by a file extension.
|
|
553
554
|
|
|
554
|
-
example :
|
|
555
|
+
example : BackendTask (List String)
|
|
555
556
|
example =
|
|
556
557
|
Glob.succeed identity
|
|
557
558
|
|> Glob.match (Glob.literal "articles/")
|
|
558
559
|
|> Glob.capture Glob.recursiveWildcard
|
|
559
560
|
|> Glob.match (Glob.literal ".txt")
|
|
560
561
|
|
|
561
|
-
matches :
|
|
562
|
+
matches : BackendTask (List String)
|
|
562
563
|
matches =
|
|
563
|
-
|
|
564
|
+
BackendTask.succeed
|
|
564
565
|
[ "google-io-2021-recap"
|
|
565
566
|
]
|
|
566
567
|
|
|
@@ -615,8 +616,8 @@ Some common uses include
|
|
|
615
616
|
- In-between wildcards, to say "these dynamic parts are separated by `/`"
|
|
616
617
|
|
|
617
618
|
```elm
|
|
618
|
-
import
|
|
619
|
-
import
|
|
619
|
+
import BackendTask exposing (BackendTask)
|
|
620
|
+
import BackendTask.Glob as Glob
|
|
620
621
|
|
|
621
622
|
blogPosts =
|
|
622
623
|
Glob.succeed
|
|
@@ -676,7 +677,7 @@ Exactly the same as `match` except it also captures the matched sub-pattern.
|
|
|
676
677
|
, slug : String
|
|
677
678
|
}
|
|
678
679
|
|
|
679
|
-
archives :
|
|
680
|
+
archives : BackendTask ArchivesArticle
|
|
680
681
|
archives =
|
|
681
682
|
Glob.succeed ArchivesArticle
|
|
682
683
|
|> Glob.match (Glob.literal "archive/")
|
|
@@ -688,13 +689,13 @@ Exactly the same as `match` except it also captures the matched sub-pattern.
|
|
|
688
689
|
|> Glob.match (Glob.literal "/")
|
|
689
690
|
|> Glob.capture Glob.wildcard
|
|
690
691
|
|> Glob.match (Glob.literal ".md")
|
|
691
|
-
|> Glob.
|
|
692
|
+
|> Glob.toBackendTask
|
|
692
693
|
|
|
693
694
|
The file `archive/1977/06/10/apple-2-released.md` will give us this match:
|
|
694
695
|
|
|
695
696
|
matches : List ArchivesArticle
|
|
696
697
|
matches =
|
|
697
|
-
|
|
698
|
+
BackendTask.succeed
|
|
698
699
|
[ { year = 1977
|
|
699
700
|
, month = 6
|
|
700
701
|
, day = 10
|
|
@@ -732,7 +733,7 @@ capture (Glob matcherPattern apply1) (Glob pattern apply2) =
|
|
|
732
733
|
|
|
733
734
|
{-|
|
|
734
735
|
|
|
735
|
-
import
|
|
736
|
+
import BackendTask.Glob as Glob
|
|
736
737
|
|
|
737
738
|
type Extension
|
|
738
739
|
= Json
|
|
@@ -743,7 +744,7 @@ capture (Glob matcherPattern apply1) (Glob pattern apply2) =
|
|
|
743
744
|
, extension : String
|
|
744
745
|
}
|
|
745
746
|
|
|
746
|
-
dataFiles :
|
|
747
|
+
dataFiles : BackendTask (List DataFile)
|
|
747
748
|
dataFiles =
|
|
748
749
|
Glob.succeed DataFile
|
|
749
750
|
|> Glob.match (Glob.literal "my-data/")
|
|
@@ -767,9 +768,9 @@ If we have the following files
|
|
|
767
768
|
|
|
768
769
|
That gives us
|
|
769
770
|
|
|
770
|
-
results :
|
|
771
|
+
results : BackendTask (List DataFile)
|
|
771
772
|
results =
|
|
772
|
-
|
|
773
|
+
BackendTask.succeed
|
|
773
774
|
[ { name = "authors"
|
|
774
775
|
, extension = Yml
|
|
775
776
|
}
|
|
@@ -780,7 +781,7 @@ That gives us
|
|
|
780
781
|
|
|
781
782
|
You could also match an optional file path segment using `oneOf`.
|
|
782
783
|
|
|
783
|
-
rootFilesMd :
|
|
784
|
+
rootFilesMd : BackendTask (List String)
|
|
784
785
|
rootFilesMd =
|
|
785
786
|
Glob.succeed (\slug -> slug)
|
|
786
787
|
|> Glob.match (Glob.literal "blog/")
|
|
@@ -792,7 +793,7 @@ You could also match an optional file path segment using `oneOf`.
|
|
|
792
793
|
)
|
|
793
794
|
)
|
|
794
795
|
|> Glob.match (Glob.literal ".md")
|
|
795
|
-
|> Glob.
|
|
796
|
+
|> Glob.toBackendTask
|
|
796
797
|
|
|
797
798
|
With these files:
|
|
798
799
|
|
|
@@ -805,9 +806,9 @@ With these files:
|
|
|
805
806
|
|
|
806
807
|
This would give us:
|
|
807
808
|
|
|
808
|
-
results :
|
|
809
|
+
results : BackendTask (List String)
|
|
809
810
|
results =
|
|
810
|
-
|
|
811
|
+
BackendTask.succeed
|
|
811
812
|
[ "first-post"
|
|
812
813
|
, "second-post"
|
|
813
814
|
]
|
|
@@ -874,7 +875,7 @@ atLeastOne ( defaultMatch, otherMatchers ) =
|
|
|
874
875
|
-- |> Maybe.withDefault (defaultMatch |> Tuple.second)
|
|
875
876
|
-- , []
|
|
876
877
|
-- )
|
|
877
|
-
|
|
878
|
+
BackendTask.Internal.Glob.extractMatches (defaultMatch |> Tuple.second) allMatchers match_
|
|
878
879
|
|> toNonEmptyWithDefault (defaultMatch |> Tuple.second)
|
|
879
880
|
, rest
|
|
880
881
|
)
|
|
@@ -894,11 +895,11 @@ toNonEmptyWithDefault default list =
|
|
|
894
895
|
( default, [] )
|
|
895
896
|
|
|
896
897
|
|
|
897
|
-
{-| In order to get match data from your glob, turn it into a `
|
|
898
|
+
{-| In order to get match data from your glob, turn it into a `BackendTask` with this function.
|
|
898
899
|
-}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
900
|
+
toBackendTask : Glob a -> BackendTask error (List a)
|
|
901
|
+
toBackendTask glob =
|
|
902
|
+
toBackendTaskWithOptions defaultOptions glob
|
|
902
903
|
|
|
903
904
|
|
|
904
905
|
{-| <https://github.com/mrmlnc/fast-glob#onlyfiles>
|
|
@@ -912,7 +913,7 @@ type Include
|
|
|
912
913
|
| FilesAndFolders
|
|
913
914
|
|
|
914
915
|
|
|
915
|
-
{-| Custom options you can pass in to run the glob with [`
|
|
916
|
+
{-| Custom options you can pass in to run the glob with [`toBackendTaskWithOptions`](#toBackendTaskWithOptions).
|
|
916
917
|
|
|
917
918
|
{ includeDotFiles = Bool -- https://github.com/mrmlnc/fast-glob#dot
|
|
918
919
|
, include = Include -- return results that are `OnlyFiles`, `OnlyFolders`, or both `FilesAndFolders` (default is `OnlyFiles`)
|
|
@@ -933,7 +934,7 @@ type alias Options =
|
|
|
933
934
|
}
|
|
934
935
|
|
|
935
936
|
|
|
936
|
-
{-| The default options used in [`
|
|
937
|
+
{-| The default options used in [`toBackendTask`](#toBackendTask). To use a custom set of options, use [`toBackendTaskWithOptions`](#toBackendTaskWithOptions).
|
|
937
938
|
-}
|
|
938
939
|
defaultOptions : Options
|
|
939
940
|
defaultOptions =
|
|
@@ -960,26 +961,26 @@ encodeOptions options =
|
|
|
960
961
|
|> Encode.object
|
|
961
962
|
|
|
962
963
|
|
|
963
|
-
{-| Same as
|
|
964
|
+
{-| Same as toBackendTask, but lets you set custom glob options. For example, to list folders instead of files,
|
|
964
965
|
|
|
965
|
-
import
|
|
966
|
+
import BackendTask.Glob as Glob exposing (OnlyFolders, defaultOptions)
|
|
966
967
|
|
|
967
|
-
matchingFiles : Glob a ->
|
|
968
|
+
matchingFiles : Glob a -> BackendTask (List a)
|
|
968
969
|
matchingFiles glob =
|
|
969
970
|
glob
|
|
970
|
-
|> Glob.
|
|
971
|
+
|> Glob.toBackendTaskWithOptions { defaultOptions | include = OnlyFolders }
|
|
971
972
|
|
|
972
973
|
-}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
974
|
+
toBackendTaskWithOptions : Options -> Glob a -> BackendTask error (List a)
|
|
975
|
+
toBackendTaskWithOptions options glob =
|
|
976
|
+
BackendTask.Internal.Request.request
|
|
976
977
|
{ name = "glob"
|
|
977
978
|
, body =
|
|
978
979
|
Encode.object
|
|
979
|
-
[ ( "pattern", Encode.string <|
|
|
980
|
+
[ ( "pattern", Encode.string <| BackendTask.Internal.Glob.toPattern glob )
|
|
980
981
|
, ( "options", encodeOptions options )
|
|
981
982
|
]
|
|
982
|
-
|>
|
|
983
|
+
|> BackendTask.Http.jsonBody
|
|
983
984
|
, expect =
|
|
984
985
|
Decode.map2 (\fullPath captures -> { fullPath = fullPath, captures = captures })
|
|
985
986
|
(Decode.field "fullPath" Decode.string)
|
|
@@ -990,24 +991,26 @@ toDataSourceWithOptions options glob =
|
|
|
990
991
|
rawGlob
|
|
991
992
|
|> List.map
|
|
992
993
|
(\{ fullPath, captures } ->
|
|
993
|
-
|
|
994
|
+
BackendTask.Internal.Glob.run fullPath captures glob
|
|
994
995
|
|> .match
|
|
995
996
|
)
|
|
996
997
|
)
|
|
997
|
-
|>
|
|
998
|
+
|> BackendTask.Http.expectJson
|
|
998
999
|
}
|
|
1000
|
+
|> BackendTask.onError
|
|
1001
|
+
(\_ -> BackendTask.succeed [])
|
|
999
1002
|
|
|
1000
1003
|
|
|
1001
1004
|
{-| Sometimes you want to make sure there is a unique file matching a particular pattern.
|
|
1002
|
-
This is a simple helper that will give you a `
|
|
1005
|
+
This is a simple helper that will give you a `BackendTask` error if there isn't exactly 1 matching file.
|
|
1003
1006
|
If there is exactly 1, then you successfully get back that single match.
|
|
1004
1007
|
|
|
1005
1008
|
For example, maybe you can have
|
|
1006
1009
|
|
|
1007
|
-
import
|
|
1008
|
-
import
|
|
1010
|
+
import BackendTask exposing (BackendTask)
|
|
1011
|
+
import BackendTask.Glob as Glob
|
|
1009
1012
|
|
|
1010
|
-
findBlogBySlug : String ->
|
|
1013
|
+
findBlogBySlug : String -> BackendTask String
|
|
1011
1014
|
findBlogBySlug slug =
|
|
1012
1015
|
Glob.succeed identity
|
|
1013
1016
|
|> Glob.captureFilePath
|
|
@@ -1032,9 +1035,9 @@ If we used `findBlogBySlug "first-post"` with these files:
|
|
|
1032
1035
|
|
|
1033
1036
|
This would give us:
|
|
1034
1037
|
|
|
1035
|
-
results :
|
|
1038
|
+
results : BackendTask String
|
|
1036
1039
|
results =
|
|
1037
|
-
|
|
1040
|
+
BackendTask.succeed "blog/first-post/index.md"
|
|
1038
1041
|
|
|
1039
1042
|
If we used `findBlogBySlug "first-post"` with these files:
|
|
1040
1043
|
|
|
@@ -1045,47 +1048,55 @@ If we used `findBlogBySlug "first-post"` with these files:
|
|
|
1045
1048
|
- index.md
|
|
1046
1049
|
```
|
|
1047
1050
|
|
|
1048
|
-
Then we will get a `
|
|
1051
|
+
Then we will get a `BackendTask` error saying `More than one file matched.` Keep in mind that `BackendTask` failures
|
|
1049
1052
|
in build-time routes will cause a build failure, giving you the opportunity to fix the problem before users see the issue,
|
|
1050
1053
|
so it's ideal to make this kind of assertion rather than having fallback behavior that could silently cover up
|
|
1051
1054
|
issues (like if we had instead ignored the case where there are two or more matching blog post files).
|
|
1052
1055
|
|
|
1053
1056
|
-}
|
|
1054
|
-
expectUniqueMatch :
|
|
1057
|
+
expectUniqueMatch :
|
|
1058
|
+
Glob a
|
|
1059
|
+
-> BackendTask { fatal : FatalError, recoverable : String } a
|
|
1055
1060
|
expectUniqueMatch glob =
|
|
1056
1061
|
glob
|
|
1057
|
-
|>
|
|
1058
|
-
|>
|
|
1062
|
+
|> toBackendTask
|
|
1063
|
+
|> BackendTask.andThen
|
|
1059
1064
|
(\matchingFiles ->
|
|
1060
1065
|
case matchingFiles of
|
|
1061
1066
|
[ file ] ->
|
|
1062
|
-
|
|
1067
|
+
BackendTask.succeed file
|
|
1063
1068
|
|
|
1064
1069
|
[] ->
|
|
1065
|
-
|
|
1070
|
+
BackendTask.fail <|
|
|
1071
|
+
FatalError.recoverable
|
|
1072
|
+
{ title = "Non-Unique Glob", body = "No files matched the pattern: " ++ toPatternString glob }
|
|
1073
|
+
("No files matched the pattern: " ++ toPatternString glob)
|
|
1066
1074
|
|
|
1067
1075
|
_ ->
|
|
1068
|
-
|
|
1076
|
+
BackendTask.fail <|
|
|
1077
|
+
FatalError.recoverable
|
|
1078
|
+
{ title = "Non-Unique Glob", body = "Expected a unique match, but more than one file matched." }
|
|
1079
|
+
"More than one file matched."
|
|
1069
1080
|
)
|
|
1070
1081
|
|
|
1071
1082
|
|
|
1072
1083
|
{-| -}
|
|
1073
|
-
expectUniqueMatchFromList : List (Glob a) ->
|
|
1084
|
+
expectUniqueMatchFromList : List (Glob a) -> BackendTask String a
|
|
1074
1085
|
expectUniqueMatchFromList globs =
|
|
1075
1086
|
globs
|
|
1076
|
-
|> List.map
|
|
1077
|
-
|>
|
|
1078
|
-
|>
|
|
1087
|
+
|> List.map toBackendTask
|
|
1088
|
+
|> BackendTask.combine
|
|
1089
|
+
|> BackendTask.andThen
|
|
1079
1090
|
(\matchingFiles ->
|
|
1080
1091
|
case List.concat matchingFiles of
|
|
1081
1092
|
[ file ] ->
|
|
1082
|
-
|
|
1093
|
+
BackendTask.succeed file
|
|
1083
1094
|
|
|
1084
1095
|
[] ->
|
|
1085
|
-
|
|
1096
|
+
BackendTask.fail <| "No files matched the patterns: " ++ (globs |> List.map toPatternString |> String.join ", ")
|
|
1086
1097
|
|
|
1087
1098
|
_ ->
|
|
1088
|
-
|
|
1099
|
+
BackendTask.fail "More than one file matched."
|
|
1089
1100
|
)
|
|
1090
1101
|
|
|
1091
1102
|
|