elm-pages 3.0.0-beta.1 → 3.0.0-beta.10

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 (49) hide show
  1. package/README.md +10 -1
  2. package/codegen/elm-pages-codegen.js +803 -284
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +285 -101
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
  12. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +140 -17
  13. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +218 -0
  14. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  15. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  16. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  17. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  18. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
  19. package/generator/src/SharedTemplate.elm +1 -1
  20. package/generator/src/build.js +75 -42
  21. package/generator/src/compatibility-key.js +1 -0
  22. package/generator/src/config.js +41 -0
  23. package/generator/src/dev-server.js +36 -56
  24. package/generator/src/generate-template-module-connector.js +0 -28
  25. package/generator/src/pre-render-html.js +31 -17
  26. package/generator/src/render.js +2 -0
  27. package/generator/src/seo-renderer.js +11 -4
  28. package/generator/src/vite-utils.js +78 -0
  29. package/generator/template/app/Api.elm +1 -1
  30. package/generator/template/app/Site.elm +6 -1
  31. package/package.json +2 -3
  32. package/src/ApiRoute.elm +0 -3
  33. package/src/DataSource/File.elm +1 -1
  34. package/src/DataSource/Internal/Request.elm +0 -5
  35. package/src/DataSource.elm +39 -31
  36. package/src/Form/Field.elm +1 -1
  37. package/src/Form.elm +1 -1
  38. package/src/Head/Seo.elm +16 -27
  39. package/src/Head.elm +126 -0
  40. package/src/HtmlPrinter.elm +7 -3
  41. package/src/Pages/Generate.elm +544 -102
  42. package/src/Pages/Internal/NotFoundReason.elm +3 -2
  43. package/src/Pages/Internal/Platform/Cli.elm +91 -27
  44. package/src/Pages/Internal/Platform/Cli.elm.bak +1276 -0
  45. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  46. package/src/Pages/Internal/Platform.elm +34 -27
  47. package/src/Pages/ProgramConfig.elm +6 -3
  48. package/src/Server/Session.elm +149 -83
  49. package/src/Server/SetCookie.elm +89 -31
@@ -171,7 +171,7 @@ just the metadata.
171
171
  (Decode.field "tags" (Decode.list Decode.string))
172
172
 
173
173
  If you wanted to use this to get this metadata for all blog posts in a folder, you could use
174
- the [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource.Glob).
174
+ the [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource-Glob).
175
175
 
176
176
  import DataSource exposing (DataSource)
177
177
  import DataSource.File as File
@@ -1,10 +1,5 @@
1
1
  module DataSource.Internal.Request exposing (request)
2
2
 
3
- {-| Build a `DataSource.Http` request (analogous to [Http.request](https://package.elm-lang.org/packages/elm/http/latest/Http#request)).
4
- This function takes in all the details to build a `DataSource.Http` request, but you can build your own simplified helper functions
5
- with this as a low-level detail, or you can use functions like [DataSource.Http.get](#get).
6
- -}
7
-
8
3
  import DataSource exposing (DataSource)
9
4
  import DataSource.Http exposing (Body, Expect)
10
5
 
@@ -7,7 +7,7 @@ module DataSource exposing
7
7
  , map2, map3, map4, map5, map6, map7, map8, map9
8
8
  )
9
9
 
10
- {-| In an `elm-pages` app, each page can define a value `data` which is a `DataSource` that will be resolved **before** `init` is called. That means it is also available
10
+ {-| In an `elm-pages` app, each Route Module can define a value `data` which is a `DataSource` that will be resolved **before** `init` is called. That means it is also available
11
11
  when the page's HTML is pre-rendered during the build step. You can also access the resolved data in `head` to use it for the page's SEO meta tags.
12
12
 
13
13
  A `DataSource` lets you pull in data from:
@@ -20,9 +20,17 @@ A `DataSource` lets you pull in data from:
20
20
  - Or any combination of the above, using `DataSource.map2`, `DataSource.andThen`, or other combining/continuing helpers from this module
21
21
 
22
22
 
23
- ## Where Does DataSource Data Come From?
23
+ ## DataSource's vs. Effect's/Cmd's
24
24
 
25
- Data from a `DataSource` is resolved when you load a page in the `elm-pages` dev server, or when you run `elm-pages build`.
25
+ DataSource's are always resolved before the page is rendered and sent to the browser. A DataSource is never executed
26
+ in the Browser. Instead, the resolved data from the DataSource is passed down to the Browser - it has been resolved
27
+ before any client-side JavaScript ever executes. In the case of a pre-rendered route, this is during the CLI build phase,
28
+ and for server-rendered routes its DataSource is resolved on the server.
29
+
30
+ Effect's/Cmd's are never executed on the CLI or server, they are only executed in the Browser. The data from a Route Module's
31
+ `init` function is used to render the initial HTML on the server or build step, but the Effect isn't executed and `update` is never called
32
+ before the page is hydrated in the Browser. This gives a deterministic mental model of what the first render will look like,
33
+ and a nicely typed way to define the initial `Data` you have to render your initial view.
26
34
 
27
35
  Because `elm-pages` hydrates into a full Elm single-page app, it does need the data in order to initialize the Elm app.
28
36
  So why not just get the data the old-fashioned way, with `elm/http`, for example?
@@ -123,16 +131,16 @@ A common use for this is to map your data into your elm-pages view:
123
131
  map : (a -> b) -> DataSource a -> DataSource b
124
132
  map fn requestInfo =
125
133
  case requestInfo of
126
- RequestError error ->
127
- RequestError error
134
+ ApiRoute value ->
135
+ ApiRoute (fn value)
128
136
 
129
137
  Request urls lookupFn ->
130
138
  Request
131
139
  urls
132
140
  (mapLookupFn fn lookupFn)
133
141
 
134
- ApiRoute value ->
135
- ApiRoute (fn value)
142
+ RequestError error ->
143
+ RequestError error
136
144
 
137
145
 
138
146
  mapLookupFn : (a -> b) -> (d -> c -> DataSource a) -> d -> c -> DataSource b
@@ -182,8 +190,8 @@ resolve =
182
190
 
183
191
  -}
184
192
  combine : List (DataSource value) -> DataSource (List value)
185
- combine =
186
- List.foldr (map2 (::)) (succeed [])
193
+ combine items =
194
+ List.foldl (map2 (::)) (succeed []) items |> map List.reverse
187
195
 
188
196
 
189
197
  {-| Like map, but it takes in two `Request`s.
@@ -212,11 +220,8 @@ combine =
212
220
  map2 : (a -> b -> c) -> DataSource a -> DataSource b -> DataSource c
213
221
  map2 fn request1 request2 =
214
222
  case ( request1, request2 ) of
215
- ( RequestError error, _ ) ->
216
- RequestError error
217
-
218
- ( _, RequestError error ) ->
219
- RequestError error
223
+ ( ApiRoute value1, ApiRoute value2 ) ->
224
+ ApiRoute (fn value1 value2)
220
225
 
221
226
  ( Request urls1 lookupFn1, Request urls2 lookupFn2 ) ->
222
227
  Request
@@ -233,8 +238,11 @@ map2 fn request1 request2 =
233
238
  urls1
234
239
  (mapReq fn (\_ _ -> ApiRoute value2) lookupFn1)
235
240
 
236
- ( ApiRoute value1, ApiRoute value2 ) ->
237
- ApiRoute (fn value1 value2)
241
+ ( RequestError error, _ ) ->
242
+ RequestError error
243
+
244
+ ( _, RequestError error ) ->
245
+ RequestError error
238
246
 
239
247
 
240
248
  mapReq : (a -> b -> c) -> (e -> d -> DataSource a) -> (e -> d -> DataSource b) -> e -> d -> DataSource c
@@ -247,9 +255,6 @@ mapReq fn lookupFn1 lookupFn2 maybeMock rawResponses =
247
255
  lookup : Maybe Pages.StaticHttpRequest.MockResolver -> DataSource value -> RequestsAndPending -> Result Pages.StaticHttpRequest.Error value
248
256
  lookup maybeMockResolver requestInfo rawResponses =
249
257
  case requestInfo of
250
- RequestError error ->
251
- Err error
252
-
253
258
  Request urls lookupFn ->
254
259
  lookup maybeMockResolver
255
260
  (addUrls urls (lookupFn maybeMockResolver rawResponses))
@@ -258,18 +263,21 @@ lookup maybeMockResolver requestInfo rawResponses =
258
263
  ApiRoute value ->
259
264
  Ok value
260
265
 
266
+ RequestError error ->
267
+ Err error
268
+
261
269
 
262
270
  addUrls : List HashRequest.Request -> DataSource value -> DataSource value
263
271
  addUrls urlsToAdd requestInfo =
264
272
  case requestInfo of
265
- RequestError error ->
266
- RequestError error
273
+ ApiRoute value ->
274
+ ApiRoute value
267
275
 
268
276
  Request initialUrls function ->
269
277
  Request (initialUrls ++ urlsToAdd) function
270
278
 
271
- ApiRoute value ->
272
- ApiRoute value
279
+ RequestError error ->
280
+ RequestError error
273
281
 
274
282
 
275
283
  {-| The full details to perform a StaticHttp request.
@@ -286,14 +294,14 @@ type alias RequestDetails =
286
294
  lookupUrls : DataSource value -> List RequestDetails
287
295
  lookupUrls requestInfo =
288
296
  case requestInfo of
289
- RequestError _ ->
290
- -- TODO should this have URLs passed through?
297
+ ApiRoute _ ->
291
298
  []
292
299
 
293
300
  Request urls _ ->
294
301
  urls
295
302
 
296
- ApiRoute _ ->
303
+ RequestError _ ->
304
+ -- TODO should this have URLs passed through?
297
305
  []
298
306
 
299
307
 
@@ -324,19 +332,19 @@ andThen fn requestInfo =
324
332
  rawResponses
325
333
  |> (\result ->
326
334
  case result of
327
- Err error ->
328
- RequestError error
329
-
330
335
  Ok value ->
331
336
  case fn value of
337
+ ApiRoute finalValue ->
338
+ ApiRoute finalValue
339
+
332
340
  Request values function ->
333
341
  Request values function
334
342
 
335
343
  RequestError error ->
336
344
  RequestError error
337
345
 
338
- ApiRoute finalValue ->
339
- ApiRoute finalValue
346
+ Err error ->
347
+ RequestError error
340
348
  )
341
349
  )
342
350
 
@@ -6,7 +6,7 @@ module Form.Field exposing
6
6
  , required, withClientValidation, withInitialValue, map
7
7
  , email, password, search, telephone, url, textarea
8
8
  , withMax, withMin, withStep, withMinLength, withMaxLength
9
- , No(..), Yes(..)
9
+ , No, Yes
10
10
  )
11
11
 
12
12
  {-|
package/src/Form.elm CHANGED
@@ -575,7 +575,7 @@ field name (Field fieldParser kind) (Form definitions parseFn toInitialValues) =
575
575
 
576
576
  {-| Declare a hidden field for the form.
577
577
 
578
- Unlike [`field`](#field) declarations which are rendered using [`Form.ViewField`](Form-ViewField)
578
+ Unlike [`field`](#field) declarations which are rendered using [`Form.FieldView`](Form-FieldView)
579
579
  functions, `hiddenField` inputs are automatically inserted into the form when you render it.
580
580
 
581
581
  You define the field's validations the same way as for `field`, with the
package/src/Head/Seo.elm CHANGED
@@ -49,10 +49,12 @@ with the `head` function that you pass to your Pages config (`Pages.application`
49
49
 
50
50
  -}
51
51
 
52
+ import DateOrDateTime exposing (DateOrDateTime)
52
53
  import Head
53
54
  import Head.Twitter as Twitter
54
55
  import LanguageTag.Country
55
56
  import LanguageTag.Language
57
+ import MimeType exposing (MimeType)
56
58
  import Pages.Url
57
59
 
58
60
 
@@ -235,9 +237,9 @@ website common =
235
237
  article :
236
238
  { tags : List String
237
239
  , section : Maybe String
238
- , publishedTime : Maybe Iso8601DateTime
239
- , modifiedTime : Maybe Iso8601DateTime
240
- , expirationTime : Maybe Iso8601DateTime
240
+ , publishedTime : Maybe DateOrDateTime
241
+ , modifiedTime : Maybe DateOrDateTime
242
+ , expirationTime : Maybe DateOrDateTime
241
243
  }
242
244
  -> Common
243
245
  -> List Head.Tag
@@ -252,7 +254,7 @@ book :
252
254
  ->
253
255
  { tags : List String
254
256
  , isbn : Maybe String
255
- , releaseDate : Maybe Iso8601DateTime
257
+ , releaseDate : Maybe DateOrDateTime
256
258
  }
257
259
  -> List Head.Tag
258
260
  book common details =
@@ -354,7 +356,7 @@ tagsForAudio : Audio -> List ( String, Maybe Head.AttributeValue )
354
356
  tagsForAudio audio =
355
357
  [ ( "og:audio", audio.url |> Head.raw |> Just )
356
358
  , ( "og:audio:secure_url", audio.url |> Head.raw |> Just )
357
- , ( "og:audio:type", audio.mimeType |> Maybe.map Head.raw )
359
+ , ( "og:audio:type", audio.mimeType |> Maybe.map (MimeType.toString >> Head.raw) )
358
360
  ]
359
361
 
360
362
 
@@ -371,14 +373,14 @@ type ContentDetails
371
373
  | Article
372
374
  { tags : List String
373
375
  , section : Maybe String
374
- , publishedTime : Maybe Iso8601DateTime
375
- , modifiedTime : Maybe Iso8601DateTime
376
- , expirationTime : Maybe Iso8601DateTime
376
+ , publishedTime : Maybe DateOrDateTime
377
+ , modifiedTime : Maybe DateOrDateTime
378
+ , expirationTime : Maybe DateOrDateTime
377
379
  }
378
380
  | Book
379
381
  { tags : List String
380
382
  , isbn : Maybe String
381
- , releaseDate : Maybe Iso8601DateTime
383
+ , releaseDate : Maybe DateOrDateTime
382
384
  }
383
385
  | Song
384
386
  {-
@@ -399,20 +401,6 @@ type ContentDetails
399
401
  }
400
402
 
401
403
 
402
- {-| <https://en.wikipedia.org/wiki/ISO_8601>
403
- -}
404
- type alias Iso8601DateTime =
405
- -- TODO should be more type-safe here
406
- String
407
-
408
-
409
- {-| <https://en.wikipedia.org/wiki/Media_type>
410
- -}
411
- type alias MimeType =
412
- -- TODO should be more type-safe here
413
- String
414
-
415
-
416
404
  {-| See <https://ogp.me/#structured>
417
405
  -}
418
406
  type alias Image =
@@ -448,6 +436,7 @@ tagsForVideo video =
448
436
  , ( "og:video:secure_url", video.url |> Head.raw |> Just )
449
437
  , ( "og:video:width", video.dimensions |> Maybe.map .width |> Maybe.map String.fromInt |> Maybe.map Head.raw )
450
438
  , ( "og:video:height", video.dimensions |> Maybe.map .height |> Maybe.map String.fromInt |> Maybe.map Head.raw )
439
+ , ( "og:video:type", video.mimeType |> Maybe.map (MimeType.toString >> Head.raw) )
451
440
  ]
452
441
 
453
442
 
@@ -466,9 +455,9 @@ tags (Content common details) =
466
455
  -}
467
456
  [ ( "og:type", "article" |> Head.raw |> Just )
468
457
  , ( "article:section", articleDetails.section |> Maybe.map Head.raw )
469
- , ( "article:published_time", articleDetails.publishedTime |> Maybe.map Head.raw )
470
- , ( "article:modified_time", articleDetails.modifiedTime |> Maybe.map Head.raw )
471
- , ( "article:expiration_time", articleDetails.expirationTime |> Maybe.map Head.raw )
458
+ , ( "article:published_time", articleDetails.publishedTime |> Maybe.map (DateOrDateTime.toIso8601 >> Head.raw) )
459
+ , ( "article:modified_time", articleDetails.modifiedTime |> Maybe.map (DateOrDateTime.toIso8601 >> Head.raw) )
460
+ , ( "article:expiration_time", articleDetails.expirationTime |> Maybe.map (DateOrDateTime.toIso8601 >> Head.raw) )
472
461
  ]
473
462
  ++ List.map
474
463
  (\tag -> ( "article:tag", tag |> Head.raw |> Just ))
@@ -477,7 +466,7 @@ tags (Content common details) =
477
466
  Book bookDetails ->
478
467
  [ ( "og:type", "book" |> Head.raw |> Just )
479
468
  , ( "og:isbn", bookDetails.isbn |> Maybe.map Head.raw )
480
- , ( "og:release_date", bookDetails.releaseDate |> Maybe.map Head.raw )
469
+ , ( "og:release_date", bookDetails.releaseDate |> Maybe.map (DateOrDateTime.toIso8601 >> Head.raw) )
481
470
  ]
482
471
  ++ List.map
483
472
  (\tag -> ( "book:tag", tag |> Head.raw |> Just ))
package/src/Head.elm CHANGED
@@ -1,6 +1,7 @@
1
1
  module Head exposing
2
2
  ( Tag, metaName, metaProperty, metaRedirect
3
3
  , rssLink, sitemapLink, rootLanguage, manifestLink
4
+ , nonLoadingNode
4
5
  , structuredData
5
6
  , AttributeValue
6
7
  , currentPageFullUrl, urlAttribute, raw
@@ -20,6 +21,8 @@ writing a plugin package to extend `elm-pages`.
20
21
  @docs Tag, metaName, metaProperty, metaRedirect
21
22
  @docs rssLink, sitemapLink, rootLanguage, manifestLink
22
23
 
24
+ @docs nonLoadingNode
25
+
23
26
 
24
27
  ## Structured Data
25
28
 
@@ -45,9 +48,11 @@ writing a plugin package to extend `elm-pages`.
45
48
 
46
49
  import Json.Encode
47
50
  import LanguageTag exposing (LanguageTag)
51
+ import List.Extra
48
52
  import MimeType
49
53
  import Pages.Internal.String as String
50
54
  import Pages.Url
55
+ import Regex
51
56
 
52
57
 
53
58
  {-| Values that can be passed to the generated `Pages.application` config
@@ -57,6 +62,7 @@ type Tag
57
62
  = Tag Details
58
63
  | StructuredData Json.Encode.Value
59
64
  | RootModifier String String
65
+ | Stripped String
60
66
 
61
67
 
62
68
  type alias Details =
@@ -211,6 +217,120 @@ canonicalLink maybePath =
211
217
  ]
212
218
 
213
219
 
220
+ {-| Escape hatch for any head tags that don't have high-level helpers. This lets you build arbitrary head nodes as long as they
221
+ are not loading or preloading directives.
222
+
223
+ Tags that do loading/pre-loading will not work from this function. `elm-pages` uses ViteJS for loading assets like
224
+ script tags, stylesheets, fonts, etc., and allows you to customize which assets to preload and how through the elm-pages.config.mjs file.
225
+ See the full discussion of the design in [#339](https://github.com/dillonkearns/elm-pages/discussions/339).
226
+
227
+ So for example the following tags would _not_ load if defined through `nonLoadingNode`, and would instead need to be registered through Vite:
228
+
229
+ - `<script src="...">`
230
+ - `<link href="/style.css">`
231
+ - `<link rel="preload">`
232
+
233
+ The following tag would successfully render as it is a non-loading tag:
234
+
235
+ Head.nonLoadingNode "link"
236
+ [ ( "rel", Head.raw "alternate" )
237
+ , ( "type", Head.raw "application/atom+xml" )
238
+ , ( "title", Head.raw "News" )
239
+ , ( "href", Head.raw "/news/atom" )
240
+ ]
241
+
242
+ Renders the head tag:
243
+
244
+ `<link rel="alternate" type="application/atom+xml" title="News" href="/news/atom">`
245
+
246
+ -}
247
+ nonLoadingNode : String -> List ( String, AttributeValue ) -> Tag
248
+ nonLoadingNode nodeName attributes =
249
+ let
250
+ relTag : Maybe AttributeValue
251
+ relTag =
252
+ attributes
253
+ |> List.Extra.find (\( key, _ ) -> key == "rel")
254
+ |> Maybe.map Tuple.second
255
+
256
+ isPreloadDirective : Bool
257
+ isPreloadDirective =
258
+ case relTag of
259
+ Just (Raw rel) ->
260
+ let
261
+ isLinkTag : Bool
262
+ isLinkTag =
263
+ nodeName |> matchesKeyword "link"
264
+ in
265
+ isLinkTag
266
+ && (rel
267
+ |> matchesOneKeyword
268
+ [ "preload"
269
+ , "modulepreload"
270
+ , "preconnect"
271
+ , "dns-prefetch"
272
+ , "stylesheet"
273
+ ]
274
+ )
275
+
276
+ _ ->
277
+ False
278
+ in
279
+ if
280
+ (nodeName |> matchesKeyword "script")
281
+ || isPreloadDirective
282
+ then
283
+ Stripped
284
+ ("<"
285
+ ++ nodeName
286
+ ++ " "
287
+ ++ (attributes
288
+ |> List.map
289
+ (\( name, value ) ->
290
+ name
291
+ ++ "=\""
292
+ ++ ((case value of
293
+ Raw rawValue ->
294
+ rawValue
295
+
296
+ _ ->
297
+ "<internals>"
298
+ )
299
+ ++ "\""
300
+ )
301
+ )
302
+ |> String.join " "
303
+ )
304
+ ++ " />"
305
+ )
306
+
307
+ else
308
+ node nodeName attributes
309
+
310
+
311
+ matchesOneKeyword : List String -> String -> Bool
312
+ matchesOneKeyword keywords string =
313
+ List.any
314
+ (\keyword -> string |> matchesKeyword keyword)
315
+ keywords
316
+
317
+
318
+ matchesKeyword : String -> String -> Bool
319
+ matchesKeyword regex string =
320
+ string |> matchesRegex ("^\\s*" ++ regex ++ "\\s*$")
321
+
322
+
323
+ matchesRegex : String -> String -> Bool
324
+ matchesRegex regex string =
325
+ string
326
+ |> Regex.contains
327
+ (Regex.fromStringWith
328
+ { caseInsensitive = True, multiline = True }
329
+ regex
330
+ |> Maybe.withDefault Regex.never
331
+ )
332
+
333
+
214
334
  {-| Let's you link to your manifest.json file, see <https://developer.mozilla.org/en-US/docs/Web/Manifest#deploying_a_manifest>.
215
335
  -}
216
336
  manifestLink : String -> Tag
@@ -443,6 +563,12 @@ toJson canonicalSiteUrl currentPagePath tag =
443
563
  , ( "keyValuePair", Json.Encode.list Json.Encode.string [ key, value ] )
444
564
  ]
445
565
 
566
+ Stripped message ->
567
+ Json.Encode.object
568
+ [ ( "type", Json.Encode.string "stripped" )
569
+ , ( "message", Json.Encode.string message )
570
+ ]
571
+
446
572
 
447
573
  encodeProperty : String -> String -> ( String, AttributeValue ) -> Json.Encode.Value
448
574
  encodeProperty canonicalSiteUrl currentPagePath ( name, value ) =
@@ -8,15 +8,19 @@ import Test.Html.Internal.ElmHtml.ToString exposing (defaultFormatOptions, nodeT
8
8
  import VirtualDom
9
9
 
10
10
 
11
- htmlToString : Html msg -> String
12
- htmlToString viewHtml =
11
+ htmlToString : Maybe { indent : Int, newLines : Bool } -> Html msg -> String
12
+ htmlToString formatOptions viewHtml =
13
13
  case
14
14
  Decode.decodeValue
15
15
  (decodeElmHtml (\_ _ -> VirtualDom.Normal (Decode.succeed ())))
16
16
  (asJsonView viewHtml)
17
17
  of
18
18
  Ok str ->
19
- nodeToStringWithOptions defaultFormatOptions str
19
+ nodeToStringWithOptions
20
+ (formatOptions
21
+ |> Maybe.withDefault defaultFormatOptions
22
+ )
23
+ str
20
24
 
21
25
  Err err ->
22
26
  "Error pre-rendering HTML in HtmlPrinter.elm: " ++ Decode.errorToString err