elm-pages 2.1.11 → 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.
Files changed (136) hide show
  1. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  2. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  3. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  4. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  5. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
  6. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
  7. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
  8. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  9. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  10. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  11. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  12. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  13. package/generator/{template/public/style.css → review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +0 -0
  14. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  15. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -0
  16. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  17. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
  18. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  23. package/generator/review/elm.json +13 -4
  24. package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
  25. package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
  26. package/generator/src/RouteBuilder.elm +420 -0
  27. package/generator/src/SharedTemplate.elm +4 -5
  28. package/generator/src/SiteConfig.elm +3 -9
  29. package/generator/src/build.js +308 -95
  30. package/generator/src/cli.js +103 -8
  31. package/generator/src/codegen.js +192 -35
  32. package/generator/src/compile-elm.js +183 -31
  33. package/generator/src/dev-server.js +353 -96
  34. package/generator/src/elm-application.json +3 -1
  35. package/generator/src/elm-codegen.js +34 -0
  36. package/generator/src/elm-file-constants.js +2 -0
  37. package/generator/src/error-formatter.js +20 -1
  38. package/generator/src/generate-template-module-connector.js +120 -924
  39. package/generator/src/hello.ts +5 -0
  40. package/generator/src/pre-render-html.js +58 -104
  41. package/generator/src/render-worker.js +27 -13
  42. package/generator/src/render.js +252 -197
  43. package/generator/src/request-cache-fs.js +18 -0
  44. package/generator/src/request-cache.js +128 -56
  45. package/generator/src/rewrite-client-elm-json.js +49 -0
  46. package/generator/src/route-codegen-helpers.js +62 -1
  47. package/generator/static-code/dev-style.css +22 -0
  48. package/generator/static-code/elm-pages.js +43 -39
  49. package/generator/static-code/hmr.js +98 -88
  50. package/generator/template/app/Api.elm +25 -0
  51. package/generator/template/app/ErrorPage.elm +38 -0
  52. package/generator/template/app/Route/Index.elm +87 -0
  53. package/generator/template/{src → app}/Shared.elm +34 -13
  54. package/generator/template/app/Site.elm +19 -0
  55. package/generator/template/{src → app}/View.elm +0 -0
  56. package/generator/template/elm-pages.config.mjs +5 -0
  57. package/generator/template/elm.json +1 -0
  58. package/generator/template/{public/index.js → index.ts} +7 -3
  59. package/generator/template/package.json +4 -4
  60. package/generator/template/public/favicon.ico +0 -0
  61. package/generator/template/public/images/icon-png.png +0 -0
  62. package/generator/template/src/.gitkeep +0 -0
  63. package/generator/template/style.css +4 -0
  64. package/package.json +30 -23
  65. package/src/ApiRoute.elm +176 -43
  66. package/src/BuildError.elm +10 -1
  67. package/src/CookieParser.elm +84 -0
  68. package/src/DataSource/Env.elm +38 -0
  69. package/src/DataSource/File.elm +27 -16
  70. package/src/DataSource/Glob.elm +126 -80
  71. package/src/DataSource/Http.elm +283 -304
  72. package/src/DataSource/Internal/Glob.elm +5 -21
  73. package/src/DataSource/Internal/Request.elm +25 -0
  74. package/src/DataSource/Port.elm +17 -14
  75. package/src/DataSource.elm +55 -318
  76. package/src/Form/Field.elm +717 -0
  77. package/src/Form/FieldStatus.elm +36 -0
  78. package/src/Form/FieldView.elm +417 -0
  79. package/src/Form/FormData.elm +22 -0
  80. package/src/Form/Validation.elm +391 -0
  81. package/src/Form/Value.elm +118 -0
  82. package/src/Form.elm +1683 -0
  83. package/src/FormData.elm +58 -0
  84. package/src/FormDecoder.elm +102 -0
  85. package/src/Head/Seo.elm +12 -4
  86. package/src/Head.elm +12 -2
  87. package/src/HtmlPrinter.elm +1 -1
  88. package/src/Internal/ApiRoute.elm +17 -4
  89. package/src/Internal/Request.elm +7 -0
  90. package/src/PageServerResponse.elm +68 -0
  91. package/src/Pages/ContentCache.elm +1 -229
  92. package/src/Pages/Fetcher.elm +58 -0
  93. package/src/Pages/FormState.elm +256 -0
  94. package/src/Pages/Generate.elm +800 -0
  95. package/src/Pages/Internal/Form.elm +17 -0
  96. package/src/Pages/Internal/NotFoundReason.elm +3 -55
  97. package/src/Pages/Internal/Platform/Cli.elm +777 -579
  98. package/src/Pages/Internal/Platform/Effect.elm +5 -5
  99. package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
  100. package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
  101. package/src/Pages/Internal/Platform.elm +1244 -504
  102. package/src/Pages/Internal/ResponseSketch.elm +19 -0
  103. package/src/Pages/Internal/RoutePattern.elm +596 -45
  104. package/src/Pages/Manifest.elm +26 -0
  105. package/src/Pages/Msg.elm +79 -0
  106. package/src/Pages/ProgramConfig.elm +67 -14
  107. package/src/Pages/SiteConfig.elm +3 -6
  108. package/src/Pages/StaticHttp/Request.elm +4 -2
  109. package/src/Pages/StaticHttpRequest.elm +50 -215
  110. package/src/Pages/Transition.elm +70 -0
  111. package/src/Path.elm +1 -0
  112. package/src/Pattern.elm +98 -0
  113. package/src/RenderRequest.elm +2 -2
  114. package/src/RequestsAndPending.elm +111 -9
  115. package/src/Server/Request.elm +1253 -0
  116. package/src/Server/Response.elm +292 -0
  117. package/src/Server/Session.elm +316 -0
  118. package/src/Server/SetCookie.elm +169 -0
  119. package/src/TerminalText.elm +1 -1
  120. package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
  121. package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
  122. package/generator/src/Page.elm +0 -359
  123. package/generator/src/codegen-template-module.js +0 -183
  124. package/generator/src/elm-pages-js-minified.js +0 -1
  125. package/generator/template/src/Api.elm +0 -14
  126. package/generator/template/src/Page/Index.elm +0 -69
  127. package/generator/template/src/Site.elm +0 -41
  128. package/src/DataSource/ServerRequest.elm +0 -60
  129. package/src/Internal/OptimizedDecoder.elm +0 -18
  130. package/src/KeepOrDiscard.elm +0 -6
  131. package/src/OptimizedDecoder/Pipeline.elm +0 -335
  132. package/src/OptimizedDecoder.elm +0 -818
  133. package/src/Pages/Internal/ApplicationType.elm +0 -6
  134. package/src/Pages/Secrets.elm +0 -83
  135. package/src/Secrets.elm +0 -111
  136. package/src/SecretsDict.elm +0 -45
@@ -0,0 +1,58 @@
1
+ module FormData exposing (encode, parse)
2
+
3
+ import Dict exposing (Dict)
4
+ import List.NonEmpty exposing (NonEmpty)
5
+ import Url
6
+
7
+
8
+ parse : String -> Dict String ( String, List String )
9
+ parse rawString =
10
+ rawString
11
+ |> String.split "&"
12
+ |> List.foldl
13
+ (\entry soFar ->
14
+ case entry |> String.split "=" of
15
+ [ key, value ] ->
16
+ let
17
+ newValue : String
18
+ newValue =
19
+ value |> decode
20
+ in
21
+ Dict.update (decode key)
22
+ (\maybeExistingList ->
23
+ maybeExistingList
24
+ |> Maybe.map (\( first, rest ) -> ( first, rest ++ [ newValue ] ))
25
+ |> Maybe.withDefault ( newValue, [] )
26
+ |> Just
27
+ )
28
+ soFar
29
+
30
+ _ ->
31
+ --( entry |> Url.percentDecode |> Maybe.withDefault entry, ( "", [] ) )
32
+ soFar
33
+ )
34
+ Dict.empty
35
+
36
+
37
+ decode : String -> String
38
+ decode string =
39
+ string
40
+ |> String.replace "+" " "
41
+ |> Url.percentDecode
42
+ |> Maybe.withDefault ""
43
+
44
+
45
+ encode : Dict String (NonEmpty String) -> String
46
+ encode dict =
47
+ dict
48
+ |> Dict.toList
49
+ |> List.concatMap
50
+ (\( key, values ) ->
51
+ values
52
+ |> List.NonEmpty.toList
53
+ |> List.map
54
+ (\value ->
55
+ Url.percentEncode key ++ "=" ++ Url.percentEncode value
56
+ )
57
+ )
58
+ |> String.join "&"
@@ -0,0 +1,102 @@
1
+ module FormDecoder exposing (encodeFormData, formDataOnSubmit, methodToString)
2
+
3
+ import Form.FormData as FormData exposing (FormData)
4
+ import Html
5
+ import Html.Events
6
+ import Json.Decode as Decode
7
+ import Json.Encode
8
+ import Url
9
+
10
+
11
+ formDataOnSubmit : Html.Attribute FormData
12
+ formDataOnSubmit =
13
+ Html.Events.preventDefaultOn "submit"
14
+ (Decode.map4 FormData
15
+ (Decode.value
16
+ |> Decode.andThen
17
+ (\decodeValue ->
18
+ case Decode.decodeValue tuplesDecoder (decoder decodeValue) of
19
+ Ok decoded ->
20
+ Decode.succeed decoded
21
+
22
+ Err error ->
23
+ Decode.succeed
24
+ [ ( "error"
25
+ , Decode.errorToString error
26
+ )
27
+ ]
28
+ )
29
+ )
30
+ (currentForm "method" methodDecoder)
31
+ (currentForm "action" Decode.string)
32
+ (currentForm "id" (Decode.nullable Decode.string))
33
+ |> Decode.map alwaysPreventDefault
34
+ )
35
+
36
+
37
+ currentForm : String -> Decode.Decoder a -> Decode.Decoder a
38
+ currentForm field decoder_ =
39
+ Decode.oneOf
40
+ [ Decode.at [ "submitter", "form" ] decoder_
41
+ , Decode.at [ "currentTarget", field ] decoder_
42
+ ]
43
+
44
+
45
+ methodDecoder : Decode.Decoder FormData.Method
46
+ methodDecoder =
47
+ Decode.string
48
+ |> Decode.map
49
+ (\methodString ->
50
+ case methodString |> String.toUpper of
51
+ "GET" ->
52
+ FormData.Get
53
+
54
+ "POST" ->
55
+ FormData.Post
56
+
57
+ _ ->
58
+ -- TODO what about "dialog" method? Is it okay for that to be interpreted as GET,
59
+ -- or should there be a variant for that?
60
+ FormData.Get
61
+ )
62
+
63
+
64
+ decoder : Decode.Value -> Decode.Value
65
+ decoder event =
66
+ Json.Encode.string "REPLACE_ME_WITH_FORM_TO_STRING"
67
+
68
+
69
+ alwaysPreventDefault : msg -> ( msg, Bool )
70
+ alwaysPreventDefault msg =
71
+ ( msg, True )
72
+
73
+
74
+ tuplesDecoder : Decode.Decoder (List ( String, String ))
75
+ tuplesDecoder =
76
+ Decode.list
77
+ (Decode.map2 Tuple.pair
78
+ (Decode.index 0 Decode.string)
79
+ (Decode.index 1 Decode.string)
80
+ )
81
+
82
+
83
+ methodToString : FormData.Method -> String
84
+ methodToString method =
85
+ case method of
86
+ FormData.Get ->
87
+ "GET"
88
+
89
+ FormData.Post ->
90
+ "POST"
91
+
92
+
93
+ encodeFormData :
94
+ FormData
95
+ -> String
96
+ encodeFormData data =
97
+ data.fields
98
+ |> List.map
99
+ (\( name, value ) ->
100
+ Url.percentEncode name ++ "=" ++ Url.percentEncode value
101
+ )
102
+ |> String.join "&"
package/src/Head/Seo.elm CHANGED
@@ -51,6 +51,8 @@ with the `head` function that you pass to your Pages config (`Pages.application`
51
51
 
52
52
  import Head
53
53
  import Head.Twitter as Twitter
54
+ import LanguageTag.Country
55
+ import LanguageTag.Language
54
56
  import Pages.Url
55
57
 
56
58
 
@@ -307,6 +309,13 @@ type alias Common =
307
309
  }
308
310
 
309
311
 
312
+ localeToString : Locale -> String
313
+ localeToString ( language, territory ) =
314
+ LanguageTag.Language.toCodeString language
315
+ ++ "_"
316
+ ++ LanguageTag.Country.toCodeString territory
317
+
318
+
310
319
  tagsForCommon : Common -> List ( String, Maybe Head.AttributeValue )
311
320
  tagsForCommon common =
312
321
  tagsForImage common.image
@@ -316,12 +325,12 @@ tagsForCommon common =
316
325
  , ( "og:url", common.canonicalUrlOverride |> Maybe.map Head.raw |> Maybe.withDefault Head.currentPageFullUrl |> Just )
317
326
  , ( "og:description", Just (Head.raw common.description) )
318
327
  , ( "og:site_name", Just (Head.raw common.siteName) )
319
- , ( "og:locale", common.locale |> Maybe.map Head.raw )
328
+ , ( "og:locale", common.locale |> Maybe.map localeToString |> Maybe.map Head.raw )
320
329
  ]
321
330
  ++ (common.alternateLocales
322
331
  |> List.map
323
332
  (\alternateLocale ->
324
- ( "og:locale:alternate", alternateLocale |> Head.raw |> Just )
333
+ ( "og:locale:alternate", alternateLocale |> localeToString |> Head.raw |> Just )
325
334
  )
326
335
  )
327
336
  ++ Twitter.rawTags common.twitterCard
@@ -350,8 +359,7 @@ tagsForAudio audio =
350
359
 
351
360
 
352
361
  type alias Locale =
353
- -- TODO make this more type-safe
354
- String
362
+ ( LanguageTag.Language.Language, LanguageTag.Country.Country )
355
363
 
356
364
 
357
365
  type Content
package/src/Head.elm CHANGED
@@ -1,6 +1,6 @@
1
1
  module Head exposing
2
2
  ( Tag, metaName, metaProperty, metaRedirect
3
- , rssLink, sitemapLink, rootLanguage
3
+ , rssLink, sitemapLink, rootLanguage, manifestLink
4
4
  , structuredData
5
5
  , AttributeValue
6
6
  , currentPageFullUrl, urlAttribute, raw
@@ -18,7 +18,7 @@ But this module might be useful if you have a special use case, or if you are
18
18
  writing a plugin package to extend `elm-pages`.
19
19
 
20
20
  @docs Tag, metaName, metaProperty, metaRedirect
21
- @docs rssLink, sitemapLink, rootLanguage
21
+ @docs rssLink, sitemapLink, rootLanguage, manifestLink
22
22
 
23
23
 
24
24
  ## Structured Data
@@ -211,6 +211,16 @@ canonicalLink maybePath =
211
211
  ]
212
212
 
213
213
 
214
+ {-| Let's you link to your manifest.json file, see <https://developer.mozilla.org/en-US/docs/Web/Manifest#deploying_a_manifest>.
215
+ -}
216
+ manifestLink : String -> Tag
217
+ manifestLink path =
218
+ node "link"
219
+ [ ( "rel", raw "manifest" )
220
+ , ( "href", raw path )
221
+ ]
222
+
223
+
214
224
  {-| Add a link to the site's RSS feed.
215
225
 
216
226
  Example:
@@ -19,7 +19,7 @@ htmlToString viewHtml =
19
19
  nodeToStringWithOptions defaultFormatOptions str
20
20
 
21
21
  Err err ->
22
- "Error: " ++ Decode.errorToString err
22
+ "Error pre-rendering HTML in HtmlPrinter.elm: " ++ Decode.errorToString err
23
23
 
24
24
 
25
25
  asJsonView : Html msg -> Decode.Value
@@ -3,11 +3,14 @@ module Internal.ApiRoute exposing
3
3
  , ApiRouteBuilder(..)
4
4
  , firstMatch
5
5
  , pathToMatches
6
+ , toPattern
6
7
  , tryMatch
7
8
  , withRoutes
8
9
  )
9
10
 
10
11
  import DataSource exposing (DataSource)
12
+ import Head
13
+ import Pattern exposing (Pattern)
11
14
  import Regex exposing (Regex)
12
15
 
13
16
 
@@ -44,12 +47,20 @@ type ApiRoute response
44
47
  , matchesToResponse : String -> DataSource (Maybe response)
45
48
  , buildTimeRoutes : DataSource (List String)
46
49
  , handleRoute : String -> DataSource Bool
50
+ , pattern : Pattern
51
+ , kind : String
52
+ , globalHeadTags : Maybe (DataSource (List Head.Tag))
47
53
  }
48
54
 
49
55
 
56
+ toPattern : ApiRoute response -> Pattern
57
+ toPattern (ApiRoute { pattern }) =
58
+ pattern
59
+
60
+
50
61
  {-| -}
51
62
  pathToMatches : String -> ApiRouteBuilder a constructor -> List String
52
- pathToMatches path (ApiRouteBuilder pattern _ _ _) =
63
+ pathToMatches path (ApiRouteBuilder _ pattern _ _ _) =
53
64
  Regex.find
54
65
  (Regex.fromString pattern
55
66
  |> Maybe.withDefault Regex.never
@@ -57,18 +68,19 @@ pathToMatches path (ApiRouteBuilder pattern _ _ _) =
57
68
  path
58
69
  |> List.concatMap .submatches
59
70
  |> List.filterMap identity
71
+ |> List.reverse
60
72
 
61
73
 
62
74
  {-| -}
63
75
  withRoutes : (constructor -> List (List String)) -> ApiRouteBuilder a constructor -> List String
64
- withRoutes buildUrls (ApiRouteBuilder _ _ toString constructor) =
76
+ withRoutes buildUrls (ApiRouteBuilder _ _ _ toString constructor) =
65
77
  buildUrls (constructor [])
66
78
  |> List.map toString
67
79
 
68
80
 
69
81
  {-| -}
70
82
  tryMatch : String -> ApiRouteBuilder response constructor -> Maybe response
71
- tryMatch path (ApiRouteBuilder pattern handler _ _) =
83
+ tryMatch path (ApiRouteBuilder _ pattern handler _ _) =
72
84
  let
73
85
  matches : List String
74
86
  matches =
@@ -79,6 +91,7 @@ tryMatch path (ApiRouteBuilder pattern handler _ _) =
79
91
  path
80
92
  |> List.concatMap .submatches
81
93
  |> List.filterMap identity
94
+ |> List.reverse
82
95
  in
83
96
  handler matches
84
97
  |> Just
@@ -86,4 +99,4 @@ tryMatch path (ApiRouteBuilder pattern handler _ _) =
86
99
 
87
100
  {-| -}
88
101
  type ApiRouteBuilder a constructor
89
- = ApiRouteBuilder String (List String -> a) (List String -> String) (List String -> constructor)
102
+ = ApiRouteBuilder Pattern String (List String -> a) (List String -> String) (List String -> constructor)
@@ -0,0 +1,7 @@
1
+ module Internal.Request exposing (Parser(..))
2
+
3
+ import Json.Decode
4
+
5
+
6
+ type Parser decodesTo validationError
7
+ = Parser (Json.Decode.Decoder ( Result validationError decodesTo, List validationError ))
@@ -0,0 +1,68 @@
1
+ module PageServerResponse exposing (PageServerResponse(..), Response, toJson, toRedirect)
2
+
3
+ import Dict
4
+ import Json.Encode
5
+ import List.Extra
6
+
7
+
8
+ type PageServerResponse data error
9
+ = RenderPage
10
+ { statusCode : Int
11
+ , headers : List ( String, String )
12
+ }
13
+ data
14
+ | ServerResponse Response
15
+ | ErrorPage error { headers : List ( String, String ) }
16
+
17
+
18
+ toRedirect : Response -> Maybe { statusCode : Int, location : String }
19
+ toRedirect response =
20
+ response.headers
21
+ |> Dict.fromList
22
+ |> Dict.get "Location"
23
+ |> Maybe.andThen
24
+ (\location ->
25
+ if response.statusCode == 302 then
26
+ Just { statusCode = 302, location = location }
27
+
28
+ else
29
+ Nothing
30
+ )
31
+
32
+
33
+ type alias Response =
34
+ { statusCode : Int
35
+ , headers : List ( String, String )
36
+ , body : Maybe String
37
+ , isBase64Encoded : Bool
38
+ }
39
+
40
+
41
+ toJson : Response -> Json.Encode.Value
42
+ toJson serverResponse =
43
+ Json.Encode.object
44
+ [ ( "body", serverResponse.body |> Maybe.map Json.Encode.string |> Maybe.withDefault Json.Encode.null )
45
+ , ( "statusCode", serverResponse.statusCode |> Json.Encode.int )
46
+ , ( "headers"
47
+ , serverResponse.headers
48
+ |> collectMultiValueHeaders
49
+ |> List.map (Tuple.mapSecond (Json.Encode.list Json.Encode.string))
50
+ |> Json.Encode.object
51
+ )
52
+ , ( "kind", Json.Encode.string "server-response" )
53
+ , ( "isBase64Encoded", Json.Encode.bool serverResponse.isBase64Encoded )
54
+ ]
55
+
56
+
57
+ collectMultiValueHeaders : List ( String, String ) -> List ( String, List String )
58
+ collectMultiValueHeaders headers =
59
+ headers
60
+ |> List.Extra.groupWhile
61
+ (\( key1, _ ) ( key2, _ ) -> key1 == key2)
62
+ |> List.map
63
+ (\( ( key, firstValue ), otherValues ) ->
64
+ ( key
65
+ , firstValue
66
+ :: (otherValues |> List.map Tuple.second)
67
+ )
68
+ )
@@ -1,212 +1,16 @@
1
1
  module Pages.ContentCache exposing
2
- ( ContentCache
3
- , ContentJson
4
- , Entry(..)
5
- , Path
6
- , contentJsonDecoder
7
- , init
8
- , is404
9
- , lazyLoad
10
- , notFoundReason
2
+ ( Path
11
3
  , pathForUrl
12
4
  )
13
5
 
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
6
  import Pages.Internal.String as String
22
- import RequestsAndPending exposing (RequestsAndPending)
23
- import Task exposing (Task)
24
7
  import Url exposing (Url)
25
8
 
26
9
 
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
10
  type alias Path =
52
11
  List String
53
12
 
54
13
 
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
14
  pathForUrl : { currentUrl : Url, basePath : List String } -> Path
211
15
  pathForUrl { currentUrl, basePath } =
212
16
  currentUrl.path
@@ -214,35 +18,3 @@ pathForUrl { currentUrl, basePath } =
214
18
  |> String.split "/"
215
19
  |> List.filter ((/=) "")
216
20
  |> 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