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
package/src/Head.elm ADDED
@@ -0,0 +1,452 @@
1
+ module Head exposing
2
+ ( Tag, metaName, metaProperty, metaRedirect
3
+ , rssLink, sitemapLink, rootLanguage
4
+ , structuredData
5
+ , AttributeValue
6
+ , currentPageFullUrl, urlAttribute, raw
7
+ , appleTouchIcon, icon
8
+ , toJson, canonicalLink
9
+ )
10
+
11
+ {-| This module contains low-level functions for building up
12
+ values that will be rendered into the page's `<head>` tag
13
+ when you run `elm-pages build`. Most likely the `Head.Seo` module
14
+ will do everything you need out of the box, and you will just need to import `Head`
15
+ so you can use the `Tag` type in your type annotations.
16
+
17
+ But this module might be useful if you have a special use case, or if you are
18
+ writing a plugin package to extend `elm-pages`.
19
+
20
+ @docs Tag, metaName, metaProperty, metaRedirect
21
+ @docs rssLink, sitemapLink, rootLanguage
22
+
23
+
24
+ ## Structured Data
25
+
26
+ @docs structuredData
27
+
28
+
29
+ ## `AttributeValue`s
30
+
31
+ @docs AttributeValue
32
+ @docs currentPageFullUrl, urlAttribute, raw
33
+
34
+
35
+ ## Icons
36
+
37
+ @docs appleTouchIcon, icon
38
+
39
+
40
+ ## Functions for use by generated code
41
+
42
+ @docs toJson, canonicalLink
43
+
44
+ -}
45
+
46
+ import Json.Encode
47
+ import LanguageTag exposing (LanguageTag)
48
+ import MimeType
49
+ import Pages.Internal.String as String
50
+ import Pages.Url
51
+
52
+
53
+ {-| Values that can be passed to the generated `Pages.application` config
54
+ through the `head` function.
55
+ -}
56
+ type Tag
57
+ = Tag Details
58
+ | StructuredData Json.Encode.Value
59
+ | RootModifier String String
60
+
61
+
62
+ type alias Details =
63
+ { name : String
64
+ , attributes : List ( String, AttributeValue )
65
+ }
66
+
67
+
68
+ {-| You can learn more about structured data in [Google's intro to structured data](https://developers.google.com/search/docs/guides/intro-structured-data).
69
+
70
+ When you add a `structuredData` item to one of your pages in `elm-pages`, it will add `json-ld` data to your document that looks like this:
71
+
72
+ ```html
73
+ <script type="application/ld+json">
74
+ {
75
+ "@context":"http://schema.org/",
76
+ "@type":"Article",
77
+ "headline":"Extensible Markdown Parsing in Pure Elm",
78
+ "description":"Introducing a new parser that extends your palette with no additional syntax",
79
+ "image":"https://elm-pages.com/images/article-covers/extensible-markdown-parsing.jpg",
80
+ "author":{
81
+ "@type":"Person",
82
+ "name":"Dillon Kearns"
83
+ },
84
+ "publisher":{
85
+ "@type":"Person",
86
+ "name":"Dillon Kearns"
87
+ },
88
+ "url":"https://elm-pages.com/blog/extensible-markdown-parsing-in-elm",
89
+ "datePublished":"2019-10-08",
90
+ "mainEntityOfPage":{
91
+ "@type":"SoftwareSourceCode",
92
+ "codeRepository":"https://github.com/dillonkearns/elm-pages",
93
+ "description":"A statically typed site generator for Elm.",
94
+ "author":"Dillon Kearns",
95
+ "programmingLanguage":{
96
+ "@type":"ComputerLanguage",
97
+ "url":"http://elm-lang.org/",
98
+ "name":"Elm",
99
+ "image":"http://elm-lang.org/",
100
+ "identifier":"http://elm-lang.org/"
101
+ }
102
+ }
103
+ }
104
+ </script>
105
+ ```
106
+
107
+ To get that data, you would write this in your `elm-pages` head tags:
108
+
109
+ import Json.Encode as Encode
110
+
111
+ {-| <https://schema.org/Article>
112
+ -}
113
+ encodeArticle :
114
+ { title : String
115
+ , description : String
116
+ , author : StructuredDataHelper { authorMemberOf | personOrOrganization : () } authorPossibleFields
117
+ , publisher : StructuredDataHelper { publisherMemberOf | personOrOrganization : () } publisherPossibleFields
118
+ , url : String
119
+ , imageUrl : String
120
+ , datePublished : String
121
+ , mainEntityOfPage : Encode.Value
122
+ }
123
+ -> Head.Tag
124
+ encodeArticle info =
125
+ Encode.object
126
+ [ ( "@context", Encode.string "http://schema.org/" )
127
+ , ( "@type", Encode.string "Article" )
128
+ , ( "headline", Encode.string info.title )
129
+ , ( "description", Encode.string info.description )
130
+ , ( "image", Encode.string info.imageUrl )
131
+ , ( "author", encode info.author )
132
+ , ( "publisher", encode info.publisher )
133
+ , ( "url", Encode.string info.url )
134
+ , ( "datePublished", Encode.string info.datePublished )
135
+ , ( "mainEntityOfPage", info.mainEntityOfPage )
136
+ ]
137
+ |> Head.structuredData
138
+
139
+ Take a look at this [Google Search Gallery](https://developers.google.com/search/docs/guides/search-gallery)
140
+ to see some examples of how structured data can be used by search engines to give rich search results. It can help boost
141
+ your rankings, get better engagement for your content, and also make your content more accessible. For example,
142
+ voice assistant devices can make use of structured data. If you're hosting a conference and want to make the event
143
+ date and location easy for attendees to find, this can make that information more accessible.
144
+
145
+ For the current version of API, you'll need to make sure that the format is correct and contains the required and recommended
146
+ structure.
147
+
148
+ Check out <https://schema.org> for a comprehensive listing of possible data types and fields. And take a look at
149
+ Google's [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool)
150
+ too make sure that your structured data is valid and includes the recommended values.
151
+
152
+ In the future, `elm-pages` will likely support a typed API, but schema.org is a massive spec, and changes frequently.
153
+ And there are multiple sources of information on the possible and recommended structure. So it will take some time
154
+ for the right API design to evolve. In the meantime, this allows you to make use of this for SEO purposes.
155
+
156
+ -}
157
+ structuredData : Json.Encode.Value -> Tag
158
+ structuredData value =
159
+ StructuredData value
160
+
161
+
162
+ {-| Create a raw `AttributeValue` (as opposed to some kind of absolute URL).
163
+ -}
164
+ raw : String -> AttributeValue
165
+ raw value =
166
+ Raw value
167
+
168
+
169
+ {-| Create an `AttributeValue` from an `ImagePath`.
170
+ -}
171
+ urlAttribute : Pages.Url.Url -> AttributeValue
172
+ urlAttribute value =
173
+ FullUrl value
174
+
175
+
176
+ {-| Create an `AttributeValue` representing the current page's full url.
177
+ -}
178
+ currentPageFullUrl : AttributeValue
179
+ currentPageFullUrl =
180
+ FullUrlToCurrentPage
181
+
182
+
183
+ {-| Values, such as between the `<>`'s here:
184
+
185
+ ```html
186
+ <meta name="<THIS IS A VALUE>" content="<THIS IS A VALUE>" />
187
+ ```
188
+
189
+ -}
190
+ type AttributeValue
191
+ = Raw String
192
+ | FullUrl Pages.Url.Url
193
+ | FullUrlToCurrentPage
194
+
195
+
196
+ {-| It's recommended that you use the `Seo` module helpers, which will provide this
197
+ for you, rather than directly using this.
198
+
199
+ Example:
200
+
201
+ Head.canonicalLink "https://elm-pages.com"
202
+
203
+ -}
204
+ canonicalLink : Maybe String -> Tag
205
+ canonicalLink maybePath =
206
+ node "link"
207
+ [ ( "rel", raw "canonical" )
208
+ , ( "href"
209
+ , maybePath |> Maybe.map raw |> Maybe.withDefault currentPageFullUrl
210
+ )
211
+ ]
212
+
213
+
214
+ {-| Add a link to the site's RSS feed.
215
+
216
+ Example:
217
+
218
+ rssLink "/feed.xml"
219
+
220
+ ```html
221
+ <link rel="alternate" type="application/rss+xml" href="/rss.xml">
222
+ ```
223
+
224
+ -}
225
+ rssLink : String -> Tag
226
+ rssLink url =
227
+ node "link"
228
+ [ ( "rel", raw "alternate" )
229
+ , ( "type", raw "application/rss+xml" )
230
+ , ( "href", raw url )
231
+ ]
232
+
233
+
234
+ {-| -}
235
+ icon : List ( Int, Int ) -> MimeType.MimeImage -> Pages.Url.Url -> Tag
236
+ icon sizes imageMimeType imageUrl =
237
+ -- TODO allow "any" for sizes value
238
+ [ ( "rel", raw "icon" |> Just )
239
+ , ( "sizes"
240
+ , sizes
241
+ |> nonEmptyList
242
+ |> Maybe.map sizesToString
243
+ |> Maybe.map raw
244
+ )
245
+ , ( "type", imageMimeType |> MimeType.Image |> MimeType.toString |> raw |> Just )
246
+ , ( "href", urlAttribute imageUrl |> Just )
247
+ ]
248
+ |> filterMaybeValues
249
+ |> node "link"
250
+
251
+
252
+ nonEmptyList : List a -> Maybe (List a)
253
+ nonEmptyList list =
254
+ if List.isEmpty list then
255
+ Nothing
256
+
257
+ else
258
+ Just list
259
+
260
+
261
+ {-| Note: the type must be png.
262
+ See <https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html>.
263
+
264
+ If a size is provided, it will be turned into square dimensions as per the recommendations here: <https://developers.google.com/web/fundamentals/design-and-ux/browser-customization/#safari>
265
+
266
+ Images must be png's, and non-transparent images are recommended. Current recommended dimensions are 180px and 192px.
267
+
268
+ -}
269
+ appleTouchIcon : Maybe Int -> Pages.Url.Url -> Tag
270
+ appleTouchIcon maybeSize imageUrl =
271
+ [ ( "rel", raw "apple-touch-icon" |> Just )
272
+ , ( "sizes"
273
+ , maybeSize
274
+ |> Maybe.map (\size -> sizesToString [ ( size, size ) ])
275
+ |> Maybe.map raw
276
+ )
277
+ , ( "href", urlAttribute imageUrl |> Just )
278
+ ]
279
+ |> filterMaybeValues
280
+ |> node "link"
281
+
282
+
283
+ {-| Set the language for a page.
284
+
285
+ <https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang>
286
+
287
+ import Head
288
+ import LanguageTag
289
+ import LanguageTag.Language
290
+
291
+ LanguageTag.Language.de -- sets the page's language to German
292
+ |> LanguageTag.build LanguageTag.emptySubtags
293
+ |> Head.rootLanguage
294
+
295
+ This results pre-rendered HTML with a global lang tag set.
296
+
297
+ ```html
298
+ <html lang="no">
299
+ ...
300
+ </html>
301
+ ```
302
+
303
+ -}
304
+ rootLanguage : LanguageTag -> Tag
305
+ rootLanguage languageTag =
306
+ languageTag
307
+ |> LanguageTag.toString
308
+ |> RootModifier "lang"
309
+
310
+
311
+
312
+ -- TODO rootDirection for
313
+
314
+
315
+ filterMaybeValues : List ( String, Maybe a ) -> List ( String, a )
316
+ filterMaybeValues list =
317
+ list
318
+ |> List.filterMap
319
+ (\( key, maybeValue ) ->
320
+ case maybeValue of
321
+ Just value ->
322
+ Just ( key, value )
323
+
324
+ Nothing ->
325
+ Nothing
326
+ )
327
+
328
+
329
+ sizesToString : List ( Int, Int ) -> String
330
+ sizesToString sizes =
331
+ sizes
332
+ |> List.map (\( x, y ) -> String.fromInt x ++ "x" ++ String.fromInt y)
333
+ |> String.join " "
334
+
335
+
336
+ {-| Add a link to the site's RSS feed.
337
+
338
+ Example:
339
+
340
+ sitemapLink "/feed.xml"
341
+
342
+ ```html
343
+ <link rel="sitemap" type="application/xml" href="/sitemap.xml">
344
+ ```
345
+
346
+ -}
347
+ sitemapLink : String -> Tag
348
+ sitemapLink url =
349
+ node "link"
350
+ [ ( "rel", raw "sitemap" )
351
+ , ( "type", raw "application/xml" )
352
+ , ( "href", raw url )
353
+ ]
354
+
355
+
356
+ {-| Example:
357
+
358
+ Head.metaProperty "fb:app_id" (Head.raw "123456789")
359
+
360
+ Results in `<meta property="fb:app_id" content="123456789" />`
361
+
362
+ -}
363
+ metaProperty : String -> AttributeValue -> Tag
364
+ metaProperty property content =
365
+ node "meta"
366
+ [ ( "property", raw property )
367
+ , ( "content", content )
368
+ ]
369
+
370
+
371
+ {-| Example:
372
+
373
+ Head.metaName "twitter:card" (Head.raw "summary_large_image")
374
+
375
+ Results in `<meta name="twitter:card" content="summary_large_image" />`
376
+
377
+ -}
378
+ metaName : String -> AttributeValue -> Tag
379
+ metaName name content =
380
+ node "meta"
381
+ [ ( "name", Raw name )
382
+ , ( "content", content )
383
+ ]
384
+
385
+
386
+ {-| Example:
387
+
388
+ metaRedirect (Raw "0; url=https://google.com")
389
+
390
+ Results in `<meta http-equiv="refresh" content="0; url=https://google.com" />`
391
+
392
+ -}
393
+ metaRedirect : AttributeValue -> Tag
394
+ metaRedirect content =
395
+ node "meta"
396
+ [ ( "http-equiv", Raw "refresh" )
397
+ , ( "content", content )
398
+ ]
399
+
400
+
401
+ {-| Low-level function for creating a tag for the HTML document's `<head>`.
402
+ -}
403
+ node : String -> List ( String, AttributeValue ) -> Tag
404
+ node name attributes =
405
+ Tag
406
+ { name = name
407
+ , attributes = attributes
408
+ }
409
+
410
+
411
+ {-| Feel free to use this, but in 99% of cases you won't need it. The generated
412
+ code will run this for you to generate your `manifest.json` file automatically!
413
+ -}
414
+ toJson : String -> String -> Tag -> Json.Encode.Value
415
+ toJson canonicalSiteUrl currentPagePath tag =
416
+ case tag of
417
+ Tag headTag ->
418
+ Json.Encode.object
419
+ [ ( "name", Json.Encode.string headTag.name )
420
+ , ( "attributes", Json.Encode.list (encodeProperty canonicalSiteUrl currentPagePath) headTag.attributes )
421
+ , ( "type", Json.Encode.string "head" )
422
+ ]
423
+
424
+ StructuredData value ->
425
+ Json.Encode.object
426
+ [ ( "contents", value )
427
+ , ( "type", Json.Encode.string "json-ld" )
428
+ ]
429
+
430
+ RootModifier key value ->
431
+ Json.Encode.object
432
+ [ ( "type", Json.Encode.string "root" )
433
+ , ( "keyValuePair", Json.Encode.list Json.Encode.string [ key, value ] )
434
+ ]
435
+
436
+
437
+ encodeProperty : String -> String -> ( String, AttributeValue ) -> Json.Encode.Value
438
+ encodeProperty canonicalSiteUrl currentPagePath ( name, value ) =
439
+ case value of
440
+ Raw rawValue ->
441
+ Json.Encode.list Json.Encode.string [ name, rawValue ]
442
+
443
+ FullUrlToCurrentPage ->
444
+ Json.Encode.list Json.Encode.string [ name, joinPaths canonicalSiteUrl currentPagePath ]
445
+
446
+ FullUrl url ->
447
+ Json.Encode.list Json.Encode.string [ name, Pages.Url.toAbsoluteUrl canonicalSiteUrl url ]
448
+
449
+
450
+ joinPaths : String -> String -> String
451
+ joinPaths base path =
452
+ String.chopEnd "/" base ++ "/" ++ String.chopStart "/" path
@@ -0,0 +1,27 @@
1
+ module HtmlPrinter exposing (htmlToString)
2
+
3
+ import Html exposing (Html)
4
+ import Json.Decode as Decode
5
+ import Json.Encode
6
+ import Test.Html.Internal.ElmHtml.InternalTypes exposing (decodeElmHtml)
7
+ import Test.Html.Internal.ElmHtml.ToString exposing (defaultFormatOptions, nodeToStringWithOptions)
8
+ import VirtualDom
9
+
10
+
11
+ htmlToString : Html msg -> String
12
+ htmlToString viewHtml =
13
+ case
14
+ Decode.decodeValue
15
+ (decodeElmHtml (\_ _ -> VirtualDom.Normal (Decode.succeed ())))
16
+ (asJsonView viewHtml)
17
+ of
18
+ Ok str ->
19
+ nodeToStringWithOptions defaultFormatOptions str
20
+
21
+ Err err ->
22
+ "Error: " ++ Decode.errorToString err
23
+
24
+
25
+ asJsonView : Html msg -> Decode.Value
26
+ asJsonView x =
27
+ Json.Encode.string "REPLACE_ME_WITH_JSON_STRINGIFY"
@@ -0,0 +1,89 @@
1
+ module Internal.ApiRoute exposing
2
+ ( ApiRoute(..)
3
+ , ApiRouteBuilder(..)
4
+ , firstMatch
5
+ , pathToMatches
6
+ , tryMatch
7
+ , withRoutes
8
+ )
9
+
10
+ import DataSource exposing (DataSource)
11
+ import Regex exposing (Regex)
12
+
13
+
14
+ {-| -}
15
+ firstMatch : String -> List (ApiRoute response) -> Maybe (ApiRoute response)
16
+ firstMatch path handlers =
17
+ case handlers of
18
+ [] ->
19
+ Nothing
20
+
21
+ first :: rest ->
22
+ case tryMatchDone path first of
23
+ Just response ->
24
+ Just response
25
+
26
+ Nothing ->
27
+ firstMatch path rest
28
+
29
+
30
+ {-| -}
31
+ tryMatchDone : String -> ApiRoute response -> Maybe (ApiRoute response)
32
+ tryMatchDone path (ApiRoute handler) =
33
+ if Regex.contains handler.regex path then
34
+ Just (ApiRoute handler)
35
+
36
+ else
37
+ Nothing
38
+
39
+
40
+ {-| -}
41
+ type ApiRoute response
42
+ = ApiRoute
43
+ { regex : Regex
44
+ , matchesToResponse : String -> DataSource (Maybe response)
45
+ , buildTimeRoutes : DataSource (List String)
46
+ , handleRoute : String -> DataSource Bool
47
+ }
48
+
49
+
50
+ {-| -}
51
+ pathToMatches : String -> ApiRouteBuilder a constructor -> List String
52
+ pathToMatches path (ApiRouteBuilder pattern _ _ _) =
53
+ Regex.find
54
+ (Regex.fromString pattern
55
+ |> Maybe.withDefault Regex.never
56
+ )
57
+ path
58
+ |> List.concatMap .submatches
59
+ |> List.filterMap identity
60
+
61
+
62
+ {-| -}
63
+ withRoutes : (constructor -> List (List String)) -> ApiRouteBuilder a constructor -> List String
64
+ withRoutes buildUrls (ApiRouteBuilder _ _ toString constructor) =
65
+ buildUrls (constructor [])
66
+ |> List.map toString
67
+
68
+
69
+ {-| -}
70
+ tryMatch : String -> ApiRouteBuilder response constructor -> Maybe response
71
+ tryMatch path (ApiRouteBuilder pattern handler _ _) =
72
+ let
73
+ matches : List String
74
+ matches =
75
+ Regex.find
76
+ (Regex.fromString pattern
77
+ |> Maybe.withDefault Regex.never
78
+ )
79
+ path
80
+ |> List.concatMap .submatches
81
+ |> List.filterMap identity
82
+ in
83
+ handler matches
84
+ |> Just
85
+
86
+
87
+ {-| -}
88
+ type ApiRouteBuilder a constructor
89
+ = ApiRouteBuilder String (List String -> a) (List String -> String) (List String -> constructor)
@@ -0,0 +1,18 @@
1
+ module Internal.OptimizedDecoder exposing (OptimizedDecoder(..), jd, jde)
2
+
3
+ import Json.Decode
4
+ import Json.Decode.Exploration
5
+
6
+
7
+ type OptimizedDecoder a
8
+ = OptimizedDecoder (Json.Decode.Decoder a) (Json.Decode.Exploration.Decoder a)
9
+
10
+
11
+ jd : OptimizedDecoder a -> Json.Decode.Decoder a
12
+ jd (OptimizedDecoder jd_ _) =
13
+ jd_
14
+
15
+
16
+ jde : OptimizedDecoder a -> Json.Decode.Exploration.Decoder a
17
+ jde (OptimizedDecoder _ jde_) =
18
+ jde_
@@ -0,0 +1,6 @@
1
+ module KeepOrDiscard exposing (KeepOrDiscard(..))
2
+
3
+
4
+ type KeepOrDiscard
5
+ = Keep
6
+ | Discard