elm-pages 2.1.10 → 3.0.0-beta.0
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/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/Pages-Review-NoContractViolationsTest.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.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/{template/public/style.css → review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +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 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
- package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
- package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
- package/generator/review/elm.json +13 -4
- package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
- package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
- package/generator/src/RouteBuilder.elm +420 -0
- package/generator/src/SharedTemplate.elm +4 -5
- package/generator/src/SiteConfig.elm +3 -9
- package/generator/src/build.js +308 -95
- package/generator/src/cli.js +103 -8
- package/generator/src/codegen.js +192 -35
- package/generator/src/compile-elm.js +183 -31
- package/generator/src/dev-server.js +353 -96
- package/generator/src/elm-application.json +3 -1
- package/generator/src/elm-codegen.js +34 -0
- package/generator/src/elm-file-constants.js +2 -0
- package/generator/src/error-formatter.js +20 -1
- package/generator/src/generate-template-module-connector.js +120 -924
- package/generator/src/hello.ts +5 -0
- package/generator/src/pre-render-html.js +58 -104
- package/generator/src/render-worker.js +27 -13
- package/generator/src/render.js +252 -197
- package/generator/src/request-cache-fs.js +18 -0
- package/generator/src/request-cache.js +128 -56
- package/generator/src/rewrite-client-elm-json.js +49 -0
- package/generator/src/route-codegen-helpers.js +62 -1
- package/generator/static-code/dev-style.css +22 -0
- package/generator/static-code/elm-pages.js +43 -39
- package/generator/static-code/hmr.js +98 -88
- package/generator/template/app/Api.elm +25 -0
- package/generator/template/app/ErrorPage.elm +38 -0
- package/generator/template/app/Route/Index.elm +87 -0
- package/generator/template/{src → app}/Shared.elm +34 -13
- package/generator/template/app/Site.elm +19 -0
- package/generator/template/{src → app}/View.elm +0 -0
- package/generator/template/elm-pages.config.mjs +5 -0
- package/generator/template/elm.json +14 -5
- package/generator/template/{public/index.js → index.ts} +7 -3
- package/generator/template/package.json +5 -5
- package/generator/template/public/favicon.ico +0 -0
- package/generator/template/public/images/icon-png.png +0 -0
- package/generator/template/src/.gitkeep +0 -0
- package/generator/template/style.css +4 -0
- package/package.json +30 -23
- package/src/ApiRoute.elm +176 -43
- package/src/BuildError.elm +10 -1
- package/src/CookieParser.elm +84 -0
- package/src/DataSource/Env.elm +38 -0
- package/src/DataSource/File.elm +27 -16
- package/src/DataSource/Glob.elm +126 -80
- package/src/DataSource/Http.elm +283 -304
- package/src/DataSource/Internal/Glob.elm +5 -21
- package/src/DataSource/Internal/Request.elm +25 -0
- package/src/DataSource/Port.elm +17 -14
- package/src/DataSource.elm +55 -318
- package/src/Form/Field.elm +717 -0
- package/src/Form/FieldStatus.elm +36 -0
- package/src/Form/FieldView.elm +417 -0
- package/src/Form/FormData.elm +22 -0
- package/src/Form/Validation.elm +391 -0
- package/src/Form/Value.elm +118 -0
- package/src/Form.elm +1683 -0
- package/src/FormData.elm +58 -0
- package/src/FormDecoder.elm +102 -0
- package/src/Head/Seo.elm +12 -4
- package/src/Head.elm +12 -2
- package/src/HtmlPrinter.elm +1 -1
- package/src/Internal/ApiRoute.elm +17 -4
- package/src/Internal/Request.elm +7 -0
- package/src/PageServerResponse.elm +68 -0
- package/src/Pages/ContentCache.elm +1 -229
- package/src/Pages/Fetcher.elm +58 -0
- package/src/Pages/FormState.elm +256 -0
- package/src/Pages/Generate.elm +800 -0
- package/src/Pages/Internal/Form.elm +17 -0
- package/src/Pages/Internal/NotFoundReason.elm +3 -55
- package/src/Pages/Internal/Platform/Cli.elm +777 -579
- package/src/Pages/Internal/Platform/Effect.elm +5 -5
- package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
- package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
- package/src/Pages/Internal/Platform.elm +1244 -504
- package/src/Pages/Internal/ResponseSketch.elm +19 -0
- package/src/Pages/Internal/RoutePattern.elm +596 -45
- package/src/Pages/Manifest.elm +26 -0
- package/src/Pages/Msg.elm +79 -0
- package/src/Pages/ProgramConfig.elm +67 -14
- package/src/Pages/SiteConfig.elm +3 -6
- package/src/Pages/StaticHttp/Request.elm +4 -2
- package/src/Pages/StaticHttpRequest.elm +50 -215
- package/src/Pages/Transition.elm +70 -0
- package/src/Path.elm +1 -0
- package/src/Pattern.elm +98 -0
- package/src/RenderRequest.elm +2 -2
- package/src/RequestsAndPending.elm +111 -9
- package/src/Server/Request.elm +1253 -0
- package/src/Server/Response.elm +292 -0
- package/src/Server/Session.elm +316 -0
- package/src/Server/SetCookie.elm +169 -0
- package/src/TerminalText.elm +1 -1
- package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
- package/generator/src/Page.elm +0 -359
- package/generator/src/codegen-template-module.js +0 -183
- package/generator/src/elm-pages-js-minified.js +0 -1
- package/generator/template/src/Api.elm +0 -14
- package/generator/template/src/Page/Index.elm +0 -69
- package/generator/template/src/Site.elm +0 -41
- package/src/DataSource/ServerRequest.elm +0 -60
- package/src/Internal/OptimizedDecoder.elm +0 -18
- package/src/KeepOrDiscard.elm +0 -6
- package/src/OptimizedDecoder/Pipeline.elm +0 -335
- package/src/OptimizedDecoder.elm +0 -818
- package/src/Pages/Internal/ApplicationType.elm +0 -6
- package/src/Pages/Secrets.elm +0 -83
- package/src/Secrets.elm +0 -111
- package/src/SecretsDict.elm +0 -45
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elm-pages",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
4
|
"homepage": "https://elm-pages.com",
|
|
5
5
|
"moduleResolution": "node",
|
|
6
6
|
"description": "Type-safe static sites, written in pure elm with your own custom elm-markup syntax.",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"start": "cd examples/end-to-end && npm
|
|
10
|
-
"test": "
|
|
11
|
-
"test:snapshot": "(cd examples/escaping && npm install && npm test
|
|
12
|
-
"cypress": "npm start & cypress run
|
|
9
|
+
"start": "cd examples/end-to-end && npm i && npx elm-pages dev",
|
|
10
|
+
"test": "./test.sh",
|
|
11
|
+
"test:snapshot": "(cd examples/escaping && npm install && npm test) && (cd examples/base-path && npm install && npm test)",
|
|
12
|
+
"cypress": "npm start & cypress run",
|
|
13
|
+
"prepare": "elm-codegen install",
|
|
13
14
|
"review": "elm-review"
|
|
14
15
|
},
|
|
15
16
|
"repository": "https://github.com/dillonkearns/elm-pages",
|
|
@@ -23,40 +24,46 @@
|
|
|
23
24
|
"author": "Dillon Kearns",
|
|
24
25
|
"license": "BSD-3-Clause",
|
|
25
26
|
"dependencies": {
|
|
26
|
-
"
|
|
27
|
-
"
|
|
27
|
+
"busboy": "^1.0.0",
|
|
28
|
+
"chokidar": "^3.5.3",
|
|
29
|
+
"commander": "^9.4.0",
|
|
28
30
|
"connect": "^3.7.0",
|
|
31
|
+
"cookie-signature": "^1.1.0",
|
|
29
32
|
"cross-spawn": "7.0.3",
|
|
30
|
-
"devcert": "^1.2.
|
|
33
|
+
"devcert": "^1.2.2",
|
|
31
34
|
"elm-doc-preview": "^5.0.5",
|
|
32
35
|
"elm-hot": "^1.1.6",
|
|
33
|
-
"
|
|
36
|
+
"esbuild": "^0.15.5",
|
|
37
|
+
"fs-extra": "^10.1.0",
|
|
34
38
|
"globby": "11.0.4",
|
|
35
39
|
"gray-matter": "^4.0.3",
|
|
36
40
|
"jsesc": "^3.0.2",
|
|
37
|
-
"kleur": "^4.1.
|
|
38
|
-
"
|
|
41
|
+
"kleur": "^4.1.5",
|
|
42
|
+
"memfs": "^3.4.7",
|
|
43
|
+
"micromatch": "^4.0.5",
|
|
44
|
+
"node-fetch": "^2.6.7",
|
|
39
45
|
"object-hash": "^2.2.0",
|
|
40
|
-
"serve-static": "^1.
|
|
41
|
-
"terser": "^5.
|
|
42
|
-
"
|
|
46
|
+
"serve-static": "^1.15.0",
|
|
47
|
+
"terser": "^5.14.2",
|
|
48
|
+
"vite": "^3.0.9",
|
|
43
49
|
"which": "^2.0.2"
|
|
44
50
|
},
|
|
45
51
|
"devDependencies": {
|
|
46
52
|
"@types/cross-spawn": "^6.0.2",
|
|
47
|
-
"@types/fs-extra": "9.0.
|
|
53
|
+
"@types/fs-extra": "^9.0.13",
|
|
48
54
|
"@types/micromatch": "^4.0.2",
|
|
49
55
|
"@types/node": "12.20.12",
|
|
50
|
-
"@types/serve-static": "1.
|
|
51
|
-
"cypress": "^
|
|
56
|
+
"@types/serve-static": "^1.15.0",
|
|
57
|
+
"cypress": "^10.6.0",
|
|
58
|
+
"elm-codegen": "^0.2.0",
|
|
52
59
|
"elm-optimize-level-2": "^0.1.5",
|
|
53
|
-
"elm-review": "^2.
|
|
54
|
-
"elm-test": "^0.19.1-
|
|
55
|
-
"elm-tooling": "^1.
|
|
56
|
-
"elm-verify-examples": "^5.
|
|
60
|
+
"elm-review": "^2.7.4",
|
|
61
|
+
"elm-test": "^0.19.1-revision9",
|
|
62
|
+
"elm-tooling": "^1.8.0",
|
|
63
|
+
"elm-verify-examples": "^5.2.0",
|
|
57
64
|
"elmi-to-json": "^1.2.0",
|
|
58
|
-
"mocha": "^
|
|
59
|
-
"typescript": "4.
|
|
65
|
+
"mocha": "^10.0.0",
|
|
66
|
+
"typescript": "^4.7.4"
|
|
60
67
|
},
|
|
61
68
|
"files": [
|
|
62
69
|
"generator/src/",
|
package/src/ApiRoute.elm
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
module ApiRoute exposing
|
|
1
|
+
module ApiRoute exposing
|
|
2
|
+
( ApiRoute, ApiRouteBuilder, Response
|
|
3
|
+
, capture, literal, slash, succeed
|
|
4
|
+
, single, preRender
|
|
5
|
+
, preRenderWithFallback, serverRender
|
|
6
|
+
, withGlobalHeadTags
|
|
7
|
+
, toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
|
|
8
|
+
)
|
|
2
9
|
|
|
3
10
|
{-| ApiRoute's are defined in `src/Api.elm` and are a way to generate files, like RSS feeds, sitemaps, or any text-based file that you output with an Elm function! You get access
|
|
4
11
|
to a DataSource so you can pull in HTTP data, etc. Because ApiRoutes don't hydrate into Elm apps (like pages in elm-pages do), you can pull in as much data as you want in
|
|
@@ -7,13 +14,42 @@ the DataSource for your ApiRoutes, and it won't effect the payload size. Instead
|
|
|
7
14
|
In a future release, ApiRoutes may be able to run at request-time in a serverless function, allowing you to use pure Elm code to create dynamic APIs, and even pulling in data from
|
|
8
15
|
DataSources dynamically.
|
|
9
16
|
|
|
10
|
-
@docs ApiRoute, ApiRouteBuilder, Response
|
|
17
|
+
@docs ApiRoute, ApiRouteBuilder, Response
|
|
18
|
+
|
|
19
|
+
@docs capture, literal, slash, succeed
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Pre-Rendering
|
|
23
|
+
|
|
24
|
+
@docs single, preRender
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Server Rendering
|
|
28
|
+
|
|
29
|
+
@docs preRenderWithFallback, serverRender
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## Including Head Tags
|
|
33
|
+
|
|
34
|
+
@docs withGlobalHeadTags
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Internals
|
|
38
|
+
|
|
39
|
+
@docs toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
|
|
11
40
|
|
|
12
41
|
-}
|
|
13
42
|
|
|
14
43
|
import DataSource exposing (DataSource)
|
|
44
|
+
import DataSource.Http
|
|
45
|
+
import Head
|
|
15
46
|
import Internal.ApiRoute exposing (ApiRoute(..), ApiRouteBuilder(..))
|
|
47
|
+
import Json.Decode as Decode
|
|
48
|
+
import Json.Encode
|
|
49
|
+
import Pattern
|
|
16
50
|
import Regex
|
|
51
|
+
import Server.Request
|
|
52
|
+
import Server.Response
|
|
17
53
|
|
|
18
54
|
|
|
19
55
|
{-| -}
|
|
@@ -22,15 +58,109 @@ type alias ApiRoute response =
|
|
|
22
58
|
|
|
23
59
|
|
|
24
60
|
{-| -}
|
|
25
|
-
single : ApiRouteBuilder (DataSource
|
|
61
|
+
single : ApiRouteBuilder (DataSource String) (List String) -> ApiRoute Response
|
|
26
62
|
single handler =
|
|
27
63
|
handler
|
|
28
|
-
|>
|
|
64
|
+
|> preRender (\constructor -> DataSource.succeed [ constructor ])
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
{-| -}
|
|
68
|
+
serverRender : ApiRouteBuilder (Server.Request.Parser (DataSource (Server.Response.Response Never Never))) constructor -> ApiRoute Response
|
|
69
|
+
serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
|
|
70
|
+
ApiRoute
|
|
71
|
+
{ regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
|
|
72
|
+
, matchesToResponse =
|
|
73
|
+
\path ->
|
|
74
|
+
Internal.ApiRoute.tryMatch path fullHandler
|
|
75
|
+
|> Maybe.map
|
|
76
|
+
(\toDataSource ->
|
|
77
|
+
DataSource.Http.get
|
|
78
|
+
"$$elm-pages$$headers"
|
|
79
|
+
(toDataSource |> Server.Request.getDecoder |> Decode.map Just)
|
|
80
|
+
|> DataSource.andThen
|
|
81
|
+
(\rendered ->
|
|
82
|
+
case rendered of
|
|
83
|
+
Just (Ok okRendered) ->
|
|
84
|
+
okRendered
|
|
85
|
+
|
|
86
|
+
Just (Err errors) ->
|
|
87
|
+
errors
|
|
88
|
+
|> Server.Request.errorsToString
|
|
89
|
+
|> Server.Response.plainText
|
|
90
|
+
|> Server.Response.withStatusCode 400
|
|
91
|
+
|> DataSource.succeed
|
|
92
|
+
|
|
93
|
+
Nothing ->
|
|
94
|
+
Server.Response.plainText "No matching request handler"
|
|
95
|
+
|> Server.Response.withStatusCode 400
|
|
96
|
+
|> DataSource.succeed
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
|> Maybe.map (DataSource.map (Server.Response.toJson >> Just))
|
|
100
|
+
|> Maybe.withDefault
|
|
101
|
+
(DataSource.succeed Nothing)
|
|
102
|
+
, buildTimeRoutes = DataSource.succeed []
|
|
103
|
+
, handleRoute =
|
|
104
|
+
\path ->
|
|
105
|
+
DataSource.succeed
|
|
106
|
+
(case Internal.ApiRoute.tryMatch path fullHandler of
|
|
107
|
+
Just _ ->
|
|
108
|
+
True
|
|
109
|
+
|
|
110
|
+
Nothing ->
|
|
111
|
+
False
|
|
112
|
+
)
|
|
113
|
+
, pattern = patterns
|
|
114
|
+
, kind = "serverless"
|
|
115
|
+
, globalHeadTags = Nothing
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
{-| -}
|
|
120
|
+
preRenderWithFallback : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource (Server.Response.Response Never Never)) constructor -> ApiRoute Response
|
|
121
|
+
preRenderWithFallback buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
|
|
122
|
+
let
|
|
123
|
+
buildTimeRoutes__ : DataSource (List String)
|
|
124
|
+
buildTimeRoutes__ =
|
|
125
|
+
buildUrls (constructor [])
|
|
126
|
+
|> DataSource.map (List.map toString)
|
|
127
|
+
in
|
|
128
|
+
ApiRoute
|
|
129
|
+
{ regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
|
|
130
|
+
, matchesToResponse =
|
|
131
|
+
\path ->
|
|
132
|
+
Internal.ApiRoute.tryMatch path fullHandler
|
|
133
|
+
|> Maybe.map (DataSource.map (Server.Response.toJson >> Just))
|
|
134
|
+
|> Maybe.withDefault
|
|
135
|
+
(DataSource.succeed Nothing)
|
|
136
|
+
, buildTimeRoutes = buildTimeRoutes__
|
|
137
|
+
, handleRoute =
|
|
138
|
+
\path ->
|
|
139
|
+
DataSource.succeed
|
|
140
|
+
(case Internal.ApiRoute.tryMatch path fullHandler of
|
|
141
|
+
Just _ ->
|
|
142
|
+
True
|
|
143
|
+
|
|
144
|
+
Nothing ->
|
|
145
|
+
False
|
|
146
|
+
)
|
|
147
|
+
, pattern = patterns
|
|
148
|
+
, kind = "prerender-with-fallback"
|
|
149
|
+
, globalHeadTags = Nothing
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
encodeStaticFileBody : String -> Response
|
|
154
|
+
encodeStaticFileBody fileBody =
|
|
155
|
+
Json.Encode.object
|
|
156
|
+
[ ( "body", fileBody |> Json.Encode.string )
|
|
157
|
+
, ( "kind", Json.Encode.string "static-file" )
|
|
158
|
+
]
|
|
29
159
|
|
|
30
160
|
|
|
31
161
|
{-| -}
|
|
32
|
-
|
|
33
|
-
|
|
162
|
+
preRender : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource String) constructor -> ApiRoute Response
|
|
163
|
+
preRender buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
|
|
34
164
|
let
|
|
35
165
|
buildTimeRoutes__ : DataSource (List String)
|
|
36
166
|
buildTimeRoutes__ =
|
|
@@ -60,7 +190,7 @@ buildTimeRoutes buildUrls ((ApiRouteBuilder pattern _ toString constructor) as f
|
|
|
60
190
|
(\found ->
|
|
61
191
|
if found then
|
|
62
192
|
Internal.ApiRoute.tryMatch path fullHandler
|
|
63
|
-
|> Maybe.map (DataSource.map Just)
|
|
193
|
+
|> Maybe.map (DataSource.map (encodeStaticFileBody >> Just))
|
|
64
194
|
|> Maybe.withDefault (DataSource.succeed Nothing)
|
|
65
195
|
|
|
66
196
|
else
|
|
@@ -76,6 +206,9 @@ buildTimeRoutes buildUrls ((ApiRouteBuilder pattern _ toString constructor) as f
|
|
|
76
206
|
in
|
|
77
207
|
preBuiltMatches
|
|
78
208
|
|> DataSource.map (List.member matches)
|
|
209
|
+
, pattern = patterns
|
|
210
|
+
, kind = "prerender"
|
|
211
|
+
, globalHeadTags = Nothing
|
|
79
212
|
}
|
|
80
213
|
|
|
81
214
|
|
|
@@ -86,33 +219,49 @@ type alias ApiRouteBuilder a constructor =
|
|
|
86
219
|
|
|
87
220
|
{-| -}
|
|
88
221
|
type alias Response =
|
|
89
|
-
|
|
222
|
+
Json.Encode.Value
|
|
90
223
|
|
|
91
224
|
|
|
92
225
|
{-| -}
|
|
93
226
|
succeed : a -> ApiRouteBuilder a (List String)
|
|
94
227
|
succeed a =
|
|
95
|
-
ApiRouteBuilder "" (\_ -> a) (\_ -> "") (\list -> list)
|
|
228
|
+
ApiRouteBuilder Pattern.empty "" (\_ -> a) (\_ -> "") (\list -> list)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
{-| Turn the route into a pattern in JSON format. For internal uses.
|
|
232
|
+
-}
|
|
233
|
+
toJson : ApiRoute response -> Json.Encode.Value
|
|
234
|
+
toJson ((ApiRoute { kind }) as apiRoute) =
|
|
235
|
+
Json.Encode.object
|
|
236
|
+
[ ( "pathPattern", apiRoute |> Internal.ApiRoute.toPattern |> Pattern.toJson )
|
|
237
|
+
, ( "kind", Json.Encode.string kind )
|
|
238
|
+
]
|
|
96
239
|
|
|
97
240
|
|
|
98
241
|
{-| -}
|
|
99
242
|
literal : String -> ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
|
|
100
|
-
literal segment (ApiRouteBuilder pattern handler toString constructor) =
|
|
101
|
-
ApiRouteBuilder
|
|
243
|
+
literal segment (ApiRouteBuilder patterns pattern handler toString constructor) =
|
|
244
|
+
ApiRouteBuilder
|
|
245
|
+
(Pattern.addLiteral segment patterns)
|
|
246
|
+
(pattern ++ segment)
|
|
247
|
+
handler
|
|
248
|
+
(\values -> toString values ++ segment)
|
|
249
|
+
constructor
|
|
102
250
|
|
|
103
251
|
|
|
104
252
|
{-| -}
|
|
105
253
|
slash : ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
|
|
106
|
-
slash (ApiRouteBuilder pattern handler toString constructor) =
|
|
107
|
-
ApiRouteBuilder (pattern ++ "/") handler (\arg -> toString arg ++ "/") constructor
|
|
254
|
+
slash (ApiRouteBuilder patterns pattern handler toString constructor) =
|
|
255
|
+
ApiRouteBuilder (patterns |> Pattern.addSlash) (pattern ++ "/") handler (\arg -> toString arg ++ "/") constructor
|
|
108
256
|
|
|
109
257
|
|
|
110
258
|
{-| -}
|
|
111
259
|
capture :
|
|
112
260
|
ApiRouteBuilder (String -> a) constructor
|
|
113
261
|
-> ApiRouteBuilder a (String -> constructor)
|
|
114
|
-
capture (ApiRouteBuilder pattern previousHandler toString constructor) =
|
|
262
|
+
capture (ApiRouteBuilder patterns pattern previousHandler toString constructor) =
|
|
115
263
|
ApiRouteBuilder
|
|
264
|
+
(patterns |> Pattern.addCapture)
|
|
116
265
|
(pattern ++ "(.*)")
|
|
117
266
|
(\matches ->
|
|
118
267
|
case matches of
|
|
@@ -136,35 +285,6 @@ capture (ApiRouteBuilder pattern previousHandler toString constructor) =
|
|
|
136
285
|
)
|
|
137
286
|
|
|
138
287
|
|
|
139
|
-
{-| -}
|
|
140
|
-
int :
|
|
141
|
-
ApiRouteBuilder (Int -> a) constructor
|
|
142
|
-
-> ApiRouteBuilder a (Int -> constructor)
|
|
143
|
-
int (ApiRouteBuilder pattern previousHandler toString constructor) =
|
|
144
|
-
ApiRouteBuilder
|
|
145
|
-
(pattern ++ "(\\d+)")
|
|
146
|
-
(\matches ->
|
|
147
|
-
case matches of
|
|
148
|
-
first :: rest ->
|
|
149
|
-
previousHandler rest (String.toInt first |> Maybe.withDefault -1)
|
|
150
|
-
|
|
151
|
-
_ ->
|
|
152
|
-
previousHandler [] -1
|
|
153
|
-
)
|
|
154
|
-
(\s ->
|
|
155
|
-
case s of
|
|
156
|
-
first :: rest ->
|
|
157
|
-
toString rest ++ first
|
|
158
|
-
|
|
159
|
-
_ ->
|
|
160
|
-
""
|
|
161
|
-
)
|
|
162
|
-
(\matches ->
|
|
163
|
-
\string ->
|
|
164
|
-
constructor (String.fromInt string :: matches)
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
|
|
168
288
|
{-| For internal use by generated code. Not so useful in user-land.
|
|
169
289
|
-}
|
|
170
290
|
getBuildTimeRoutes : ApiRoute response -> DataSource (List String)
|
|
@@ -172,6 +292,19 @@ getBuildTimeRoutes (ApiRoute handler) =
|
|
|
172
292
|
handler.buildTimeRoutes
|
|
173
293
|
|
|
174
294
|
|
|
295
|
+
{-| Include head tags on every page's HTML.
|
|
296
|
+
-}
|
|
297
|
+
withGlobalHeadTags : DataSource (List Head.Tag) -> ApiRoute response -> ApiRoute response
|
|
298
|
+
withGlobalHeadTags globalHeadTags (ApiRoute handler) =
|
|
299
|
+
ApiRoute { handler | globalHeadTags = Just globalHeadTags }
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
{-| -}
|
|
303
|
+
getGlobalHeadTagsDataSource : ApiRoute response -> Maybe (DataSource (List Head.Tag))
|
|
304
|
+
getGlobalHeadTagsDataSource (ApiRoute handler) =
|
|
305
|
+
handler.globalHeadTags
|
|
306
|
+
|
|
307
|
+
|
|
175
308
|
|
|
176
309
|
--captureRest : ApiRouteBuilder (List String -> a) b -> ApiRouteBuilder a b
|
|
177
310
|
--captureRest previousHandler =
|
package/src/BuildError.elm
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module BuildError exposing (BuildError, encode, errorToString, errorsToString)
|
|
1
|
+
module BuildError exposing (BuildError, encode, errorToString, errorsToString, internal)
|
|
2
2
|
|
|
3
3
|
import Json.Encode as Encode
|
|
4
4
|
import TerminalText as Terminal
|
|
@@ -12,6 +12,15 @@ type alias BuildError =
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
internal : String -> { title : String, path : String, message : List Terminal.Text, fatal : Bool }
|
|
16
|
+
internal string =
|
|
17
|
+
{ title = "Internal Error"
|
|
18
|
+
, path = ""
|
|
19
|
+
, message = [ Terminal.text string ]
|
|
20
|
+
, fatal = True
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
15
24
|
errorsToString : List BuildError -> String
|
|
16
25
|
errorsToString errors =
|
|
17
26
|
errors
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module CookieParser exposing (parse)
|
|
2
|
+
|
|
3
|
+
import Dict exposing (Dict)
|
|
4
|
+
import Parser exposing ((|.), (|=), Parser, Step(..))
|
|
5
|
+
import Url
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
parse : String -> Dict String String
|
|
9
|
+
parse input =
|
|
10
|
+
Parser.run parser input
|
|
11
|
+
|> Result.withDefault Dict.empty
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
parser : Parser (Dict String String)
|
|
15
|
+
parser =
|
|
16
|
+
Parser.loop [] keyValuePair
|
|
17
|
+
|> Parser.map Dict.fromList
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
keyValuePair : List ( String, String ) -> Parser (Step (List ( String, String )) (List ( String, String )))
|
|
21
|
+
keyValuePair revChunks =
|
|
22
|
+
Parser.oneOf
|
|
23
|
+
[ Parser.end
|
|
24
|
+
|> Parser.map (\_ -> Done (List.reverse revChunks))
|
|
25
|
+
, Parser.succeed (Loop revChunks)
|
|
26
|
+
|. Parser.chompIf isSpace
|
|
27
|
+
|. Parser.chompWhile isSpace
|
|
28
|
+
, Parser.succeed Tuple.pair
|
|
29
|
+
|= parseKey
|
|
30
|
+
|= Parser.oneOf
|
|
31
|
+
[ Parser.succeed Nothing
|
|
32
|
+
|. Parser.token ";"
|
|
33
|
+
, Parser.succeed Just
|
|
34
|
+
|. Parser.token "="
|
|
35
|
+
|= valueParser
|
|
36
|
+
|. Parser.oneOf
|
|
37
|
+
[ Parser.token ";"
|
|
38
|
+
, Parser.succeed ()
|
|
39
|
+
]
|
|
40
|
+
]
|
|
41
|
+
|> Parser.andThen
|
|
42
|
+
(\( key, maybeValue ) ->
|
|
43
|
+
case maybeValue of
|
|
44
|
+
Just value ->
|
|
45
|
+
Parser.succeed (Loop (( key, value ) :: revChunks))
|
|
46
|
+
|
|
47
|
+
Nothing ->
|
|
48
|
+
Parser.succeed (Loop revChunks)
|
|
49
|
+
)
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
valueParser : Parser String
|
|
54
|
+
valueParser =
|
|
55
|
+
Parser.succeed identity
|
|
56
|
+
|. Parser.chompWhile isSpace
|
|
57
|
+
|= Parser.oneOf
|
|
58
|
+
[ Parser.succeed ""
|
|
59
|
+
|. Parser.token ";"
|
|
60
|
+
, Parser.succeed identity
|
|
61
|
+
|. Parser.token "\""
|
|
62
|
+
|= (Parser.chompUntil "\""
|
|
63
|
+
|> Parser.getChompedString
|
|
64
|
+
)
|
|
65
|
+
|. Parser.token "\""
|
|
66
|
+
, Parser.chompWhile (\c -> c /= ';')
|
|
67
|
+
|> Parser.getChompedString
|
|
68
|
+
]
|
|
69
|
+
|> Parser.map String.trim
|
|
70
|
+
|> Parser.map (\value -> value |> Url.percentDecode |> Maybe.withDefault "")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
parseKey : Parser String
|
|
74
|
+
parseKey =
|
|
75
|
+
Parser.succeed identity
|
|
76
|
+
|= (Parser.chompWhile (\c -> c /= '=' && c /= ';')
|
|
77
|
+
|> Parser.getChompedString
|
|
78
|
+
|> Parser.map String.trim
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
isSpace : Char -> Bool
|
|
83
|
+
isSpace c =
|
|
84
|
+
c == ' '
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module DataSource.Env exposing (get, expect)
|
|
2
|
+
|
|
3
|
+
{-|
|
|
4
|
+
|
|
5
|
+
@docs get, expect
|
|
6
|
+
|
|
7
|
+
-}
|
|
8
|
+
|
|
9
|
+
import DataSource exposing (DataSource)
|
|
10
|
+
import DataSource.Http
|
|
11
|
+
import DataSource.Internal.Request
|
|
12
|
+
import Json.Decode as Decode
|
|
13
|
+
import Json.Encode as Encode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
{-| -}
|
|
17
|
+
get : String -> DataSource (Maybe String)
|
|
18
|
+
get envVariableName =
|
|
19
|
+
DataSource.Internal.Request.request
|
|
20
|
+
{ name = "env"
|
|
21
|
+
, body = DataSource.Http.jsonBody (Encode.string envVariableName)
|
|
22
|
+
, expect =
|
|
23
|
+
DataSource.Http.expectJson
|
|
24
|
+
(Decode.nullable Decode.string)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
{-| -}
|
|
29
|
+
expect : String -> DataSource String
|
|
30
|
+
expect envVariableName =
|
|
31
|
+
envVariableName
|
|
32
|
+
|> get
|
|
33
|
+
|> DataSource.andThen
|
|
34
|
+
(\maybeValue ->
|
|
35
|
+
maybeValue
|
|
36
|
+
|> Result.fromMaybe ("DataSource.Env.expect was expecting a variable `" ++ envVariableName ++ "` but couldn't find a variable with that name.")
|
|
37
|
+
|> DataSource.fromResult
|
|
38
|
+
)
|
package/src/DataSource/File.elm
CHANGED
|
@@ -30,7 +30,7 @@ The frontmatter is in the [YAML format](https://en.wikipedia.org/wiki/YAML) here
|
|
|
30
30
|
Hey there! This is my first post :)
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Whether it's YAML or JSON, you use an `
|
|
33
|
+
Whether it's YAML or JSON, you use an `Decode` to decode your frontmatter, so it feels just like using
|
|
34
34
|
plain old JSON in Elm.
|
|
35
35
|
|
|
36
36
|
@docs bodyWithFrontmatter, bodyWithoutFrontmatter, onlyFrontmatter
|
|
@@ -44,20 +44,20 @@ plain old JSON in Elm.
|
|
|
44
44
|
|
|
45
45
|
import DataSource exposing (DataSource)
|
|
46
46
|
import DataSource.Http
|
|
47
|
-
import
|
|
48
|
-
import
|
|
47
|
+
import DataSource.Internal.Request
|
|
48
|
+
import Json.Decode as Decode exposing (Decoder)
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
frontmatter : Decoder frontmatter -> Decoder frontmatter
|
|
52
52
|
frontmatter frontmatterDecoder =
|
|
53
|
-
|
|
53
|
+
Decode.field "parsedFrontmatter" frontmatterDecoder
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
{-|
|
|
57
57
|
|
|
58
58
|
import DataSource exposing (DataSource)
|
|
59
59
|
import DataSource.File as File
|
|
60
|
-
import
|
|
60
|
+
import Decode as Decode exposing (Decoder)
|
|
61
61
|
|
|
62
62
|
blogPost : DataSource BlogPostMetadata
|
|
63
63
|
blogPost =
|
|
@@ -93,8 +93,8 @@ It's common to parse the body with a markdown parser or other format.
|
|
|
93
93
|
|
|
94
94
|
import DataSource exposing (DataSource)
|
|
95
95
|
import DataSource.File as File
|
|
96
|
+
import Decode as Decode exposing (Decoder)
|
|
96
97
|
import Html exposing (Html)
|
|
97
|
-
import OptimizedDecoder as Decode exposing (Decoder)
|
|
98
98
|
|
|
99
99
|
example :
|
|
100
100
|
DataSource
|
|
@@ -137,7 +137,7 @@ bodyWithFrontmatter : (String -> Decoder frontmatter) -> String -> DataSource fr
|
|
|
137
137
|
bodyWithFrontmatter frontmatterDecoder filePath =
|
|
138
138
|
read filePath
|
|
139
139
|
(body
|
|
140
|
-
|>
|
|
140
|
+
|> Decode.andThen
|
|
141
141
|
(\bodyString ->
|
|
142
142
|
frontmatter (frontmatterDecoder bodyString)
|
|
143
143
|
)
|
|
@@ -151,7 +151,7 @@ just the metadata.
|
|
|
151
151
|
|
|
152
152
|
import DataSource exposing (DataSource)
|
|
153
153
|
import DataSource.File as File
|
|
154
|
-
import
|
|
154
|
+
import Decode as Decode exposing (Decoder)
|
|
155
155
|
|
|
156
156
|
blogPost : DataSource BlogPostMetadata
|
|
157
157
|
blogPost =
|
|
@@ -175,7 +175,7 @@ the [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource.Glo
|
|
|
175
175
|
|
|
176
176
|
import DataSource exposing (DataSource)
|
|
177
177
|
import DataSource.File as File
|
|
178
|
-
import
|
|
178
|
+
import Decode as Decode exposing (Decoder)
|
|
179
179
|
|
|
180
180
|
blogPostFiles : DataSource (List String)
|
|
181
181
|
blogPostFiles =
|
|
@@ -237,7 +237,7 @@ This is the function you want if you are reading in a file directly. For example
|
|
|
237
237
|
have frontmatter.
|
|
238
238
|
|
|
239
239
|
There's a special function for reading in JSON files, [`jsonFile`](#jsonFile). If you're reading a JSON file then be sure to
|
|
240
|
-
use `jsonFile` to get the benefits of the `
|
|
240
|
+
use `jsonFile` to get the benefits of the `Decode` here.
|
|
241
241
|
|
|
242
242
|
You could read a file called `hello.txt` in your root project directory like this:
|
|
243
243
|
|
|
@@ -251,12 +251,12 @@ You could read a file called `hello.txt` in your root project directory like thi
|
|
|
251
251
|
-}
|
|
252
252
|
rawFile : String -> DataSource String
|
|
253
253
|
rawFile filePath =
|
|
254
|
-
read filePath (
|
|
254
|
+
read filePath (Decode.field "rawFile" Decode.string)
|
|
255
255
|
|
|
256
256
|
|
|
257
257
|
{-| Read a file as JSON.
|
|
258
258
|
|
|
259
|
-
The
|
|
259
|
+
The Decode will strip off any unused JSON data.
|
|
260
260
|
|
|
261
261
|
import DataSource exposing (DataSource)
|
|
262
262
|
import DataSource.File as File
|
|
@@ -273,16 +273,27 @@ The OptimizedDecoder will strip off any unused JSON data.
|
|
|
273
273
|
-}
|
|
274
274
|
jsonFile : Decoder a -> String -> DataSource a
|
|
275
275
|
jsonFile jsonFileDecoder filePath =
|
|
276
|
-
|
|
276
|
+
rawFile filePath
|
|
277
|
+
|> DataSource.andThen
|
|
278
|
+
(\jsonString ->
|
|
279
|
+
jsonString
|
|
280
|
+
|> Decode.decodeString jsonFileDecoder
|
|
281
|
+
|> Result.mapError Decode.errorToString
|
|
282
|
+
|> DataSource.fromResult
|
|
283
|
+
)
|
|
277
284
|
|
|
278
285
|
|
|
279
286
|
{-| Gives us the file's content without stripping off frontmatter.
|
|
280
287
|
-}
|
|
281
288
|
body : Decoder String
|
|
282
289
|
body =
|
|
283
|
-
|
|
290
|
+
Decode.field "withoutFrontmatter" Decode.string
|
|
284
291
|
|
|
285
292
|
|
|
286
293
|
read : String -> Decoder a -> DataSource a
|
|
287
|
-
read filePath =
|
|
288
|
-
DataSource.
|
|
294
|
+
read filePath decoder =
|
|
295
|
+
DataSource.Internal.Request.request
|
|
296
|
+
{ name = "read-file"
|
|
297
|
+
, body = DataSource.Http.stringBody "" filePath
|
|
298
|
+
, expect = decoder |> DataSource.Http.expectJson
|
|
299
|
+
}
|