elm-pages 2.1.7 → 2.1.11

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.
Files changed (75) hide show
  1. package/generator/review/elm.json +34 -0
  2. package/generator/review/src/ReviewConfig.elm +10 -0
  3. package/generator/src/basepath-middleware.js +15 -9
  4. package/generator/src/build.js +77 -4
  5. package/generator/src/cli.js +13 -9
  6. package/generator/src/compile-elm.js +43 -0
  7. package/generator/src/dev-server.js +63 -11
  8. package/generator/src/error-formatter.js +62 -9
  9. package/generator/src/generate-template-module-connector.js +17 -4
  10. package/generator/src/init.js +4 -0
  11. package/generator/src/pre-render-html.js +19 -12
  12. package/generator/src/render-worker.js +0 -1
  13. package/generator/src/render.js +1 -2
  14. package/generator/src/seo-renderer.js +21 -2
  15. package/generator/static-code/hmr.js +43 -6
  16. package/generator/template/elm.json +13 -5
  17. package/generator/template/package.json +3 -2
  18. package/package.json +14 -8
  19. package/src/ApiRoute.elm +178 -0
  20. package/src/AriaLiveAnnouncer.elm +36 -0
  21. package/src/BuildError.elm +60 -0
  22. package/src/DataSource/File.elm +288 -0
  23. package/src/DataSource/Glob.elm +1050 -0
  24. package/src/DataSource/Http.elm +467 -0
  25. package/src/DataSource/Internal/Glob.elm +74 -0
  26. package/src/DataSource/Port.elm +87 -0
  27. package/src/DataSource/ServerRequest.elm +60 -0
  28. package/src/DataSource.elm +801 -0
  29. package/src/Head/Seo.elm +516 -0
  30. package/src/Head/Twitter.elm +109 -0
  31. package/src/Head.elm +452 -0
  32. package/src/HtmlPrinter.elm +27 -0
  33. package/src/Internal/ApiRoute.elm +89 -0
  34. package/src/Internal/OptimizedDecoder.elm +18 -0
  35. package/src/KeepOrDiscard.elm +6 -0
  36. package/src/OptimizedDecoder/Pipeline.elm +335 -0
  37. package/src/OptimizedDecoder.elm +818 -0
  38. package/src/Pages/ContentCache.elm +248 -0
  39. package/src/Pages/Flags.elm +26 -0
  40. package/src/Pages/Http.elm +10 -0
  41. package/src/Pages/Internal/ApplicationType.elm +6 -0
  42. package/src/Pages/Internal/NotFoundReason.elm +256 -0
  43. package/src/Pages/Internal/Platform/Cli.elm +1015 -0
  44. package/src/Pages/Internal/Platform/Effect.elm +14 -0
  45. package/src/Pages/Internal/Platform/StaticResponses.elm +540 -0
  46. package/src/Pages/Internal/Platform/ToJsPayload.elm +138 -0
  47. package/src/Pages/Internal/Platform.elm +745 -0
  48. package/src/Pages/Internal/RoutePattern.elm +122 -0
  49. package/src/Pages/Internal/Router.elm +116 -0
  50. package/src/Pages/Internal/StaticHttpBody.elm +54 -0
  51. package/src/Pages/Internal/String.elm +39 -0
  52. package/src/Pages/Manifest/Category.elm +240 -0
  53. package/src/Pages/Manifest.elm +412 -0
  54. package/src/Pages/PageUrl.elm +38 -0
  55. package/src/Pages/ProgramConfig.elm +73 -0
  56. package/src/Pages/Review/NoContractViolations.elm +397 -0
  57. package/src/Pages/Secrets.elm +83 -0
  58. package/src/Pages/SiteConfig.elm +13 -0
  59. package/src/Pages/StaticHttp/Request.elm +42 -0
  60. package/src/Pages/StaticHttpRequest.elm +320 -0
  61. package/src/Pages/Url.elm +60 -0
  62. package/src/Path.elm +96 -0
  63. package/src/QueryParams.elm +216 -0
  64. package/src/RenderRequest.elm +163 -0
  65. package/src/RequestsAndPending.elm +20 -0
  66. package/src/Secrets.elm +111 -0
  67. package/src/SecretsDict.elm +45 -0
  68. package/src/StructuredData.elm +236 -0
  69. package/src/TerminalText.elm +242 -0
  70. package/src/Test/Html/Internal/ElmHtml/Constants.elm +53 -0
  71. package/src/Test/Html/Internal/ElmHtml/Helpers.elm +17 -0
  72. package/src/Test/Html/Internal/ElmHtml/InternalTypes.elm +529 -0
  73. package/src/Test/Html/Internal/ElmHtml/Markdown.elm +56 -0
  74. package/src/Test/Html/Internal/ElmHtml/ToString.elm +197 -0
  75. package/src/Test/Internal/KernelConstants.elm +34 -0
@@ -0,0 +1,248 @@
1
+ module Pages.ContentCache exposing
2
+ ( ContentCache
3
+ , ContentJson
4
+ , Entry(..)
5
+ , Path
6
+ , contentJsonDecoder
7
+ , init
8
+ , is404
9
+ , lazyLoad
10
+ , notFoundReason
11
+ , pathForUrl
12
+ )
13
+
14
+ import BuildError exposing (BuildError)
15
+ import Codec
16
+ import Dict exposing (Dict)
17
+ import Html exposing (Html)
18
+ import Http
19
+ import Json.Decode as Decode
20
+ import Pages.Internal.NotFoundReason
21
+ import Pages.Internal.String as String
22
+ import RequestsAndPending exposing (RequestsAndPending)
23
+ import Task exposing (Task)
24
+ import Url exposing (Url)
25
+
26
+
27
+ type alias Content =
28
+ List ( List String, { extension : String, frontMatter : String, body : Maybe String } )
29
+
30
+
31
+ type alias ContentCache =
32
+ Dict Path Entry
33
+
34
+
35
+ type alias Errors =
36
+ List ( Html Never, BuildError )
37
+
38
+
39
+ type alias ContentCacheInner =
40
+ Dict Path Entry
41
+
42
+
43
+ type Entry
44
+ = Parsed ContentJson
45
+
46
+
47
+ type alias ParseError =
48
+ String
49
+
50
+
51
+ type alias Path =
52
+ List String
53
+
54
+
55
+ init :
56
+ Maybe ( Path, ContentJson )
57
+ -> ContentCache
58
+ init maybeInitialPageContent =
59
+ case maybeInitialPageContent of
60
+ Nothing ->
61
+ Dict.empty
62
+
63
+ Just ( urls, contentJson ) ->
64
+ Dict.singleton urls (Parsed contentJson)
65
+
66
+
67
+ {-| Get from the Cache... if it's not already parsed, it will
68
+ parse it before returning it and store the parsed version in the Cache
69
+ -}
70
+ lazyLoad :
71
+ { currentUrl : Url, basePath : List String }
72
+ -> ContentCache
73
+ -> Task Http.Error ( Url, ContentJson, ContentCache )
74
+ lazyLoad urls cache =
75
+ case Dict.get (pathForUrl urls) cache of
76
+ Just (Parsed contentJson) ->
77
+ Task.succeed
78
+ ( urls.currentUrl
79
+ , contentJson
80
+ , cache
81
+ )
82
+
83
+ Nothing ->
84
+ urls.currentUrl
85
+ |> httpTask
86
+ |> Task.map
87
+ (\downloadedContent ->
88
+ ( urls.currentUrl
89
+ , downloadedContent
90
+ , update
91
+ cache
92
+ urls
93
+ downloadedContent
94
+ )
95
+ )
96
+
97
+
98
+ httpTask : Url -> Task Http.Error ContentJson
99
+ httpTask url =
100
+ Http.task
101
+ { method = "GET"
102
+ , headers = []
103
+ , url =
104
+ url.path
105
+ |> String.chopForwardSlashes
106
+ |> String.split "/"
107
+ |> List.filter ((/=) "")
108
+ |> (\l -> l ++ [ "content.json" ])
109
+ |> String.join "/"
110
+ |> String.append "/"
111
+ , body = Http.emptyBody
112
+ , resolver =
113
+ Http.stringResolver
114
+ (\response ->
115
+ case response of
116
+ Http.BadUrl_ url_ ->
117
+ Err (Http.BadUrl url_)
118
+
119
+ Http.Timeout_ ->
120
+ Err Http.Timeout
121
+
122
+ Http.NetworkError_ ->
123
+ Err Http.NetworkError
124
+
125
+ Http.BadStatus_ metadata _ ->
126
+ Err (Http.BadStatus metadata.statusCode)
127
+
128
+ Http.GoodStatus_ _ body ->
129
+ body
130
+ |> Decode.decodeString contentJsonDecoder
131
+ |> Result.mapError (\err -> Http.BadBody (Decode.errorToString err))
132
+ )
133
+ , timeout = Nothing
134
+ }
135
+
136
+
137
+ type alias ContentJson =
138
+ { staticData : RequestsAndPending
139
+ , is404 : Bool
140
+ , path : Maybe String
141
+ , notFoundReason : Maybe Pages.Internal.NotFoundReason.Payload
142
+ }
143
+
144
+
145
+ contentJsonDecoder : Decode.Decoder ContentJson
146
+ contentJsonDecoder =
147
+ Decode.field "is404" Decode.bool
148
+ |> Decode.andThen
149
+ (\is404Value ->
150
+ if is404Value then
151
+ Decode.map4 ContentJson
152
+ (Decode.succeed Dict.empty)
153
+ (Decode.succeed is404Value)
154
+ (Decode.field "path" Decode.string |> Decode.map Just)
155
+ (Decode.at [ "staticData", "notFoundReason" ]
156
+ (Decode.string
157
+ |> Decode.andThen
158
+ (\jsonString ->
159
+ case
160
+ Decode.decodeString
161
+ (Codec.decoder Pages.Internal.NotFoundReason.codec
162
+ |> Decode.map Just
163
+ )
164
+ jsonString
165
+ of
166
+ Ok okValue ->
167
+ Decode.succeed okValue
168
+
169
+ Err error ->
170
+ Decode.fail
171
+ (Decode.errorToString error)
172
+ )
173
+ )
174
+ )
175
+
176
+ else
177
+ Decode.map4 ContentJson
178
+ (Decode.field "staticData" RequestsAndPending.decoder)
179
+ (Decode.succeed is404Value)
180
+ (Decode.succeed Nothing)
181
+ (Decode.succeed Nothing)
182
+ )
183
+
184
+
185
+ update :
186
+ ContentCache
187
+ -> { currentUrl : Url, basePath : List String }
188
+ -> ContentJson
189
+ -> ContentCache
190
+ update cache urls rawContent =
191
+ Dict.update
192
+ (pathForUrl urls)
193
+ (\entry ->
194
+ case entry of
195
+ Just (Parsed _) ->
196
+ entry
197
+
198
+ Nothing ->
199
+ { staticData = rawContent.staticData
200
+ , is404 = rawContent.is404
201
+ , path = rawContent.path
202
+ , notFoundReason = rawContent.notFoundReason
203
+ }
204
+ |> Parsed
205
+ |> Just
206
+ )
207
+ cache
208
+
209
+
210
+ pathForUrl : { currentUrl : Url, basePath : List String } -> Path
211
+ pathForUrl { currentUrl, basePath } =
212
+ currentUrl.path
213
+ |> String.chopForwardSlashes
214
+ |> String.split "/"
215
+ |> List.filter ((/=) "")
216
+ |> List.drop (List.length basePath)
217
+
218
+
219
+ is404 :
220
+ ContentCache
221
+ -> { currentUrl : Url, basePath : List String }
222
+ -> Bool
223
+ is404 dict urls =
224
+ dict
225
+ |> Dict.get (pathForUrl urls)
226
+ |> Maybe.map
227
+ (\entry ->
228
+ case entry of
229
+ Parsed data ->
230
+ data.is404
231
+ )
232
+ |> Maybe.withDefault True
233
+
234
+
235
+ notFoundReason :
236
+ ContentCache
237
+ -> { currentUrl : Url, basePath : List String }
238
+ -> Maybe Pages.Internal.NotFoundReason.Payload
239
+ notFoundReason dict urls =
240
+ dict
241
+ |> Dict.get (pathForUrl urls)
242
+ |> Maybe.map
243
+ (\entry ->
244
+ case entry of
245
+ Parsed data ->
246
+ data.notFoundReason
247
+ )
248
+ |> Maybe.withDefault Nothing
@@ -0,0 +1,26 @@
1
+ module Pages.Flags exposing (Flags(..))
2
+
3
+ {-|
4
+
5
+ @docs Flags
6
+
7
+ -}
8
+
9
+ import Json.Decode
10
+
11
+
12
+ {-| elm-pages apps run in two different contexts
13
+
14
+ 1. In the browser (like a regular Elm app)
15
+ 2. In pre-render mode. For example when you run `elm-pages build`, there is no browser involved, it just runs Elm directly.
16
+
17
+ You can pass in Flags and use them in your `Shared.init` function. You can store data in your `Shared.Model` from these flags and then access it across any page.
18
+
19
+ You will need to handle the `PreRender` case with no flags value because there is no browser to get flags from. For example, say you wanted to get the
20
+ current user's Browser window size and pass it in as a flag. When that page is pre-rendered, you need to decide on a value to use for the window size
21
+ since there is no window (the user hasn't requested the page yet, and the page isn't even loaded in a Browser window yet).
22
+
23
+ -}
24
+ type Flags
25
+ = BrowserFlags Json.Decode.Value
26
+ | PreRenderFlags
@@ -0,0 +1,10 @@
1
+ module Pages.Http exposing (Error(..))
2
+
3
+ import Http
4
+
5
+
6
+ type Error
7
+ = BadUrl String
8
+ | Timeout
9
+ | NetworkError
10
+ | BadStatus Http.Metadata String
@@ -0,0 +1,6 @@
1
+ module Pages.Internal.ApplicationType exposing (ApplicationType(..))
2
+
3
+
4
+ type ApplicationType
5
+ = Browser
6
+ | Cli
@@ -0,0 +1,256 @@
1
+ module Pages.Internal.NotFoundReason exposing (codec, ModuleContext, NotFoundReason(..), Payload, Record, document)
2
+
3
+ {-| Exposed for internal use only (used in generated code).
4
+
5
+ @docs codec, ModuleContext, NotFoundReason, Payload, Record, document
6
+
7
+ -}
8
+
9
+ import Codec exposing (Codec)
10
+ import Html exposing (Html)
11
+ import Html.Attributes as Attr
12
+ import Pages.Internal.RoutePattern exposing (RoutePattern)
13
+ import Path exposing (Path)
14
+
15
+
16
+ {-| -}
17
+ type alias ModuleContext =
18
+ { moduleName : List String
19
+ , routePattern : RoutePattern
20
+ , matchedRouteParams : Record
21
+ }
22
+
23
+
24
+ {-| -}
25
+ type alias Payload =
26
+ { path : Path
27
+ , reason : NotFoundReason
28
+ }
29
+
30
+
31
+ {-| -}
32
+ type alias Record =
33
+ List ( String, String )
34
+
35
+
36
+ {-| -}
37
+ type NotFoundReason
38
+ = NoMatchingRoute
39
+ | NotPrerendered ModuleContext (List Record)
40
+ | NotPrerenderedOrHandledByFallback ModuleContext (List Record)
41
+ | UnhandledServerRoute ModuleContext
42
+
43
+
44
+ {-| -}
45
+ document :
46
+ List RoutePattern
47
+ -> Payload
48
+ -> { title : String, body : Html msg }
49
+ document pathPatterns payload =
50
+ { title = "Page not found"
51
+ , body =
52
+ Html.div
53
+ [ Attr.id "not-found-reason"
54
+ , Attr.style "padding" "30px"
55
+ ]
56
+ (case payload.reason of
57
+ NoMatchingRoute ->
58
+ [ Html.text <| "No route found for "
59
+ , Html.code []
60
+ [ Html.text
61
+ (payload.path
62
+ |> Path.toAbsolute
63
+ )
64
+ ]
65
+ , Html.text " Did you mean to go to one of these routes:"
66
+ , Html.ul
67
+ [ Attr.style "padding-top" "30px"
68
+ ]
69
+ (pathPatterns
70
+ |> List.map
71
+ (\route ->
72
+ Html.li
73
+ [ Attr.style "list-style" "inside"
74
+ ]
75
+ [ route
76
+ |> Pages.Internal.RoutePattern.view
77
+ ]
78
+ )
79
+ )
80
+ ]
81
+
82
+ NotPrerendered moduleContext routes ->
83
+ [ Html.h1 []
84
+ [ Html.text "Page Not Found"
85
+ ]
86
+ , Html.code []
87
+ [ Html.text
88
+ (payload.path
89
+ |> Path.toAbsolute
90
+ )
91
+ ]
92
+ , Html.text " successfully matched the route "
93
+ , Html.br [] []
94
+ , Html.br [] []
95
+ , Html.code []
96
+ [ Pages.Internal.RoutePattern.view moduleContext.routePattern
97
+ ]
98
+ , Html.br [] []
99
+ , Html.br [] []
100
+ , Html.text " from the Page Module "
101
+ , Html.br [] []
102
+ , Html.br [] []
103
+ , Html.code []
104
+ [ Html.text (moduleName moduleContext)
105
+ ]
106
+ , prerenderedOptionsView moduleContext routes
107
+ ]
108
+
109
+ _ ->
110
+ [ Html.text "Page not found"
111
+ , Html.text <| "TODO"
112
+ ]
113
+ )
114
+ }
115
+
116
+
117
+ prerenderedOptionsView : ModuleContext -> List Record -> Html msg
118
+ prerenderedOptionsView moduleContext routes =
119
+ case routes of
120
+ [] ->
121
+ Html.div []
122
+ [ Html.br [] []
123
+ , Html.text "But this Page module has no pre-rendered routes! If you want to pre-render this page, add these "
124
+ , Html.code [] [ Html.text "RouteParams" ]
125
+ , Html.text " to the module's "
126
+ , Html.code [] [ Html.text "routes" ]
127
+ , Html.br [] []
128
+ , Html.br [] []
129
+ , Html.code
130
+ [ Attr.style "border-bottom" "dotted 2px"
131
+ , Attr.style "font-weight" "bold"
132
+ ]
133
+ [ Html.text <| recordToString moduleContext.matchedRouteParams
134
+ ]
135
+ ]
136
+
137
+ _ ->
138
+ Html.div []
139
+ [ Html.br [] []
140
+ , Html.br [] []
141
+ , Html.text " but these RouteParams were not present "
142
+ , Html.br [] []
143
+ , Html.br [] []
144
+ , Html.code
145
+ [ Attr.style "border-bottom" "dotted 2px"
146
+ , Attr.style "font-weight" "bold"
147
+ ]
148
+ [ Html.text <| recordToString moduleContext.matchedRouteParams
149
+ ]
150
+ , Html.br [] []
151
+ , Html.br [] []
152
+ , Html.text "The following RouteParams are pre-rendered:"
153
+ , Html.ul
154
+ [ Attr.style "padding-top" "30px"
155
+ ]
156
+ (routes
157
+ |> List.map
158
+ (\record ->
159
+ Html.li
160
+ [ Attr.style "list-style" "inside"
161
+ ]
162
+ [ --Html.a
163
+ -- [-- Attr.href "/blog/extensible-markdown-parsing-in-elm"
164
+ -- -- TODO get href data
165
+ -- ]
166
+ -- [
167
+ Html.code
168
+ []
169
+ [ Html.text (recordToString record)
170
+ ]
171
+
172
+ --]
173
+ ]
174
+ )
175
+ )
176
+ , Html.br [] []
177
+ , Html.br [] []
178
+ , Html.p []
179
+ [ Html.text "Try changing "
180
+ , Html.code [] [ Html.text "routes" ]
181
+ , Html.text " in "
182
+ , Html.code [] [ Html.text (moduleName moduleContext) ]
183
+ , Html.text " to make sure it includes these "
184
+ , Html.code [] [ Html.text "RouteParams" ]
185
+ , Html.text "."
186
+ ]
187
+ ]
188
+
189
+
190
+ {-| -}
191
+ codec : Codec Payload
192
+ codec =
193
+ Codec.object Payload
194
+ |> Codec.field "path"
195
+ .path
196
+ (Codec.list Codec.string
197
+ |> Codec.map Path.join Path.toSegments
198
+ )
199
+ |> Codec.field "reason" .reason reasonCodec
200
+ |> Codec.buildObject
201
+
202
+
203
+ reasonCodec : Codec NotFoundReason
204
+ reasonCodec =
205
+ Codec.custom
206
+ (\vNoMatchingRoute vNotPrerendered vNotPrerenderedOrHandledByFallback vUnhandledServerRoute value ->
207
+ case value of
208
+ NoMatchingRoute ->
209
+ vNoMatchingRoute
210
+
211
+ NotPrerendered moduleContext prerenderedRoutes ->
212
+ vNotPrerendered moduleContext prerenderedRoutes
213
+
214
+ NotPrerenderedOrHandledByFallback moduleContext prerenderedRoutes ->
215
+ vNotPrerenderedOrHandledByFallback moduleContext prerenderedRoutes
216
+
217
+ UnhandledServerRoute moduleContext ->
218
+ vUnhandledServerRoute moduleContext
219
+ )
220
+ |> Codec.variant0 "NoMatchingRoute" NoMatchingRoute
221
+ |> Codec.variant2 "NotPrerendered" NotPrerendered moduleContextCodec (Codec.list recordCodec)
222
+ |> Codec.variant2 "NotPrerenderedOrHandledByFallback" NotPrerenderedOrHandledByFallback moduleContextCodec (Codec.list recordCodec)
223
+ |> Codec.variant1 "UnhandledServerRoute" UnhandledServerRoute moduleContextCodec
224
+ |> Codec.buildCustom
225
+
226
+
227
+ moduleContextCodec : Codec ModuleContext
228
+ moduleContextCodec =
229
+ Codec.object ModuleContext
230
+ |> Codec.field "moduleName" .moduleName (Codec.list Codec.string)
231
+ |> Codec.field "routePattern" .routePattern Pages.Internal.RoutePattern.codec
232
+ |> Codec.field "matchedRouteParams" .matchedRouteParams recordCodec
233
+ |> Codec.buildObject
234
+
235
+
236
+ recordCodec : Codec (List ( String, String ))
237
+ recordCodec =
238
+ Codec.list (Codec.tuple Codec.string Codec.string)
239
+
240
+
241
+ recordToString : List ( String, String ) -> String
242
+ recordToString fields =
243
+ "{ "
244
+ ++ (fields
245
+ |> List.map
246
+ (\( key, value ) ->
247
+ key ++ " = " ++ value
248
+ )
249
+ |> String.join ", "
250
+ )
251
+ ++ " }"
252
+
253
+
254
+ moduleName : ModuleContext -> String
255
+ moduleName moduleContext =
256
+ ("src" :: moduleContext.moduleName |> String.join "/") ++ ".elm"