├── .github └── workflows │ └── haskell-ci.yml ├── .gitignore ├── .stylish-haskell.yaml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Setup.hs ├── cabal.haskell-ci ├── example └── Main.hs ├── renovate.json ├── servant-blaze.cabal └── src └── Servant └── HTML └── Blaze.hs /.github/workflows/haskell-ci.yml: -------------------------------------------------------------------------------- 1 | # This GitHub workflow config has been generated by a script via 2 | # 3 | # haskell-ci 'github' 'servant-blaze.cabal' '--allow-failures' '>= 9.2' '--distribution' 'focal' 4 | # 5 | # To regenerate the script (for example after adjusting tested-with) run 6 | # 7 | # haskell-ci regenerate 8 | # 9 | # For more information, see https://github.com/haskell-CI/haskell-ci 10 | # 11 | # version: 0.19.20250115 12 | # 13 | # REGENDATA ("0.19.20250115",["github","servant-blaze.cabal","--allow-failures",">= 9.2","--distribution","focal"]) 14 | # 15 | name: Haskell-CI 16 | on: 17 | push: 18 | branches: 19 | - master 20 | pull_request: 21 | branches: 22 | - master 23 | jobs: 24 | linux: 25 | name: Haskell-CI - Linux - ${{ matrix.compiler }} 26 | runs-on: ubuntu-20.04 27 | timeout-minutes: 28 | 60 29 | container: 30 | image: buildpack-deps:focal 31 | continue-on-error: ${{ matrix.allow-failure }} 32 | strategy: 33 | matrix: 34 | include: 35 | - compiler: ghc-9.10.1 36 | compilerKind: ghc 37 | compilerVersion: 9.10.1 38 | setup-method: ghcup 39 | allow-failure: true 40 | - compiler: ghc-9.8.4 41 | compilerKind: ghc 42 | compilerVersion: 9.8.4 43 | setup-method: ghcup 44 | allow-failure: true 45 | - compiler: ghc-9.6.6 46 | compilerKind: ghc 47 | compilerVersion: 9.6.6 48 | setup-method: ghcup 49 | allow-failure: true 50 | - compiler: ghc-9.4.8 51 | compilerKind: ghc 52 | compilerVersion: 9.4.8 53 | setup-method: ghcup 54 | allow-failure: true 55 | - compiler: ghc-9.2.8 56 | compilerKind: ghc 57 | compilerVersion: 9.2.8 58 | setup-method: ghcup 59 | allow-failure: true 60 | - compiler: ghc-9.0.2 61 | compilerKind: ghc 62 | compilerVersion: 9.0.2 63 | setup-method: ghcup 64 | allow-failure: false 65 | - compiler: ghc-8.10.7 66 | compilerKind: ghc 67 | compilerVersion: 8.10.7 68 | setup-method: ghcup 69 | allow-failure: false 70 | - compiler: ghc-8.8.4 71 | compilerKind: ghc 72 | compilerVersion: 8.8.4 73 | setup-method: ghcup 74 | allow-failure: false 75 | - compiler: ghc-8.6.5 76 | compilerKind: ghc 77 | compilerVersion: 8.6.5 78 | setup-method: ghcup 79 | allow-failure: false 80 | fail-fast: false 81 | steps: 82 | - name: apt-get install 83 | run: | 84 | apt-get update 85 | apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5 86 | - name: Install GHCup 87 | run: | 88 | mkdir -p "$HOME/.ghcup/bin" 89 | curl -sL https://downloads.haskell.org/ghcup/0.1.30.0/x86_64-linux-ghcup-0.1.30.0 > "$HOME/.ghcup/bin/ghcup" 90 | chmod a+x "$HOME/.ghcup/bin/ghcup" 91 | - name: Install cabal-install 92 | run: | 93 | "$HOME/.ghcup/bin/ghcup" install cabal 3.12.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false) 94 | echo "CABAL=$HOME/.ghcup/bin/cabal-3.12.1.0 -vnormal+nowrap" >> "$GITHUB_ENV" 95 | - name: Install GHC (GHCup) 96 | if: matrix.setup-method == 'ghcup' 97 | run: | 98 | "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false) 99 | HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER") 100 | HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#') 101 | HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#') 102 | echo "HC=$HC" >> "$GITHUB_ENV" 103 | echo "HCPKG=$HCPKG" >> "$GITHUB_ENV" 104 | echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV" 105 | env: 106 | HCKIND: ${{ matrix.compilerKind }} 107 | HCNAME: ${{ matrix.compiler }} 108 | HCVER: ${{ matrix.compilerVersion }} 109 | - name: Set PATH and environment variables 110 | run: | 111 | echo "$HOME/.cabal/bin" >> $GITHUB_PATH 112 | echo "LANG=C.UTF-8" >> "$GITHUB_ENV" 113 | echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV" 114 | echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV" 115 | HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))') 116 | echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV" 117 | echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV" 118 | echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV" 119 | echo "HEADHACKAGE=false" >> "$GITHUB_ENV" 120 | echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV" 121 | env: 122 | HCKIND: ${{ matrix.compilerKind }} 123 | HCNAME: ${{ matrix.compiler }} 124 | HCVER: ${{ matrix.compilerVersion }} 125 | - name: env 126 | run: | 127 | env 128 | - name: write cabal config 129 | run: | 130 | mkdir -p $CABAL_DIR 131 | cat >> $CABAL_CONFIG <> $CABAL_CONFIG < cabal-plan.xz 164 | echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c - 165 | xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan 166 | rm -f cabal-plan.xz 167 | chmod a+x $HOME/.cabal/bin/cabal-plan 168 | cabal-plan --version 169 | - name: checkout 170 | uses: actions/checkout@v4 171 | with: 172 | path: source 173 | - name: initial cabal.project for sdist 174 | run: | 175 | touch cabal.project 176 | echo "packages: $GITHUB_WORKSPACE/source/." >> cabal.project 177 | cat cabal.project 178 | - name: sdist 179 | run: | 180 | mkdir -p sdist 181 | $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist 182 | - name: unpack 183 | run: | 184 | mkdir -p unpacked 185 | find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \; 186 | - name: generate cabal.project 187 | run: | 188 | PKGDIR_servant_blaze="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/servant-blaze-[0-9.]*')" 189 | echo "PKGDIR_servant_blaze=${PKGDIR_servant_blaze}" >> "$GITHUB_ENV" 190 | rm -f cabal.project cabal.project.local 191 | touch cabal.project 192 | touch cabal.project.local 193 | echo "packages: ${PKGDIR_servant_blaze}" >> cabal.project 194 | echo "package servant-blaze" >> cabal.project 195 | echo " ghc-options: -Werror=missing-methods" >> cabal.project 196 | cat >> cabal.project <> cabal.project.local 199 | cat cabal.project 200 | cat cabal.project.local 201 | - name: dump install plan 202 | run: | 203 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all 204 | cabal-plan 205 | - name: restore cache 206 | uses: actions/cache/restore@v4 207 | with: 208 | key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} 209 | path: ~/.cabal/store 210 | restore-keys: ${{ runner.os }}-${{ matrix.compiler }}- 211 | - name: install dependencies 212 | run: | 213 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all 214 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all 215 | - name: build w/o tests 216 | run: | 217 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all 218 | - name: build 219 | run: | 220 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always 221 | - name: tests 222 | run: | 223 | $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct 224 | - name: cabal check 225 | run: | 226 | cd ${PKGDIR_servant_blaze} || false 227 | ${CABAL} -vnormal check 228 | - name: haddock 229 | run: | 230 | $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all 231 | - name: unconstrained build 232 | run: | 233 | rm -f cabal.project.local 234 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all 235 | - name: prepare for constraint sets 236 | run: | 237 | rm -f cabal.project.local 238 | - name: constraint set servant-0.20 239 | run: | 240 | if [ $((HCNUMVER >= 81000 && HCNUMVER < 90800)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.20.*' all --dry-run ; fi 241 | if [ $((HCNUMVER >= 81000 && HCNUMVER < 90800)) -ne 0 ] ; then cabal-plan topo | sort ; fi 242 | if [ $((HCNUMVER >= 81000 && HCNUMVER < 90800)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.20.*' --dependencies-only -j2 all ; fi 243 | if [ $((HCNUMVER >= 81000 && HCNUMVER < 90800)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.20.*' all ; fi 244 | - name: constraint set servant-0.19 245 | run: | 246 | if [ $((HCNUMVER >= 80800 && HCNUMVER < 90600)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.19.*' all --dry-run ; fi 247 | if [ $((HCNUMVER >= 80800 && HCNUMVER < 90600)) -ne 0 ] ; then cabal-plan topo | sort ; fi 248 | if [ $((HCNUMVER >= 80800 && HCNUMVER < 90600)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.19.*' --dependencies-only -j2 all ; fi 249 | if [ $((HCNUMVER >= 80800 && HCNUMVER < 90600)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.19.*' all ; fi 250 | - name: constraint set servant-0.18 251 | run: | 252 | if [ $((HCNUMVER < 90200)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.18.*' all --dry-run ; fi 253 | if [ $((HCNUMVER < 90200)) -ne 0 ] ; then cabal-plan topo | sort ; fi 254 | if [ $((HCNUMVER < 90200)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.18.*' --dependencies-only -j2 all ; fi 255 | if [ $((HCNUMVER < 90200)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.18.*' all ; fi 256 | - name: constraint set servant-0.17 257 | run: | 258 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.17.*' all --dry-run ; fi 259 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then cabal-plan topo | sort ; fi 260 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.17.*' --dependencies-only -j2 all ; fi 261 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.17.*' all ; fi 262 | - name: constraint set servant-0.16 263 | run: | 264 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.16.*' all --dry-run ; fi 265 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then cabal-plan topo | sort ; fi 266 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.16.*' --dependencies-only -j2 all ; fi 267 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.16.*' all ; fi 268 | - name: save cache 269 | if: always() 270 | uses: actions/cache/save@v4 271 | with: 272 | key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} 273 | path: ~/.cabal/store 274 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist-newstyle 2 | -------------------------------------------------------------------------------- /.stylish-haskell.yaml: -------------------------------------------------------------------------------- 1 | # stylish-haskell configuration file 2 | # ================================== 3 | 4 | # The stylish-haskell tool is mainly configured by specifying steps. These steps 5 | # are a list, so they have an order, and one specific step may appear more than 6 | # once (if needed). Each file is processed by these steps in the given order. 7 | steps: 8 | # Convert some ASCII sequences to their Unicode equivalents. This is disabled 9 | # by default. 10 | # - unicode_syntax: 11 | # # In order to make this work, we also need to insert the UnicodeSyntax 12 | # # language pragma. If this flag is set to true, we insert it when it's 13 | # # not already present. You may want to disable it if you configure 14 | # # language extensions using some other method than pragmas. Default: 15 | # # true. 16 | # add_language_pragma: true 17 | 18 | # Import cleanup 19 | - imports: 20 | # There are different ways we can align names and lists. 21 | # 22 | # - global: Align the import names and import list throughout the entire 23 | # file. 24 | # 25 | # - file: Like global, but don't add padding when there are no qualified 26 | # imports in the file. 27 | # 28 | # - group: Only align the imports per group (a group is formed by adjacent 29 | # import lines). 30 | # 31 | # - none: Do not perform any alignment. 32 | # 33 | # Default: global. 34 | align: global 35 | 36 | # Language pragmas 37 | - language_pragmas: 38 | # We can generate different styles of language pragma lists. 39 | # 40 | # - vertical: Vertical-spaced language pragmas, one per line. 41 | # 42 | # - compact: A more compact style. 43 | # 44 | # - compact_line: Similar to compact, but wrap each line with 45 | # `{-#LANGUAGE #-}'. 46 | # 47 | # Default: vertical. 48 | style: vertical 49 | 50 | # stylish-haskell can detect redundancy of some language pragmas. If this 51 | # is set to true, it will remove those redundant pragmas. Default: true. 52 | remove_redundant: true 53 | 54 | # Align the types in record declarations 55 | - records: {} 56 | 57 | # Replace tabs by spaces. This is disabled by default. 58 | # - tabs: 59 | # # Number of spaces to use for each tab. Default: 8, as specified by the 60 | # # Haskell report. 61 | # spaces: 8 62 | 63 | # Remove trailing whitespace 64 | - trailing_whitespace: {} 65 | 66 | # A common setting is the number of columns (parts of) code will be wrapped 67 | # to. Different steps take this into account. Default: 80. 68 | columns: 80 69 | 70 | # Sometimes, language extensions are specified in a cabal file or from the 71 | # command line instead of using language pragmas in the file. stylish-haskell 72 | # needs to be aware of these, so it can parse the file correctly. 73 | # 74 | # No language extensions are enabled by default. 75 | language_extensions: 76 | - TemplateHaskell 77 | - QuasiQuotes 78 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.9 2 | 3 | - Also accept content type without character set i.e `text/html` 4 | - Support only GHC >= 8.0 5 | 6 | # 0.8 7 | 8 | - Only single `MimeRender HTML a` instance. `blaze-markup` has `ToMarkup Markup` instance. 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2016, Servant Contributors 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Julian K. Arni nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # servant-blaze - Blaze-html support for servant 2 | 3 | ![servant](https://raw.githubusercontent.com/haskell-servant/servant/master/servant.png) 4 | 5 | This package allows you to use [blaze-html](http://hackage.haskell.org/package/blaze-html-0.8.0.0/docs/Text-Blaze-Html5.html) to serve html pages in your servant APIs. More specifically, it exports a `HTML` datatype with the correct `MimeRender` instances so that you can write `type API = Get '[HTML] User` for example. 6 | 7 | ## Minimal example: 8 | 9 | ```haskell 10 | {-# LANGUAGE OverloadedStrings, DataKinds #-} 11 | 12 | module Test where 13 | 14 | import Servant 15 | import Servant.HTML.Blaze 16 | import qualified Text.Blaze.Html5 as H 17 | 18 | type API = Get '[HTML] Homepage 19 | type Homepage = H.Html 20 | 21 | server :: Server API 22 | server = return myHome 23 | 24 | myHome :: Homepage 25 | myHome = H.docTypeHtml $ do 26 | H.head $ do 27 | H.title "Live to serve" 28 | H.body $ do 29 | H.h1 "Templates!" 30 | H.p "This will be type-checked, rendered and served" 31 | ``` 32 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /cabal.haskell-ci: -------------------------------------------------------------------------------- 1 | branches: master 2 | 3 | constraint-set servant-0.16 4 | ghc: >= 8.0 && <8.10 5 | constraints: servant ==0.16.* 6 | 7 | constraint-set servant-0.17 8 | ghc: >= 8.0 && <8.10 9 | constraints: servant ==0.17.* 10 | 11 | constraint-set servant-0.18 12 | ghc: >= 8.0 && <9.2 13 | constraints: servant ==0.18.* 14 | 15 | constraint-set servant-0.19 16 | ghc: >= 8.8 && <9.6 17 | constraints: servant ==0.19.* 18 | 19 | constraint-set servant-0.20 20 | ghc: >= 8.10 && <9.8 21 | constraints: servant ==0.20.* 22 | -------------------------------------------------------------------------------- /example/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE TypeOperators #-} 3 | {-# LANGUAGE OverloadedStrings #-} 4 | module Main (main) where 5 | 6 | import Data.Maybe (fromMaybe) 7 | import Network.Wai (Application) 8 | import Servant 9 | import Servant.HTML.Blaze 10 | import System.Environment (getArgs, lookupEnv) 11 | import Text.Read (readMaybe) 12 | 13 | import qualified Text.Blaze.Html5 as H 14 | import qualified Network.Wai.Handler.Warp as Warp 15 | 16 | type API = "string" :> Get '[HTML] String 17 | :<|> "html" :> Get '[HTML] H.Html 18 | 19 | api :: Proxy API 20 | api = Proxy 21 | 22 | server :: Server API 23 | server = return "example" :<|> return html where 24 | html :: H.Html 25 | html = do 26 | H.b "bar" 27 | H.i "iik" 28 | 29 | app :: Application 30 | app = serve api server 31 | 32 | main :: IO () 33 | main = do 34 | args <- getArgs 35 | case args of 36 | ("run":_) -> do 37 | port <- fmap (fromMaybe 8000 . (>>= readMaybe)) (lookupEnv "PORT") 38 | putStrLn $ "http://localhost:" ++ show port ++ "/" 39 | Warp.run port app 40 | _ -> do 41 | putStrLn "Example application, used as a compilation check" 42 | putStrLn "To run, pass run argument: --test-arguments run" 43 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /servant-blaze.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: >=1.10 2 | name: servant-blaze 3 | version: 0.9.1 4 | 5 | synopsis: Blaze-html support for servant 6 | category: Servant, Web 7 | description: 8 | Servant support for blaze-html 9 | . 10 | 'HTML' content type which will use `ToMarkup` class. 11 | 12 | homepage: http://haskell-servant.readthedocs.org/ 13 | bug-reports: http://github.com/haskell-servant/servant-blaze/issues 14 | license: BSD3 15 | license-file: LICENSE 16 | author: Servant Contributors 17 | maintainer: haskell-servant-maintainers@googlegroups.com 18 | copyright: 2015-2018 Servant Contributors 19 | build-type: Simple 20 | tested-with: 21 | GHC ==8.6.5 22 | || ==8.8.4 23 | || ==8.10.7 24 | || ==9.0.2 25 | || ==9.2.8 26 | || ==9.4.8 27 | || ==9.6.6 28 | || ==9.8.4 29 | || ==9.10.1 30 | extra-source-files: CHANGELOG.md 31 | 32 | source-repository head 33 | type: git 34 | location: http://github.com/haskell-servant/servant-blaze.git 35 | 36 | library 37 | exposed-modules: Servant.HTML.Blaze 38 | build-depends: base >=4.9 && <5 39 | , servant >=0.10 && <0.21 40 | , http-media >=0.6.4 && <0.9 41 | , blaze-html >=0.9.0.1 && <0.10 42 | hs-source-dirs: src 43 | default-language: Haskell2010 44 | ghc-options: -Wall 45 | 46 | test-suite example 47 | type: exitcode-stdio-1.0 48 | main-is: Main.hs 49 | hs-source-dirs: 50 | example 51 | ghc-options: -Wall 52 | build-depends: 53 | base 54 | , blaze-html 55 | , servant-blaze 56 | , servant-server >=0.4.4.5 && <0.21 57 | , wai >=3.0.3.0 && <3.3 58 | , warp >=3.0.13.1 && <3.5 59 | default-language: Haskell2010 60 | -------------------------------------------------------------------------------- /src/Servant/HTML/Blaze.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE DeriveDataTypeable #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE OverloadedStrings #-} 6 | 7 | -- | An @HTML@ empty data type with `MimeRender` instances for @blaze-html@'s 8 | -- `ToMarkup` class and `Html` datatype. 9 | -- You should only need to import this module for its instances and the 10 | -- `HTML` datatype: 11 | -- 12 | -- >>> type Eg = Get '[HTML] a 13 | -- 14 | -- Will then check that @a@ has a `ToMarkup` instance, or is `Html`. 15 | module Servant.HTML.Blaze where 16 | 17 | import Data.Typeable (Typeable) 18 | import qualified Network.HTTP.Media as M 19 | import Servant.API (Accept (..), MimeRender (..)) 20 | import Text.Blaze.Html (Html, ToMarkup, toHtml) 21 | import Text.Blaze.Html.Renderer.Utf8 (renderHtml) 22 | import qualified Data.List.NonEmpty as NE 23 | 24 | data HTML deriving Typeable 25 | 26 | -- | @text/html;charset=utf-8@ 27 | instance Accept HTML where 28 | contentTypes _ = 29 | "text" M.// "html" M./: ("charset", "utf-8") NE.:| 30 | ["text" M.// "html"] 31 | 32 | instance ToMarkup a => MimeRender HTML a where 33 | mimeRender _ = renderHtml . toHtml 34 | --------------------------------------------------------------------------------