├── .github └── workflows │ ├── bump.yml │ └── haskell-ci.yml ├── .gitignore ├── .stylish-haskell.yaml ├── README.md ├── cabal.haskell-ci ├── cabal.project ├── renovate.json ├── screenshot.png ├── servant-swagger-ui-core ├── Changelog.md ├── LICENSE ├── servant-swagger-ui-core.cabal └── src │ └── Servant │ └── Swagger │ └── UI │ └── Core.hs ├── servant-swagger-ui-example ├── LICENSE ├── Setup.hs ├── servant-swagger-ui-example.cabal └── src │ └── Main.hs ├── servant-swagger-ui-jensoleg ├── LICENSE ├── jensoleg-dist │ ├── css │ │ ├── api-explorer.css │ │ ├── index.css │ │ ├── print.css │ │ ├── reset.css │ │ ├── screen.css │ │ ├── standalone.css │ │ └── typography.css │ ├── fonts │ │ ├── droid-sans-v6-latin-700.eot │ │ ├── droid-sans-v6-latin-700.svg │ │ ├── droid-sans-v6-latin-700.ttf │ │ ├── droid-sans-v6-latin-700.woff │ │ ├── droid-sans-v6-latin-700.woff2 │ │ ├── droid-sans-v6-latin-regular.eot │ │ ├── droid-sans-v6-latin-regular.svg │ │ ├── droid-sans-v6-latin-regular.ttf │ │ ├── droid-sans-v6-latin-regular.woff │ │ └── droid-sans-v6-latin-regular.woff2 │ ├── images │ │ ├── Swagger_explorer.png │ │ ├── Swagger_explorer_min.png │ │ ├── explorer_icons.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── json_editor_integration.png │ │ ├── logo_small.png │ │ ├── pet_store_api.png │ │ ├── senodio.png │ │ ├── throbber.gif │ │ └── wordnik_api.png │ ├── index.html │ ├── lib │ │ ├── backbone-min.js │ │ ├── bootstrap.min.js │ │ ├── handlebars-2.0.0.js │ │ ├── highlight.7.3.pack.js │ │ ├── jquery-1.8.0.min.js │ │ ├── jquery.ba-bbq.min.js │ │ ├── jquery.slideto.min.js │ │ ├── jquery.wiggle.min.js │ │ ├── jsoneditor.js │ │ ├── marked.js │ │ ├── swagger-oauth.js │ │ └── underscore-min.js │ ├── moncierge.json │ ├── o2c.html │ ├── petstore.json │ ├── swagger-ui.js │ ├── swagger-ui.min.js │ └── swagger.json ├── jensoleg.index.html.tmpl ├── servant-swagger-ui-jensoleg.cabal └── src │ └── Servant │ └── Swagger │ └── UI │ └── JensOleG.hs ├── servant-swagger-ui-redoc ├── CHANGELOG.md ├── LICENSE ├── redoc-dist-1.22.3 │ └── redoc.min.js ├── redoc.index.html.tmpl ├── servant-swagger-ui-redoc.cabal └── src │ └── Servant │ └── Swagger │ └── UI │ └── ReDoc.hs └── servant-swagger-ui ├── CHANGELOG.md ├── LICENSE ├── index.html.tmpl ├── servant-swagger-ui.cabal ├── src └── Servant │ └── Swagger │ └── UI.hs └── swagger-ui-dist-5.0.0 ├── favicon-16x16.png ├── favicon-32x32.png ├── index.css ├── oauth2-redirect.html ├── swagger-initializer.js ├── swagger-ui-bundle.js ├── swagger-ui-bundle.js.map ├── swagger-ui-es-bundle-core.js ├── swagger-ui-es-bundle-core.js.map ├── swagger-ui-es-bundle.js ├── swagger-ui-es-bundle.js.map ├── swagger-ui-standalone-preset.js ├── swagger-ui-standalone-preset.js.map ├── swagger-ui.css ├── swagger-ui.css.map ├── swagger-ui.js └── swagger-ui.js.map /.github/workflows/bump.yml: -------------------------------------------------------------------------------- 1 | # Based on nomeata's dep bumper, should go back to using that when it supports executing build-tzdata.sh after checkout 2 | name: Create dependency bump PR 3 | on: 4 | # allows manual triggering from https://github.com/../../actions/workflows/bump.yml 5 | workflow_dispatch: 6 | # runs weekly on Thursday at 8:00 7 | schedule: 8 | - cron: '0 8 * * 4' 9 | 10 | permissions: 11 | contents: write 12 | pull-requests: write 13 | 14 | jobs: 15 | bump: 16 | runs-on: ubuntu-latest 17 | defaults: 18 | run: 19 | working-directory: ./servant-swagger-ui-core 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Cache cabal store 24 | id: cache 25 | uses: actions/cache/restore@v4 26 | with: 27 | key: bump-action-cabal-store-${{ runner.os }}-${{ github.sha }} 28 | path: ~/.cabal/store 29 | restore-keys: bump-action-cabal-store-${{ runner.os }}- 30 | 31 | - uses: haskell/actions/setup@v2 32 | with: 33 | ghc-version: latest 34 | 35 | - name: Run cabal outdated 36 | shell: bash 37 | run: | 38 | cabal outdated 39 | 40 | # also remember the values and the number of changes 41 | echo 'Output of `cabal outdated`:' >> $GITHUB_STEP_SUMMARY 42 | echo '```' >> $GITHUB_STEP_SUMMARY 43 | cabal outdated >> $GITHUB_STEP_SUMMARY 44 | echo '```' >> $GITHUB_STEP_SUMMARY 45 | 46 | DELIMITER=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) 47 | echo "CABAL_OUTDATED<<$DELIMITER" >> $GITHUB_ENV 48 | cabal outdated | tail -n +2 | sort | uniq >> $GITHUB_ENV 49 | echo "$DELIMITER" >> $GITHUB_ENV 50 | 51 | echo "CABAL_COUNT<<$DELIMITER" >> $GITHUB_ENV 52 | cabal outdated | tail -n +2 | sort | uniq | wc -l >> $GITHUB_ENV 53 | echo "$DELIMITER" >> $GITHUB_ENV 54 | 55 | echo "CABAL_FLAGS<<$DELIMITER" >> $GITHUB_ENV 56 | cabal outdated | tail -n +2 | sort | uniq | 57 | perl -ne 'print "--allow-newer=*:$1 --constraint=$1==$2 " if /([a-zA-Z0-9-]*).*\(latest: (.*)\)/' >> $GITHUB_ENV 58 | echo "" >> $GITHUB_ENV 59 | echo "$DELIMITER" >> $GITHUB_ENV 60 | 61 | - name: Gather PR description 62 | if: env.CABAL_COUNT > 0 63 | shell: bash 64 | run: | 65 | DELIMITER=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) 66 | echo "GIT_PR_TITLE<<$DELIMITER" >> $GITHUB_ENV 67 | if [ "$CABAL_COUNT" = 1 ] 68 | then 69 | echo "Bumping $CABAL_COUNT dependency" >> $GITHUB_ENV 70 | else 71 | echo "Bumping $CABAL_COUNT dependencies" >> $GITHUB_ENV 72 | fi 73 | echo "$DELIMITER" >> $GITHUB_ENV 74 | 75 | echo "GIT_PR_BODY<<$DELIMITER" >> $GITHUB_ENV 76 | echo '```' >> $GITHUB_ENV 77 | echo "$CABAL_OUTDATED" >> $GITHUB_ENV 78 | echo '```' >> $GITHUB_ENV 79 | echo >> $GITHUB_ENV 80 | echo "(Close and reopen this PR to trigger CI checks.)" >> $GITHUB_ENV 81 | echo "$DELIMITER" >> $GITHUB_ENV 82 | 83 | echo "GIT_COMMIT_MESSAGE<<$DELIMITER" >> $GITHUB_ENV 84 | if [ "$CABAL_COUNT" = 1 ] 85 | then 86 | echo "Bumping $CABAL_COUNT dependency" >> $GITHUB_ENV 87 | else 88 | echo "Bumping $CABAL_COUNT dependencies" >> $GITHUB_ENV 89 | fi 90 | echo "" >> $GITHUB_ENV 91 | cabal outdated >> $GITHUB_ENV 92 | echo "$DELIMITER" >> $GITHUB_ENV 93 | 94 | - name: Build dependencies 95 | id: dependency-build 96 | if: env.CABAL_COUNT > 0 97 | shell: bash 98 | continue-on-error: true 99 | run: | 100 | cabal build --only-dependencies --enable-tests --write-ghc-environment-files=always ${{ env.CABAL_FLAGS }} 101 | 102 | - name: Save cache 103 | uses: actions/cache/save@v4 104 | if: always() 105 | with: 106 | key: ${{ steps.cache.outputs.cache-primary-key }} 107 | path: ~/.cabal/store 108 | 109 | - name: Build local package 110 | if: env.CABAL_COUNT > 0 && steps.dependency-build.outcome == 'success' 111 | shell: bash 112 | run: | 113 | cabal build --enable-tests --write-ghc-environment-files=always ${{ env.CABAL_FLAGS }} 114 | cabal test ${{ env.CABAL_FLAGS }} 115 | 116 | - name: Fetch cabal-plan-bounds 117 | if: env.CABAL_COUNT > 0 && steps.dependency-build.outcome == 'success' 118 | shell: bash 119 | run: | 120 | curl -L https://github.com/nomeata/cabal-plan-bounds/releases/latest/download/cabal-plan-bounds.linux.gz | gunzip > /usr/local/bin/cabal-plan-bounds 121 | chmod +x /usr/local/bin/cabal-plan-bounds 122 | 123 | - name: Update .cabal file 124 | if: env.CABAL_COUNT > 0 && steps.dependency-build.outcome == 'success' 125 | shell: bash 126 | run: | 127 | # This line was added just for servant-swagger-ui, and counter-acts the default 128 | cd .. 129 | 130 | cabal-plan-bounds --extend dist-newstyle/cache/plan.json -c *.cabal 131 | git diff *.cabal 132 | 133 | - name: Create Pull Request 134 | id: cpr 135 | if: env.CABAL_COUNT > 0 && steps.dependency-build.outcome == 'success' 136 | uses: peter-evans/create-pull-request@v7 137 | with: 138 | branch: "cabal-updates" 139 | title: ${{ env.GIT_PR_TITLE }} 140 | body: ${{ env.GIT_PR_BODY }} 141 | commit-message: ${{ env.GIT_COMMIT_MESSAGE }} 142 | delete-branch: true 143 | add-paths: | 144 | servant-swagger-ui-core/*.cabal 145 | 146 | - name: Link to Pull Requst from summary 147 | if: env.CABAL_COUNT > 0 && steps.cpr.outputs.pull-request-number 148 | shell: bash 149 | run: | 150 | # This line was added just for servant-swagger-ui, and counter-acts the default 151 | cd .. 152 | 153 | echo "See [pull request ${{ steps.cpr.outputs.pull-request-number }}](${{ steps.cpr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY 154 | -------------------------------------------------------------------------------- /.github/workflows/haskell-ci.yml: -------------------------------------------------------------------------------- 1 | # This GitHub workflow config has been generated by a script via 2 | # 3 | # haskell-ci 'github' '--config=cabal.haskell-ci' 'cabal.project' 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.20250315 12 | # 13 | # REGENDATA ("0.19.20250315",["github","--config=cabal.haskell-ci","cabal.project"]) 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-24.04 27 | timeout-minutes: 28 | 60 29 | container: 30 | image: buildpack-deps:jammy 31 | continue-on-error: ${{ matrix.allow-failure }} 32 | strategy: 33 | matrix: 34 | include: 35 | - compiler: ghc-9.12.2 36 | compilerKind: ghc 37 | compilerVersion: 9.12.2 38 | setup-method: ghcup 39 | allow-failure: false 40 | - compiler: ghc-9.10.1 41 | compilerKind: ghc 42 | compilerVersion: 9.10.1 43 | setup-method: ghcup 44 | allow-failure: false 45 | - compiler: ghc-9.8.4 46 | compilerKind: ghc 47 | compilerVersion: 9.8.4 48 | setup-method: ghcup 49 | allow-failure: false 50 | - compiler: ghc-9.6.7 51 | compilerKind: ghc 52 | compilerVersion: 9.6.7 53 | setup-method: ghcup 54 | allow-failure: false 55 | - compiler: ghc-9.4.8 56 | compilerKind: ghc 57 | compilerVersion: 9.4.8 58 | setup-method: ghcup 59 | allow-failure: false 60 | - compiler: ghc-9.2.8 61 | compilerKind: ghc 62 | compilerVersion: 9.2.8 63 | setup-method: ghcup 64 | allow-failure: false 65 | - compiler: ghc-9.0.2 66 | compilerKind: ghc 67 | compilerVersion: 9.0.2 68 | setup-method: ghcup 69 | allow-failure: false 70 | - compiler: ghc-8.10.7 71 | compilerKind: ghc 72 | compilerVersion: 8.10.7 73 | setup-method: ghcup 74 | allow-failure: false 75 | - compiler: ghc-8.8.4 76 | compilerKind: ghc 77 | compilerVersion: 8.8.4 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.50.1/x86_64-linux-ghcup-0.1.50.1 > "$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.14.2.0 || (cat "$HOME"/.ghcup/logs/*.* && false) 94 | echo "CABAL=$HOME/.ghcup/bin/cabal-3.14.2.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/servant-swagger-ui" >> cabal.project 177 | echo "packages: $GITHUB_WORKSPACE/source/servant-swagger-ui-core" >> cabal.project 178 | echo "packages: $GITHUB_WORKSPACE/source/servant-swagger-ui-example" >> cabal.project 179 | echo "packages: $GITHUB_WORKSPACE/source/servant-swagger-ui-jensoleg" >> cabal.project 180 | echo "packages: $GITHUB_WORKSPACE/source/servant-swagger-ui-redoc" >> cabal.project 181 | cat cabal.project 182 | - name: sdist 183 | run: | 184 | mkdir -p sdist 185 | $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist 186 | - name: unpack 187 | run: | 188 | mkdir -p unpacked 189 | find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \; 190 | - name: generate cabal.project 191 | run: | 192 | PKGDIR_servant_swagger_ui="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/servant-swagger-ui-[0-9.]*')" 193 | echo "PKGDIR_servant_swagger_ui=${PKGDIR_servant_swagger_ui}" >> "$GITHUB_ENV" 194 | PKGDIR_servant_swagger_ui_core="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/servant-swagger-ui-core-[0-9.]*')" 195 | echo "PKGDIR_servant_swagger_ui_core=${PKGDIR_servant_swagger_ui_core}" >> "$GITHUB_ENV" 196 | PKGDIR_servant_swagger_ui_example="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/servant-swagger-ui-example-[0-9.]*')" 197 | echo "PKGDIR_servant_swagger_ui_example=${PKGDIR_servant_swagger_ui_example}" >> "$GITHUB_ENV" 198 | PKGDIR_servant_swagger_ui_jensoleg="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/servant-swagger-ui-jensoleg-[0-9.]*')" 199 | echo "PKGDIR_servant_swagger_ui_jensoleg=${PKGDIR_servant_swagger_ui_jensoleg}" >> "$GITHUB_ENV" 200 | PKGDIR_servant_swagger_ui_redoc="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/servant-swagger-ui-redoc-[0-9.]*')" 201 | echo "PKGDIR_servant_swagger_ui_redoc=${PKGDIR_servant_swagger_ui_redoc}" >> "$GITHUB_ENV" 202 | rm -f cabal.project cabal.project.local 203 | touch cabal.project 204 | touch cabal.project.local 205 | echo "packages: ${PKGDIR_servant_swagger_ui}" >> cabal.project 206 | echo "packages: ${PKGDIR_servant_swagger_ui_core}" >> cabal.project 207 | echo "packages: ${PKGDIR_servant_swagger_ui_example}" >> cabal.project 208 | echo "packages: ${PKGDIR_servant_swagger_ui_jensoleg}" >> cabal.project 209 | echo "packages: ${PKGDIR_servant_swagger_ui_redoc}" >> cabal.project 210 | echo "package servant-swagger-ui" >> cabal.project 211 | echo " ghc-options: -Werror=missing-methods" >> cabal.project 212 | echo "package servant-swagger-ui-core" >> cabal.project 213 | echo " ghc-options: -Werror=missing-methods" >> cabal.project 214 | echo "package servant-swagger-ui-example" >> cabal.project 215 | echo " ghc-options: -Werror=missing-methods" >> cabal.project 216 | echo "package servant-swagger-ui-jensoleg" >> cabal.project 217 | echo " ghc-options: -Werror=missing-methods" >> cabal.project 218 | echo "package servant-swagger-ui-redoc" >> cabal.project 219 | echo " ghc-options: -Werror=missing-methods" >> cabal.project 220 | cat >> cabal.project <> cabal.project.local 223 | cat cabal.project 224 | cat cabal.project.local 225 | - name: dump install plan 226 | run: | 227 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all 228 | cabal-plan 229 | - name: restore cache 230 | uses: actions/cache/restore@v4 231 | with: 232 | key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} 233 | path: ~/.cabal/store 234 | restore-keys: ${{ runner.os }}-${{ matrix.compiler }}- 235 | - name: install dependencies 236 | run: | 237 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all 238 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all 239 | - name: build w/o tests 240 | run: | 241 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all 242 | - name: build 243 | run: | 244 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always 245 | - name: cabal check 246 | run: | 247 | cd ${PKGDIR_servant_swagger_ui} || false 248 | ${CABAL} -vnormal check 249 | cd ${PKGDIR_servant_swagger_ui_core} || false 250 | ${CABAL} -vnormal check 251 | cd ${PKGDIR_servant_swagger_ui_example} || false 252 | ${CABAL} -vnormal check 253 | cd ${PKGDIR_servant_swagger_ui_jensoleg} || false 254 | ${CABAL} -vnormal check 255 | cd ${PKGDIR_servant_swagger_ui_redoc} || false 256 | ${CABAL} -vnormal check 257 | - name: haddock 258 | run: | 259 | $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all 260 | - name: unconstrained build 261 | run: | 262 | rm -f cabal.project.local 263 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all 264 | - name: prepare for constraint sets 265 | run: | 266 | rm -f cabal.project.local 267 | - name: constraint set servant-0.20 268 | run: | 269 | if [ $((HCNUMVER >= 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.20.*' all --dry-run ; fi 270 | if [ $((HCNUMVER >= 81000)) -ne 0 ] ; then cabal-plan topo | sort ; fi 271 | if [ $((HCNUMVER >= 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.20.*' --dependencies-only -j2 all ; fi 272 | if [ $((HCNUMVER >= 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.20.*' all ; fi 273 | - name: constraint set servant-0.19 274 | run: | 275 | if [ $((HCNUMVER < 90600)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.19.*' all --dry-run ; fi 276 | if [ $((HCNUMVER < 90600)) -ne 0 ] ; then cabal-plan topo | sort ; fi 277 | if [ $((HCNUMVER < 90600)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.19.*' --dependencies-only -j2 all ; fi 278 | if [ $((HCNUMVER < 90600)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.19.*' all ; fi 279 | - name: constraint set servant-0.18 280 | run: | 281 | if [ $((HCNUMVER < 90000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.18.*' all --dry-run ; fi 282 | if [ $((HCNUMVER < 90000)) -ne 0 ] ; then cabal-plan topo | sort ; fi 283 | if [ $((HCNUMVER < 90000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.18.*' --dependencies-only -j2 all ; fi 284 | if [ $((HCNUMVER < 90000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.18.*' all ; fi 285 | - name: constraint set servant-0.17 286 | run: | 287 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.17.*' all --dry-run ; fi 288 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then cabal-plan topo | sort ; fi 289 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.17.*' --dependencies-only -j2 all ; fi 290 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.17.*' all ; fi 291 | - name: constraint set servant-0.16 292 | run: | 293 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.16.*' all --dry-run ; fi 294 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then cabal-plan topo | sort ; fi 295 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.16.*' --dependencies-only -j2 all ; fi 296 | if [ $((HCNUMVER < 81000)) -ne 0 ] ; then $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='servant ==0.16.*' all ; fi 297 | - name: save cache 298 | if: always() 299 | uses: actions/cache/save@v4 300 | with: 301 | key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} 302 | path: ~/.cabal/store 303 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | dist-newstyle/ 3 | .ghc.environment.* 4 | .stack-work/ 5 | .cabal-sandbox 6 | cabal.sandbox.config 7 | src/highlight.js 8 | src/style.css 9 | -------------------------------------------------------------------------------- /.stylish-haskell.yaml: -------------------------------------------------------------------------------- 1 | steps: 2 | - imports: 3 | align: group 4 | list_align: after_alias 5 | long_list_align: new_line 6 | empty_list_align: right_after 7 | list_padding: module_name 8 | - language_pragmas: 9 | style: vertical 10 | remove_redundant: true 11 | - trailing_whitespace: {} 12 | columns: 80 13 | language_extensions: 14 | - MultiParamTypeClasses 15 | - FlexibleContexts 16 | - ExplicitForAll 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # servant-swagger-ui 2 | 3 | *Provide a Swagger UI for your Servant API* 4 | 5 | "[Swagger UI](http://swagger.io/swagger-ui/) allows anyone — be it your development team or your end consumers — to visualize and interact with the API’s resources without having any of the implementation logic in place." 6 | 7 | [![Build Status](https://travis-ci.org/phadej/servant-swagger-ui.svg?branch=master)](https://travis-ci.org/phadej/servant-swagger-ui) 8 | [![Hackage](https://img.shields.io/hackage/v/servant-swagger-ui.svg)](http://hackage.haskell.org/package/servant-swagger-ui) 9 | [![Stackage LTS 5](http://stackage.org/package/servant-swagger-ui/badge/lts-5)](http://stackage.org/lts-5/package/servant-swagger-ui) 10 | [![Stackage Nightly](http://stackage.org/package/servant-swagger-ui/badge/nightly)](http://stackage.org/nightly/package/servant-swagger-ui) 11 | 12 | ## Example 13 | 14 | ![example screenshot](https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/master/screenshot.png) 15 | 16 | Check [`servant-swagger-ui-example/src/Main.hs`](https://github.com/haskell-servant/servant-swagger-ui/blob/master/servant-swagger-ui-example/src/Main.hs) for an example. 17 | 18 | ## Development 19 | 20 | ### Updating of bundled swagger-ui version: 21 | 22 | - Extract `dist` directory of `swagger-ui` into `swagger-dist-<version>`. Remove the `*.map` files. 23 | - update `extra-source-files` in the `.cabal` 24 | - move `index.html` into `index.html.tmpl`, do the diff, port the changes 25 | - search replace the embbeded directory (in `Servant/Swagger/UI.hs`) 26 | - test it works 27 | -------------------------------------------------------------------------------- /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.6 && <9.0 13 | constraints: servant ==0.18.* 14 | 15 | constraint-set servant-0.19 16 | ghc: >= 8.6 && <9.6 17 | constraints: servant ==0.19.* 18 | 19 | constraint-set servant-0.20 20 | ghc: >= 8.10 && <9.14 21 | constraints: servant ==0.20.* 22 | -------------------------------------------------------------------------------- /cabal.project: -------------------------------------------------------------------------------- 1 | packages: 2 | servant-swagger-ui/ 3 | servant-swagger-ui-core/ 4 | servant-swagger-ui-example/ 5 | servant-swagger-ui-jensoleg/ 6 | servant-swagger-ui-redoc/ 7 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/screenshot.png -------------------------------------------------------------------------------- /servant-swagger-ui-core/Changelog.md: -------------------------------------------------------------------------------- 1 | # 0.3.5 2 | 3 | - Generalize `SwaggerSchemaUI` and `swaggerSchemaUIServerImpl` to support arbitrary `Value` instead 4 | of hardcoded `Swagger` type. 5 | 6 | # 0.3.3 7 | 8 | - Add `swaggerSchemaUIServerImpl'` 9 | 10 | # 0.3.1 11 | 12 | - Support `servant-0.14` 13 | -------------------------------------------------------------------------------- /servant-swagger-ui-core/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Oleg Grenrus 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 Oleg Grenrus 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 | 32 | --- 33 | 34 | Bundled swagger-ui (index.html.tmpl original and swagger-dist-2.1.4 directory): 35 | 36 | Copyright 2016 SmartBear Software 37 | 38 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 39 | this file except in compliance with the License. You may obtain a copy of the 40 | License at apache.org/licenses/LICENSE-2.0 41 | 42 | Unless required by applicable law or agreed to in writing, software distributed 43 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 44 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 45 | specific language governing permissions and limitations under the License. 46 | -------------------------------------------------------------------------------- /servant-swagger-ui-core/servant-swagger-ui-core.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 1.12 2 | name: servant-swagger-ui-core 3 | version: 0.3.5 4 | synopsis: Servant swagger ui core components 5 | category: Web, Servant, Swagger 6 | description: 7 | Provide embedded swagger UI for servant and swagger (i.e. servant-swagger) 8 | . 9 | See servant-swagger-ui, servant-swagger-ui-jensoleg or 10 | servant-swagger-ui-redoc for "concrete" implementations. 11 | 12 | homepage: https://github.com/haskell-servant/servant-swagger-ui 13 | bug-reports: 14 | https://github.com/haskell-servant/servant-swagger-ui/issues 15 | 16 | author: Oleg Grenrus 17 | maintainer: haskell-servant-maintainers@googlegroups.com 18 | license: BSD3 19 | license-file: LICENSE 20 | build-type: Simple 21 | tested-with: 22 | GHC ==8.8.4 23 | || ==8.10.7 24 | || ==9.0.2 25 | || ==9.2.8 26 | || ==9.4.8 27 | || ==9.6.7 28 | || ==9.8.4 29 | || ==9.10.1 30 | || ==9.12.2 31 | 32 | extra-source-files: Changelog.md 33 | 34 | source-repository head 35 | type: git 36 | location: https://github.com/haskell-servant/servant-swagger-ui 37 | 38 | library 39 | hs-source-dirs: src 40 | ghc-options: -Wall 41 | build-depends: 42 | base >=4.7 && <4.22 43 | , aeson >=0.8.0.2 && <2.3 44 | , blaze-markup >=0.7.0.2 && <0.9 45 | , bytestring >=0.10.4.0 && <0.13 46 | , http-media >=0.7.1.3 && <0.9 47 | , servant >=0.14 && <0.21 48 | , servant-blaze >=0.8 && <0.10 49 | , servant-server >=0.14 && <0.21 50 | , text >=1.2.3.0 && <2.2 51 | , transformers >=0.3 && <0.7 52 | , transformers-compat >=0.3 && <0.8 53 | , wai-app-static >=3.0.1.1 && <3.2 54 | 55 | exposed-modules: Servant.Swagger.UI.Core 56 | default-language: Haskell2010 57 | -------------------------------------------------------------------------------- /servant-swagger-ui-core/src/Servant/Swagger/UI/Core.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE DeriveGeneric #-} 4 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 5 | {-# LANGUAGE MultiParamTypeClasses #-} 6 | {-# LANGUAGE OverloadedStrings #-} 7 | {-# LANGUAGE ScopedTypeVariables #-} 8 | {-# LANGUAGE TypeFamilies #-} 9 | {-# LANGUAGE TypeOperators #-} 10 | {-# LANGUAGE UndecidableInstances #-} 11 | ----------------------------------------------------------------------------- 12 | -- 13 | -- Provides 'SwaggerUI' and corresponding 'swaggerUIServer' to embed 14 | -- into the application. 15 | -- 16 | -- All of UI files are embedded into the binary. 17 | -- 18 | -- /An example:/ 19 | -- 20 | -- @ 21 | -- -- | Actual API. 22 | -- type BasicAPI = Get '[PlainText, JSON] Text 23 | -- :\<|> "cat" :> Capture ":name" CatName :> Get '[JSON] Cat 24 | -- 25 | -- -- | API type with bells and whistles, i.e. schema file and swagger-ui. 26 | -- type API = 'SwaggerSchemaUI' "swagger-ui" "swagger.json" 27 | -- :\<|> BasicAPI 28 | -- 29 | -- -- | Servant server for an API 30 | -- server :: Server API 31 | -- server = 'swaggerSchemaUIServer' swaggerDoc 32 | -- :\<|> (pure "Hello World" :\<|> catEndpoint) 33 | -- where 34 | -- catEndpoint name = pure $ Cat name False 35 | -- @ 36 | 37 | module Servant.Swagger.UI.Core ( 38 | -- * Swagger UI API 39 | SwaggerSchemaUI, 40 | SwaggerSchemaUI', 41 | 42 | -- * Implementation details 43 | SwaggerUiHtml(..), 44 | swaggerSchemaUIServerImpl, 45 | swaggerSchemaUIServerImpl', 46 | Handler, 47 | ) where 48 | 49 | import Data.Aeson (ToJSON (..), Value) 50 | import Data.ByteString (ByteString) 51 | import GHC.TypeLits (KnownSymbol, Symbol, symbolVal) 52 | import Network.Wai.Application.Static (embeddedSettings, staticApp) 53 | import Servant 54 | import Servant.HTML.Blaze (HTML) 55 | import Text.Blaze (ToMarkup (..)) 56 | 57 | import qualified Data.Text as T 58 | 59 | -- | Swagger schema + ui api. 60 | -- 61 | -- @SwaggerSchemaUI "swagger-ui" "swagger.json"@ will result into following hierarchy: 62 | -- 63 | -- @ 64 | -- \/swagger.json 65 | -- \/swagger-ui 66 | -- \/swagger-ui\/index.html 67 | -- \/swagger-ui\/... 68 | -- @ 69 | -- 70 | -- This type does not actually force served type to be @Swagger@ from @swagger2@ package, 71 | -- it could be arbitrary @aeson@ 'Value'. 72 | type SwaggerSchemaUI (dir :: Symbol) (schema :: Symbol) = 73 | SwaggerSchemaUI' dir (schema :> Get '[JSON] Value) 74 | 75 | -- | Use 'SwaggerSchemaUI'' when you need even more control over 76 | -- where @swagger.json@ is served (e.g. subdirectory). 77 | type SwaggerSchemaUI' (dir :: Symbol) (api :: *) = 78 | api 79 | :<|> dir :> 80 | ( Get '[HTML] (SwaggerUiHtml dir api) 81 | :<|> "index.html" :> Get '[HTML] (SwaggerUiHtml dir api) 82 | :<|> Raw 83 | ) 84 | 85 | -- | Index file for swagger ui. 86 | -- 87 | -- It's configured by the location of swagger schema and directory it lives under. 88 | -- 89 | -- Implementation detail: the @index.html@ is prepopulated with parameters 90 | -- to find schema file automatically. 91 | data SwaggerUiHtml (dir :: Symbol) (api :: *) = SwaggerUiHtml T.Text 92 | 93 | instance (KnownSymbol dir, HasLink api, Link ~ MkLink api Link, IsElem api api) 94 | => ToMarkup (SwaggerUiHtml dir api) 95 | where 96 | toMarkup (SwaggerUiHtml template) = preEscapedToMarkup 97 | $ T.replace "SERVANT_SWAGGER_UI_SCHEMA" schema 98 | $ T.replace "SERVANT_SWAGGER_UI_DIR" dir 99 | $ template 100 | where 101 | schema = T.pack $ uriPath . linkURI $ safeLink proxyApi proxyApi 102 | dir = T.pack $ symbolVal (Proxy :: Proxy dir) 103 | proxyApi = Proxy :: Proxy api 104 | 105 | swaggerSchemaUIServerImpl 106 | :: (Monad m, ServerT api m ~ m Value, ToJSON a) 107 | => T.Text -> [(FilePath, ByteString)] 108 | -> a -> ServerT (SwaggerSchemaUI' dir api) m 109 | swaggerSchemaUIServerImpl indexTemplate files swagger 110 | = swaggerSchemaUIServerImpl' indexTemplate files $ return $ toJSON swagger 111 | 112 | -- | Use a custom server to serve the Swagger spec source. 113 | swaggerSchemaUIServerImpl' 114 | :: Monad m 115 | => T.Text 116 | -> [(FilePath, ByteString)] 117 | -> ServerT api m 118 | -> ServerT (SwaggerSchemaUI' dir api) m 119 | swaggerSchemaUIServerImpl' indexTemplate files server 120 | = server 121 | :<|> return (SwaggerUiHtml indexTemplate) 122 | :<|> return (SwaggerUiHtml indexTemplate) 123 | :<|> rest 124 | where 125 | rest = Tagged $ staticApp $ embeddedSettings files 126 | -------------------------------------------------------------------------------- /servant-swagger-ui-example/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Oleg Grenrus 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 Oleg Grenrus 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 | -------------------------------------------------------------------------------- /servant-swagger-ui-example/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /servant-swagger-ui-example/servant-swagger-ui-example.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 2.0 2 | name: servant-swagger-ui-example 3 | version: 0 4 | synopsis: servant-swagger-ui example 5 | category: Web, Servant, Swagger 6 | description: A kind of test-suite of servant-swagger-ui 7 | homepage: https://github.com/haskell-servant/servant-swagger-ui 8 | bug-reports: 9 | https://github.com/haskell-servant/servant-swagger-ui/issues 10 | 11 | author: Oleg Grenrus 12 | maintainer: haskell-servant-maintainers@googlegroups.com 13 | license: BSD3 14 | license-file: LICENSE 15 | build-type: Simple 16 | tested-with: 17 | GHC ==8.8.4 18 | || ==8.10.7 19 | || ==9.0.2 20 | || ==9.2.8 21 | || ==9.4.8 22 | || ==9.6.7 23 | || ==9.8.4 24 | || ==9.10.1 25 | || ==9.12.2 26 | 27 | source-repository head 28 | type: git 29 | location: https://github.com/haskell-servant/servant-swagger-ui 30 | 31 | executable servant-swagger-ui-example 32 | main-is: Main.hs 33 | ghc-options: -threaded 34 | build-depends: 35 | aeson >=0.8.0.2 && <2.3 36 | , base >=4.7 && <4.22 37 | , base-compat >=0.9.3 && <0.15 38 | , lens >=4.7.0.1 && <5.4 39 | , servant 40 | , servant-server 41 | , servant-swagger 42 | , servant-swagger-ui 43 | , servant-swagger-ui-core 44 | , servant-swagger-ui-jensoleg 45 | , servant-swagger-ui-redoc 46 | , swagger2 47 | , text 48 | , wai >=3.0.3.0 && <3.3 49 | , warp >=3.0.13.1 && <3.5 50 | 51 | hs-source-dirs: src 52 | default-language: Haskell2010 53 | -------------------------------------------------------------------------------- /servant-swagger-ui-example/src/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE DeriveGeneric #-} 4 | {-# LANGUAGE FlexibleInstances #-} 5 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 6 | {-# LANGUAGE MultiParamTypeClasses #-} 7 | {-# LANGUAGE OverloadedStrings #-} 8 | {-# LANGUAGE ScopedTypeVariables #-} 9 | {-# LANGUAGE TypeFamilies #-} 10 | {-# LANGUAGE TypeOperators #-} 11 | {-# LANGUAGE UndecidableInstances #-} 12 | {-# OPTIONS_GHC -fno-warn-orphans #-} 13 | module Main (main, catIsMale, catName) where 14 | 15 | import Prelude () 16 | import Prelude.Compat 17 | 18 | import Control.Lens hiding ((.=)) 19 | import Data.Aeson (FromJSON, ToJSON, Value) 20 | import Data.Maybe (fromMaybe) 21 | import Data.String (IsString (..)) 22 | import Data.Text (Text) 23 | import GHC.Generics (Generic) 24 | import Network.Wai (Application) 25 | import System.Environment (getArgs, lookupEnv) 26 | import Text.Read (readMaybe) 27 | 28 | import Data.Swagger 29 | import Servant 30 | import Servant.Swagger 31 | import Servant.Swagger.UI 32 | import Servant.Swagger.UI.Core 33 | import Servant.Swagger.UI.JensOleG 34 | import Servant.Swagger.UI.ReDoc 35 | 36 | import qualified Network.Wai.Handler.Warp as Warp 37 | 38 | #if MIN_VERSION_servant(0,12,0) 39 | #define SUMMARY(d) Summary d :> 40 | #else 41 | #define SUMMARY(d) 42 | #endif 43 | 44 | #if MIN_VERSION_servant(0,13,0) 45 | #if __GLASGOW_HASKELL__ >= 802 && MIN_VERSION_base(4,10,0) 46 | import GHC.Generics (D1, Meta (..), Rep) 47 | import GHC.TypeLits (AppendSymbol, Symbol) 48 | #endif 49 | #endif 50 | 51 | -- data types 52 | data Cat = Cat { catName :: CatName, catIsMale :: Bool } 53 | deriving (Generic, Show) 54 | 55 | newtype CatName = CatName Text 56 | deriving ( Eq, Show, Generic 57 | #if MIN_VERSION_servant(0,5,0) 58 | , FromHttpApiData 59 | #else 60 | , FromText 61 | #endif 62 | ) 63 | 64 | instance IsString CatName where 65 | fromString = CatName . fromString 66 | 67 | -- swagger instances 68 | instance ToJSON Cat 69 | instance ToJSON CatName 70 | instance FromJSON Cat 71 | instance FromJSON CatName 72 | instance ToParamSchema CatName 73 | instance ToSchema Cat 74 | instance ToSchema CatName 75 | 76 | -- api 77 | 78 | #if MIN_VERSION_servant(0,13,0) 79 | #if __GLASGOW_HASKELL__ >= 802 && MIN_VERSION_base(4,10,0) 80 | -- | Get a typename as type-level 'Symbol'. 81 | -- 82 | -- Few non-Generic things are hard-coded, for else we fallback to 'Generic' 83 | -- 84 | -- >>> :kind! TypeName Int 85 | -- TypeName Int :: Symbol 86 | -- = "Int" 87 | -- 88 | -- >>> :kind! TypeName CatName 89 | -- TypeName CatName :: Symbol 90 | -- = "CatName" 91 | -- 92 | -- Unfortunately we cannot use 'TypeError' for other cases, 93 | -- as 'Rep' isn't reduced so 'GenericTypeName' cannot fall past first 94 | -- equation. So you will get somewhat obscure errors saying 95 | -- "no instance for (KnownSymbol ... (GenericTypeName YourNonGenericType ..." 96 | -- 97 | -- >>> :kind! TypeName Float 98 | -- TypeName Float :: Symbol 99 | -- = GenericTypeName Float (Rep Float ()) 100 | -- 101 | -- It would be nice if there were such type family for 'Typeable', i.e. all 102 | -- types :) 103 | -- 104 | type family TypeName (x :: *) :: Symbol where 105 | TypeName Int = "Int" 106 | TypeName Text = "Text" 107 | TypeName x = GenericTypeName x (Rep x ()) 108 | 109 | type family GenericTypeName t (r :: *) :: Symbol where 110 | GenericTypeName t (D1 ('MetaData name mod pkg nt) f x) = name 111 | 112 | type Desc t n = Description (AppendSymbol (TypeName t) (AppendSymbol " | " n)) 113 | #else 114 | type Desc t n = Description n 115 | #endif 116 | #endif 117 | 118 | type FirstCatEndpoint = 119 | #if MIN_VERSION_servant(0,13,0) 120 | "cat" 121 | :> Summary "First cat endpoint" 122 | :> Capture' '[Desc CatName "Cat's name"] ":name" CatName 123 | :> QueryParam' '[Required, Desc Int "Random number"] "num" Int 124 | :> QueryParam' '[Optional, Desc Text "Random text"] "text" Text 125 | :> Get '[JSON] Cat 126 | #else 127 | "cat" :> Capture ":name" CatName 128 | :> QueryParam "num" Int :> QueryParam "text" Text :> Get '[JSON] Cat 129 | #endif 130 | 131 | type BasicAPI = Get '[PlainText, JSON] Text 132 | :<|> FirstCatEndpoint 133 | :<|> SUMMARY("Second cat") "cat2" :> Capture ":name" CatName :> Get '[JSON] Cat 134 | :<|> SUMMARY("Third cat") "cat3" :> Capture ":name" CatName :> Get '[JSON] Cat 135 | :<|> SUMMARY("Post endpoint") "post-cat" :> ReqBody '[JSON] Cat :> Post '[JSON] Cat 136 | 137 | type API = 138 | -- this serves both: swagger.json and swagger-ui 139 | SwaggerSchemaUI "swagger-ui" "swagger.json" 140 | :<|> BasicAPI 141 | 142 | -- To test nested case 143 | type API' = API 144 | :<|> "nested" :> API 145 | :<|> SwaggerSchemaUI' "foo-ui" ("foo" :> "swagger.json" :> Get '[JSON] Value) 146 | 147 | -- Implementation 148 | 149 | -- | We test different ways to nest API, so we have an enumeration 150 | data Variant 151 | = Normal 152 | | Nested 153 | | SpecDown 154 | deriving (Eq) 155 | 156 | data UIFlavour 157 | = Original 158 | | JensOleG 159 | | ReDoc 160 | deriving (Eq) 161 | 162 | server' :: UIFlavour -> Server API' 163 | server' uiFlavour = server Normal 164 | :<|> server Nested 165 | :<|> schemaUiServer (swaggerDoc' SpecDown) 166 | where 167 | server :: Variant -> Server API 168 | server variant = 169 | schemaUiServer (swaggerDoc' variant) 170 | :<|> (return "Hello World" :<|> catEndpoint' :<|> catEndpoint :<|> catEndpoint :<|> return) 171 | where 172 | catEndpoint' n _ _ = return $ Cat n (variant == Normal) 173 | catEndpoint n = return $ Cat n (variant == Normal) 174 | -- Unfortunately we have to specify the basePath manually atm. 175 | 176 | schemaUiServer 177 | :: (Server api ~ Handler Value) 178 | => Swagger -> Server (SwaggerSchemaUI' dir api) 179 | schemaUiServer = case uiFlavour of 180 | Original -> swaggerSchemaUIServer 181 | JensOleG -> jensolegSwaggerSchemaUIServer 182 | ReDoc -> redocSchemaUIServer 183 | 184 | swaggerDoc' Normal = swaggerDoc 185 | swaggerDoc' Nested = swaggerDoc 186 | & basePath ?~ "/nested" 187 | & info.description ?~ "Nested API" 188 | swaggerDoc' SpecDown = swaggerDoc 189 | & info.description ?~ "Spec nested" 190 | 191 | -- Boilerplate 192 | 193 | swaggerDoc :: Swagger 194 | swaggerDoc = toSwagger (Proxy :: Proxy BasicAPI) 195 | & info.title .~ "Cats API" 196 | & info.version .~ "2016.8.7" 197 | & info.description ?~ "This is an API that tests servant-swagger support" 198 | 199 | api :: Proxy API' 200 | api = Proxy 201 | 202 | app :: UIFlavour -> Application 203 | app = serve api . server' 204 | 205 | main :: IO () 206 | main = do 207 | args <- getArgs 208 | let uiFlavour | "jensoleg" `elem` args = JensOleG 209 | | "redoc" `elem` args = ReDoc 210 | | otherwise = Original 211 | p <- fromMaybe 8000 . (>>= readMaybe) <$> lookupEnv "PORT" 212 | putStrLn $ "http://localhost:" ++ show p ++ "/" 213 | Warp.run p (app uiFlavour) 214 | -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Oleg Grenrus 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 Oleg Grenrus 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 | 32 | --- 33 | 34 | Bundled swagger-ui (index.html.tmpl original and swagger-dist-2.1.4 directory): 35 | 36 | Copyright 2016 SmartBear Software 37 | 38 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 39 | this file except in compliance with the License. You may obtain a copy of the 40 | License at apache.org/licenses/LICENSE-2.0 41 | 42 | Unless required by applicable law or agreed to in writing, software distributed 43 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 44 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 45 | specific language governing permissions and limitations under the License. 46 | -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ 2 | html, 3 | body, 4 | div, 5 | span, 6 | applet, 7 | object, 8 | iframe, 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p, 16 | blockquote, 17 | pre, 18 | a, 19 | abbr, 20 | acronym, 21 | address, 22 | big, 23 | cite, 24 | code, 25 | del, 26 | dfn, 27 | em, 28 | img, 29 | ins, 30 | kbd, 31 | q, 32 | s, 33 | samp, 34 | small, 35 | strike, 36 | strong, 37 | sub, 38 | sup, 39 | tt, 40 | var, 41 | b, 42 | u, 43 | i, 44 | center, 45 | dl, 46 | dt, 47 | dd, 48 | ol, 49 | ul, 50 | li, 51 | fieldset, 52 | form, 53 | label, 54 | legend, 55 | table, 56 | caption, 57 | tbody, 58 | tfoot, 59 | thead, 60 | tr, 61 | th, 62 | td, 63 | article, 64 | aside, 65 | canvas, 66 | details, 67 | embed, 68 | figure, 69 | figcaption, 70 | footer, 71 | header, 72 | hgroup, 73 | menu, 74 | nav, 75 | output, 76 | ruby, 77 | section, 78 | summary, 79 | time, 80 | mark, 81 | audio, 82 | video { 83 | margin: 0; 84 | padding: 0; 85 | border: 0; 86 | font-size: 100%; 87 | font: inherit; 88 | vertical-align: baseline; 89 | } 90 | /* HTML5 display-role reset for older browsers */ 91 | article, 92 | aside, 93 | details, 94 | figcaption, 95 | figure, 96 | footer, 97 | header, 98 | hgroup, 99 | menu, 100 | nav, 101 | section { 102 | display: block; 103 | } 104 | body { 105 | line-height: 1; 106 | } 107 | ol, 108 | ul { 109 | list-style: none; 110 | } 111 | blockquote, 112 | q { 113 | quotes: none; 114 | } 115 | blockquote:before, 116 | blockquote:after, 117 | q:before, 118 | q:after { 119 | content: ''; 120 | content: none; 121 | } 122 | table { 123 | border-collapse: collapse; 124 | border-spacing: 0; 125 | } 126 | -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/css/screen.css: -------------------------------------------------------------------------------- 1 | .swagger-section .swagger-collapse:before { 2 | content: "-"; 3 | } 4 | .swagger-section .swagger-expand:before { 5 | content: "+"; 6 | } 7 | .swagger-section .property-selector input[type="checkbox"] { 8 | margin: 3px; 9 | } 10 | -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/css/standalone.css: -------------------------------------------------------------------------------- 1 | /*========== Header ==========*/ 2 | header.site-header { 3 | z-index: 1000; 4 | background: transparent; 5 | font-size: 14px; 6 | position: static; 7 | padding: 20px 0 20px 0; 8 | } 9 | header.site-header.header-fixed { 10 | background: rgba(255,255,255,0.8); 11 | position: fixed; 12 | } 13 | header.site-header a { 14 | color: #333; 15 | } 16 | header.site-header li * { 17 | -webkit-backface-visibility: hidden !important; 18 | } 19 | header.site-header nav { 20 | background: none; 21 | border: 0; 22 | margin: 0; 23 | } 24 | header.site-header nav li.active a { 25 | background: none; 26 | color: #000; 27 | } 28 | header.site-header nav ul, 29 | header.site-header nav li { 30 | margin: 0; 31 | } 32 | header.site-header nav .navbar-brand { 33 | font-weight: bold; 34 | margin: 0; 35 | display: inline-block; 36 | float: left; 37 | font-size: 24px; 38 | margin-right: 20px; 39 | color: #000; 40 | padding: 0 15px 0 15px; 41 | margin: 0; 42 | width: 120px; 43 | } 44 | header.site-header nav .navbar-brand a { 45 | background: url("../images/senodio.png") center left no-repeat; 46 | width: 130px; 47 | height: 40px; 48 | display: block; 49 | margin-top: 5px; 50 | background-size: 48%; 51 | } 52 | header.site-header nav .navbar-brand img { 53 | position: relative; 54 | height: 36px; 55 | margin-right: 10px; 56 | top: 2px; 57 | display: none; 58 | } 59 | header.site-header nav .navbar-brand span { 60 | display: none; 61 | } 62 | header.site-header .navbar-default .navbar-collapse { 63 | border-color: transparent; 64 | } 65 | header.site-header .navbar-default .navbar-nav>.active>a, 66 | header.site-header .navbar-default .navbar-default .navbar-nav>.active>a:hover, 67 | header.site-header .navbar-default .navbar-default .navbar-nav>.active>a:focus { 68 | background: transparent; 69 | } 70 | header.site-header .navbar-default .navbar-nav>.open>a { 71 | background: none; 72 | } 73 | header.site-header .navbar-toggle { 74 | border: 0; 75 | } 76 | header.site-header .navbar-toggle:hover { 77 | background: none; 78 | } 79 | header.site-header .navbar-toggle:hover .icon-bar { 80 | background: #000; 81 | } 82 | header.site-header .btn-dro { 83 | padding: 15px; 84 | line-height: 20px; 85 | background: none; 86 | display: inline-block; 87 | color: #777; 88 | cursor: pointer; 89 | } 90 | header.site-header .btn-dro:hover { 91 | color: #666; 92 | } 93 | header.site-header .btn-dro i { 94 | position: relative; 95 | top: 1px; 96 | margin-left: 5px; 97 | width: 6px; 98 | display: inline-block; 99 | font-size: 10px; 100 | } 101 | header.site-header .dropdown .dropdown-menu>.active>a, 102 | header.site-header .dropdown .dropdown-menu>.active>a:hover, 103 | header.site-header .dropdown .dropdown-menu>.active>a:focus { 104 | background-color: none; 105 | } 106 | header.site-header .dropdown .dropdown-menu { 107 | min-width: 130px; 108 | background: #fff; 109 | -webkit-transform: scale(0.8) translateY(-10%); 110 | transform: scale(0.8) translateY(-10%); 111 | transition: 0.1s cubic-bezier(0.3, 0, 0, 1.3); 112 | opacity: 0; 113 | pointer-events: none; 114 | display: block; 115 | left: 0; 116 | border: 0; 117 | border-radius: 3px; 118 | } 119 | header.site-header .dropdown .dropdown-menu ::after { 120 | position: absolute; 121 | top: -6px; 122 | left: 26px; 123 | display: inline-block; 124 | border-right: 6px solid transparent; 125 | border-bottom: 6px solid #fff; 126 | border-left: 6px solid transparent; 127 | content: ''; 128 | } 129 | header.site-header .dropdown .dropdown-menu .divider { 130 | background-color: rgba(0,0,0,0.1); 131 | } 132 | header.site-header .dropdown.open .dropdown-menu { 133 | opacity: 1; 134 | pointer-events: auto; 135 | -webkit-transform: none; 136 | transform: none; 137 | } 138 | header.site-header a.login { 139 | color: #666; 140 | border: 1px solid #f1f1f1; 141 | border-radius: 100px; 142 | margin-left: 10px; 143 | text-transform: uppercase; 144 | letter-spacing: 1px; 145 | font-weight: bold; 146 | padding: 0; 147 | line-height: 30px; 148 | display: inline-block; 149 | padding-left: 15px; 150 | padding-right: 14px; 151 | margin-top: 10px; 152 | font-size: 12px; 153 | } 154 | header.site-header a.login:hover { 155 | background: #f1f1f1; 156 | } 157 | /*========== Header with dark background behind ==========*/ 158 | @media screen and (min-width: 990px) { 159 | .header-dark header.site-header { 160 | position: absolute; 161 | left: 0; 162 | right: 0; 163 | top: 0; 164 | border-bottom: 1px solid rgba(255,255,255,0.1); 165 | } 166 | .header-dark header.site-header h1.navbar-brand a { 167 | background-image: url("/auth0-styleguide/img/logo-grey-horizontal.png"); 168 | } 169 | .header-dark header.site-header .navbar-default .navbar-nav>.active>a, 170 | .header-dark header.site-header .navbar-default .navbar-nav>.active>a:hover, 171 | .header-dark header.site-header .navbar-default .navbar-nav>.active>a:focus { 172 | color: #fff; 173 | } 174 | .header-dark header.site-header .dropdown a { 175 | color: #333; 176 | } 177 | .header-dark header.site-header .navbar-default .navbar-nav>li>a { 178 | color: #d0d2d3; 179 | } 180 | .header-dark header.site-header .navbar-default .navbar-nav>li>a:hover { 181 | color: #fff; 182 | background: none; 183 | } 184 | .header-dark header.site-header nav li .btn-dro { 185 | color: #d0d2d3; 186 | } 187 | .header-dark header.site-header nav li .btn-dro:hover { 188 | color: #fff; 189 | } 190 | .header-dark header.site-header a.btn { 191 | border-color: #fff; 192 | } 193 | .header-dark header.site-header a.btn:hover { 194 | border-color: #fff; 195 | color: #000; 196 | } 197 | .site-header.navbar-fixed-top, 198 | .site-header.navbar-fixed-bottom { 199 | background: #fff; 200 | position: fixed !important; 201 | right: 0; 202 | left: 0; 203 | z-index: 1030; 204 | transform: translate3d(0, 0, 0); 205 | -webkit-transform: translate3d(0, 0, 0); 206 | background: rgba(255,255,255,0.9); 207 | } 208 | } 209 | .navbar-header { 210 | position: relative; 211 | } 212 | a.hiring { 213 | background: #44c7f4; 214 | text-transform: uppercase; 215 | position: absolute; 216 | top: 16px; 217 | left: -104px; 218 | font-weight: bold; 219 | padding: 2px 6px; 220 | border-radius: 3px; 221 | color: #fff !important; 222 | display: inline-block; 223 | font-size: 11px; 224 | } 225 | a.hiring::after { 226 | position: absolute; 227 | content: ""; 228 | right: -4px; 229 | top: 5px; 230 | width: 0; 231 | height: 0; 232 | border-top: 5px solid transparent; 233 | border-bottom: 5px solid transparent; 234 | border-left: 5px solid #44c7f4; 235 | } 236 | /*========== Responsive ==========*/ 237 | @media screen and (max-width: 990px) { 238 | header.site-header { 239 | position: static; 240 | text-align: left; 241 | padding: 10px 0; 242 | } 243 | header.site-header .navbar-left { 244 | border-top: 1px solid #f1f1f1; 245 | } 246 | header.site-header li { 247 | padding: 8px 0; 248 | border-bottom: 1px solid #f1f1f1; 249 | } 250 | header.site-header li:last-child { 251 | border-bottom: 0; 252 | } 253 | header.site-header li a { 254 | display: block; 255 | } 256 | header.site-header li.dropdown { 257 | display: block; 258 | padding: 0; 259 | opacity: 1; 260 | overflow: hidden; 261 | } 262 | header.site-header li.dropdown .btn-dro { 263 | display: none; 264 | } 265 | header.site-header li.dropdown .divider { 266 | display: none; 267 | } 268 | header.site-header li.dropdown ul.dropdown-menu { 269 | min-width: 0; 270 | position: static; 271 | margin: 0; 272 | box-shadow: none; 273 | border-left: 4px solid #ccc; 274 | opacity: 1; 275 | transform: none; 276 | transition: none; 277 | border-radius: 0; 278 | margin: 0; 279 | padding: 0; 280 | width: 100%; 281 | background: #f8f8f8; 282 | pointer-events: all; 283 | } 284 | header.site-header li.dropdown ul.dropdown-menu li:last-child { 285 | border-bottom: 0; 286 | } 287 | header.site-header nav a.login { 288 | margin-bottom: 20px; 289 | font-size: 14px; 290 | padding: 10px; 291 | display: block; 292 | text-align: center; 293 | } 294 | } -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/css/typography.css: -------------------------------------------------------------------------------- 1 | /* droid-sans-regular - latin */ 2 | @font-face { 3 | font-family: 'Droid Sans'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: url('../fonts/droid-sans-v6-latin-regular.eot'); /* IE9 Compat Modes */ 7 | src: local('Droid Sans'), local('DroidSans'), 8 | url('../fonts/droid-sans-v6-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 9 | url('../fonts/droid-sans-v6-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ 10 | url('../fonts/droid-sans-v6-latin-regular.woff') format('woff'), /* Modern Browsers */ 11 | url('../fonts/droid-sans-v6-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ 12 | url('../fonts/droid-sans-v6-latin-regular.svg#DroidSans') format('svg'); /* Legacy iOS */ 13 | } 14 | /* droid-sans-700 - latin */ 15 | @font-face { 16 | font-family: 'Droid Sans'; 17 | font-style: normal; 18 | font-weight: 700; 19 | src: url('../fonts/droid-sans-v6-latin-700.eot'); /* IE9 Compat Modes */ 20 | src: local('Droid Sans Bold'), local('DroidSans-Bold'), 21 | url('../fonts/droid-sans-v6-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 22 | url('../fonts/droid-sans-v6-latin-700.woff2') format('woff2'), /* Super Modern Browsers */ 23 | url('../fonts/droid-sans-v6-latin-700.woff') format('woff'), /* Modern Browsers */ 24 | url('../fonts/droid-sans-v6-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */ 25 | url('../fonts/droid-sans-v6-latin-700.svg#DroidSans') format('svg'); /* Legacy iOS */ 26 | } 27 | -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.eot -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.ttf -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.woff -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-700.woff2 -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.eot -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.ttf -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.woff -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/fonts/droid-sans-v6-latin-regular.woff2 -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/Swagger_explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/Swagger_explorer.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/Swagger_explorer_min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/Swagger_explorer_min.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/explorer_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/explorer_icons.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/favicon-16x16.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/favicon-32x32.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/favicon.ico -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/json_editor_integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/json_editor_integration.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/logo_small.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/pet_store_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/pet_store_api.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/senodio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/senodio.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/throbber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/throbber.gif -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/images/wordnik_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-servant/servant-swagger-ui/29713c56e71ef7e571de2b4e33393db6732b3821/servant-swagger-ui-jensoleg/jensoleg-dist/images/wordnik_api.png -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Swagger explorer 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 42 | 43 | 114 | 115 | 195 | 196 | 201 | 202 | 203 | 204 | 205 | 224 | 225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /servant-swagger-ui-jensoleg/jensoleg-dist/lib/backbone-min.js: -------------------------------------------------------------------------------- 1 | // Backbone.js 1.1.2 2 | 3 | (function(t,e){if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,r,s){t.Backbone=e(t,s,i,r)})}else if(typeof exports!=="undefined"){var i=require("underscore");e(t,exports,i)}else{t.Backbone=e(t,{},t._,t.jQuery||t.Zepto||t.ender||t.$)}})(this,function(t,e,i,r){var s=t.Backbone;var n=[];var a=n.push;var o=n.slice;var h=n.splice;e.VERSION="1.1.2";e.$=r;e.noConflict=function(){t.Backbone=s;return this};e.emulateHTTP=false;e.emulateJSON=false;var u=e.Events={on:function(t,e,i){if(!c(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,r){if(!c(this,"once",t,[e,r])||!e)return this;var s=this;var n=i.once(function(){s.off(t,n);e.apply(this,arguments)});n._callback=e;return this.on(t,n,r)},off:function(t,e,r){var s,n,a,o,h,u,l,f;if(!this._events||!c(this,"off",t,[e,r]))return this;if(!t&&!e&&!r){this._events=void 0;return this}o=t?[t]:i.keys(this._events);for(h=0,u=o.length;h").attr(t);this.setElement(r,false)}else{this.setElement(i.result(this,"el"),false)}}});e.sync=function(t,r,s){var n=T[t];i.defaults(s||(s={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:n,dataType:"json"};if(!s.url){a.url=i.result(r,"url")||M()}if(s.data==null&&r&&(t==="create"||t==="update"||t==="patch")){a.contentType="application/json";a.data=JSON.stringify(s.attrs||r.toJSON(s))}if(s.emulateJSON){a.contentType="application/x-www-form-urlencoded";a.data=a.data?{model:a.data}:{}}if(s.emulateHTTP&&(n==="PUT"||n==="DELETE"||n==="PATCH")){a.type="POST";if(s.emulateJSON)a.data._method=n;var o=s.beforeSend;s.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",n);if(o)return o.apply(this,arguments)}}if(a.type!=="GET"&&!s.emulateJSON){a.processData=false}if(a.type==="PATCH"&&k){a.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var h=s.xhr=e.ajax(i.extend(a,s));r.trigger("request",r,h,s);return h};var k=typeof window!=="undefined"&&!!window.ActiveXObject&&!(window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent);var T={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var $=e.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var S=/\((.*?)\)/g;var H=/(\(\?)?:\w+/g;var A=/\*\w+/g;var I=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend($.prototype,u,{initialize:function(){},route:function(t,r,s){if(!i.isRegExp(t))t=this._routeToRegExp(t);if(i.isFunction(r)){s=r;r=""}if(!s)s=this[r];var n=this;e.history.route(t,function(i){var a=n._extractParameters(t,i);n.execute(s,a);n.trigger.apply(n,["route:"+r].concat(a));n.trigger("route",r,a);e.history.trigger("route",n,r,a)});return this},execute:function(t,e){if(t)t.apply(this,e)},navigate:function(t,i){e.history.navigate(t,i);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=i.result(this,"routes");var t,e=i.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(I,"\\$&").replace(S,"(?:$1)?").replace(H,function(t,e){return e?t:"([^/?]+)"}).replace(A,"([^?]*?)");return new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var r=t.exec(e).slice(1);return i.map(r,function(t,e){if(e===r.length-1)return t||null;return t?decodeURIComponent(t):null})}});var N=e.History=function(){this.handlers=[];i.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var R=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var P=/msie [\w.]+/;var C=/\/$/;var j=/#.*$/;N.started=false;i.extend(N.prototype,u,{interval:50,atRoot:function(){return this.location.pathname.replace(/[^\/]$/,"$&/")===this.root},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=decodeURI(this.location.pathname+this.location.search);var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.slice(i.length)}else{t=this.getHash()}}return t.replace(R,"")},start:function(t){if(N.started)throw new Error("Backbone.history has already been started");N.started=true;this.options=i.extend({root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var r=this.getFragment();var s=document.documentMode;var n=P.exec(navigator.userAgent.toLowerCase())&&(!s||s<=7);this.root=("/"+this.root+"/").replace(O,"/");if(n&&this._wantsHashChange){var a=e.$('