[{"name":"ApiRoute","comment":"\n\n@docs Done, Handler, Response, buildTimeRoutes, capture, int, literal, single, slash, succeed\n\n","unions":[],"aliases":[{"name":"Done","comment":" ","args":["response"],"type":"Internal.ApiRoute.Done response"},{"name":"Handler","comment":" ","args":["a","constructor"],"type":"Internal.ApiRoute.Handler a constructor"},{"name":"Response","comment":" ","args":[],"type":"{ body : String.String }"}],"values":[{"name":"buildTimeRoutes","comment":" ","type":"(constructor -> DataSource.DataSource (List.List (List.List String.String))) -> ApiRoute.Handler (DataSource.DataSource ApiRoute.Response) constructor -> ApiRoute.Done ApiRoute.Response"},{"name":"capture","comment":" ","type":"ApiRoute.Handler (String.String -> a) constructor -> ApiRoute.Handler a (String.String -> constructor)"},{"name":"int","comment":" ","type":"ApiRoute.Handler (Basics.Int -> a) constructor -> ApiRoute.Handler a (Basics.Int -> constructor)"},{"name":"literal","comment":" ","type":"String.String -> ApiRoute.Handler a constructor -> ApiRoute.Handler a constructor"},{"name":"single","comment":" ","type":"ApiRoute.Handler (DataSource.DataSource ApiRoute.Response) (List.List String.String) -> ApiRoute.Done ApiRoute.Response"},{"name":"slash","comment":" ","type":"ApiRoute.Handler a constructor -> ApiRoute.Handler a constructor"},{"name":"succeed","comment":" ","type":"a -> ApiRoute.Handler a (List.List String.String)"}],"binops":[]},{"name":"DataSource","comment":" StaticHttp requests are an alternative to doing Elm HTTP requests the traditional way using the `elm/http` package.\n\nThe key differences are:\n\n - `StaticHttp.Request`s are performed once at build time (`Http.Request`s are performed at runtime, at whenever point you perform them)\n - `StaticHttp.Request`s strip out unused JSON data from the data your decoder doesn't touch to minimize the JSON payload\n - `StaticHttp.Request`s can use [`Pages.Secrets`](Pages.Secrets) to securely use credentials from your environment variables which are completely masked in the production assets.\n - `StaticHttp.Request`s have a built-in `StaticHttp.andThen` that allows you to perform follow-up requests without using tasks\n\n\n## Scenarios where StaticHttp is a good fit\n\nIf you need data that is refreshed often you may want to do a traditional HTTP request with the `elm/http` package.\nThe kinds of situations that are served well by static HTTP are with data that updates moderately frequently or infrequently (or never).\nA common pattern is to trigger a new build when data changes. Many JAMstack services\nallow you to send a WebHook to your host (for example, Netlify is a good static file host that supports triggering builds with webhooks). So\nyou may want to have your site rebuild everytime your calendar feed has an event added, or whenever a page or article is added\nor updated on a CMS service like Contentful.\n\nIn scenarios like this, you can serve data that is just as up-to-date as it would be using `elm/http`, but you get the performance\ngains of using `StaticHttp.Request`s as well as the simplicity and robustness that comes with it. Read more about these benefits\nin [this article introducing StaticHttp requests and some concepts around it](https://elm-pages.com/blog/static-http).\n\n\n## Scenarios where StaticHttp is not a good fit\n\n - Data that is specific to the logged-in user\n - Data that needs to be the very latest and changes often (for example, sports scores)\n\n@docs DataSource\n\n@docs map, succeed, fail\n\n@docs fromResult\n\n\n## Building a StaticHttp Request Body\n\nThe way you build a body is analogous to the `elm/http` package. Currently, only `emptyBody` and\n`stringBody` are supported. If you have a use case that calls for a different body type, please open a Github issue\nand describe your use case!\n\n@docs Body, emptyBody, stringBody, jsonBody\n\n\n## Chaining Requests\n\n@docs andThen, resolve, combine\n\n@docs andMap\n\n@docs map2, map3, map4, map5, map6, map7, map8, map9\n\n\n## Optimizing Page Data\n\nDistilling data lets you reduce the amount of data loaded on the client. You can also use it to perform computations at\nbuild-time or server-request-time, store the result of the computation and then simply load that result on the client\nwithout needing redo the computation again on the client.\n\n@docs distill, validate, distillCodec, distillSerializeCodec\n\n\n### Ensuring Unique Distill Keys\n\nIf you use the same string key for two different distilled values that have differing encoded JSON, then you\nwill get a build error (and an error in the dev server for that page). That means you can safely distill values\nand let the build command tell you about these issues if they arise.\n\n","unions":[],"aliases":[{"name":"Body","comment":" A body for a StaticHttp request.\n","args":[],"type":"Pages.Internal.StaticHttpBody.Body"},{"name":"DataSource","comment":" A DataSource represents data that will be gathered at build time. Multiple `DataSource`s can be combined together using the `mapN` functions,\nvery similar to how you can manipulate values with Json Decoders in Elm.\n","args":["value"],"type":"Pages.StaticHttpRequest.RawRequest value"}],"values":[{"name":"andMap","comment":" A helper for combining `DataSource`s in pipelines.\n","type":"DataSource.DataSource a -> DataSource.DataSource (a -> b) -> DataSource.DataSource b"},{"name":"andThen","comment":" Build off of the response from a previous `StaticHttp` request to build a follow-up request. You can use the data\nfrom the previous response to build up the URL, headers, etc. that you send to the subsequent request.\n\n import DataSource\n import Json.Decode as Decode exposing (Decoder)\n\n licenseData : StaticHttp.Request String\n licenseData =\n StaticHttp.get\n (Secrets.succeed \"https://api.github.com/repos/dillonkearns/elm-pages\")\n (Decode.at [ \"license\", \"url\" ] Decode.string)\n |> StaticHttp.andThen\n (\\licenseUrl ->\n StaticHttp.get (Secrets.succeed licenseUrl) (Decode.field \"description\" Decode.string)\n )\n\n","type":"(a -> DataSource.DataSource b) -> DataSource.DataSource a -> DataSource.DataSource b"},{"name":"combine","comment":" Turn a list of `StaticHttp.Request`s into a single one.\n\n import DataSource\n import Json.Decode as Decode exposing (Decoder)\n\n type alias Pokemon =\n { name : String\n , sprite : String\n }\n\n pokemonDetailRequest : StaticHttp.Request (List Pokemon)\n pokemonDetailRequest =\n StaticHttp.get\n (Secrets.succeed \"https://pokeapi.co/api/v2/pokemon/?limit=3\")\n (Decode.field \"results\"\n (Decode.list\n (Decode.map2 Tuple.pair\n (Decode.field \"name\" Decode.string)\n (Decode.field \"url\" Decode.string)\n |> Decode.map\n (\\( name, url ) ->\n StaticHttp.get (Secrets.succeed url)\n (Decode.at\n [ \"sprites\", \"front_default\" ]\n Decode.string\n |> Decode.map (Pokemon name)\n )\n )\n )\n )\n )\n |> StaticHttp.andThen StaticHttp.combine\n\n","type":"List.List (DataSource.DataSource value) -> DataSource.DataSource (List.List value)"},{"name":"distill","comment":" This is the low-level `distill` function. In most cases, you'll want to use `distill` with a `Codec` from either\n[`miniBill/elm-codec`](https://package.elm-lang.org/packages/miniBill/elm-codec/latest/) or\n[`MartinSStewart/elm-serialize`](https://package.elm-lang.org/packages/MartinSStewart/elm-serialize/latest/)\n","type":"String.String -> (raw -> Json.Encode.Value) -> (Json.Decode.Value -> Result.Result String.String distilled) -> DataSource.DataSource raw -> DataSource.DataSource distilled"},{"name":"distillCodec","comment":" [`distill`](#distill) with a `Codec` from [`miniBill/elm-codec`](https://package.elm-lang.org/packages/miniBill/elm-codec/latest/).\n\n import Codec\n import DataSource\n import DataSource.Http\n import Secrets\n\n millionRandomSum : DataSource Int\n millionRandomSum =\n DataSource.Http.get\n (Secrets.succeed \"https://example.com/api/one-million-random-numbers.json\")\n (Decode.list Decode.int)\n |> DataSource.map List.sum\n -- all of this expensive computation and data will happen before it hits the client!\n -- the user's browser simply loads up a single Int and runs an Int decoder to get it\n |> DataSource.distillCodec \"million-random-sum\" Codec.int\n\nIf we didn't distill the data here, then all million Ints would have to be loaded in order to load the page.\nThe reason the data for these `DataSource`s needs to be loaded is that `elm-pages` hydrates into an Elm app. If it\noutput only HTML then we could build the HTML and throw away the data. But we need to ensure that the hydrated Elm app\nhas all the data that a page depends on, even if it the HTML for the page is also pre-rendered.\n\nUsing a `Codec` makes it safer to distill data because you know it is reversible.\n\n","type":"String.String -> Codec.Codec value -> DataSource.DataSource value -> DataSource.DataSource value"},{"name":"distillSerializeCodec","comment":" [`distill`](#distill) with a `Serialize.Codec` from [`MartinSStewart/elm-serialize`](https://package.elm-lang.org/packages/MartinSStewart/elm-serialize/latest).\n\n import DataSource\n import DataSource.Http\n import Secrets\n import Serialize\n\n millionRandomSum : DataSource Int\n millionRandomSum =\n DataSource.Http.get\n (Secrets.succeed \"https://example.com/api/one-million-random-numbers.json\")\n (Decode.list Decode.int)\n |> DataSource.map List.sum\n -- all of this expensive computation and data will happen before it hits the client!\n -- the user's browser simply loads up a single Int and runs an Int decoder to get it\n |> DataSource.distillSerializeCodec \"million-random-sum\" Serialize.int\n\nIf we didn't distill the data here, then all million Ints would have to be loaded in order to load the page.\nThe reason the data for these `DataSource`s needs to be loaded is that `elm-pages` hydrates into an Elm app. If it\noutput only HTML then we could build the HTML and throw away the data. But we need to ensure that the hydrated Elm app\nhas all the data that a page depends on, even if it the HTML for the page is also pre-rendered.\n\nUsing a `Codec` makes it safer to distill data because you know it is reversible.\n\n","type":"String.String -> Serialize.Codec error value -> DataSource.DataSource value -> DataSource.DataSource value"},{"name":"emptyBody","comment":" Build an empty body for a StaticHttp request. See [elm/http's `Http.emptyBody`](https://package.elm-lang.org/packages/elm/http/latest/Http#emptyBody).\n","type":"DataSource.Body"},{"name":"fail","comment":" Stop the StaticHttp chain with the given error message. If you reach a `fail` in your request,\nyou will get a build error. Or in the dev server, you will see the error message in an overlay in your browser (and in\nthe terminal).\n","type":"String.String -> DataSource.DataSource a"},{"name":"fromResult","comment":" Turn an Err into a DataSource failure.\n","type":"Result.Result String.String value -> DataSource.DataSource value"},{"name":"jsonBody","comment":" Builds a JSON body for a StaticHttp request. See [elm/http's `Http.jsonBody`](https://package.elm-lang.org/packages/elm/http/latest/Http#jsonBody).\n","type":"Json.Encode.Value -> DataSource.Body"},{"name":"map","comment":" Transform a request into an arbitrary value. The same underlying HTTP requests will be performed during the build\nstep, but mapping allows you to change the resulting values by applying functions to the results.\n\nA common use for this is to map your data into your elm-pages view:\n\n import DataSource\n import Json.Decode as Decode exposing (Decoder)\n\n view =\n StaticHttp.get\n (Secrets.succeed \"https://api.github.com/repos/dillonkearns/elm-pages\")\n (Decode.field \"stargazers_count\" Decode.int)\n |> StaticHttp.map\n (\\stars ->\n { view =\n \\model viewForPage ->\n { title = \"Current stars: \" ++ String.fromInt stars\n , body = Html.text <| \"⭐️ \" ++ String.fromInt stars\n , head = []\n }\n }\n )\n\n","type":"(a -> b) -> DataSource.DataSource a -> DataSource.DataSource b"},{"name":"map2","comment":" Like map, but it takes in two `Request`s.\n\n view siteMetadata page =\n StaticHttp.map2\n (\\elmPagesStars elmMarkdownStars ->\n { view =\n \\model viewForPage ->\n { title = \"Repo Stargazers\"\n , body = starsView elmPagesStars elmMarkdownStars\n }\n , head = head elmPagesStars elmMarkdownStars\n }\n )\n (get\n (Secrets.succeed \"https://api.github.com/repos/dillonkearns/elm-pages\")\n (Decode.field \"stargazers_count\" Decode.int)\n )\n (get\n (Secrets.succeed \"https://api.github.com/repos/dillonkearns/elm-markdown\")\n (Decode.field \"stargazers_count\" Decode.int)\n )\n\n","type":"(a -> b -> c) -> DataSource.DataSource a -> DataSource.DataSource b -> DataSource.DataSource c"},{"name":"map3","comment":" ","type":"(value1 -> value2 -> value3 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource valueCombined"},{"name":"map4","comment":" ","type":"(value1 -> value2 -> value3 -> value4 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource value4 -> DataSource.DataSource valueCombined"},{"name":"map5","comment":" ","type":"(value1 -> value2 -> value3 -> value4 -> value5 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource value4 -> DataSource.DataSource value5 -> DataSource.DataSource valueCombined"},{"name":"map6","comment":" ","type":"(value1 -> value2 -> value3 -> value4 -> value5 -> value6 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource value4 -> DataSource.DataSource value5 -> DataSource.DataSource value6 -> DataSource.DataSource valueCombined"},{"name":"map7","comment":" ","type":"(value1 -> value2 -> value3 -> value4 -> value5 -> value6 -> value7 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource value4 -> DataSource.DataSource value5 -> DataSource.DataSource value6 -> DataSource.DataSource value7 -> DataSource.DataSource valueCombined"},{"name":"map8","comment":" ","type":"(value1 -> value2 -> value3 -> value4 -> value5 -> value6 -> value7 -> value8 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource value4 -> DataSource.DataSource value5 -> DataSource.DataSource value6 -> DataSource.DataSource value7 -> DataSource.DataSource value8 -> DataSource.DataSource valueCombined"},{"name":"map9","comment":" ","type":"(value1 -> value2 -> value3 -> value4 -> value5 -> value6 -> value7 -> value8 -> value9 -> valueCombined) -> DataSource.DataSource value1 -> DataSource.DataSource value2 -> DataSource.DataSource value3 -> DataSource.DataSource value4 -> DataSource.DataSource value5 -> DataSource.DataSource value6 -> DataSource.DataSource value7 -> DataSource.DataSource value8 -> DataSource.DataSource value9 -> DataSource.DataSource valueCombined"},{"name":"resolve","comment":" Helper to remove an inner layer of Request wrapping.\n","type":"DataSource.DataSource (List.List (DataSource.DataSource value)) -> DataSource.DataSource (List.List value)"},{"name":"stringBody","comment":" Builds a string body for a StaticHttp request. See [elm/http's `Http.stringBody`](https://package.elm-lang.org/packages/elm/http/latest/Http#stringBody).\n\nNote from the `elm/http` docs:\n\n> The first argument is a [MIME type](https://en.wikipedia.org/wiki/Media_type) of the body. Some servers are strict about this!\n\n","type":"String.String -> String.String -> DataSource.Body"},{"name":"succeed","comment":" This is useful for prototyping with some hardcoded data, or for having a view that doesn't have any StaticHttp data.\n\n import DataSource\n\n view :\n List ( PagePath, Metadata )\n ->\n { path : PagePath\n , frontmatter : Metadata\n }\n ->\n StaticHttp.Request\n { view : Model -> View -> { title : String, body : Html Msg }\n , head : List (Head.Tag Pages.PathKey)\n }\n view siteMetadata page =\n StaticHttp.succeed\n { view =\n \\model viewForPage ->\n mainView model viewForPage\n , head = head page.frontmatter\n }\n\n","type":"a -> DataSource.DataSource a"},{"name":"validate","comment":" ","type":"(unvalidated -> validated) -> (unvalidated -> DataSource.DataSource (Result.Result String.String ())) -> DataSource.DataSource unvalidated -> DataSource.DataSource validated"}],"binops":[]},{"name":"DataSource.File","comment":" This module lets you read files from the local filesystem as a [`DataSource`](DataSource#DataSource).\nFile paths are relative to the root of your `elm-pages` project (next to the `elm.json` file and `src/` directory).\n\n\n## Files With Frontmatter\n\nFrontmatter is a convention used to keep metadata at the top of a file between `---`'s.\n\nFor example, you might have a file called `blog/hello-world.md` with this content:\n\n```markdown\n---\ntitle: Hello, World!\ntags: elm\n---\nHey there! This is my first post :)\n```\n\nThe frontmatter is in the [YAML format](https://en.wikipedia.org/wiki/YAML) here. You can also use JSON in your elm-pages frontmatter.\n\n```markdown\n---\n{\"title\": \"Hello, World!\", \"tags\": \"elm\"}\n---\nHey there! This is my first post :)\n```\n\nWhether it's YAML or JSON, you use an `OptimizedDecoder` to decode your frontmatter, so it feels just like using\nplain old JSON in Elm.\n\n@docs bodyWithFrontmatter, bodyWithoutFrontmatter, onlyFrontmatter\n\n\n## Reading Files Without Frontmatter\n\n@docs jsonFile, rawFile\n\n","unions":[],"aliases":[],"values":[{"name":"bodyWithFrontmatter","comment":"\n\n import DataSource exposing (DataSource)\n import DataSource.File as File\n import OptimizedDecoder as Decode exposing (Decoder)\n\n blogPost : DataSource ( String, BlogPostMetadata )\n blogPost =\n File.bodyWithFrontmatter blogPostDecoder\n \"blog/hello-world.md\"\n\n type alias BlogPostMetadata =\n { body : String\n , title : String\n , tags : List String\n }\n\n blogPostDecoder : Decoder BlogPostMetadata\n blogPostDecoder body =\n Decode.map2 (BlogPostMetadata body)\n (Decode.field \"title\" Decode.string)\n (Decode.field \"tags\" tagsDecoder)\n\n tagsDecoder : Decoder (List String)\n tagsDecoder =\n Decode.map (String.split \" \")\n Decode.string\n\nThis will give us a DataSource that results in the following value:\n\n value =\n { body = \"Hey there! This is my first post :)\"\n , title = \"Hello, World!\"\n , tags = [ \"elm\" ]\n }\n\nIt's common to parse the body with a markdown parser or other format.\n\n import DataSource exposing (DataSource)\n import DataSource.File as File\n import Html exposing (Html)\n import OptimizedDecoder as Decode exposing (Decoder)\n\n example :\n DataSource\n { title : String\n , body : List (Html msg)\n }\n example =\n File.bodyWithFrontmatter\n (\\markdownString ->\n Decode.map2\n (\\title renderedMarkdown ->\n { title = title\n , body = renderedMarkdown\n }\n )\n (Decode.field \"title\" Decode.string)\n (markdownString\n |> markdownToView\n |> Decode.fromResult\n )\n )\n \"foo.md\"\n\n markdownToView :\n String\n -> Result String (List (Html msg))\n markdownToView markdownString =\n markdownString\n |> Markdown.Parser.parse\n |> Result.mapError (\\_ -> \"Markdown error.\")\n |> Result.andThen\n (\\blocks ->\n Markdown.Renderer.render\n Markdown.Renderer.defaultHtmlRenderer\n blocks\n )\n\n","type":"(String.String -> OptimizedDecoder.Decoder frontmatter) -> String.String -> DataSource.DataSource frontmatter"},{"name":"bodyWithoutFrontmatter","comment":" Same as `bodyWithFrontmatter` except it doesn't include the frontmatter.\n\nFor example, if you have a file called `blog/hello-world.md` with\n\n```markdown\n---\ntitle: Hello, World!\ntags: elm\n---\nHey there! This is my first post :)\n```\n\n import DataSource exposing (DataSource)\n\n data : DataSource String\n data =\n bodyWithoutFrontmatter \"blog/hello-world.md\"\n\nThen data will yield the value `\"Hey there! This is my first post :)\"`.\n\n","type":"String.String -> DataSource.DataSource String.String"},{"name":"jsonFile","comment":" Read a file as JSON.\n\nThe OptimizedDecoder will strip off any unused JSON data.\n\n import DataSource exposing (DataSource)\n import DataSource.File as File\n\n sourceDirectories : DataSource (List String)\n sourceDirectories =\n File.jsonFile\n (Decode.field\n \"source-directories\"\n (Decode.list Decode.string)\n )\n \"elm.json\"\n\n","type":"OptimizedDecoder.Decoder a -> String.String -> DataSource.DataSource a"},{"name":"onlyFrontmatter","comment":" Same as `bodyWithFrontmatter` except it doesn't include the body.\n\nThis is often useful when you're aggregating data, for example getting a listing of blog posts and need to extract\njust the metadata.\n\n import DataSource exposing (DataSource)\n import DataSource.File as File\n import OptimizedDecoder as Decode exposing (Decoder)\n\n blogPost : DataSource BlogPostMetadata\n blogPost =\n File.onlyFrontmatter \"blog/hello-world.md\"\n blogPostDecoder\n\n type alias BlogPostMetadata =\n { title : String\n , tags : List String\n }\n\n blogPostDecoder : Decoder BlogPostMetadata\n blogPostDecoder =\n Decode.map2 BlogPostMetadata\n (Decode.field \"title\" Decode.string)\n (Decode.field \"tags\" (Decode.list Decode.string))\n\nIf you wanted to use this to get this metadata for all blog posts in a folder, you could use\nthe [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource.Glob).\n\n import DataSource exposing (DataSource)\n import DataSource.File as File\n import OptimizedDecoder as Decode exposing (Decoder)\n\n blogPostFiles : DataSource (List String)\n blogPostFiles =\n Glob.succeed identity\n |> Glob.captureFilePath\n |> Glob.match (Glob.literal \"content/blog/\")\n |> Glob.match Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\n allMetadata : DataSource (List BlogPostMetadata)\n allMetadata =\n blogPostFiles\n |> DataSource.map\n (List.map\n (File.onlyFrontmatter\n blogPostDecoder\n )\n )\n |> DataSource.resolve\n\n","type":"OptimizedDecoder.Decoder frontmatter -> String.String -> DataSource.DataSource frontmatter"},{"name":"rawFile","comment":" Get the raw file content. Unlike the frontmatter helpers in this module, this function will not strip off frontmatter if there is any.\n\nThis is the function you want if you are reading in a file directly. For example, if you read in a CSV file, a raw text file, or any other file that doesn't\nhave frontmatter.\n\nThere's a special function for reading in JSON files, [`jsonFile`](#jsonFile). If you're reading a JSON file then be sure to\nuse `jsonFile` to get the benefits of the `OptimizedDecoder` here.\n\nYou could read a file called `hello.txt` in your root project directory like this:\n\n import DataSource exposing (DataSource)\n import DataSource.File as File\n\n elmJsonFile : DataSource String\n elmJsonFile =\n File.rawFile \"hello.txt\"\n\n","type":"String.String -> DataSource.DataSource String.String"}],"binops":[]},{"name":"DataSource.Glob","comment":"\n\n@docs Glob\n\nThis module helps you get a List of matching file paths from your local file system as a [`DataSource`](DataSource#DataSource). See the [`DataSource`](DataSource) module documentation\nfor ways you can combine and map `DataSource`s.\n\nA common example would be to find all the markdown files of your blog posts. If you have all your blog posts in `content/blog/*.md`\n, then you could use that glob pattern in most shells to refer to each of those files.\n\nWith the `DataSource.Glob` API, you could get all of those files like so:\n\n import DataSource exposing (DataSource)\n\n blogPostsGlob : DataSource (List String)\n blogPostsGlob =\n Glob.succeed (\\slug -> slug)\n |> Glob.match (Glob.literal \"content/blog/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nLet's say you have these files locally:\n\n```shell\n- elm.json\n- src/\n- content/\n - blog/\n - first-post.md\n - second-post.md\n```\n\nWe would end up with a `DataSource` like this:\n\n DataSource.succeed [ \"first-post\", \"second-post\" ]\n\nOf course, if you add or remove matching files, the DataSource will get those new files (unlike `DataSource.succeed`). That's why we have Glob!\n\nYou can even see the `elm-pages dev` server will automatically flow through any added/removed matching files with its hot module reloading.\n\nBut why did we get `\"first-post\"` instead of a full file path, like `\"content/blog/first-post.md\"`? That's the difference between\n`capture` and `match`.\n\n\n## Capture and Match\n\nThere are two functions for building up a Glob pattern: `capture` and `match`.\n\n`capture` and `match` both build up a `Glob` pattern that will match 0 or more files on your local file system.\nThere will be one argument for every `capture` in your pipeline, whereas `match` does not apply any arguments.\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n blogPostsGlob : DataSource (List String)\n blogPostsGlob =\n Glob.succeed (\\slug -> slug)\n -- no argument from this, but we will only\n -- match files that begin with `content/blog/`\n |> Glob.match (Glob.literal \"content/blog/\")\n -- we get the value of the `wildcard`\n -- as the slug argument\n |> Glob.capture Glob.wildcard\n -- no argument from this, but we will only\n -- match files that end with `.md`\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nSo to understand _which_ files will match, you can ignore whether you are using `capture` or `match` and just read\nthe patterns you're using in order to understand what will match. To understand what Elm data type you will get\n_for each matching file_, you need to see which parts are being captured and how each of those captured values are being\nused in the function you use in `Glob.succeed`.\n\n@docs capture, match\n\n`capture` is a lot like building up a JSON decoder with a pipeline.\n\nLet's try our blogPostsGlob from before, but change every `match` to `capture`.\n\n import DataSource exposing (DataSource)\n\n blogPostsGlob :\n DataSource\n (List\n { filePath : String\n , slug : String\n }\n )\n blogPostsGlob =\n Glob.succeed\n (\\capture1 capture2 capture3 ->\n { filePath = capture1 ++ capture2 ++ capture3\n , slug = capture2\n }\n )\n |> Glob.capture (Glob.literal \"content/blog/\")\n |> Glob.capture Glob.wildcard\n |> Glob.capture (Glob.literal \".md\")\n |> Glob.toDataSource\n\nNotice that we now need 3 arguments at the start of our pipeline instead of 1. That's because\nwe apply 1 more argument every time we do a `Glob.capture`, much like `Json.Decode.Pipeline.required`, or other pipeline APIs.\n\nNow we actually have the full file path of our files. But having that slug (like `first-post`) is also very helpful sometimes, so\nwe kept that in our record as well. So we'll now have the equivalent of this `DataSource` with the current `.md` files in our `blog` folder:\n\n DataSource.succeed\n [ { filePath = \"content/blog/first-post.md\"\n , slug = \"first-post\"\n }\n , { filePath = \"content/blog/second-post.md\"\n , slug = \"second-post\"\n }\n ]\n\nHaving the full file path lets us read in files. But concatenating it manually is tedious\nand error prone. That's what the [`captureFilePath`](#captureFilePath) helper is for.\n\n\n## Reading matching files\n\n@docs captureFilePath\n\nIn many cases you will want to take the matching files from a `Glob` and then read the body or frontmatter from matching files.\n\n\n## Reading Metadata for each Glob Match\n\nFor example, if we had files like this:\n\n```markdown\n---\ntitle: My First Post\n---\nThis is my first post!\n```\n\nThen we could read that title for our blog post list page using our `blogPosts` `DataSource` that we defined above.\n\n import DataSource.File\n import OptimizedDecoder as Decode exposing (Decoder)\n\n titles : DataSource (List BlogPost)\n titles =\n blogPosts\n |> DataSource.map\n (List.map\n (\\blogPost ->\n DataSource.File.request\n blogPost.filePath\n (DataSource.File.frontmatter blogFrontmatterDecoder)\n )\n )\n |> DataSource.resolve\n\n type alias BlogPost =\n { title : String }\n\n blogFrontmatterDecoder : Decoder BlogPost\n blogFrontmatterDecoder =\n Decode.map BlogPost\n (Decode.field \"title\" Decode.string)\n\nThat will give us\n\n DataSource.succeed\n [ { title = \"My First Post\" }\n , { title = \"My Second Post\" }\n ]\n\n\n## Capturing Patterns\n\n@docs wildcard, recursiveWildcard\n\n\n## Capturing Specific Characters\n\n@docs int, digits\n\n\n## Matching a Specific Number of Files\n\n@docs expectUniqueMatch\n\n\n## Glob Patterns\n\n@docs literal\n\n@docs map, succeed, toDataSource\n\n@docs oneOf\n\n@docs zeroOrMore, atLeastOne\n\n","unions":[],"aliases":[{"name":"Glob","comment":" A pattern to match local files and capture parts of the path into a nice Elm data type.\n","args":["a"],"type":"DataSource.Internal.Glob.Glob a"}],"values":[{"name":"atLeastOne","comment":" ","type":"( ( String.String, a ), List.List ( String.String, a ) ) -> DataSource.Glob.Glob ( a, List.List a )"},{"name":"capture","comment":" Adds on to the glob pattern, and captures it in the resulting Elm match value. That means this both changes which\nfiles will match, and gives you the sub-match as Elm data for each matching file.\n\nExactly the same as `match` except it also captures the matched sub-pattern.\n\n type alias ArchivesArticle =\n { year : String\n , month : String\n , day : String\n , slug : String\n }\n\n archives : DataSource ArchivesArticle\n archives =\n Glob.succeed ArchivesArticle\n |> Glob.match (Glob.literal \"archive/\")\n |> Glob.capture Glob.int\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.int\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.int\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nThe file `archive/1977/06/10/apple-2-released.md` will give us this match:\n\n matches : List ArchivesArticle\n matches =\n DataSource.succeed\n [ { year = 1977\n , month = 6\n , day = 10\n , slug = \"apple-2-released\"\n }\n ]\n\nWhen possible, it's best to grab data and turn it into structured Elm data when you have it. That way,\nyou don't end up with duplicate validation logic and data normalization, and your code will be more robust.\n\nIf you only care about getting the full matched file paths, you can use `match`. `capture` is very useful because\nyou can pick apart structured data as you build up your glob pattern. This follows the principle of\n[Parse, Don't Validate](https://elm-radio.com/episode/parse-dont-validate/).\n\n","type":"DataSource.Glob.Glob a -> DataSource.Glob.Glob (a -> value) -> DataSource.Glob.Glob value"},{"name":"captureFilePath","comment":"\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n blogPosts :\n DataSource\n (List\n { filePath : String\n , slug : String\n }\n )\n blogPosts =\n Glob.succeed\n (\\filePath slug ->\n { filePath = filePath\n , slug = slug\n }\n )\n |> Glob.captureFilePath\n |> Glob.match (Glob.literal \"content/blog/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nThis function does not change which files will or will not match. It just gives you the full matching\nfile path in your `Glob` pipeline.\n\nWhenever possible, it's a good idea to use function to make sure you have an accurate file path when you need to read a file.\n\n","type":"DataSource.Glob.Glob (String.String -> value) -> DataSource.Glob.Glob value"},{"name":"digits","comment":" This is similar to [`wildcard`](#wildcard), but it will only match 1 or more digits (i.e. `[0-9]+`).\n\nSee [`int`](#int) for a convenience function to get an Int value instead of a String of digits.\n\n","type":"DataSource.Glob.Glob String.String"},{"name":"expectUniqueMatch","comment":" Sometimes you want to make sure there is a unique file matching a particular pattern.\nThis is a simple helper that will give you a `DataSource` error if there isn't exactly 1 matching file.\nIf there is exactly 1, then you successfully get back that single match.\n\nFor example, maybe you can have\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n findBlogBySlug : String -> DataSource String\n findBlogBySlug slug =\n Glob.succeed identity\n |> Glob.captureFilePath\n |> Glob.match (Glob.literal \"blog/\")\n |> Glob.capture (Glob.literal slug)\n |> Glob.match\n (Glob.oneOf\n ( ( \"\", () )\n , [ ( \"/index\", () ) ]\n )\n )\n |> Glob.match (Glob.literal \".md\")\n |> Glob.expectUniqueMatch\n\nIf we used `findBlogBySlug \"first-post\"` with these files:\n\n```markdown\n- blog/\n - first-post/\n - index.md\n```\n\nThis would give us:\n\n results : DataSource String\n results =\n DataSource.succeed \"blog/first-post/index.md\"\n\nIf we used `findBlogBySlug \"first-post\"` with these files:\n\n```markdown\n- blog/\n - first-post.md\n - first-post/\n - index.md\n```\n\nThen we will get a `DataSource` error saying `More than one file matched.` Keep in mind that `DataSource` failures\nin build-time routes will cause a build failure, giving you the opportunity to fix the problem before users see the issue,\nso it's ideal to make this kind of assertion rather than having fallback behavior that could silently cover up\nissues (like if we had instead ignored the case where there are two or more matching blog post files).\n\n","type":"DataSource.Glob.Glob a -> DataSource.DataSource a"},{"name":"int","comment":" Same as [`digits`](#digits), but it safely turns the digits String into an `Int`.\n\nLeading 0's are ignored.\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n slides : DataSource (List Int)\n slides =\n Glob.succeed identity\n |> Glob.match (Glob.literal \"slide-\")\n |> Glob.capture Glob.int\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nWith files\n\n```shell\n- slide-no-match.md\n- slide-.md\n- slide-1.md\n- slide-01.md\n- slide-2.md\n- slide-03.md\n- slide-4.md\n- slide-05.md\n- slide-06.md\n- slide-007.md\n- slide-08.md\n- slide-09.md\n- slide-10.md\n- slide-11.md\n```\n\nYields\n\n matches : DataSource (List Int)\n matches =\n DataSource.succeed\n [ 1\n , 1\n , 2\n , 3\n , 4\n , 5\n , 6\n , 7\n , 8\n , 9\n , 10\n , 11\n ]\n\nNote that neither `slide-no-match.md` nor `slide-.md` match.\nAnd both `slide-1.md` and `slide-01.md` match and turn into `1`.\n\n","type":"DataSource.Glob.Glob Basics.Int"},{"name":"literal","comment":" Match a literal part of a path. Can include `/`s.\n\nSome common uses include\n\n - The leading part of a pattern, to say \"starts with `content/blog/`\"\n - The ending part of a pattern, to say \"ends with `.md`\"\n - In-between wildcards, to say \"these dynamic parts are separated by `/`\"\n\n```elm\nimport DataSource exposing (DataSource)\nimport DataSource.Glob as Glob\n\nblogPosts =\n Glob.succeed\n (\\section slug ->\n { section = section, slug = slug }\n )\n |> Glob.match (Glob.literal \"content/blog/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n```\n\n","type":"String.String -> DataSource.Glob.Glob String.String"},{"name":"map","comment":" A `Glob` can be mapped. This can be useful for transforming a sub-match in-place.\n\nFor example, if you wanted to take the slugs for a blog post and make sure they are normalized to be all lowercase, you\ncould use\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n blogPostsGlob : DataSource (List String)\n blogPostsGlob =\n Glob.succeed (\\slug -> slug)\n |> Glob.match (Glob.literal \"content/blog/\")\n |> Glob.capture (Glob.wildcard |> Glob.map String.toLower)\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nIf you want to validate file formats, you can combine that with some `DataSource` helpers to turn a `Glob (Result String value)` into\na `DataSource (List value)`.\n\nFor example, you could take a date and parse it.\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n example : DataSource (List ( String, String ))\n example =\n Glob.succeed\n (\\dateResult slug ->\n dateResult\n |> Result.map (\\okDate -> ( okDate, slug ))\n )\n |> Glob.match (Glob.literal \"blog/\")\n |> Glob.capture (Glob.recursiveWildcard |> Glob.map expectDateFormat)\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n |> DataSource.map (List.map DataSource.fromResult)\n |> DataSource.resolve\n\n expectDateFormat : List String -> Result String String\n expectDateFormat dateParts =\n case dateParts of\n [ year, month, date ] ->\n Ok (String.join \"-\" [ year, month, date ])\n\n _ ->\n Err \"Unexpected date format, expected yyyy/mm/dd folder structure.\"\n\n","type":"(a -> b) -> DataSource.Glob.Glob a -> DataSource.Glob.Glob b"},{"name":"match","comment":" Adds on to the glob pattern, but does not capture it in the resulting Elm match value. That means this changes which\nfiles will match, but does not change the Elm data type you get for each matching file.\n\nExactly the same as `capture` except it doesn't capture the matched sub-pattern.\n\n","type":"DataSource.Glob.Glob a -> DataSource.Glob.Glob value -> DataSource.Glob.Glob value"},{"name":"oneOf","comment":"\n\n import DataSource.Glob as Glob\n\n type Extension\n = Json\n | Yml\n\n type alias DataFile =\n { name : String\n , extension : String\n }\n\n dataFiles : DataSource (List DataFile)\n dataFiles =\n Glob.succeed DataFile\n |> Glob.match (Glob.literal \"my-data/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".\")\n |> Glob.capture\n (Glob.oneOf\n ( ( \"yml\", Yml )\n , [ ( \"json\", Json )\n ]\n )\n )\n\nIf we have the following files\n\n```shell\n- my-data/\n - authors.yml\n - events.json\n```\n\nThat gives us\n\n results : DataSource (List DataFile)\n results =\n DataSource.succeed\n [ { name = \"authors\"\n , extension = Yml\n }\n , { name = \"events\"\n , extension = Json\n }\n ]\n\nYou could also match an optional file path segment using `oneOf`.\n\n rootFilesMd : DataSource (List String)\n rootFilesMd =\n Glob.succeed (\\slug -> slug)\n |> Glob.match (Glob.literal \"blog/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match\n (Glob.oneOf\n ( ( \"\", () )\n , [ ( \"/index\", () ) ]\n )\n )\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\nWith these files:\n\n```markdown\n- blog/\n - first-post.md\n - second-post/\n - index.md\n```\n\nThis would give us:\n\n results : DataSource (List String)\n results =\n DataSource.succeed\n [ \"first-post\"\n , \"second-post\"\n ]\n\n","type":"( ( String.String, a ), List.List ( String.String, a ) ) -> DataSource.Glob.Glob a"},{"name":"recursiveWildcard","comment":" Matches any number of characters, including `/`, as long as it's the only thing in a path part.\n\nIn contrast, `wildcard` will never match `/`, so it only matches within a single path part.\n\nThis is the elm-pages equivalent of `**/*.txt` in standard shell syntax:\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n example : DataSource (List ( List String, String ))\n example =\n Glob.succeed Tuple.pair\n |> Glob.match (Glob.literal \"articles/\")\n |> Glob.capture Glob.recursiveWildcard\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".txt\")\n |> Glob.toDataSource\n\nWith these files:\n\n```shell\n- articles/\n - google-io-2021-recap.txt\n - archive/\n - 1977/\n - 06/\n - 10/\n - apple-2-announced.txt\n```\n\nWe would get the following matches:\n\n matches : DataSource (List ( List String, String ))\n matches =\n DataSource.succeed\n [ ( [ \"archive\", \"1977\", \"06\", \"10\" ], \"apple-2-announced\" )\n , ( [], \"google-io-2021-recap\" )\n ]\n\nNote that the recursive wildcard conveniently gives us a `List String`, where\neach String is a path part with no slashes (like `archive`).\n\nAnd also note that it matches 0 path parts into an empty list.\n\nIf we didn't include the `wildcard` after the `recursiveWildcard`, then we would only get\na single level of matches because it is followed by a file extension.\n\n example : DataSource (List String)\n example =\n Glob.succeed identity\n |> Glob.match (Glob.literal \"articles/\")\n |> Glob.capture Glob.recursiveWildcard\n |> Glob.match (Glob.literal \".txt\")\n\n matches : DataSource (List String)\n matches =\n DataSource.succeed\n [ \"google-io-2021-recap\"\n ]\n\nThis is usually not what is intended. Using `recursiveWildcard` is usually followed by a `wildcard` for this reason.\n\n","type":"DataSource.Glob.Glob (List.List String.String)"},{"name":"succeed","comment":" `succeed` is how you start a pipeline for a `Glob`. You will need one argument for each `capture` in your `Glob`.\n","type":"constructor -> DataSource.Glob.Glob constructor"},{"name":"toDataSource","comment":" In order to get match data from your glob, turn it into a `DataSource` with this function.\n","type":"DataSource.Glob.Glob a -> DataSource.DataSource (List.List a)"},{"name":"wildcard","comment":" Matches anything except for a `/` in a file path. You may be familiar with this syntax from shells like bash\nwhere you can run commands like `rm client/*.js` to remove all `.js` files in the `client` directory.\n\nJust like a `*` glob pattern in bash, this `Glob.wildcard` function will only match within a path part. If you need to\nmatch 0 or more path parts like, see `recursiveWildcard`.\n\n import DataSource exposing (DataSource)\n import DataSource.Glob as Glob\n\n type alias BlogPost =\n { year : String\n , month : String\n , day : String\n , slug : String\n }\n\n example : DataSource (List BlogPost)\n example =\n Glob.succeed BlogPost\n |> Glob.match (Glob.literal \"blog/\")\n |> Glob.match Glob.wildcard\n |> Glob.match (Glob.literal \"-\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \"-\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \"/\")\n |> Glob.capture Glob.wildcard\n |> Glob.match (Glob.literal \".md\")\n |> Glob.toDataSource\n\n```shell\n\n- blog/\n - 2021-05-27/\n - first-post.md\n```\n\nThat will match to:\n\n results : DataSource (List BlogPost)\n results =\n DataSource.succeed\n [ { year = \"2021\"\n , month = \"05\"\n , day = \"27\"\n , slug = \"first-post\"\n }\n ]\n\nNote that we can \"destructure\" the date part of this file path in the format `yyyy-mm-dd`. The `wildcard` matches\nwill match _within_ a path part (think between the slashes of a file path). `recursiveWildcard` can match across path parts.\n\n","type":"DataSource.Glob.Glob String.String"},{"name":"zeroOrMore","comment":" ","type":"List.List String.String -> DataSource.Glob.Glob (Maybe.Maybe String.String)"}],"binops":[]},{"name":"DataSource.Http","comment":" StaticHttp requests are an alternative to doing Elm HTTP requests the traditional way using the `elm/http` package.\n\nThe key differences are:\n\n - `StaticHttp.Request`s are performed once at build time (`Http.Request`s are performed at runtime, at whenever point you perform them)\n - `StaticHttp.Request`s strip out unused JSON data from the data your decoder doesn't touch to minimize the JSON payload\n - `StaticHttp.Request`s can use [`Pages.Secrets`](Pages.Secrets) to securely use credentials from your environment variables which are completely masked in the production assets.\n - `StaticHttp.Request`s have a built-in `StaticHttp.andThen` that allows you to perform follow-up requests without using tasks\n\n\n## Scenarios where StaticHttp is a good fit\n\nIf you need data that is refreshed often you may want to do a traditional HTTP request with the `elm/http` package.\nThe kinds of situations that are served well by static HTTP are with data that updates moderately frequently or infrequently (or never).\nA common pattern is to trigger a new build when data changes. Many JAMstack services\nallow you to send a WebHook to your host (for example, Netlify is a good static file host that supports triggering builds with webhooks). So\nyou may want to have your site rebuild everytime your calendar feed has an event added, or whenever a page or article is added\nor updated on a CMS service like Contentful.\n\nIn scenarios like this, you can serve data that is just as up-to-date as it would be using `elm/http`, but you get the performance\ngains of using `StaticHttp.Request`s as well as the simplicity and robustness that comes with it. Read more about these benefits\nin [this article introducing StaticHttp requests and some concepts around it](https://elm-pages.com/blog/static-http).\n\n\n## Scenarios where StaticHttp is not a good fit\n\n - Data that is specific to the logged-in user\n - Data that needs to be the very latest and changes often (for example, sports scores)\n\n@docs RequestDetails\n@docs get, request\n\n\n## Building a StaticHttp Request Body\n\nThe way you build a body is analogous to the `elm/http` package. Currently, only `emptyBody` and\n`stringBody` are supported. If you have a use case that calls for a different body type, please open a Github issue\nand describe your use case!\n\n@docs Body, emptyBody, stringBody, jsonBody\n\n\n## Unoptimized Requests\n\nWarning - use these at your own risk! It's highly recommended that you use the other request functions that make use of\n`zwilias/json-decode-exploration` in order to allow you to reduce down your JSON to only the values that are used by\nyour decoders. This can significantly reduce download sizes for your StaticHttp requests.\n\n@docs unoptimizedRequest\n\n\n### Expect for unoptimized requests\n\n@docs Expect, expectString, expectUnoptimizedJson\n\n","unions":[{"name":"Expect","comment":" Analgous to the `Expect` type in the `elm/http` package. This represents how you will process the data that comes\nback in your StaticHttp request.\n\nYou can derive `ExpectUnoptimizedJson` from `ExpectString`. Or you could build your own helper to process the String\nas XML, for example, or give an `elm-pages` build error if the response can't be parsed as XML.\n\n","args":["value"],"cases":[]}],"aliases":[{"name":"Body","comment":" A body for a StaticHttp request.\n","args":[],"type":"Pages.Internal.StaticHttpBody.Body"},{"name":"RequestDetails","comment":" The full details to perform a StaticHttp request.\n","args":[],"type":"{ url : String.String, method : String.String, headers : List.List ( String.String, String.String ), body : DataSource.Http.Body }"}],"values":[{"name":"emptyBody","comment":" Build an empty body for a StaticHttp request. See [elm/http's `Http.emptyBody`](https://package.elm-lang.org/packages/elm/http/latest/Http#emptyBody).\n","type":"DataSource.Http.Body"},{"name":"expectString","comment":" Request a raw String. You can validate the String if you need to check the formatting, or try to parse it\nin something besides JSON. Be sure to use the `StaticHttp.request` function if you want an optimized request that\nstrips out unused JSON to optimize your asset size.\n\nIf the function you pass to `expectString` yields an `Err`, then you will get at StaticHttpDecodingError that will\nfail your `elm-pages` build and print out the String from the `Err`.\n\n request =\n StaticHttp.unoptimizedRequest\n (Secrets.succeed\n { url = \"https://example.com/file.txt\"\n , method = \"GET\"\n , headers = []\n , body = StaticHttp.emptyBody\n }\n )\n (StaticHttp.expectString\n (\\string ->\n if String.toUpper string == string then\n Ok string\n\n else\n Err \"String was not uppercased\"\n )\n )\n\n","type":"(String.String -> Result.Result String.String value) -> DataSource.Http.Expect value"},{"name":"expectUnoptimizedJson","comment":" Handle the incoming response as JSON and don't optimize the asset and strip out unused values.\nBe sure to use the `StaticHttp.request` function if you want an optimized request that\nstrips out unused JSON to optimize your asset size. This function makes sense to use for things like a GraphQL request\nwhere the JSON payload is already trimmed down to the data you explicitly requested.\n\nIf the function you pass to `expectString` yields an `Err`, then you will get at StaticHttpDecodingError that will\nfail your `elm-pages` build and print out the String from the `Err`.\n\n","type":"Json.Decode.Decoder value -> DataSource.Http.Expect value"},{"name":"get","comment":" A simplified helper around [`StaticHttp.request`](#request), which builds up a StaticHttp GET request.\n\n import DataSource\n import Json.Decode as Decode exposing (Decoder)\n\n getRequest : StaticHttp.Request Int\n getRequest =\n StaticHttp.get\n (Secrets.succeed \"https://api.github.com/repos/dillonkearns/elm-pages\")\n (Decode.field \"stargazers_count\" Decode.int)\n\n","type":"Pages.Secrets.Value String.String -> OptimizedDecoder.Decoder a -> DataSource.DataSource a"},{"name":"jsonBody","comment":" Builds a JSON body for a StaticHttp request. See [elm/http's `Http.jsonBody`](https://package.elm-lang.org/packages/elm/http/latest/Http#jsonBody).\n","type":"Json.Encode.Value -> DataSource.Http.Body"},{"name":"request","comment":" Build a `StaticHttp` request (analagous to [Http.request](https://package.elm-lang.org/packages/elm/http/latest/Http#request)).\nThis function takes in all the details to build a `StaticHttp` request, but you can build your own simplified helper functions\nwith this as a low-level detail, or you can use functions like [StaticHttp.get](#get).\n","type":"Pages.Secrets.Value DataSource.Http.RequestDetails -> OptimizedDecoder.Decoder a -> DataSource.DataSource a"},{"name":"stringBody","comment":" Builds a string body for a StaticHttp request. See [elm/http's `Http.stringBody`](https://package.elm-lang.org/packages/elm/http/latest/Http#stringBody).\n\nNote from the `elm/http` docs:\n\n> The first argument is a [MIME type](https://en.wikipedia.org/wiki/Media_type) of the body. Some servers are strict about this!\n\n","type":"String.String -> String.String -> DataSource.Http.Body"},{"name":"unoptimizedRequest","comment":" This is an alternative to the other request functions in this module that doesn't perform any optimizations on the\nasset. Be sure to use the optimized versions, like `StaticHttp.request`, if you can. Using those can significantly reduce\nyour asset sizes by removing all unused fields from your JSON.\n\nYou may want to use this function instead if you need XML data or plaintext. Or maybe you're hitting a GraphQL API,\nso you don't need any additional optimization as the payload is already reduced down to exactly what you requested.\n\n","type":"Pages.Secrets.Value DataSource.Http.RequestDetails -> DataSource.Http.Expect a -> DataSource.DataSource a"}],"binops":[]},{"name":"DataSource.ServerRequest","comment":"\n\n@docs ServerRequest, expectHeader, init, optionalHeader, staticData, toStaticHttp\n\n","unions":[{"name":"ServerRequest","comment":" ","args":["decodesTo"],"cases":[]}],"aliases":[],"values":[{"name":"expectHeader","comment":" ","type":"String.String -> DataSource.ServerRequest.ServerRequest (String.String -> value) -> DataSource.ServerRequest.ServerRequest value"},{"name":"init","comment":" ","type":"constructor -> DataSource.ServerRequest.ServerRequest constructor"},{"name":"optionalHeader","comment":" ","type":"String.String -> DataSource.ServerRequest.ServerRequest (Maybe.Maybe String.String -> value) -> DataSource.ServerRequest.ServerRequest value"},{"name":"staticData","comment":" ","type":"DataSource.DataSource String.String"},{"name":"toStaticHttp","comment":" ","type":"DataSource.ServerRequest.ServerRequest decodesTo -> DataSource.DataSource decodesTo"}],"binops":[]},{"name":"Head","comment":" This module contains low-level functions for building up\nvalues that will be rendered into the page's `
` tag\nwhen you run `elm-pages build`. Most likely the `Head.Seo` module\nwill do everything you need out of the box, and you will just need to import `Head`\nso you can use the `Tag` type in your type annotations.\n\nBut this module might be useful if you have a special use case, or if you are\nwriting a plugin package to extend `elm-pages`.\n\n@docs Tag, metaName, metaProperty\n@docs rssLink, sitemapLink, rootLanguage\n\n\n## Structured Data\n\n@docs structuredData\n\n\n## `AttributeValue`s\n\n@docs AttributeValue\n@docs currentPageFullUrl, urlAttribute, raw\n\n\n## Icons\n\n@docs appleTouchIcon, icon\n\n\n## Functions for use by generated code\n\n@docs toJson, canonicalLink\n\n","unions":[{"name":"AttributeValue","comment":" Values, such as between the `<>`'s here:\n\n```html\n\" content=\"