[{"name":"Markdown.Scaffolded","comment":"\n\n\n# Rendering Markdown with Scaffolds and Folds\n\n(This is called recursion-schemes in other languages, but don't worry, you don't have to\nwrite recursive functions!)\n\nThis is module provides a more **complicated**, but also **more powerful and\ncomposable** way of rendering markdown than the built-in elm-markdown\n[`Renderer`](https://package.elm-lang.org/packages/dillonkearns/elm-markdown/latest/Markdown-Renderer).\n\nIf you feel a little overwhelmed with this module at first, I recommend taking a look at\nthe [What are folds?](#what-are-folds-) section.\n\n\n# Main Datastructure\n\n@docs Block\n\n@docs map\n\n\n# High-level Transformations\n\nThese functions are not as composable as [fold building blocks](#fold-building-blocks),\nbut might suffice for your use case. Take a look at the other section if you find you need\nsomething better.\n\n@docs parameterized, validating, withStaticHttpRequests\n\n\n# Fold Building Blocks\n\n@docs foldHtml, foldFunction, foldWords, foldResults, foldStaticHttpRequests\n@docs reduce\n\n\n### What are folds?\n\nOften, we're working with functions of the type `Block view -> view`, where `view` might\nbe something like `Html Msg` or `String`, etc. or, generally, functions of structure\n`Block a -> b`.\n\nI refer to functions of that structure as 'folds'. (This is somewhat different to the\n'real' terminology, but I feel like they capture the nature of 'folding once' very well.)\n\nIf you know `List.foldr` you already know an example for a fold!\nThe folds in this module are no different, we just write them in different ways.\n\nWe can do the same thing we did for this library for lists:\n\n    type ListScaffold elem a\n        = Empty\n        | Cons elem a\n\n    foldEmpty = 0\n\n    foldCons a b = a + b\n\n    handler listElement =\n        case listElement of\n            Empty ->\n                foldEmpty\n\n            Cons elem accumulated ->\n                foldCons elem accumulated\n\n    foldl : (ListScaffold a b -> b) -> List a -> b\n    foldl handle list =\n        case list of\n            [] -> handle Empty\n            (x:xs) -> handle (Cons x xs)\n\n    foldl handler == List.foldl foldCons foldEmpty\n\nThe last line illustrates how differnt ways of writing these folds relate: For\n`List.foldl` we simply provide the cases (empty or cons) as different arguments,\nfor folds in this library, we create a custom type case for empty and cons.\n\n\n### Combining Folds\n\nYou can combine multiple 'folds' into one. There's no function for doing this, but a\npattern you might want to follow.\n\nLet's say you want to accumulate both all the words in your markdown and the `Html` you\nwant it to render to, then you can do this:\n\n    type alias Rendered =\n        { html : Html Msg\n        , words : List String\n        }\n\n    foldRendered : Block Rendered -> Rendered\n    foldRendered block =\n        { html = block |> map .html |> foldHtml\n        , words = block |> map .words |> foldWords\n        }\n\nIf you want to render to more things, just add another parameter to the record type and\nfollow the pattern. It is even possible to let the rendered html to depend on the words\ninside itself (or maybe something else you're additionally folding to).\n\n\n# Conversions\n\nDid you already start to write a custom elm-markdown `Renderer`, but want to use this\nlibrary? Don't worry. They're compatible. You can convert between them!\n\n@docs fromRenderer, toRenderer\n\n\n# Utilities\n\nI mean to aggregate utilites for transforming Blocks in this section.\n\n@docs bumpHeadings\n\n","unions":[{"name":"Block","comment":" A datatype that enumerates all possible ways markdown could wrap some children.\n\nKind of like a 'Scaffold' around something that's already built, which will get torn down\nafter building is finished.\n\nThis does not include Html tags.\n\nIf you look at the left hand sides of all of the functions in the elm-markdown\n[`Renderer`](https://package.elm-lang.org/packages/dillonkearns/elm-markdown/latest/Markdown-Renderer),\nyou'll notice a similarity to this custom type, except it's missing a type for 'html'.\n\nDefining this data structure has some advantages in composing multiple Renderers.\n\nIt has a type parameter `children`, which is supposed to be filled with `String`,\n`Html msg` or similar. Take a look at some [folds](#fold-building-blocks) for examples of this.\n\nThere are some neat tricks you can do with this data structure, for example, `Block Never`\nrepresents only non-nested blocks of markdown.\n\n","args":["children"],"cases":[["Heading",["{ level : Markdown.Block.HeadingLevel, rawText : String.String, children : List.List children }"]],["Paragraph",["List.List children"]],["BlockQuote",["List.List children"]],["Text",["String.String"]],["CodeSpan",["String.String"]],["Strong",["List.List children"]],["Emphasis",["List.List children"]],["Link",["{ title : Maybe.Maybe String.String, destination : String.String, children : List.List children }"]],["Image",["{ alt : String.String, src : String.String, title : Maybe.Maybe String.String }"]],["UnorderedList",["{ items : List.List (Markdown.Block.ListItem children) }"]],["OrderedList",["{ startingIndex : Basics.Int, items : List.List (List.List children) }"]],["CodeBlock",["{ body : String.String, language : Maybe.Maybe String.String }"]],["HardLineBreak",[]],["ThematicBreak",[]],["Table",["List.List children"]],["TableHeader",["List.List children"]],["TableBody",["List.List children"]],["TableRow",["List.List children"]],["TableCell",["List.List children"]],["TableHeaderCell",["Maybe.Maybe Markdown.Block.Alignment","List.List children"]]]}],"aliases":[],"values":[{"name":"bumpHeadings","comment":" Bump all `Heading` elements by given positive amount of levels.\n\n    import Markdown.Block as Block\n\n    bumpHeadings 2\n        (Heading\n            { level = Block.H1\n            , rawText = \"\"\n            , children = []\n            }\n        )\n    --> Heading\n    -->     { level = Block.H3\n    -->     , rawText = \"\"\n    -->     , children = []\n    -->     }\n\n    bumpHeadings 1\n        (Heading\n            { level = Block.H6\n            , rawText = \"\"\n            , children = []\n            }\n        )\n    --> Heading\n    -->     { level = Block.H6\n    -->     , rawText = \"\"\n    -->     , children = []\n    -->     }\n\n    bumpHeadings -1\n        (Heading\n            { level = Block.H2\n            , rawText = \"\"\n            , children = []\n            }\n        )\n    --> Heading\n    -->     { level = Block.H2\n    -->     , rawText = \"\"\n    -->     , children = []\n    -->     }\n\n","type":"Basics.Int -> Markdown.Scaffolded.Block view -> Markdown.Scaffolded.Block view"},{"name":"foldFunction","comment":" Transform a block that contains functions into a function that produces blocks.\n\nOne really common use-case is having access to a `Model` inside your html renderers.\nIn these cases you want your markdown to be 'rendered to a function'.\n\nSo let's say you've got a\n[`Markdown.Html.Renderer`]()\nlike so:\n\n    renderHtml :\n        Markdown.Html.Renderer\n            (List (Model -> Html Msg)\n             -> (Model -> Html Msg)\n            )\n\nIt has this type to be able to depend on the `Model`. Eventually you'll want to render to\n`Model -> Html Msg`.\n\nSo now you can define your\n[`Markdown.Renderer.Renderer`]()\nlike so:\n\n\n    renderer : Markdown.Renderer.Renderer (Model -> Html Msg)\n    renderer =\n        toRenderer\n            { renderHtml = renderHtml\n            , renderMarkdown = renderMarkdown\n            }\n\n    renderMarkdown :\n        Block (Model -> Html Msg)\n        -> (Model -> Html Msg)\n    renderMarkdown block model =\n        foldFunction block\n            -- ^ result : Model -> Block (Html Msg)\n            model\n            -- ^ result : Block (Html Msg)\n            |> foldHtml\n\n    -- ^ result : Html Msg\n\n","type":"Markdown.Scaffolded.Block (environment -> view) -> environment -> Markdown.Scaffolded.Block view"},{"name":"foldHtml","comment":" This will fold a `Block` to `Html` similar to what the\n[`defaultHtmlRenderer` in elm-markdown](https://package.elm-lang.org/packages/dillonkearns/elm-markdown/latest/Markdown-Renderer#defaultHtmlRenderer)\ndoes. That is, it renders similar to what the CommonMark spec expects.\n\nIt also takes a list of attributes for convenience, so if you want to attach styles,\nid's, classes or events, you can use this.\n\nHowever, **the attributes parameter is ignored for `Text` nodes**.\n\n","type":"List.List (Html.Attribute msg) -> Markdown.Scaffolded.Block (Html.Html msg) -> Html.Html msg"},{"name":"foldResults","comment":" Thread results through your Blocks.\n\nThe input is a block that contains possibly failed views. The output becomes `Err`, if\nany of the input block's children had an error (then it's the first error).\nIf all of the block's children were `Ok`, then the result is going to be `Ok`.\n\n","type":"Markdown.Scaffolded.Block (Result.Result error view) -> Result.Result error (Markdown.Scaffolded.Block view)"},{"name":"foldStaticHttpRequests","comment":" Accumulate elm-page's\n[`StaticHttp.Request`](https://package.elm-lang.org/packages/dillonkearns/elm-pages/latest/Pages-StaticHttp#Request)s\nover blocks.\n\nUsing this, it is possible to write folds that produce views as a result of performing\nstatic http requests.\n\n","type":"Markdown.Scaffolded.Block (Pages.StaticHttp.Request view) -> Pages.StaticHttp.Request (Markdown.Scaffolded.Block view)"},{"name":"foldWords","comment":" Extracts all words from the blocks and inlines. Excludes any markup characters, if\nthey had an effect on the markup.\n\nThe words are split according to the `\\s` javascript regular expression (regex).\n\nInline code spans are split, but **code blocks fragments are ignored** (code spans are\nincluded).\n\nIf you need something more specific, I highly recommend rolling your own function for\nthis.\n\nThis is useful if you need to e.g. create header slugs.\n\n","type":"Markdown.Scaffolded.Block (List.List String.String) -> List.List String.String"},{"name":"fromRenderer","comment":" There are two ways of thinking about this function:\n\n1.  Render a `Block` using the given elm-markdown `Renderer`.\n2.  Extract a function of type `(Block view -> view)` out of\n    the elm-markdown `Renderer`. This is useful if you want to make use\n    of the utilities present in this library.\n\n","type":"Markdown.Renderer.Renderer view -> Markdown.Scaffolded.Block view -> view"},{"name":"map","comment":" Transform each child of a `Block` using the given function.\n\nFor example, we can transform the lists of words inside each block into concatenated\nStrings:\n\n    wordsToWordlist : Block (List String) -> Block String\n    wordsToWordlist block =\n        map (\\listOfWords -> String.join \", \" listOfWords)\n            block\n\nThe ability to define this function is one of the reasons for our `Block` definition. If\nyou try defining `map` for elm-markdown's `Renderer` you'll find out it doesn't work.\n\n","type":"(a -> b) -> Markdown.Scaffolded.Block a -> Markdown.Scaffolded.Block b"},{"name":"parameterized","comment":" Use this function if you want to parameterize your view by an environment.\n\nAnother way of thinking about this use-case is: use this if you want to 'render to\nfunctions'.\n\nExamples for what the `environment` type variable can be:\n\n  - A `Model`, for rendering to `Model -> Html Msg` for `view`.\n  - Templating information, in case you want to use markdown as templates and want to\n    render to a function that expects templating parameters.\n\nUsually, for the above usecases you would have to define a function of type\n\n    foldTemplate :\n        Block (TemplateInfo -> Html msg)\n        -> (TemplateInfo -> Html msg)\n\nfor example, so that you can turn it back into a `Renderer (Template Info -> Html msg)`\nfor elm-markdown.\n\nIf you were to define such a function, you would have to pass around the `TemplateInfo`\nparameter a lot. This function will take care of that for you.\n\n\n### Anti use-cases\n\nIn some cases using this function would be overkill. The alternative to this function is\nto simply parameterize your whole renderer (and not use this library):\n\n    renderMarkdown : List String -> Block (Html Msg) -> Html Msg\n    renderMarkdown censoredWords markdown =\n        ...\n\n    renderer : List String -> Markdown.Renderer (Html Msg)\n    renderer censoredWords =\n        toRenderer\n            { renderHtml = ...\n            , renderMarkdown = renderMarkdown censoredWords\n            }\n\nIn this example you can see how we pass through the 'censored words'. It behaves kind of\nlike some global context in which we create our renderer.\n\nIt is hard to convey the abstract notion of when to use `parameterized` and when not to.\nI'll give it a try: If you want to parse your markdown once and need to quickly render\ndifferent versions of it (for example with different `Model`s or different\n`TemplateInfo`s), then use this. In other cases, if you probably only want to de-couple\nsome variable out of your renderer that is pretty static in general (for example censored\nwords), don't use this.\n\n\n### `parameterized` over multiple Parameters\n\nIf you want to parameterize your renderer over multiple variables, there are two options:\n\n1.  Add a field to the `environment` type used in this function\n2.  Take another parameter in curried form\n\nAlthough both are possible, I highly recommend the first option, as it is by far easier\nto deal with only one call to `parameterized`, not with two calls that would be required\nfor option 2.\n\n\n### Missing Functionality\n\nIf this function doesn't quite do what you want, just try to re-create what you need by\nusing `map` directly. `parameterized` basically just documents a pattern that is really\neasy to re-create: Its implementation is just 1 line of code.\n\n","type":"(Markdown.Scaffolded.Block view -> environment -> view) -> Markdown.Scaffolded.Block (environment -> view) -> environment -> view"},{"name":"reduce","comment":" Reduces a block down to anything that can be accumulated.\n\nYou provide two functions\n\n  - `accumulate`: Describe how values of type `a` are combined. Examples: `List.concat`,\n    `List.sum`, etc.\n  - `extract`: Descibe how a blocks generate values that are supposed to be accumulated.\n\nFor example, this can count the amount of headings in a markdown document:\n\n    reduce\n        { accumulate = List.sum\n        , extract =\n            \\block ->\n                case block of\n                    Heading _ ->\n                        1\n\n                    _ ->\n                        0\n        }\n\nOr this extracts code blocks:\n\n    reduce\n        { accumulate = List.concat\n        , extract =\n            \\block ->\n                case block of\n                    CodeBlock codeBlock ->\n                        [ codeBlock ]\n\n                    _ ->\n                        []\n        }\n\nThe special thing about this function is how you don't have to worry about accumulating\nthe other generated values recursively.\n\n","type":"{ accumulate : List.List a -> a, extract : Markdown.Scaffolded.Block a -> a } -> Markdown.Scaffolded.Block a -> a"},{"name":"toRenderer","comment":" Convert a function that works with `Block` to a `Renderer` for use with\nelm-markdown.\n\n(The second parameter is a [`Markdown.Html.Renderer`](/packages/dillonkearns/elm-markdown/3.0.0/Markdown-Html#Renderer))\n\n","type":"{ renderMarkdown : Markdown.Scaffolded.Block view -> view, renderHtml : Markdown.Html.Renderer (List.List view -> view) } -> Markdown.Renderer.Renderer view"},{"name":"validating","comment":" This transform enables validating the content of your `Block` before\nrendering.\n\nThis function's most prominent usecases are linting markdown files, so for example:\n\n  - Make sure all your code snippets are specified only with valid languages\n    ('elm', 'javascript', 'js', 'html' etc.)\n  - Make sure all your links are `https://` links\n  - Generate errors/warnings on typos or words not contained in a dictionary\n  - Disallow `h1` (alternatively, consider bumping the heading level)\n\nBut it might also be possible that your `view` type can't _always_ be folded from a\n`Block view` to a `view`, so you need to generate an error in these cases.\n\n\n### Missing Functionality\n\nIf this function doesn't quite do what you need to do, try using `foldResults`.\nThe `validating` definition basically just documents a common pattern. Its implementation\nis just 1 line of code.\n\n","type":"(Markdown.Scaffolded.Block view -> Result.Result error view) -> Markdown.Scaffolded.Block (Result.Result error view) -> Result.Result error view"},{"name":"withStaticHttpRequests","comment":" This transform allows you to perform elm-pages' StaticHttp requests without having to\nthink about how to thread these through your renderer.\n\nSome applications that can be realized like this:\n\n  - Verifying that all links in your markdown do resolve at page build-time\n    (Note: This currently needs some change in elm-pages, so it's not possible _yet_)\n  - Giving custom elm-markdown HTML elements the ability to perform StaticHttp requests\n\n\n### Missing Functionality\n\nIf this function doesn't quite do what you need to do, try using `foldStaticHttpRequests`.\nThe `wihtStaticHttpRequests` definition basically just documents a common pattern.\nIts implementation is just 1 line of code.\n\n","type":"(Markdown.Scaffolded.Block view -> Pages.StaticHttp.Request view) -> Markdown.Scaffolded.Block (Pages.StaticHttp.Request view) -> Pages.StaticHttp.Request view"}],"binops":[]}]