diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 47775182..c1f42448 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: true contact_links: - name: '🛟 Help on Slack' - url: https://slack.wiremock.org/ + url: https://wiremock.org/docs/community/slack about: | You can ask questions on the community Slack in the '#help' or '#help-contributing' channels. Please do not raise GitHub issues for questions. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c70aa783..9f7c059d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,23 @@ jobs: run: bundle exec jekyll build --config '_config.yml' --baseurl "${{ steps.pages.outputs.base_path }}" env: JEKYLL_ENV: development + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install and configure Poetry + uses: snok/install-poetry@v1 + with: + version: 1.5.1 + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Build the docs + run: mkdocs build + - name: Build 2.x with Jekyll # Outputs to the './_site' directory by default run: | @@ -52,6 +69,7 @@ jobs: # with: # directory: ./_site # enforce_https: false - - name: Upload artifact - # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v1 + +# - name: Upload artifact +# # Automatically uploads an artifact from the './_site' directory by default +# uses: actions/upload-pages-artifact@v1 diff --git a/.github/workflows/deploy-mkdocs-preview.yaml b/.github/workflows/deploy-mkdocs-preview.yaml new file mode 100644 index 00000000..314722c1 --- /dev/null +++ b/.github/workflows/deploy-mkdocs-preview.yaml @@ -0,0 +1,111 @@ +name: Deploy Preview to GitHub Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main", "mkdocs"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: "true" + - name: Setup Ruby + uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 + with: + ruby-version: '2.7.6' # Not needed with a .ruby-version file + bundler: '2.4.10' + bundler-cache: false # runs 'bundle install' and caches installed gems automatically + cache-version: 3 # Increment this number if you need to re-download cached gems + - name: Setup Pages + id: pages + uses: actions/configure-pages@v3 + - name: Update RubyGems and Co + run: gem update --system + - name: Install Ruby Bundles + run: bundle install + + - name: Build with Jekyll + # Outputs to the './_site' directory by default + run: bundle exec jekyll build --config '_config.yml,_config-oleg-nenashev.yml' --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install and configure Poetry + uses: snok/install-poetry@v1 + with: + version: 1.5.1 + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Build the docs site + run: mkdocs build + + - name: Build 2.x with Jekyll + # Outputs to the './_site' directory by default + run: | + cd .submodules/wiremock.org-2.x + bundle exec jekyll build --config '../../_config.yml,../../_config-2.x.yml,../../_config-oleg-nenashev-2.x.yml' --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + #- name: Build 3.x with Jekyll + # We use the same as the root build, but with additional config + # run: | + # bundle exec jekyll build --config '_config.yml,_config-3.x.yml,_config-oleg-nenashev-3.x.yml' --baseurl "${{ steps.pages.outputs.base_path }}" + # env: + # JEKYLL_ENV: production + - name: Deploy version branches to the website + run: | + ruby .scripts/merge-sitemaps.rb + mkdir _site/2.x + cp -R .submodules/wiremock.org-2.x/tmp/site_2x/* _site/2.x/ + mkdir -p _site/docs + cp -R _site-docs/* _site/docs/ + mkdir -p _site/3.x/docs + cp -R _site-docs/* _site/3.x/docs/ +# TODO: Uncomment when cleaned up (if ever) +# - name: Validate HTML and links +# uses: anishathalye/proof-html@v2 +# with: +# directory: ./_site +# enforce_https: false + - name: Upload artifact + # Automatically uploads an artifact from the './_site' directory by default + uses: actions/upload-pages-artifact@v1 + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/.github/workflows/deploy-to-amplify.yaml b/.github/workflows/deploy-to-amplify.yaml new file mode 100644 index 00000000..4714bbde --- /dev/null +++ b/.github/workflows/deploy-to-amplify.yaml @@ -0,0 +1,105 @@ +name: Deploy to AWS Amplify + +on: + # Runs on pushes targeting the default branch + push: + branches: ["wiremock-amplify"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +concurrency: + group: "amplify" + cancel-in-progress: true + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - uses: aws-actions/configure-aws-credentials@v4.0.1 + with: + role-to-assume: arn:aws:iam::499333472133:role/GitHub-wiremock.org-Deploy + aws-region: us-east-1 + + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: "true" + - name: Setup Ruby + uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 + with: + ruby-version: '2.7.6' # Not needed with a .ruby-version file + bundler: '2.4.10' + bundler-cache: false # runs 'bundle install' and caches installed gems automatically + cache-version: 3 # Increment this number if you need to re-download cached gems + + - name: Update RubyGems and Co + run: | + gem uninstall rubygems-update + gem install rubygems-update -v 3.4.22 + update_rubygems + gem update --system + - name: Install Ruby Bundles + run: bundle install + + - name: Build with Jekyll + # Outputs to the './_site' directory by default + run: bundle exec jekyll build --config '_config.yml' --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + - name: Build 2.x with Jekyll + # Outputs to the './_site' directory by default + run: | + cd .submodules/wiremock.org-2.x + bundle exec jekyll build --config '../../_config.yml,../../_config-2.x.yml' --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + - name: Build 3.x with Jekyll + # We use the same as the root build, but with additional config + run: | + bundle exec jekyll build --config '_config.yml,_config-3.x.yml' --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install and configure Poetry + uses: snok/install-poetry@v1 + with: + version: 1.5.1 + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Build the docs site + run: mkdocs build + + - name: Copy docs into _site + run: cp -r _site-docs _site/docs + + - name: Deploy version branches to the website + run: | + ruby .scripts/merge-sitemaps.rb + mkdir _site/2.x + cp -R .submodules/wiremock.org-2.x/tmp/site_2x/* _site/2.x/ + mkdir _site/3.x + cp -R tmp/site_3x/* _site/3.x/ +# TODO: Uncomment when cleaned up (if ever) +# - name: Validate HTML and links +# uses: anishathalye/proof-html@v2 +# with: +# directory: ./_site +# enforce_https: false + + - name: Deploy to Amplify + run: | + bash -x ./deploy-amplify.sh diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index adfb4b90..25f9baa8 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -1,4 +1,4 @@ -name: Deploy Jekyll site to Pages +name: Deploy to GitHub Pages on: # Runs on pushes targeting the default branch diff --git a/.gitignore b/.gitignore index b7c045cb..e81da85c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ .jekyll-cache .sass-cache _asset_bundler_cache -_site codekit-config.json node_modules npm-debug.log* @@ -18,3 +17,10 @@ main.css /tmp **/.DS_Store + +# MkDocs +/temp_dir/ +/_site-docs/ +.cache + +wiremock-org-amplify.zip diff --git a/.gitmodules b/.gitmodules index e479c790..3634ebfb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,7 @@ path = .submodules/wiremock.org-2.x url = https://github.com/wiremock/wiremock.org.git branch = 2.x +[submodule "extra_sass/vendor/breakpoint"] + path = extra_sass/vendor/breakpoint + url = https://github.com/at-import/breakpoint.git + branch = main diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..c8cfe395 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index 37c2961c..00000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.2 diff --git a/.scripts/merge-sitemaps.rb b/.scripts/merge-sitemaps.rb index 94ec37d3..45fe4a1c 100644 --- a/.scripts/merge-sitemaps.rb +++ b/.scripts/merge-sitemaps.rb @@ -1,5 +1,5 @@ # Merges sitemaps, to be called from the root directory -header, footer, content_main, content_2x, content_3x = [] +header, footer, content_main, content_2x, content_docs = [] File.open( "_site/sitemap.xml", 'r' ) do |f1| content_main = (IO.readlines f1) @@ -13,14 +13,14 @@ content_2x.slice!( -1 ) end -File.open( "./tmp/site_3x/sitemap.xml", 'r' ) do |f3| - content_3x = (IO.readlines f3) - content_3x.slice!( 0..11 ) - content_3x.slice!( -1 ) +File.open( "./_site-docs/sitemap.xml", 'r' ) do |f3| + content_docs = (IO.readlines f3) + content_docs.slice!( 0..11 ) + content_docs.slice!( -1 ) end File.open( "_site/sitemap.xml", 'w' ) do |f4| - f4.write ( header + content_main + content_2x + content_3x + footer ).join() + f4.write ( header + content_main + content_docs + content_2x + footer ).join() end diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..45100a01 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "search.exclude": { + "**/wiremock.org-2.x/**": true + } + } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7aa5e072..99cccf15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to the WireMock website -[![a](https://img.shields.io/badge/slack-Join%20us-brightgreen?style=flat&logo=slack)](https://slack.wiremock.org/) +[![a](https://img.shields.io/badge/slack-Join%20us-brightgreen?style=flat&logo=slack)](https://wiremock.org/docs/community/slack) All contributions to the website are welcome! Whether you develop new documentation, want to share your use-case, @@ -32,21 +32,57 @@ that is included as a submodule and build by the CD flow. To update the documentation, submit pull requests against the branch, and they will be included into the main release line. -## Editing +## Documentation + +The documentation is built using +[MkDocs](https://www.mkdocs.org/), +[mkdocs-multirepo-plugin](https://github.com/jdoiro3/mkdocs-multirepo-plugin/tree/main) and +[Material for MkDocs](https://squidfunk.github.io/mkdocs-material) + +### Building + +The documentation website uses some sources from submodules, +so make sure to pull them before building the site. + +Requirements: + +- Python and PiP, recent versions +- Submodules are pulled in your local git clone + +```shell +pip install -r requirements.txt +mkdocs build +``` + +### Local development + +To serve the site locally: + +```shell +mkdocs serve +``` + +NOTE: on some OS's you might need to cd into your local clone and run 'git submodule init' and 'git submodule update' to get all of the plugins working properly. + +> **WARNING:** Note that the multi-repo site maybe quite slow during the +> first build and then during the rebuilds. +> You can disable it for local development just by commenting out the plugin section in `mkdocs.yml` +> The same goes to the SCSS compiler which cannot be disabled. +> There are [jdoiro3/mkdocs-multirepo-plugin #129](https://github.com/jdoiro3/mkdocs-multirepo-plugin/issues/129) +> and [orzih/mkdocs-extra-sass-plugin #6](https://github.com/orzih/mkdocs-extra-sass-plugin/issues/6) +> submitted to improve the developer experience. ### Code Tabs To reduce vertical space and provide examples by multiple technology stacks, we added support for code tabs in the documentation. -It is a custom Jekyll plugin providing the `{% codetabs %}` macro in Markdown. See the example here: https://wiremock.org/docs/stubbing/ . Example: ```markdown - {% codetabs %} - {% codetab JSON %} +=== "JSON" ```json { @@ -64,9 +100,8 @@ Example: } ``` - {% endcodetab %} - {% codetab Java %} +=== "Java" ```java @Test @@ -77,16 +112,13 @@ Example: } ``` - {% endcodetab %} - - {% endcodetabs %} ``` - When editing the existing code, make sure to also copy-edit text around it to ensure consistency. -Example of a patch: [PR #165 - Code tabs in stubbing overview](https://github.com/wiremock/wiremock.org/pull/165). -## Preparing the developer environment +## Main site + +### Preparing the developer environment The website is powered by Jekyll, and hence the Ruby developer environment is needed. It is recommended to use `Ruby 2.7.6` because of the known compatibility issues between recent Jekyll version and Ruby 3. @@ -98,7 +130,7 @@ Prerequisites: - Ruby 2.7.6 - Bundler 2.4.10 -## Building the website +### Building the website ```bash # Install the dependencies including Jekyll @@ -110,7 +142,7 @@ bundle exec jekyll build --config '_config.yml' Note that `_config_preview.yml' is used to disable analytics in the deployed versions -## Running the website locally +### Running the website locally You can run the website locally and get live preview of the changes on the website and in the documentation contents. diff --git a/Gemfile b/Gemfile deleted file mode 100644 index c6286c14..00000000 --- a/Gemfile +++ /dev/null @@ -1,15 +0,0 @@ -source "https://rubygems.org" - -gem "nokogiri", ">= 1.7.2" -gem "json", "~> 1.8.6" - -gem 'jekyll', '~>4' -gem "jekyll-paginate", "~> 1.1" -gem 'jekyll-redirect-from' -gem 'jekyll-sitemap' -gem 'jekyll-gist' -gem 'jekyll-feed' -gem 'jemoji' -gem "wdm", "~> 0.1.0" if Gem.win_platform? - -gem "webrick", "~> 1.7" diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index b968d007..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,133 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - activesupport (7.0.4.3) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - addressable (2.8.4) - public_suffix (>= 2.0.2, < 6.0) - colorator (1.1.0) - concurrent-ruby (1.2.2) - em-websocket (0.5.3) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0) - eventmachine (1.2.7) - eventmachine (1.2.7-x64-mingw32) - faraday (2.7.4) - faraday-net_http (>= 2.0, < 3.1) - ruby2_keywords (>= 0.0.4) - faraday-net_http (3.0.2) - ffi (1.15.5) - ffi (1.15.5-x64-mingw32) - forwardable-extended (2.6.0) - gemoji (4.1.0) - google-protobuf (3.22.3-arm64-darwin) - google-protobuf (3.22.3-x64-mingw32) - google-protobuf (3.22.3-x86_64-linux) - html-pipeline (2.14.3) - activesupport (>= 2) - nokogiri (>= 1.4) - http_parser.rb (0.8.0) - i18n (1.13.0) - concurrent-ruby (~> 1.0) - jekyll (4.3.2) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (~> 1.0) - jekyll-sass-converter (>= 2.0, < 4.0) - jekyll-watch (~> 2.0) - kramdown (~> 2.3, >= 2.3.1) - kramdown-parser-gfm (~> 1.0) - liquid (~> 4.0) - mercenary (>= 0.3.6, < 0.5) - pathutil (~> 0.9) - rouge (>= 3.0, < 5.0) - safe_yaml (~> 1.0) - terminal-table (>= 1.8, < 4.0) - webrick (~> 1.7) - jekyll-feed (0.17.0) - jekyll (>= 3.7, < 5.0) - jekyll-gist (1.5.0) - octokit (~> 4.2) - jekyll-paginate (1.1.0) - jekyll-redirect-from (0.16.0) - jekyll (>= 3.3, < 5.0) - jekyll-sass-converter (3.0.0) - sass-embedded (~> 1.54) - jekyll-sitemap (1.4.0) - jekyll (>= 3.7, < 5.0) - jekyll-watch (2.2.1) - listen (~> 3.0) - jemoji (0.13.0) - gemoji (>= 3, < 5) - html-pipeline (~> 2.2) - jekyll (>= 3.0, < 5.0) - json (1.8.6) - kramdown (2.4.0) - rexml - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) - liquid (4.0.4) - listen (3.8.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.4.0) - minitest (5.18.0) - nokogiri (1.14.3-arm64-darwin) - racc (~> 1.4) - nokogiri (1.14.3-x64-mingw32) - racc (~> 1.4) - nokogiri (1.14.3-x86_64-linux) - racc (~> 1.4) - octokit (4.25.1) - faraday (>= 1, < 3) - sawyer (~> 0.9) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (5.0.1) - racc (1.6.2) - rake (13.0.6) - rb-fsevent (0.11.2) - rb-inotify (0.10.1) - ffi (~> 1.0) - rexml (3.2.5) - rouge (4.1.0) - ruby2_keywords (0.0.5) - safe_yaml (1.0.5) - sass-embedded (1.62.1) - google-protobuf (~> 3.21) - rake (>= 10.0.0) - sawyer (0.9.2) - addressable (>= 2.3.5) - faraday (>= 0.17.3, < 3) - terminal-table (3.0.2) - unicode-display_width (>= 1.1.1, < 3) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - unicode-display_width (2.4.2) - wdm (0.1.1) - webrick (1.8.1) - -PLATFORMS - arm64-darwin-21 - x64-mingw32 - x86_64-linux - -DEPENDENCIES - jekyll (~> 4) - jekyll-feed - jekyll-gist - jekyll-paginate (~> 1.1) - jekyll-redirect-from - jekyll-sitemap - jemoji - json (~> 1.8.6) - nokogiri (>= 1.7.2) - wdm (~> 0.1.0) - webrick (~> 1.7) - -BUNDLED WITH - 2.4.10 diff --git a/README.md b/README.md index 6ee29f74..e6cd81e5 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ Repository that stores the WireMock website and documentation. Powered by Jekyll and Markdown. The website uses the [Minimal Mistakes Theme](https://mmistakes.github.io/minimal-mistakes/) for Jekyll. +The documentation is built using +[MkDocs](https://www.mkdocs.org/), +[mkdocs-multirepo-plugin](https://github.com/jdoiro3/mkdocs-multirepo-plugin/tree/main) and +[Material for MkDocs](https://squidfunk.github.io/mkdocs-material) ## Contributing diff --git a/_config-oleg-nenashev-2.x.yml b/_config-oleg-nenashev-2.x.yml new file mode 100644 index 00000000..066c2660 --- /dev/null +++ b/_config-oleg-nenashev-2.x.yml @@ -0,0 +1,2 @@ +url: "https://oleg-nenashev.github.io/wiremock.org" +baseurl: "wiremock.org/2.x/" diff --git a/_config-oleg-nenashev-3.x.yml b/_config-oleg-nenashev-3.x.yml new file mode 100644 index 00000000..5e78d6cb --- /dev/null +++ b/_config-oleg-nenashev-3.x.yml @@ -0,0 +1,2 @@ +url: "https://oleg-nenashev.github.io/" +baseurl: "wiremock.org/3.x" diff --git a/_config-oleg-nenashev.yml b/_config-oleg-nenashev.yml new file mode 100644 index 00000000..2c1a27f6 --- /dev/null +++ b/_config-oleg-nenashev.yml @@ -0,0 +1,21 @@ +url: "https://oleg-nenashev.github.io/" +baseurl: "wiremock.org/" + +# Analytics +analytics: + google: + # gtag + id: "G-F923LHBYYT" + + # MS Clarity + clarity: + enabled: true + vwo: + enabled: true + +# TODO: Update plugin code to support more fancy navigation +breadcrumbs: + root: + hide: true + image: true + imagePath: /wiremock.org/images/logos/doc-sections/home.svg diff --git a/_config.yml b/_config.yml index 0dc9f33e..2394fd54 100644 --- a/_config.yml +++ b/_config.yml @@ -104,6 +104,7 @@ author: include: - .htaccess - _pages + - _redirects exclude: - vendor/ - "*.sublime-project" @@ -130,6 +131,8 @@ exclude: - tmp # Served via symbolic links - .submodules + # Delegated to MkDocs + - _docs keep_files: - .git - .svn @@ -241,7 +244,7 @@ pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ grpc_extension_version: 0.4.0 community_slack: - join_url: https://slack.wiremock.org/ + join_url: /docs/community/slack # Default link for wiremock signup button in header # This can be overridden in pages using frontmatter start_link variable diff --git a/_data/baselines.yml b/_data/baselines.yml deleted file mode 100644 index badf2b79..00000000 --- a/_data/baselines.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Current GA Version of WireMock -current: - id: 3.x - absoluteUrl: https://wiremock.org -# List of preview versions -preview: -# List of old versions documentation for which is served on the website -archive: - id: 2.x - absoluteUrl: https://wiremock.org/2.x - branch: 2.x diff --git a/_data/doc-categories.yml b/_data/doc-categories.yml deleted file mode 100644 index 2e6a15f4..00000000 --- a/_data/doc-categories.yml +++ /dev/null @@ -1,92 +0,0 @@ -setup: - title: Getting started - link: /docs/overview - pages: - - overview - - quickstart/java-junit - - download-and-installation - - getting-started - - faq - -standalone: - title: WireMock Standalone - link: /docs/standalone - pages: - - standalone/docker - - standalone/java-jar - - standalone/administration - -java: - title: Java Usage - link: /docs/solutions/jvm/ - pages: - - junit-jupiter - - junit-extensions - - spring-boot - - java-usage - - configuration - - running-without-http-server - - android - -stubbing-and-verifying: - title: Stubbing & Verifying - link: /docs/stubbing - pages: - - stubbing - - request-matching - - response-templating - - simulating-faults - - stateful-behaviour - - proxying - - verifying - -templating: - title: Templating - link: /docs/mock-api-templates - pages: - - mock-api-templates - - mock-api-templates/usage - -record-playback: - title: Record & Playback - link: /docs/record-playback/ - pages: - - record-playback - -protocols: - title: Protocols - pages: - - webhooks-and-callbacks - - grpc - - solutions/graphql - - https - -configuration: - title: Advanced use-cases - pages: - - multi-domain-mocking - - advanced/deploy-to-servlet-container - - advanced/java7 - -extensibility: - title: Extensibility - link: /docs/extending-wiremock/ - pages: - - extending-wiremock - - extensibility/filtering-requests - - extensibility/transforming-responses - - extensibility/custom-matching - - extensibility/listening-for-serve-events - - extensibility/extending-the-admin-api - - extensibility/adding-template-helpers - - extensibility/adding-template-model-data - - extensibility/listening-for-stub-changes - - extensibility/listening-for-settings-changes - - extensibility/adding-mappings-loader - - stub-metadata - -reference: - title: Reference - pages: - - standalone/admin-api-reference - - mock-api-templates diff --git a/_data/misc.yml b/_data/misc.yml deleted file mode 100644 index b28e5750..00000000 --- a/_data/misc.yml +++ /dev/null @@ -1,2 +0,0 @@ -blank: '_blank' -wiremock_studio_version: 2.32.0-18 diff --git a/_data/navigation.yml b/_data/navigation.yml deleted file mode 100644 index 36f82d91..00000000 --- a/_data/navigation.yml +++ /dev/null @@ -1,83 +0,0 @@ -# main links links -main: - - - title: "Docs" - link: "/docs" - icon: "/images/logos/doc-sections/documentBar.svg" - subnav: "docs" - subnavLinks: - - name: "WireMock" - subnavLink: "/docs/" - - name: "Mock API Templates" - subnavLink: "/docs/mock-api-templates" - - name: "WireMock Cloud" - subnavLink: "https://docs.wiremock.io/getting-started/?utm_source=wiremock.org&utm_medium=masthead_doc-links&utm_campaign=2022_baseline" - - name: "External Resources" - subnavLink: "/external-resources" - - name: "WireMock 2.x (Archive)" - subnavLink: "/2.x/docs/" - wiremock_baseline: 2.x - - name: "WireMock 3.x" - subnavLink: "/2.x/docs/" - wiremock_baseline: 3.x - - - title: "Need Help?" - link: "/support" - icon: "/images/logos/doc-sections/helpsec.svg" - subnav: "help" - subnavLinks: - - name: "Q&A on Slack" - subnavLink: "https://slack.wiremock.org/" - - name: "StackOverflow" - subnavLink: "https://stackoverflow.com/questions/tagged/wiremock" - - name: "Commercial Options" - subnavLink: "/support/commercial" - - - title: "Participate" - link: '/participate' - icon: "/images/logos/doc-sections/team.svg" - subnav: "participate" - subnavLinks: - - name: "Community Slack" - subnavLink: "https://slack.wiremock.org/" - - name: "Contributor Guide" - subnavLink: "https://github.com/wiremock/community/blob/main/contributing/README.md" - - name: "Our GitHub" - subnavLink: "https://github.com/wiremock/" - - name: "This Website" - subnavLink: "https://github.com/wiremock/wiremock.org" - - name: "Code of Conduct" - subnavLink: "https://github.com/wiremock/.github/blob/main/CODE_OF_CONDUCT.md" - - - title: "Resources" - link: "/external-resources" - icon: "/images/logos/doc-sections/plusnew.svg" - subnav: "resources" - subnavLinks: - - name: "Mock API Templates Library" - subnavLink: "https://library.wiremock.org/" - - name: "WireMock Ecosystem" - subnavLink: "https://github.com/wiremock/ecosystem" - - name: "Twitter" - subnavLink: "https://twitter.com/wiremockorg" - - name: "Mastodon" - subnavLink: "https://fosstodon.org/@wiremock" - - name: "Slack Archive" - subnavLink: "https://community.wiremock.io/" - - name: "External Resources" - subnavLink: "/external-resources" - -# TODO: re-enable once/if there are more commercial offerings -# - title: "Commercial Offerings" -# new_window: true -# icon: "/images/logos/doc-sections/cloud.svg" -# subnav: "commercial" -# subnavLinks: -# - name: "WireMock Cloud" -# subnavLink: "https://docs.wiremock.io/getting-started/?utm_source=wiremock.org&utm_medium=masthead_doc-links&utm_campaign=2022_baseline" -# - name: "WireMock Studio (Discontinued)" -# subnavLink: "/studio/docs/" -# - name: "MockLab (Deprecated)" -# subnavLink: "https://www.mocklab.io/docs/getting-started/?utm_source=wiremock.org&utm_medium=masthead_doc-links&utm_campaign=2022_baseline" - - diff --git a/_data/studio-doc-categories.yml b/_data/studio-doc-categories.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/_data/ui-text.yml b/_data/ui-text.yml deleted file mode 100644 index 43c2c835..00000000 --- a/_data/ui-text.yml +++ /dev/null @@ -1,102 +0,0 @@ -# User interface text and labels - -# English (default) -# ----------------- -en: &DEFAULT_EN - page : "Page" - pagination_previous : "Previous" - pagination_next : "Next" - breadcrumb_home_label : "Home" - breadcrumb_separator : "/" - toc_label : "On This Page" - ext_link_label : "Direct Link" - less_than : "less than" - minute_read : "minute read" - share_on_label : "Share on" - meta_label : - tags_label : "Tags:" - categories_label : "Categories:" - date_label : "Updated:" - comments_label : "Leave a Comment" - more_label : "Learn More" - related_label : "You May Also Enjoy" - follow_label : "Follow:" - feed_label : "Feed" - powered_by : "Powered by" - website_label : "Website" - email_label : "Email" - recent_posts : "Recent Posts" - undefined_wpm : "Undefined parameter words_per_minute at _config.yml" -en-US: - <<: *DEFAULT_EN -en-UK: - <<: *DEFAULT_EN - -# Spanish -# -------------- -es: &DEFAULT_ES - page : "Página" - pagination_previous : "Anterior" - pagination_next : "Siguiente" - breadcrumb_home_label : "Inicio" - breadcrumb_separator : "/" - toc_label : "Contenidos" - ext_link_label : "Enlace" - less_than : "menos de" - minute_read : "minuto de lectura" - share_on_label : "Compartir" - meta_label : - tags_label : "Etiquetas:" - categories_label : "Categorías:" - date_label : "Actualizado:" - comments_label : "Comentar" - more_label : "Ver más" - related_label : "Podrías ver también" - follow_label : "Seguir:" - feed_label : "Feed" - powered_by : "Powered by" - website_label : "Sitio web" - email_label : "Email" - recent_posts : "Entradas recientes" - undefined_wpm : "Parametro words_per_minute (Palabras por minuto) no definido en _config.yml" -es-ES: - <<: *DEFAULT_ES -es-CO: - <<: *DEFAULT_ES - -# French -# ----------------- -fr: &DEFAULT_FR - page : "Page" - pagination_previous : "Précédent" - pagination_next : "Suivant" - breadcrumb_home_label : "Accueil" - breadcrumb_separator : "/" - toc_label : "Sur cette page" - ext_link_label : "Lien direct" - less_than : "plus petit que" - minute_read : "minute de lecture" - share_on_label : "Partager sur" - meta_label : - tags_label : "Tags :" - categories_label : "Catégories :" - date_label : "Mis à jour :" - comments_label : "Laisser un commentaire" - more_label : "Lire plus" - related_label : "Vous pourriez aimer" - follow_label : "Suivez moi" - feed_label : "Flux" - powered_by : "Propulsé par" - website_label : "Site" - email_label : "Email" - recent_posts : "Posts récents" - undefined_wpm : "Le paramètre words_per_minute n'est pas défini dans _config.yml" -fr-FR: - <<: *DEFAULT_FR -fr-BE: - <<: *DEFAULT_FR -fr-CH: - <<: *DEFAULT_FR - -# Another locale -# -------------- diff --git a/_docs/advanced/deploy-to-servlet-container.md b/_docs/advanced/deploy-to-servlet-container.md deleted file mode 100644 index 49963616..00000000 --- a/_docs/advanced/deploy-to-servlet-container.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: docs -title: Deploying into a servlet container -meta_title: Deploying into a servlet container | WireMock -description: "WireMock can be packaged up as a WAR and deployed into a servlet -container. Here is how" ---- - -WireMock can be packaged up as a WAR and deployed into a servlet -container, with some caveats: fault injection and browser proxying won't -work, \_\_files won't be treated as a docroot as with standalone, the -server cannot be remotely shutdown, and the container must be configured -to explode the WAR on deployment. This has only really been tested in -Tomcat 6 and Jetty, so YMMV. Running standalone is definitely the -preferred option. - -The easiest way to create a WireMock WAR project is to clone the -[sample app](https://github.com/wiremock/wiremock/tree/master/sample-war). - -### Deploying under a sub-path of the context root - -If you want WireMock's servlet to have a non-root path, the additional -init param `mappedUnder` must be set with the sub-path web.xml (in -addition to configuring the servlet mapping appropriately). - -See [the custom mapped WAR -example](https://github.com/wiremock/wiremock/blob/master/sample-war/src/main/webappCustomMapping/WEB-INF/web.xml) -for details. diff --git a/_docs/advanced/java7.md b/_docs/advanced/java7.md deleted file mode 100644 index b4b81f49..00000000 --- a/_docs/advanced/java7.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -layout: docs -title: WireMock on Java 1.7 -meta_title: "Using old WireMock versions with Java 1.7" -description: Recent WireMock versions do not support Java 1.7, but you can run older versions to achieve that ---- - -> **WARNING:** Recent WireMock versions do not support Java 1.7, but you can run older versions to achieve that. -> The Java 7 version was deprecated in the 2.x line and version 2.27.2 is the last release available. -> There will be no bugfixes and security patches provided. -> Make sure to update as soon as possible to Java 11 or above. - -The Java 7 distribution is aimed primarily at Android developers and enterprise Java teams still using Java Runtime Environment (JRE) 1.7. -Some of its dependencies are not set to the latest versions e.g. Jetty 9.2.x is used, -as this is the last minor version to retain Java 7 compatibility. - -## Maven dependencies - -JUnit: - -```xml - - com.github.tomakehurst - wiremock - 2.27.2 - test - -``` - -Standalone JAR: - -```xml - - com.github.tomakehurst - wiremock-standalone - 2.27.2 - test - -``` - -## Gradle dependencies - -JUnit: - -```groovy -testImplementation "com.github.tomakehurst:wiremock:2.27.2" -``` - -Standalone JAR: - -```groovy -testImplementation "com.github.tomakehurst:wiremock-standalone:2.27.2" -``` diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md deleted file mode 100644 index 6c7fa81a..00000000 --- a/_docs/download-and-installation.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -layout: docs -title: Download and Installation -meta_title: "How to Download and Install WireMock" -toc_rank: 13 -description: > - WireMock is available as a standalone service (for Docker of Java), Java library - and integrations for modern languages and technology stacks. -redirect_from: - - "/download.html" - - "/download/" - - "/downloads.html" - - "/downloads/" - - "/docs/download.html" - - "/docs/download/" ---- - - -## Download options - -WireMock Java is distributed in two flavours - a standard JAR containing just WireMock, and a standalone uber JAR containing -WireMock plus all its dependencies. - -Most of the standalone JAR's dependencies are shaded i.e. they are hidden in alternative packages. This allows WireMock to be used in projects with -conflicting versions of its dependencies. The standalone JAR is also runnable (see [Running as a Standalone Process](../running-standalone/)). - -## Test dependencies - -
- {% include downloads.html %} -
- -## Standalone Service - -Run the following in a terminal: - -{% codetabs %} - -{% codetab Docker %} - -```bash -docker run -it --rm -p 8080:8080 --name wiremock \ - wiremock/wiremock:{{ site.wiremock_version }} -``` - -{% endcodetab %} - -{% codetab Maven %} - -```xml - - org.wiremock - wiremock-standalone - {{ site.wiremock_version }} - test - -``` - -{% endcodetab %} - -{% codetab Gradle Groovy %} - -```groovy -testImplementation "org.wiremock:wiremock-standalone:{{ site.wiremock_version }}" -``` - -{% endcodetab %} - -{% endcodetabs %} - -Learn more in the [Docker guide](../docker). - -### Direct download - -If you want to run WireMock as a standalone process you can -download the standalone JAR from -here diff --git a/_docs/extending-wiremock.md b/_docs/extending-wiremock.md deleted file mode 100644 index bebd4462..00000000 --- a/_docs/extending-wiremock.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -layout: docs -title: Extending WireMock -meta_title: Extending WireMock via custom code | WireMock -toc_rank: 110 -redirect_from: "/extending-wiremock.html" -description: You can register the extension programmatically via its class name, class or an instance ---- - -WireMock can be customised via a variety of extension points. - -Each extension point is defined by an interface that extends from `Extension` and extension implementations are loaded at startup time. - -At present, the following extension interfaces are available: -* `RequestFilterV2`/`AdminRequestFilterV2`/`StubRequestFilterV2`: Intercept requests, modifying them or taking alternative actions based on their content. -* `ResponseDefinitionTransformerV2`: Modify the response definition used to generate a response. See [Transforming responses](../extensibility/transforming-responses/). -* `ResponseTransformerV2`: Modify the response served to the client. See [Transforming responses](../extensibility/transforming-responses/). -* `ServeEventListener`: Listen for events at various points in the request processing lifecycle. See [Listening for Serve Events](../extensibility/listening-for-serve-events/). -* `AdminApiExtension`: Add admin API functions. See [Admin API Extensions](../extensibility/extending-the-admin-api/). -* `RequestMatcherExtension`: Implement custom request matching logic. See [Custom matching](../extensibility/custom-matching/). -* `GlobalSettingsListener`: Listen for changes to the settings object. See [Listening for Settings Changes](../extensibility/listening-for-settings-changes/). -* `StubLifecycleListener`: Listen for changes to the stub mappings. See [Listening for Stub Changes](../extensibility/listening-for-stub-changes/). -* `TemplateHelperProviderExtension`: Provide custom Handlebars helpers to the template engine. See [Adding Template Helpers](../extensibility/adding-template-helpers/). -* `TemplateModelDataProviderExtension`: Provide additional data to the model passed to response templates. See [Adding Template Model Data](../extensibility/adding-template-model-data/). -* `MappingsLoaderExtension`: Provide additional source to load the stub mappings. See [Adding Mappings Loader](../extensibility/adding-mappings-loader/). - -The interfaces in this list ending with `V2` supercede deprecated equivalents with an older, more restrictive interface. Additionally `ServeEventListener` deprecates `PostServeAction`. - - -## Registering Extensions - -You can directly register the extension programmatically via its class name, -class or an instance: - -```java -new WireMockServer(wireMockConfig() - .extensions("com.mycorp.BodyContentTransformer", "com.mycorp.HeaderMangler")); - -new WireMockServer(wireMockConfig() - .extensions(BodyContentTransformer.class, HeaderMangler.class)); - -new WireMockServer(wireMockConfig() - .extensions(new BodyContentTransformer(), new HeaderMangler())); -``` - -See [Running as a Standalone Process](../running-standalone/) for details on running with extensions from the command line. - -### Factories - -You can also register an extension factory, which allows an extension to be created with various core WireMock services passed to the constructor: - -```java -new WireMockServer(wireMockConfig() - .extensions(services -> - List.of( - new MiscInfoApi( - services.getAdmin(), - services.getOptions(), - services.getStores(), - services.getFiles(), - services.getExtensions() - )))); -``` - -Services currently available to extension factories are: -* `Admin`: the main WireMock functional interface for stubbing, verification and configuration tasks. -* `Options`: the configuration object built at startup. -* `Stores`: the root interface for gaining access to the various stores of WireMock's state and creating/using custom stores. -* `FileSource`: the `__files` directory where larger response body files are often kept. -* `Extensions`: the service for creating and providing extension implementations. -* `TemplateEngine`: the Handlebars template engine. - -## Extension registration via service loading - -Extensions that are packaged with the relevant [Java service loader framework](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) metadata -will be loaded automatically if they are placed on the classpath. - -See [https://github.com/wiremock/wiremock/tree/master/test-extension](https://github.com/wiremock/wiremock/tree/master/test-extension) for an example of such an extension. - - -## Attaching sub-events during request processing - -Sub-events are a used to report interesting/useful information during request processing. WireMock attaches the diff report generated when a request is not matched as a sub-event, and custom extension can exploit this approach to surface e.g. diagnostic and validation data in the serve event log, where it can be retrieved later via the API or exported to monitoring/observability tools via listeners. - - -Several types of extension act on WireMock's request processing: `RequestFilterV2` (and its stub/admin sub-interfaces), `ResponseDefinitionTransformer`, `ResponseTransformer` and `ServeEventListener`. - -The primary method in each of these takes the current `ServeEvent` as a parameter and sub-events can be attached to this: - -```java -serveEvent.appendSubEvent( - "JSON_PARSE_WARNING", - Map.of("message", "Single quotes are not permitted") -); -``` - -The second parameter to `appendSubEvent()` can be a Map or object containing any data required. \ No newline at end of file diff --git a/_docs/index.html b/_docs/index.html deleted file mode 100644 index 087b0d39..00000000 --- a/_docs/index.html +++ /dev/null @@ -1,320 +0,0 @@ ---- -layout: docs -title: "WireMock User Documentation" -meta_title: "WireMock User Documentation | WireMock" -crumbtitle: "Documentation" -toc_rank: 1001 -permalink: /docs/ -docs-wide: true -description: > - All of WireMock’s features are accessible via its REST (JSON) interface and its Java API. - Additionally, stubs can be configured via JSON files. Read the full doc here. ---- - - - -

- WireMock is a popular open-source tool for API mock testing, with over 5 - million downloads per month. It can help you to create stable test and - development environments, isolate yourself from flakey 3rd parties and - simulate APIs that don't exist yet. -

- - -

Getting Started

- -
- - - Overview - - - - Quick Start - - - - Download - - - - Get Help - -
- -

Distributions

- -

- WireMock provides the following generic distributions that allow running it as - a - standalone server - in a container or within a Java Virtual Machine. -

- -
- - - Standalone JAR - - - - Docker - - - - Helm (Experimental) - - - - WireMock Cloud (commercial SaaS) - - - - NPM - -
- -

By use-case

- -

- Below you can find links to the documentation for WireMock key use-cases. You - can find more documentation pages on the sidebar. -

- -
- - Wiremock Features - Advanced request matching - - - wiremock dynamic response - Dynamic response templating - - - - wiremock unit tests - Use API Mocking in your unit tests - - - wiremock fault and latency - Fault and latency injection - - - wiremock record playback - Record / Playback - - - - WireMock API Templates - Use pre-defined Mock API templates - - - Extending WireMock - Extending WireMock - -
- -

By protocol

- -

- WireMock can serve all HTTP-based protocols and REST API. Through built-in - features and extensions, it provides additional capabilities for widely used - protocols. -

- -
- - - Webhooks and Callbacks - - - - HTTPs - - - - gRPC - - - - GraphQL - -
- -

By technology

- -

- There are also solutions and guides for particular technologies and - frameworks, provided by the WireMock community and external contributors. -

- -
- - - Java and JVM - - - - Python - - - - Spring Boot - - - - Node.js - - - - Android - - - - .NET - - - - Golang - - - - Rust - - - - Groovy - - - - Kotlin - - - - Kubernetes - - - - Testcontainers - - - - Quarkus - - - - C/C++ - -
diff --git a/_docs/java-usage.md b/_docs/java-usage.md deleted file mode 100644 index 964b9d26..00000000 --- a/_docs/java-usage.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -layout: docs -title: Plain Java -meta_title: Use WireMock from Java or other JVM languages | WireMock -redirect_from: - - "/java-usage.html" - - "/docs/plain-java.html" -description: If you want to use WireMock from Java (or any other JVM language) outside of JUnit you can programmatically create, start and stop the server. ---- - -If you're not using JUnit or neither of the WireMock rules manage its -lifecycle in a suitable way you can construct and start the server -directly. - -## The Server - -If you want to use WireMock from Java (or any other JVM language) -outside of JUnit you can programmatically create, start and stop the -server: - -```java -WireMockServer wireMockServer = new WireMockServer(options().port(8089)); //No-args constructor will start on port 8080, no HTTPS -wireMockServer.start(); - -// Sometime later - -wireMockServer.stop(); -``` - -For more details of the `options()` builder accepted by the constructor see [Configuration](../configuration/) for details. - -As with stubbing and verification via the [JUnit rule](../junit-rule/) you can call the -stubbing/verifying DSL from the server object as an alternative to -calling the client. - -### Managing ports - -If you've changed the port number and/or you're running the server on -another host, you'll need to tell the client: - -```java -WireMock.configureFor("wiremock.host", 8089); -``` - -And if you've deployed it into a servlet container under a path other -than root you'll need to set that too: - -```java -WireMock.configureFor("tomcat.host", 8080, "/wiremock"); -``` - -## The Client - -The `WireMock` class provides an over-the-wire client to a WireMock -server (the local one by default). - -### Configuring for static calls - -To configure the static client for an alternative host and port: - -```java -import static com.github.tomakehurst.wiremock.client.WireMock.*; - -configureFor("wiremock.host", 8089); -stubFor(get(....)); -``` - -If you've deployed the server into a servlet container under a path -other than root you'll need to set that too: - -```java -WireMock.configureFor("tomcat.host", 8080, "/wiremock"); -``` - -### Newing up - -Instances of `WireMock` can also be created. This is useful if you need -to talk to more than one server instance. - -```java -WireMock wireMock = new WireMock("some.host", 9090, "/wm"); // As above, 3rd param is for non-root servlet deployments -wireMock.register(get(....)); // Equivalent to stubFor() -``` diff --git a/_docs/junit-extensions.md b/_docs/junit-extensions.md deleted file mode 100644 index aad4035b..00000000 --- a/_docs/junit-extensions.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -layout: docs -title: 'JUnit 4 and Vintage' -meta_title: Using Junit 4 and Vintage to Manage WireMock instances | WireMock -redirect_from: - - "/junit-rule.html" - - "/docs/junit-rule/index.html" - - "/docs/junit-rule/" - - "/junit-rule/" - - "/docs/junit-4.html" -description: WireMock includes a JUnit rule, compatible with JUnit 4.x and JUnit 5 Vintage. This provides a convenient way to manage one or more WireMock instances in your test cases. ---- - -WireMock includes a JUnit rule, compatible with JUnit 4.x and JUnit 5 Vintage. -This provides a convenient way to manage one or more WireMock instances in your -test cases. It handles the lifecycle for you, starting the server before -each test method and stopping afterwards. - -## Basic usage - -To make WireMock available to your tests on its default port (8080): - -```java -@Rule -public WireMockRule wireMockRule = new WireMockRule(); -``` - -The rule's constructor can take an `Options` instance to override -various settings. An `Options` implementation can be created via the -`WireMockConfiguration.options()` builder: - -```java -@Rule -public WireMockRule wireMockRule = new WireMockRule(options().port(8888).httpsPort(8889)); -``` - -See [Configuration](../configuration/) for details. - -## Unmatched requests - -The JUnit rule will verify that all requests received during the course of a test case are served by a configured stub, rather than the default 404. If any are not -a `VerificationException` is thrown, failing the test. This behaviour can be disabled by passing an extra constructor flag: - -```java -@Rule -public WireMockRule wireMockRule = new WireMockRule(options().port(8888), false); -``` - -## Other @Rule configurations - -With a bit more effort you can make the WireMock server continue to run -between test cases. This is easiest in JUnit 4.10: - -```java -@ClassRule -@Rule -public static WireMockClassRule wireMockRule = new WireMockClassRule(8089); -``` - -Unfortunately JUnit 4.11 and above prohibits `@Rule` on static members so a -slightly more verbose form is required: - -```java -@ClassRule -public static WireMockClassRule wireMockRule = new WireMockClassRule(8089); - -@Rule -public WireMockClassRule instanceRule = wireMockRule; -``` - - -## Accessing the stubbing and verification DSL from the rule - -In addition to the static methods on the `WireMock` class, it is also -possible to configure stubs etc. via the rule object directly. There are -two advantages to this - 1) it's a bit faster as it avoids sending -commands over HTTP, and 2) if you want to mock multiple services you can -declare a rule per service but not have to create a client object for -each e.g. - -```java -@Rule -public WireMockRule service1 = new WireMockRule(8081); - -@Rule -public WireMockRule service2 = new WireMockRule(8082); - -@Test -public void bothServicesDoStuff() { - service1.stubFor(get(urlEqualTo("/blah")).....); - service2.stubFor(post(urlEqualTo("/blap")).....); - - ... -} -``` diff --git a/_docs/mock-api-templates.md b/_docs/mock-api-templates.md deleted file mode 100644 index aa0dbc56..00000000 --- a/_docs/mock-api-templates.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -layout: docs -title: WireMock API Templates Library -meta_title: WireMock API Templates Library -toc_rank: 66 -description: > - The library.wiremock.org site provides a catalog of API Templates - that can be used with both WireMock or WireMock Cloud. ---- - -The [library.wiremock.org](https://library.wiremock.org) site provides a catalog of API Templates -that can be used with both -[WireMock](https://wiremock.org/) or [WireMock Cloud](https://wiremock.io). -You can browse our library of mock API templates and examples, -find the API that you need, -and get a running mock in seconds - on your local machine or in the cloud. - -[![Mock API Templates Library](https://library.wiremock.org/images/logo/template-library-wide.png)](https://library.wiremock.org/) - -## Using templates in WireMock - -1. Go to the [Mock API Templates Library](https://library.wiremock.org) site -2. Choose a template you need. There are categories and search capabilities at your disposal -3. Click the _Download WireMock JSON_ button to download the JSON file -4. Use the JSON file to configure your WireMock instance - See [Using Templates](./usage) - -## Using templates in WireMock Cloud - - - -For WireMock Cloud there is also the _Run in WireMock Cloud_ button that -allows you to quickly import the Mock API definition into your project. - -## Editing and Adding templates - -Template definitions can be found in another repository: -[wiremock/api-template-library](https://github.com/wiremock/api-template-library). - -If you would like to edit the existing template -or to contribute a new API template, -feel free to submit a pull request to -[wiremock/api-template-library](https://github.com/wiremock/api-template-library). -This is a public repository enables WireMock and WireMock Cloud users -to build their own Mock APIs based off a public template, -e.g. for your public service. - -A template can be added to featured list by adding the `featured` tag in the metadata JSON. -If a template is somehow related to WireMock, please also use the `wiremock` tag. - -It may take some time to propagate changes to -WireMock or WireMock Cloud. - -## References - -- [Templates Repository](https://github.com/wiremock/api-template-library) -- [WireMock Library Sources](https://github.com/wiremock/library.wiremock.org-sources) diff --git a/_docs/overview.md b/_docs/overview.md deleted file mode 100644 index b0342301..00000000 --- a/_docs/overview.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -layout: docs -title: Overview -meta_title: WireMock Overview and Basics -toc_rank: 1 -description: Top-level overview of WireMock ---- - -**WireMock** is a popular open-source tool for API mock testing -with over 5 million downloads per month. -It can help you to create stable test and development environments, -isolate yourself from flakey 3rd parties -and simulate APIs that don't exist yet. - -Started in 2011 as a Java library by [Tom Akehurst](https://github.com/tomakehurst), -now WireMock spans across multiple programming languages and technology stacks. -It can run as a library or client wrapper in many languages, or as a standalone server. -There is a big community behind the project and its ecosystem. - -WireMock supports several approaches for creating mock APIs - -in code, via its REST API, as JSON files and by recording HTTP traffic proxied to another destination. -WireMock has a rich matching system, allowing any part of an incoming request to be matched against complex and precise criteria. -Responses of any complexity can be dynamically generated via the Handlebars based templating system. -Finally, WireMock is easy to integrate into any workflow due to its numerous extension points and comprehensive APIs. - -## Key features - -- HTTP response stubbing, matchable on URL, header and body content patterns -- Request verification -- Runs in unit tests, as a standalone process or as a WAR app -- Record/playback of stubs -- Configurable response delays and Fault injection -- Per-request conditional proxying -- Browser proxying for request inspection and replacement -- Stateful behaviour simulation - -All the features are configurable via a fluent Java API and JSON files, -or via JSON over HTTP for the standalone service. - -## Getting Started - -Check out WireMock Quick-starts and tutorials [here](../getting-started). - -## WireMock Ecosystem - -WireMock has implementations and adapters for other languages and test frameworks. -It supports adapters and implementations for various technology stacks, including Python, .NET, Golang, and Rust. -For the JVM ecosystem, there are libraries for Spring Boot, Quarkus, Kotlin, Testcontainers and other. -WireMock can also run on Android support, and soon to provide official gRPC and GraphQL adapters. - -You can learn more about [WireMock Ecosystem here](https://github.com/wiremock/ecosystem). diff --git a/_docs/record-playback.md b/_docs/record-playback.md deleted file mode 100644 index 2a993910..00000000 --- a/_docs/record-playback.md +++ /dev/null @@ -1,382 +0,0 @@ ---- -layout: docs -title: Record and Playback -meta_title: Record and Playback an API to Create a Mock | WireMock -redirect_from: "/record-playback.html" -description: WireMock can create stub mappings from requests it has received. Combined with its proxying feature this allows you to “record” stub mappings from interaction with existing APIs. ---- - -WireMock can create stub mappings from requests it has received. Combined with its proxying feature this allows you to "record" -stub mappings from interaction with existing APIs. - -Two approaches are available: Recording or snapshotting. The same results can be achieved with either, so which you choose should depend on whatever -fits best with your workflow. If you're new to WireMock, recording is probably the simplest option for getting started. - -Both approaches are described in more detail below. - -## Quick start - -The fastest way to get started with WireMock's recorder is to use the simple web UI provided. - -First, start an instance of [WireMock running standalone](../running-standalone). -Once that's running visit the recorder UI page at [http://localhost:8080/\_\_admin/recorder](http://localhost:8080/__admin/recorder) -(assuming you started WireMock on the default port of 8080). - -![Recorder UI]({{ '/images/recorder-screenshot.png' | absolute_url }}) - -Enter the URL you wish to record from in the target URL field and click the Record button. You can use `http://examples.wiremockapi.cloud` to try it out. - -Now you need to make a request through WireMock to the target API so that it can be recorded. If you're using the example URL, you can generate a request using curl: - -```bash -$ curl http://localhost:8080/recordables/123 -``` - -Now click stop. You should see a message indicating that one stub was captured. - -You should also see that a file has been created called something like `recordables_123-40a93c4a-d378-4e07-8321-6158d5dbcb29.json` -under the `mappings` directory created when WireMock started up, and that a new mapping has appeared at [http://localhost:8080/\_\_admin/mappings](http://localhost:8080/__admin/mappings). - -Requesting the same URL again (possibly disabling your wifi first if you want firm proof) will now serve the recorded result: - -``` -$ curl http://localhost:8080/recordables/123 - -{ - "message": "Congratulations on your first recording!" -} -``` - -> **note** -> -> Stub mappings will only be created at the point that the recording is stopped. - -> **note** -> -> "Playback" doesn't require any explicit action. Recorded stubs will start being served immediately after recording is stopped. - -## Recording - -Recording can also be started and stopped via WireMock's JSON API and Java DSL. - -Java: - -```java -// Static DSL -WireMock.startRecording("http://examples.wiremockapi.cloud/"); -List recordedMappings = WireMock.stopRecording(); - -// Client instance -WireMock wireMockClient = new WireMock(8080); -wireMockClient.startStubRecording("http://examples.wiremockapi.cloud/"); -List recordedMappings = wireMockClient.stopStubRecording(); - -// Directly -WireMockServer wireMockServer = new WireMockServer(); -wireMockServer.start(); -wireMockServer.startRecording("http://examples.wiremockapi.cloud/"); -List recordedMappings = wireMockServer.stopRecording(); -``` - -API: - -```json -POST /__admin/recordings/start -{ - "targetBaseUrl": "http://examples.wiremockapi.cloud/" -} -``` - -``` -POST /__admin/recordings/stop -``` - -## Snapshotting - -Snapshotting is effectively "recording after the fact". Rather than starting recording at a specific point, snapshotting allows you to convert requests already received by WireMock -into stub mappings. - -An implication of this order of events is that if you want to record an external API, you'll need to have configured proxying before you start generating traffic. -See [Proxying](../proxying) for details on proxy configuration, but in summary this can be achieved by creating a proxy mapping via the API or Java DSL: - -Java: - -```java -stubFor(proxyAllTo("http://examples.wiremockapi.cloud/").atPriority(1)); -``` - -API: - -```json -POST /__admin/mappings -{ - "priority": 1, - "request": { - "method": "ANY" - }, - "response": { - "proxyBaseUrl" : "http://examples.wiremockapi.cloud/" - } -} -``` - -> **note** -> -> You can still take snapshots without a proxy stub configured. -> You might want to do this e.g. if you want to capture requests made by your application under test that you can then modify by hand to provide the appropriate responses. - -Once you have made some requests through WireMock (which you can view under http://localhost:8080/\_\_admin/requests) you can trigger a snapshot to generate stub mappings: - -Java: - -```java -// Static DSL -List recordedMappings = WireMock.snapshotRecord(); - -// Client instance -WireMock wireMockClient = new WireMock(8080); -List recordedMappings = wireMockClient.takeSnapshotRecording(); - -// Directly -WireMockServer wireMockServer = new WireMockServer(); -wireMockServer.start(); -List recordedMappings = wireMockServer.snapshotRecord(); -``` - -API: - -``` -POST /__admin/recordings/snapshot -{} -``` - -## Customising your recordings - -The default recording behaviour can be tweaked in a number of ways by passing a "record spec" to the record or snapshot actions. - -In Java this achieved using the DSL: - -```java -startRecording( - recordSpec() - .forTarget("http://examples.wiremockapi.cloud/") - .onlyRequestsMatching(getRequestedFor(urlPathMatching("/api/.*"))) - .captureHeader("Accept") - .captureHeader("Content-Type", true) - .extractBinaryBodiesOver(10240) - .extractTextBodiesOver(2048) - .makeStubsPersistent(false) - .ignoreRepeatRequests() - .transformers("modify-response-header") - .transformerParameters(Parameters.one("headerValue", "123")) - .matchRequestBodyWithEqualToJson(false, true) - ); -``` - -And via the API: - -```json -POST /__admin/recordings/start -{ - "targetBaseUrl" : "http://examples.wiremockapi.cloud/", - "filters" : { - "urlPathPattern" : "/api/.*", - "method" : "GET", - "allowNonProxied": true - }, - "captureHeaders" : { - "Accept" : { }, - "Content-Type" : { - "caseInsensitive" : true - } - }, - "requestBodyPattern" : { - "matcher" : "equalToJson", - "ignoreArrayOrder" : false, - "ignoreExtraElements" : true - }, - "extractBodyCriteria" : { - "textSizeThreshold" : "2048", - "binarySizeThreshold" : "10240" - }, - "persist" : false, - "repeatsAsScenarios" : false, - "transformers" : [ "modify-response-header" ], - "transformerParameters" : { - "headerValue" : "123" - } -} -``` - -The same specification can also be passed when snapshotting: - -Java: - -```java -snapshotRecord( - recordSpec() - .onlyRequestsMatching(getRequestedFor(urlPathMatching("/api/.*"))) - .onlyRequestIds(singletonList(UUID.fromString("40a93c4a-d378-4e07-8321-6158d5dbcb29"))) - .allowNonProxied(true) - .captureHeader("Accept") - .captureHeader("Content-Type", true) - .extractBinaryBodiesOver(10240) - .extractTextBodiesOver(2048) - .makeStubsPersistent(false) - .ignoreRepeatRequests() - .transformers("modify-response-header") - .transformerParameters(Parameters.one("headerValue", "123")) - .chooseBodyMatchTypeAutomatically() - ); -``` - -API: - -```json -POST /__admin/recordings/snapshot -{ - "filters" : { - "urlPathPattern" : "/api/.*", - "method" : "GET", - "ids" : [ "40a93c4a-d378-4e07-8321-6158d5dbcb29" ] - }, - "captureHeaders" : { - "Accept" : { }, - "Content-Type" : { - "caseInsensitive" : true - } - }, - "requestBodyPattern" : { - "matcher" : "equalToJson", - "ignoreArrayOrder" : false, - "ignoreExtraElements" : true - }, - "extractBodyCriteria" : { - "textSizeThreshold" : "2 kb", - "binarySizeThreshold" : "1 Mb" - }, - "outputFormat" : "FULL", - "persist" : false, - "repeatsAsScenarios" : false, - "transformers" : [ "modify-response-header" ], - "transformerParameters" : { - "headerValue" : "123" - } -} -``` - -The following sections will detail each parameter in turn: - -### Filtering - -`filters` supports selection of requests to be recorded according to the same [request matcher](../request-matching) format used elsewhere in WireMock. - -Additionally, when snapshotting the `ids` parameter allows specific serve events to be selected by ID. - -The `allowNonProxied` attribute, when set to `true` will cause requests that did not get proxied to a target service to be recorded/snapshotted. This is useful if -you wish to "teach" WireMock your API by feeding it requests from your app that initially don't match a stub, then snapshotting to generate the correct stubs. - -### Capturing request headers - -You may want your recorded stub mappings to match on one or more specific request headers. -For instance if you're intending to record from an API that supports both XML and JSON responses via content negotiation, -then you will need to capture the value of the `Accept` header sent in each request. - -The `captureHeaders` attribute allows you to specify a map of header names to match parameter objects. Currently the only parameter -available is `caseInsensitive`, which defaults to false if absent. - -### Body files extraction size criteria - -By default, recorded response bodies will be included directly in the stub mapping response part, via the `body` attribute for text or `base64Body` for binary content. - -However, this can be overridden by setting the `textSizeThreshold` and `binarySizeThreshold` values under `extractBodyCriteria`. -The size values are of type string, and support friendly syntax for specifying the order of magnitude e.g. - -``` -"56 kb" -"10 Mb" -"18.2 GB" -"255" // bytes when no magnitude specified -``` - -In the Java DSL these values are specified as a `long` number of bytes: - -```java -recordSpec().extractBinaryBodiesOver(204800) -``` - -### Output format - -By default the stop recording and snapshot API calls will return the full JSON of all mappings captured. -If you only require the IDs of captured stubs you can specify: - -```json -{ - "outputFormat": "IDS" -} -``` - -### Persist stubs - -By default generated stubs will be set to persistent, meaning that they will be saved to the file system -(or other back-end if you've implemented your own `MappingsSource`) and will survive calls to reset mappings to default. - -Setting `persist` to `false` means that stubs will not be saved and will be deleted on the next reset. - -### Repeats as scenarios - -What happens when the recorder sees two identical requests that produce different results? - -There are two ways to handle this. Setting `repeatsAsScenarios` to `false` means that after the first request, subsequent identical ones will be ignored. - -However, when set to `true` (which is the default if omitted), multiple identical requests will be added to a [Scenario](../stateful-behaviour), meaning that when -playing back, a series of requests matching this stub will yield the same series of responses captured during recording. If more requests are made after the end of the series -is reached, the last response will continue to be returned. - -### Transforming generated stubs - -If you need even more control over how your recorded stubs are generated, you can write one or more custom transformers that will be applied to stubs as they are captured. - -A transformer is an implementations of `StubMappingTransformer` and needs to be registered when starting WireMock as described in [Extending WireMock](../extending-wiremock). - -Transformer implementations supply a name, and this is used to identify them in the `transformers` parameter e.g. - -```json -"transformers": ["transformer-one", "transformer-two"] -``` - -As with other types of WireMock extension, parameters can be supplied. The exact parameters required depend on the specifics of the transformer (or it may not require any). - -```json -"transformerParameters": { - "simpleParam1": "One", - "arrayParam2": [1, 2, 3], - ... -} -``` - -### Request body matching - -By default, the body match operator for a recorded stub is based on the `Content-Type` header of the request. For MIME types containing the string "json", the operator will be `equalToJson` with both the `ignoreArrayOrder` and `ignoreExtraElements` options set to `true`. For MIME types containing `xml`, it will use `equalToXml`. Otherwise, it will use `equalTo` with the `caseInsensitive` option set to `false`. - -This behavior can be customized via the `requestBodyPattern` parameter, which accepts a `matcher` (either `equalTo`, `equalToJson`, `equalToXml`, or `auto`) and any relevant matcher options (`ignoreArrayOrder`, `ignoreExtraElements`, or `caseInsensitive`). For example, here's how to preserve the default behavior, but set `ignoreArrayOrder` to `false` when `equalToJson` is used: - -```json -"requestBodyPattern" : { - "matcher": "auto", - "ignoreArrayOrder" : false - } -``` - -If you want to always match request bodies with `equalTo` case-insensitively, regardless of the MIME type, use: - -```json -"requestBodyPattern" : { - "matcher": "equalTo", - "caseInsensitive" : true - } -``` - -> **note** -> -> The `targetBaseUrl` parameter will be ignored when snapshotting and the `filters/ids` parameter will be ignored when recording. diff --git a/_docs/request-matching.md b/_docs/request-matching.md deleted file mode 100644 index 73b06d58..00000000 --- a/_docs/request-matching.md +++ /dev/null @@ -1,1692 +0,0 @@ ---- -layout: docs -title: Request Matching -meta_title: Matching and filtering HTTP requests in WireMock | WireMock -toc_rank: 61 -description: WireMock supports matching of requests to stubs and verification queries using the following attributes. ---- - -WireMock enables flexible definition of a [mock API](/) by supporting rich matching of incoming requests. Stub matching and verification queries can use the following request attributes: - -- URL -- HTTP Method -- Query parameters -- Form parameters -- Headers -- Basic authentication (a special case of header matching) -- Cookies -- Request body -- Multipart/form-data - -Here's an example showing all attributes being matched using WireMock's in-built match operators. It is also possible to write [custom matching logic](../extending-wiremock#custom-request-matchers) if -you need more precise control: - -## Request with XML Body - -Code: - -```java -stubFor(any(urlPathEqualTo("/everything")) - .withHeader("Accept", containing("xml")) - .withCookie("session", matching(".*12345.*")) - .withQueryParam("search_term", equalTo("WireMock")) - .withBasicAuth("jeff@example.com", "jeffteenjefftyjeff") - .withRequestBody(equalToXml("")) - .withRequestBody(matchingXPath("//search-results")) - .withMultipartRequestBody( - aMultipart() - .withName("info") - .withHeader("Content-Type", containing("charset")) - .withBody(equalToJson("{}")) - ) - .willReturn(aResponse())); -``` - -Configuration file: - -```json -{ - "request": { - "urlPath": "/everything", - "method": "ANY", - "headers": { - "Accept": { - "contains": "xml" - } - }, - "queryParameters": { - "search_term": { - "equalTo": "WireMock" - } - }, - "cookies": { - "session": { - "matches": ".*12345.*" - } - }, - "bodyPatterns": [ - { - "equalToXml": "" - }, - { - "matchesXPath": "//search-results" - } - ], - "multipartPatterns": [ - { - "matchingType": "ANY", - "headers": { - "Content-Disposition": { - "contains": "name=\"info\"" - }, - "Content-Type": { - "contains": "charset" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{}" - } - ] - } - ], - "basicAuthCredentials": { - "username": "jeff@example.com", - "password": "jeffteenjefftyjeff" - } - }, - "response": { - "status": 200 - } -} -``` - -## Request with Form Parameters - -```java -stubFor(post(urlPathEqualTo("/mock")) - .withFormParam("tool", equalTo("WireMock")) -).willReturn(ok())); -``` - -```json -{ - "request": { - "urlPath": "/mock", - "method": "POST", - "formParameters": { - "tool": { - "equalTo": "WireMock" - } - } - }, - "response": { - "status": 200 - } -} -``` - -The following sections describe each type of matching strategy in detail. - -## URL matching - -URLs can be matched either by equality or by regular expression. You also have a choice of whether to match just the path part of the URL or the path and query together. - -It is usually preferable to match on path only if you want to match multiple query parameters in an order invariant manner. - -### Equality matching on path and query - -Java: - -```java -urlEqualTo("/your/url?and=query") -``` - -JSON: - -```json -{ - "request": { - "url": "/your/url?and=query" - ... - }, - ... -} -``` - -### Regex matching on path and query - -Java: - -```java -urlMatching("/your/([a-z]*)\\?and=query") -``` - -JSON: - -```json -{ - "request": { - "urlPattern": "/your/([a-z]*)\\?and=query" - ... - }, - ... -} -``` - -### Equality matching on the path only - -Java: - -```java -urlPathEqualTo("/your/url") -``` - -JSON: - -```json -{ - "request": { - "urlPath": "/your/url" - ... - }, - ... -} -``` - -### Regex matching on the path only - -Java: - -```java -urlPathMatching("/your/([a-z]*)") -``` - -JSON: - -```json -{ - "request": { - "urlPathPattern": "/your/([a-z]*)" - ... - }, - ... -} -``` - -### Path templates - -WireMock from 3.0.0 onwards supports matching on URL path templates conforming to the [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570) standard. - -When the path template URL match type is used this enables - -1. The ability to match path variables in the same way as query parameters, headers etc. -2. The ability to reference path variables by name in [response templates](../response-templating/#the-request-model). - -To match any request URL that conforms to the path template, you can do the following. - -Java: - -```java -stubFor( - get(urlPathTemplate("/contacts/{contactId}/addresses/{addressId}")) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "urlPathTemplate": "/contacts/{contactId}/addresses/{addressId}" - "method" : "GET", - - }, - "response" : { - "status" : 200 - } -} -``` - -To further constrain the match to specific values of the path variables you can add match clauses for some or all of the variables in the path expression. - -```java -stubFor( - get(urlPathTemplate("/contacts/{contactId}/addresses/{addressId}")) - .withPathParam("contactId", equalTo("12345")) - .withPathParam("addressId", equalTo("99876")) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request" : { - "urlPathTemplate" : "/v1/contacts/{contactId}/addresses/{addressId}", - "method" : "GET", - "pathParameters" : { - "contactId" : { - "equalTo" : "12345" - }, - "addressId" : { - "equalTo" : "99876" - } - } - }, - "response" : { - "status" : 200 - } -} -``` - - -## Matching other attributes - -All request attributes other than the URL can be matched using the following set of operators. - -### Equality - -Deems a match if the entire attribute value equals the expected value. - -Java: - -```java -.withHeader("Content-Type", equalTo("application/json")) -``` - -JSON: - -```json -{ - "request": { - ... - "headers": { - "Content-Type": { - "equalTo": "application/json" - } - } - ... - }, - ... -} -``` - -### Case-insensitive equality - -Deems a match if the entire attribute value equals the expected value, ignoring case. - -Java: - -```java -.withHeader("Content-Type", equalToIgnoreCase("application/json")) -``` - -JSON: - -```json -{ - "request": { - ... - "headers": { - "Content-Type": { - "equalTo": "application/json", - "caseInsensitive": true - } - } - ... - }, - ... -} -``` - -### Binary Equality - -Deems a match if the entire binary attribute value equals the expected value. Unlike the above equalTo operator, this compares byte arrays (or their equivalent base64 representation). - -Java: - -```java -// Specifying the expected value as a byte array -.withRequestBody(binaryEqualTo(new byte[] { 1, 2, 3 })) - -// Specifying the expected value as a base64 String -.withRequestBody(binaryEqualTo("AQID")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [{ - "binaryEqualTo" : "AQID" // Base 64 - }] - ... - }, - ... -} -``` - -### Substring (contains) - -Deems a match if the a portion of the attribute value equals the expected value. - -Java: - -```java -.withCookie("my_profile", containing("johnsmith@example.com")) -``` - -JSON: - -```json -{ - "request": { - ... - "cookies" : { - "my_profile" : { - "contains" : "johnsmith@example.com" - } - } - ... - }, - ... -} -``` - -### Negative substring (does not contain) - -Deems a match if the attribute value does not contain the expected value. - -Java: - -```java -.withCookie("my_profile", notContaining("johnsmith@example.com")) -``` - -JSON: - -```json -{ - "request": { - ... - "cookies" : { - "my_profile" : { - "doesNotContain" : "johnsmith@example.com" - } - } - ... - }, - ... -} -``` - -### Regular expression - -Deems a match if the entire attribute value matched the expected regular expression. - -Java: - -```java -.withQueryParam("search_term", matching("^(.*)wiremock([A-Za-z]+)$")) -``` - -JSON: - -```json -{ - "request": { - ... - "queryParameters" : { - "search_term" : { - "matches" : "^(.*)wiremock([A-Za-z]+)$" - } - } - ... - }, - ... -} -``` - -It is also possible to perform a negative match i.e. the match succeeds when the attribute value does not match the regex: - -Java: - -```java -.withQueryParam("search_term", notMatching("^(.*)wiremock([A-Za-z]+)$")) -``` - -JSON: - -```json -{ - "request": { - ... - "queryParameters" : { - "search_term" : { - "doesNotMatch" : "^(.*)wiremock([A-Za-z]+)$" - } - } - ... - }, - ... -} -``` - -### JSON equality - -Deems a match if the attribute (most likely the request body in practice) is valid JSON and is a semantic match for the expected value. - -Java: - -```java -.withRequestBody(equalToJson("{ \"total_results\": 4 }")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToJson" : { "total_results": 4 } - } ] - ... - }, - ... -} -``` - -JSON with string literal: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToJson" : "{ \"total_results\": 4 }" - } ] - ... - }, - ... -} -``` - -#### Less strict matching - -By default different array orderings and additional object attributes will trigger a non-match. However, both of these conditions can be disabled individually. - -Java: - -```java -.withRequestBody(equalToJson("{ \"total_results\": 4 }", true, true)) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToJson" : "{ \"total_results\": 4 }", - "ignoreArrayOrder" : true, - "ignoreExtraElements" : true - } ] - ... - }, - ... -} -``` - -#### Placeholders - -JSON equality matching is based on [JsonUnit](https://github.com/lukas-krecan/JsonUnit) and therefore supports placeholders. -This allows specific attributes to be treated as wildcards, rather than an exactly value being required for a match. - -For instance, the following: - -```json -{ "id": "${json-unit.any-string}" } -``` - -would match a request with a JSON body of: - -```json -{ "id": "abc123" } -``` - -It's also possible to use placeholders that constrain the expected value by type or regular expression. -See [the JsonUnit placeholders documentation](https://github.com/lukas-krecan/JsonUnit#typeplc) for the full syntax. - -### JSON Path - -Deems a match if the attribute value is valid JSON and matches the [JSON Path](http://goessner.net/articles/JsonPath/) expression supplied. A JSON body will be considered to match a path expression if the expression returns either a non-null single value (string, integer etc.), or a non-empty object or array. - -#### Presence matching - -Deems a match if the attribute value is present in the JSON. - -Java: - -```java -.withRequestBody(matchingJsonPath("$.name")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesJsonPath" : "$.name" - } ] - ... - }, - ... -} -``` - -Request body example: - -``` -// matching -{ "name": "Wiremock" } -// not matching -{ "price": 15 } -``` - -#### Equality matching - -Deems a match if the attribute value equals the expected value. - -Java: - -```java -.withRequestBody(matchingJsonPath("$.things[?(@.name == 'RequiredThing')]")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesJsonPath" : "$.things[?(@.name == 'RequiredThing')]" - } ] - ... - }, - ... -} -``` - -Request body example: - -``` -// matching -{ "things": { "name": "RequiredThing" } } -{ "things": [ { "name": "RequiredThing" }, { "name": "Wiremock" } ] } -// not matching -{ "price": 15 } -{ "things": { "name": "Wiremock" } } -``` - -#### Regex matching - -Deems a match if the attribute value matches the regex expected value. - -Java: - -```java -.withRequestBody(matchingJsonPath("$.things[?(@.name =~ /Required.*/i)]")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesJsonPath" : "$.things[?(@.name =~ /Required.*/i)]" - } ] - ... - }, - ... -} -``` - -Request body example: - -```json -// matching -{ "things": { "name": "RequiredThing" } } -{ "things": [ { "name": "Required" }, { "name": "Wiremock" } ] } -// not matching -{ "price": 15 } -{ "things": { "name": "Wiremock" } } -{ "things": [ { "name": "Thing" }, { "name": "Wiremock" } ] } -``` - -#### Size matching - -Deems a match if the attribute size matches the expected size. - -Java: - -```java -.withRequestBody(matchingJsonPath("$[?(@.things.size() == 2)]")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.things.size() == 2)]" - } ] - ... - }, - ... -} -``` - -Request body example: - -```json -// matching -{ "things": [ { "name": "RequiredThing" }, { "name": "Wiremock" } ] } -// not matching -{ "things": [ { "name": "RequiredThing" } ] } -``` - -#### Nested value matching - -The JSONPath matcher can be combined with another matcher, such that the value returned from the JSONPath query is evaluated against it: - -Java: - -```java -.withRequestBody(matchingJsonPath("$..todoItem", containing("wash"))) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesJsonPath" : { - "expression": "$..todoItem", - "contains": "wash" - } - } ] - ... - }, - ... -} -``` - -Since WireMock's matching operators all work on strings, the value selected by the JSONPath expression will be coerced to a string before the match is evaluated. This true even if the returned value -is an object or array. A benefit of this is that this allows a sub-document to be selected using JSONPath, then matched using the `equalToJson` operator. E.g. for the following request body: - -```json -{ - "outer": { - "inner": 42 - } -} -``` - -The following will match: - -```java -.withRequestBody(matchingJsonPath("$.outer", equalToJson("{ \n" + - " \"inner\": 42 \n" + - "}"))) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesJsonPath" : { - "expression": "$.outer", - "equalToJson": "{ \"inner\": 42 }" - } - } ] - ... - }, - ... -} -``` - -### JSON schema - -Deems a match if the value conforms to the expected JSON schema. - -By default the [V202012](https://json-schema.org/draft/2020-12/schema){:target="{{site.data.misc.blank}}"} version of the JSON schema spec will be used, but this can be changed to one of `V4`, `V6`, `V7`, `V201909`, `V202012` via the `schemaVersion` parameter. - -Java: - -```java -stubFor( - post(urlPathEqualTo("/schema-match")) - .withRequestBody(matchingJsonSchema("{\n" + - " \"type\": \"object\",\n" + - " \"required\": [\n" + - " \"name\"\n" + - " ],\n" + - " \"properties\": {\n" + - " \"name\": {\n" + - " \"type\": \"string\"\n" + - " },\n" + - " \"tag\": {\n" + - " \"type\": \"string\"\n" + - " }\n" + - " }\n" + - "}")) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request" : { - "urlPath" : "/schema-match", - "method" : "POST", - "bodyPatterns" : [ { - "matchesJsonSchema" : "{\n \"type\": \"object\",\n \"required\": [\n \"name\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"tag\": {\n \"type\": \"string\"\n }\n }\n}", - "schemaVersion" : "V202012" - } ] - }, - "response" : { - "status" : 200 - } -} -``` - - -### XML equality - -Deems a match if the attribute value is valid XML and is semantically equal to the expected XML document. The underlying engine for determining XML equality is [XMLUnit](http://www.xmlunit.org/). - -Java: - -```java -.withRequestBody(equalToXml("Hello")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToXml" : "Hello" - } ] - ... - }, - ... -} -``` - -#### Use of placeholders - -The XMLUnit [placeholders](https://github.com/xmlunit/user-guide/wiki/Placeholders) feature is supported in WireMock. For example, when comparing the XML documents, you can ignore some text nodes. - -Java: - -```java -.withRequestBody( - equalToXml("${xmlunit.ignore}Hello", true) -) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToXml" : "${xmlunit.ignore}Hello", - "enablePlaceholders" : true - } ] - ... - }, - ... -} -``` - -When the actual request body is `123456Hello`, it will be deemed a match. - -If the default placeholder delimiters `${` and `}` can not be used, you can specify custom delimiters (using regular expressions). For example - -Java: - -```java -.withRequestBody( - equalToXml("[[xmlunit.ignore]]Hello", - true, - "\\[\\[", - "]]" - ) -) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToXml" : "[[xmlunit.ignore]]Hello", - "enablePlaceholders" : true, - "placeholderOpeningDelimiterRegex" : "\\[\\[", - "placeholderClosingDelimiterRegex" : "]]" - } ] - ... - }, - ... -} -``` - -#### Excluding specific types of comparison - -You can further tune how XML documents are compared for equality by disabling specific [XMLUnit comparison types](https://www.xmlunit.org/api/java/2.7.0/org/xmlunit/diff/ComparisonType.html). - -Java: - -```java -import static org.xmlunit.diff.ComparisonType.*; - -... - -.withRequestBody(equalToXml("Hello") - .exemptingComparisons(NAMESPACE_URI, ELEMENT_TAG_NAME) -) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "equalToXml" : "Hello", - "exemptedComparisons": ["NAMESPACE_URI", "ELEMENT_TAG_NAME"] - } ] - ... - }, - ... -} -``` - -The full list of comparison types used by default is as follows: - -`ELEMENT_TAG_NAME` -`SCHEMA_LOCATION` -`NO_NAMESPACE_SCHEMA_LOCATION` -`NODE_TYPE` -`NAMESPACE_URI` -`TEXT_VALUE` -`PROCESSING_INSTRUCTION_TARGET` -`PROCESSING_INSTRUCTION_DATA` -`ELEMENT_NUM_ATTRIBUTES` -`ATTR_VALUE` -`CHILD_NODELIST_LENGTH` -`CHILD_LOOKUP` -`ATTR_NAME_LOOKUP` - -### XPath - -Deems a match if the attribute value is valid XML and matches the XPath expression supplied. An XML document will be considered to match if any elements are returned by the XPath evaluation. WireMock delegates to Java's in-built XPath engine (via XMLUnit), therefore up to (at least) Java 8 it supports XPath version 1.0. - -Java: - -```java -.withRequestBody(matchingXPath("/todo-list[count(todo-item) = 3]")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesXPath" : "/todo-list[count(todo-item) = 3]" - } ] - ... - }, - ... -} -``` - -The above example will select elements based on their local name if used with a namespaced XML document. - -If you need to be able to select elements based on their namespace in addition to their name you can declare the prefix -to namespace URI mappings and use them in your XPath expression: - -Java: - -```java -.withRequestBody(matchingXPath("/stuff:outer/more:inner[.=111]") - .withXPathNamespace("stuff", "http://stuff.example.com") - .withXPathNamespace("more", "http://more.example.com")) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesXPath" : "/stuff:outer/more:inner[.=111]", - "xPathNamespaces" : { - "stuff" : "http://stuff.example.com", - "more" : "http://more.example.com" - } - } ] - ... - }, - ... -} -``` - -#### Nested value matching - -The XPath matcher described above can be combined with another matcher, such that the value returned from the XPath query is evaluated against it: - -Java: - -```java -.withRequestBody(matchingXPath("//todo-item/text()", containing("wash"))) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesXPath" : { - "expression": "//todo-item/text()", - "contains": "wash" - } - } ] - ... - }, - ... -} -``` - -If multiple nodes are returned from the XPath query, all will be evaluated and the returned match will be the one with the shortest distance. - -If the XPath expression returns an XML element rather than a value, this will be rendered as an XML string before it is passed to the value matcher. -This can be usefully combined with the `equalToXml` matcher e.g. - -Java: - -```java -.withRequestBody(matchingXPath("//todo-item", equalToXml("Do the washing"))) -``` - -JSON: - -```json -{ - "request": { - ... - "bodyPatterns" : [ { - "matchesXPath" : { - "expression": "//todo-item", - "equalToXml": "Do the washing" - } - } ] - ... - }, - ... -} -``` - -### Absence - -Deems a match if the attribute specified is absent from the request. - -Java: - -```java -.withCookie("session", absent()) -.withQueryParam("search_term", absent()) -.withHeader("X-Absent", absent()) -``` - -JSON: - -```json -{ - "request": { - ... - "headers" : { - "X-Absent" : { - "absent" : true - } - }, - "queryParameters" : { - "search_term" : { - "absent" : true - } - }, - "cookies" : { - "session" : { - "absent" : true - } - } - ... - }, - ... -} -``` - -## Multipart/form-data - -Deems a match if a multipart value is valid and matches any or all the multipart pattern matchers supplied. As a Multipart is a 'mini' HTTP request in itself all existing Header and Body content matchers can by applied to a Multipart pattern. -A Multipart pattern can be defined as matching `ANY` request multiparts or `ALL`. The default matching type is `ANY`. - -Java: - -```java -stubFor(...) - ... - .withMultipartRequestBody( - aMultipart() - .withName("info") - .withHeader("Content-Type", containing("charset")) - .withMultipartBody(equalToJson("{}")) - ) -``` - -JSON: - -```json -{ - "request": { - ... - "multipartPatterns" : [ { - "matchingType" : "ANY", - "headers" : { - "Content-Disposition" : { - "contains" : "name=\"info\"" - }, - "Content-Type" : { - "contains" : "charset" - } - }, - "bodyPatterns" : [ { - "equalToJson" : "{}" - } ] - } ], - ... - }, - ... -} -``` - -## Basic Authentication - -Although matching on HTTP basic authentication could be supported via a -correctly encoded `Authorization` header, you can also do this more simply -via the API. - -Java: - -```java -stubFor(get(urlEqualTo("/basic-auth")).withBasicAuth("user", "pass") -``` - -JSON: - -```json -{ - "request": { - "method": "GET", - "url": "/basic-auth", - "basicAuth": { - "username": "user", - "password": "pass" - } - }, - "response": { - "status": 200 - } -} -``` - -## Dates and times - -Dates and times can be matched in several ways. Three comparison operators are available: `before`, `after` and -`equalToDateTime`, all of which have the same set of parameters. - -Additionally, the expected value can be either literal (fixed) or an offset from the current date. Both the expected and -actual dates can be truncated in various ways. - -### Literal date/times - -You can match an incoming date/time against a fixed value e.g. "match if the X-Munged-Date request header is after x": - -Java: - -```java -stubFor(post("/dates") - .withHeader("X-Munged-Date", after("2021-05-01T00:00:00Z")) - .willReturn(ok())); - -// You can also use a ZonedDateTime or LocalDateTime object -stubFor(post("/dates") - .withHeader("X-Munged-Date", after(ZonedDateTime.parse("2021-05-01T00:00:00Z"))) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "url": "/dates", - "method": "POST", - "headers": { - "X-Munged-Date": { - "after": "2021-05-01T00:00:00Z" - } - } - }, - "response": { - "status": 200 - } -} -``` - -### Offset - -You can also match in incoming value against the current date/time or an offset from it: - -Java: - -```java -stubFor(post("/dates") - .withHeader("X-Munged-Date", beforeNow().expectedOffset(3, DateTimeUnit.DAYS)) - .withHeader("X-Finalised-Date", before("now +2 months")) // This form and beforeNow() are equivalent - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "url": "/dates", - "method": "POST", - "headers": { - "X-Munged-Date": { - "before": "now +3 days" - }, - "X-Finalised-Date": { - // This is equivalent to "now +2 months" - "before": "now", - "expectedOffset": 2, - "expectedOffsetUnit": "months" - } - } - } -} -``` - -### Local vs. Zoned - -Both the expected and actual date/time values can either have timezone information or not. For instance a -date in ISO8601 format could be zoned: `2021-06-24T13:40:27+01:00` or `2021-06-24T12:40:27Z`, or local: `2021-06-24T12:40:27`. - -Likewise a date/time in RFC 1123 (HTTP standard) format is also zoned: `Tue, 01 Jun 2021 15:16:17 GMT`. - -Whether the expected and actual values are zoned or not affects whether they can be matched and how. Generally, the best -approach is to try to ensure you're using the same on both sides - if you're expected a zoned actual date, then use one -as the expected date also, plus the equivalent for local dates. - -If the expected date is zoned and the actual is local, the actual date will assume the system timezone before the -comparison is attempted. - -If the expected date is local and the actual is zoned, the timezone will be stripped from the actual value before the -comparison is attempted. - -### Date formats - -By default these matchers will attempt to parse date/times in ISO8601 format, plus the three standard formats defined by -HTTP RFCs 1123, 1036 and asctime (taken from C but also valid for specifying HTTP dates). - -It is also possible to specify your own format using -[Java's date format strings](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns). - -Java: - -```java -stubFor(post("/dates") - .withHeader("X-Munged-Date", - equalToDateTime("2021-06-24T00:00:00").actualFormat("dd/MM/yyyy")) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "url": "/dates", - "method": "POST", - "headers": { - "X-Munged-Date": { - "equalToDateTime": "2021-06-24T00:00:00", - "actualFormat": "dd/MM/yyyy" - } - } - } -} -``` - -### Truncation - -Both the expected and actual date/times can be truncated in various ways e.g. to the first hour of the day. When using -offset from now as the expected date with truncation, the truncation will be applied first followed by the offsetting. - -Truncation is useful if you want to create expressions like "before the end of this month" or "equal to the current hour". - -It can usefully be combined with offsetting so e.g. if the match required is "after the 15th of this month" we could do -as follows. - -Java: - -```java -stubFor(post("/dates") - .withRequestBody(matchingJsonPath( - "$.completedDate", - after("now +15 days").truncateExpected(FIRST_DAY_OF_MONTH)) - ) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "url": "/dates", - "method": "POST", - "bodyPatterns": [ - { - "matchesJsonPath": { - "expression": "$.completedDate", - "after": "now +15 days", - "truncateExpected": "first day of month" - } - } - ] - } -} -``` - -Truncating the actual value can be useful when checking for equality with literal date/times e.g. to say "is in March 2020": - -```java -stubFor(post("/dates") - .withRequestBody(matchingJsonPath( - "$.completedDate", - equalToDateTime("2020-03-01T00:00:00Z").truncateActual(FIRST_DAY_OF_MONTH)) - ) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "url": "/dates", - "method": "POST", - "bodyPatterns": [ - { - "matchesJsonPath": { - "expression": "$.completedDate", - "equalToDateTime": "2020-03-01T00:00:00Z", - "truncateActual": "first day of month" - } - } - ] - } -} -``` - -
-The full list of available truncations is: - -- `first minute of hour` -- `first hour of day` -- `first day of month` -- `first day of next month` -- `last day of month` -- `first day of year` -- `first day of next year` -- `last day of year` - -## Logical AND and OR - -You can combine two or more matchers in an AND expression. - -Java: - -```java -// Both statements are equivalent - -stubFor(get(urlPathEqualTo("/and")) - .withHeader("X-Some-Value", and( - matching("[a-z]+"), - containing("magicvalue")) - ) - .willReturn(ok())); - -stubFor(get(urlPathEqualTo("/and")) - .withHeader("X-Some-Value", matching("[a-z]+").and(containing("magicvalue"))) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "urlPath": "/and", - "method": "GET", - "headers": { - "X-Some-Value": { - "and": [ - { - "matches": "[a-z]+" - }, - { - "contains": "magicvalue" - } - ] - } - } - } -} -``` - -Similarly you can also construct an OR expression. - -Java: - -```java -// Both statements are equivalent - -stubFor(get(urlPathEqualTo("/or")) - .withQueryParam("search", or( - matching("[a-z]+"), - absent()) - ) - .willReturn(ok())); - -stubFor(get(urlPathEqualTo("/or")) - .withQueryParam("search", matching("[a-z]+").or(absent())) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "urlPath": "/or", - "method": "GET", - "queryParameters": { - "search": { - "or": [ - { - "matches": "[a-z]+" - }, - { - "absent": true - } - ] - } - } - } -} -``` - -### Combining date matchers as JSONPath/XPath sub-matchers - -As an example of how various matchers can be combined, suppose we want to match if a field named `date` in a JSON request body -is a date/time between two points. - -We can do this by extracting the field using `matchesJsonPath` then matching the result -of this against the `before` and `after` matchers AND'd together. - -Java: - -```java -stubFor(post("/date-range") - .withRequestBody(matchingJsonPath("$.date", - before("2022-01-01T00:00:00").and( - after("2020-01-01T00:00:00")))) - .willReturn(ok())); -``` - -JSON: - -```json -{ - "request": { - "url": "/date-range", - "method": "POST", - "bodyPatterns": [ - { - "matchesJsonPath": { - "expression": "$.date", - "and": [ - { - "before": "2022-01-01T00:00:00" - }, - { - "after": "2020-01-01T00:00:00" - } - ] - } - } - ] - } -} -``` - -This would match the following JSON request body: - -```json -{ - "date": "2021-01-01T00:00:00" -} -``` - -### Matching Header/Query parameter containing multiple values - -You can match multiple values of a query parameter or header with below provided matchers. - -Exactly matcher exactly matches multiple values or patterns and make sure that it does not contain any other value. - -```java -// There must be 3 values of id exactly whose values are 1, 2, and 3 -stubFor(get(urlPathEqualTo("/things")) - .withQueryParam("id", havingExactly("1", "2", "3")) - .willReturn(ok())); -``` - -```json -{ - "mapping": { - "request" : { - "urlPath" : "/things", - "method" : "GET", - "queryParameters" : { - "id" : { - "hasExactly" : [ - { - "equalTo": "1" - }, - { - "equalTo": "2" - }, - { - "equalTo": "3" - } - ] - } - } - }, - "response" : { - "status" : 200 - } - } -} -``` - -```java -// There must be 3 values of id exactly whose values conform to the match expressions - stubFor(get(urlPathEqualTo("/things")) - .withQueryParam("id", havingExactly( - equalTo("1"), - containing("2"), - notContaining("3") - )).willReturn(ok())); -``` - -```json -{ - "mapping": { - "request" : { - "urlPath" : "/things", - "method" : "GET", - "queryParameters" : { - "id" : { - "hasExactly" : [ - { - "equalTo": "1" - }, - { - "contains": "2" - }, - { - "doesNotContain": "3" - } - ] - } - } - }, - "response" : { - "status" : 200 - } - } -} -``` - -Includes matcher matches multiple values or patterns specified and may contain other values as well. - -```java -// The values of id must include 1, 2, and 3. -stubFor(get(urlPathEqualTo("/things")) - .withQueryParam("id", including("1", "2", "3")) - .willReturn(ok())); -``` - -```json -{ - "mapping": { - "request" : { - "urlPath" : "/things", - "method" : "GET", - "queryParameters" : { - "id" : { - "includes" : [ - { - "equalTo": "1" - }, - { - "equalTo": "2" - }, - { - "equalTo": "3" - } - ] - } - } - }, - "response" : { - "status" : 200 - } - } -} -``` - -```java -//values of id must conform to the match expressions -stubFor(get(urlPathEqualTo("/things")) - .withQueryParam("id", including( - equalTo("1"), - containing("2"), - notContaining("3") - )).willReturn(ok())); -``` - -```json -{ - "mapping": { - "request" : { - "urlPath" : "/things", - "method" : "GET", - "queryParameters" : { - "id" : { - "includes" : [ - { - "equalTo": "1" - }, - { - "contains": "2" - }, - { - "doesNotContain": "3" - } - ] - } - } - }, - "response" : { - "status" : 200 - } - } -} -``` diff --git a/_docs/running-without-http-server.md b/_docs/running-without-http-server.md deleted file mode 100644 index f18c33ac..00000000 --- a/_docs/running-without-http-server.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -layout: docs -title: Running without the HTTP Server -meta_title: Running WireMock without an HTTP Server | WireMock -toc_rank: 42 -redirect_from: "/running-without-http-server.html" -description: Running WireMock inside a Java process, without running the inbuilt HTTP layer. ---- - -If you want to run Wiremock inside another process, such as wrapping it in a serverless function such as on AWS Lambda, or using it as part of an application's integration tests, you previously would need to resort to [Running as a Standalone Process](../running-standalone/). - -This works well, but has the overhead of a full HTTP server and HTTP calls back and forth that in some cases may not be relevant, and adds a fair bit of overhead to each call, and the memory footprint of the application. - -Since Wiremock v2.32.0, the `DirectCallHttpServer` provides the ability to run a Wiremock server without ever interacting with an HTTP layer. - -It can be constructed and used like so (example usage is adapted from `DirectCallHttpServerIntegrationTest`): - -```java -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.http.Response; -import com.github.tomakehurst.wiremock.direct.DirectCallHttpServer; -import com.github.tomakehurst.wiremock.direct.DirectCallHttpServerFactory; - -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -// .. - -DirectCallHttpServerFactory factory = new DirectCallHttpServerFactory(); -WireMockServer wm = new WireMockServer(wireMockConfig().httpServerFactory(factory)); -wm.start(); // no-op, not required - -DirectCallHttpServer server = factory.getHttpServer(); - -Request request = new Request() { - // fill in with the incoming request data -} - -Response response = server.stubRequest(request); -// then use the `response`'s data, and map it accordingly -``` - -Note that prior to Wiremock v2.32.0, you can use [the workaround as described by Jamie Tanna](https://www.jvt.me/posts/2021/04/29/wiremock-serverless/), which uses internal APIs for this. diff --git a/_docs/standalone.md b/_docs/standalone.md deleted file mode 100644 index 5c731e2b..00000000 --- a/_docs/standalone.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -layout: docs -title: WireMock Standalone -meta_title: WireMock as a Standalone Service -toc_rank: 41 -redirect_from: - - "/standalone.html" -description: > - WireMock can be run as a standalone service. - We provide the JAR file and Docker image distributions for it. ---- - -WireMock can run as a standalone service, -configured via the Java API, JSON over HTTP or JSON files. -We provide the JAR file and Docker image distributions for it. - -## Running WireMock - -- [Running as a Docker Image](../docker) -- [Running as a JAR file](./java-jar) - -## Management - -When WireMock runs as a standalone service, it can be managed through its REST API. - -- [WireMock Administration](./administration) -- [Admin API Reference](./admin-api-reference/) - -## API Clients - -There is a number of API clients that work with the standalone WireMock instance. -Check out the [Solution pages](../../docs) for more info and pointers. - diff --git a/_docs/standalone/admin-api-reference.md b/_docs/standalone/admin-api-reference.md deleted file mode 100644 index 8476f05e..00000000 --- a/_docs/standalone/admin-api-reference.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: splash -title: Admin API Reference -meta_title: WireMock Admin REST API Documentation | WireMock -toc_rank: 120 -description: The WireMock admin API is described in OpenAPI 3.0. -redirect_from: - - "/wiremock-admin-api.html" - - "/docs/api.html" - - "/docs/api/" ---- - -The WireMock admin API is described in [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md). The spec file plus an instance of Swagger UI can be accessed from a running WireMock instance under `/__admin/docs/`, e.g. `http://localhost:8080/__admin/docs/`. - -Below is the full API reference: - - - - diff --git a/_docs/stateful-behaviour.md b/_docs/stateful-behaviour.md deleted file mode 100644 index d4a5838a..00000000 --- a/_docs/stateful-behaviour.md +++ /dev/null @@ -1,181 +0,0 @@ ---- -layout: docs -title: Stateful Behaviour -meta_title: Simulating Stateful Behavior for Testing | WireMock -redirect_from: "/stateful-behaviour.html" -description: Most web services tend to have some state, which changes as you and others interact with it. ---- - -**Most web services tend to have some state, which changes as you and -others interact with it. So it's pretty useful to be able to simulate -this when you've swapped a real service for a test double.** - -## Scenarios - -WireMock supports state via the notion of scenarios. A scenario is -essentially a state machine whose states can be arbitrarily assigned. Its -starting state is always `Scenario.STARTED`. Stub mappings can be -configured to match on scenario state, such that stub A can be returned -initially, then stub B once the next scenario state has been triggered. - -For example, suppose we're writing a to-do list application consisting -of a rich client of some kind talking to a REST service. We want to test -that our UI can read the to-do list, add an item and refresh itself, -showing the updated list. - -In Java this could be set up like this: - -```java -@Test -public void toDoListScenario() { - stubFor(get(urlEqualTo("/todo/items")).inScenario("To do list") - .whenScenarioStateIs(STARTED) - .willReturn(aResponse() - .withBody("" + - " Buy milk" + - ""))); - - stubFor(post(urlEqualTo("/todo/items")).inScenario("To do list") - .whenScenarioStateIs(STARTED) - .withRequestBody(containing("Cancel newspaper subscription")) - .willReturn(aResponse().withStatus(201)) - .willSetStateTo("Cancel newspaper item added")); - - stubFor(get(urlEqualTo("/todo/items")).inScenario("To do list") - .whenScenarioStateIs("Cancel newspaper item added") - .willReturn(aResponse() - .withBody("" + - " Buy milk" + - " Cancel newspaper subscription" + - ""))); - - WireMockResponse response = testClient.get("/todo/items"); - assertThat(response.content(), containsString("Buy milk")); - assertThat(response.content(), not(containsString("Cancel newspaper subscription"))); - - response = testClient.postWithBody("/todo/items", "Cancel newspaper subscription", "text/plain", "UTF-8"); - assertThat(response.statusCode(), is(201)); - - response = testClient.get("/todo/items"); - assertThat(response.content(), containsString("Buy milk")); - assertThat(response.content(), containsString("Cancel newspaper subscription")); -} -``` - -The JSON equivalent for the above three stubs is: - -```json -{ - "mappings": [ - { - "scenarioName": "To do list", - "requiredScenarioState": "Started", - "request": { - "method": "GET", - "url": "/todo/items" - }, - "response": { - "status": 200, - "body": "Buy milk" - } - }, - { - "scenarioName": "To do list", - "requiredScenarioState": "Started", - "newScenarioState": "Cancel newspaper item added", - "request": { - "method": "POST", - "url": "/todo/items", - "bodyPatterns": [ - { "contains": "Cancel newspaper subscription" } - ] - }, - "response": { - "status": 201 - } - }, - { - "scenarioName": "To do list", - "requiredScenarioState": "Cancel newspaper item added", - "request": { - "method": "GET", - "url": "/todo/items" - }, - "response": { - "status": 200, - "body": "Buy milkCancel newspaper subscription" - } - } - ] -} -``` - -## Getting scenario state - -The names, current state and possible states of all scenarios can be fetched. - -Java: - -```java -List allScenarios = getAllScenarios(); -``` - -JSON: - -```json -GET /__admin/scenarios -{ - "scenarios" : [ { - "id" : "my_scenario", - "name" : "my_scenario", - "state" : "Started", - "possibleStates" : [ "Started", "state_2", "state_3" ] - } ] -} -``` - -## Resetting scenarios - -The state of all configured scenarios can be reset back to -`Scenario.START` either by calling - -Java: - -```java -WireMock.resetAllScenarios() -``` - -To do the equivalent via the HTTP API, send an empty `POST` request to `/__admin/scenarios/reset`. - - -## Resetting a single scenario - -You can reset the state of an individual scenario. - -Java: - -```java -WireMock.resetScenario("my_scenario"); -``` - -The do the equivalent via the HTTP API, send an empty `PUT` to `/__admin/scenarios/my_scenario/state`. - - -## Setting the state of an individual scenario - -You can also set the state of an individual scenario to a specific value. - -Java: - -```java -WireMock.setScenarioState("my_scenario", "state_2"); -``` - -HTTP: - -```json -PUT /__admin/scenarios/my_scenario/state -{ - "state": "state_2" -} -``` \ No newline at end of file diff --git a/_docs/stub-metadata.md b/_docs/stub-metadata.md deleted file mode 100644 index 4fbc1295..00000000 --- a/_docs/stub-metadata.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -layout: docs -title: "Stub Metadata" -meta_title: Associating and using metadata with API stubs | WireMock -toc_rank: 117 -description: It is possible to attach arbitrary metadata to stub mappings, which can be later used to search or deletion, or simply retrieval. ---- - -It is possible to attach arbitrary metadata to stub mappings, which can be later used to search or deletion, or simply retrieval. - -## Adding metadata to stubs - -Data under the `metadata` key is a JSON object (represented in Java by a `Map`). It can be added to a stub mapping on creation. - -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(get("/with-metadata") - .withMetadata(metadata() - .attr("singleItem", 1234) - .list("listItem", 1, 2, 3, 4) - .attr("nestedObject", metadata() - .attr("innerItem", "Hello") - ) -)); -``` - -{% endcodetab %} - -{% codetab JSON %} - -```json -{ - "request": { - "url": "/with-metadata" - }, - "response": { - "status": 200 - }, - - "metadata": { - "singleItem": 1234, - "listItem": [1, 2, 3, 4], - "nestedObject": { - "innerItem": "Hello" - } - } -} -``` - -{% endcodetab %} - -{% endcodetabs %} - -## Search for stubs by metadata - -Stubs can be found by matching against their metadata using the same matching strategies as when [matching HTTP requests](../request-matching/). -The most useful matcher for this is `matchesJsonPath`: - -{% codetabs %} - -{% codetab Java %} - -```java -List stubs = - findStubsByMetadata(matchingJsonPath("$.singleItem", containing("123"))); -``` - -{% endcodetab %} - -{% codetab JSON %} - -```json -POST /__admin/mappings/find-by-metadata - -{ - "matchesJsonPath" : { - "expression" : "$.singleItem", - "contains" : "123" - } -} -``` - -{% endcodetab %} - -{% endcodetabs %} - -## Remove stubs by metadata - -Similarly, stubs with matching metadata can be removed: - -{% codetabs %} - -{% codetab Java %} - -```java -removeStubsByMetadata(matchingJsonPath("$.singleItem", containing("123"))); -``` - -{% endcodetab %} - -{% codetab JSON %} - -POST /__admin/mappings/remove-by-metadata - -```json -{ - "matchesJsonPath" : { - "expression" : "$.singleItem", - "contains" : "123" - } -} -``` - -{% endcodetab %} - -{% endcodetabs %} - -## Remove request journal events by metadata - -See [Removing items from the journal](../verifying#by-criteria) diff --git a/_docs/webhooks-and-callbacks.md b/_docs/webhooks-and-callbacks.md deleted file mode 100644 index 809fcfbe..00000000 --- a/_docs/webhooks-and-callbacks.md +++ /dev/null @@ -1,296 +0,0 @@ ---- -layout: docs -title: Webhooks and Callbacks -meta_title: Simulating Webhooks and Callbacks | WireMock -toc_rank: 105 -description: Configuring WireMock to fire outbound HTTP requests when specific stubs are matched. ---- - -WireMock can make asynchronous outbound HTTP calls when an incoming request is matched to a specific stub. This pattern -is commonly referred to as webhooks or callbacks and is a common design in APIs that need to proactively notify their clients -of events or perform long-running processing asynchronously without blocking. - -## Enabling webhooks - -Prior to WireMock 3.1.0 webhooks were provided via an extension and needed to be explicitly enabled. See [the 2.x docs](https://wiremock.org/2.x/docs/webhooks-and-callbacks/) for details on how to do this. - -From version 3.1.0 the webhooks extension is part of WireMock's core and enabled by default. - -### Old vs. new extension point - -The revised version of webhooks in 3.1.0 makes use of the new `ServeEventListener` extension point. -This article shows how to use this newer extension point, however the legacy `PostServeAction` interface is still supported for backwards compatibility. - -## Creating a simple, single webhook - -You can trigger a single webhook request to a fixed URL, with fixed data like this: - -Java: - -```java -import static org.wiremock.webhooks.Webhooks.*; -... - -wm.stubFor(post(urlPathEqualTo("/something-async")) - .willReturn(ok()) - .withServeEventListener("webhook", webhook() - .withMethod(POST) - .withUrl("http://my-target-host/callback") - .withHeader("Content-Type", "application/json") - .withBody("{ \"result\": \"SUCCESS\" }")) - ); -``` - -JSON: - -```json -{ - "request": { - "urlPath": "/something-async", - "method": "POST" - }, - "response": { - "status": 200 - }, - "serveEventListeners": [ - { - "name": "webhook", - "parameters": { - "method": "POST", - "url": "http://my-target-host/callback", - "headers": { - "Content-Type": "application/json" - }, - "body": "{ \"result\": \"SUCCESS\" }" - } - } - ] -} -``` - -## Using data from the original request - -Webhooks use the same [templating system](../response-templating/) as WireMock responses. This means that any of the -configuration fields can be provided with a template expression which will be resolved before firing the webhook. - -Similarly to response templates the original request data is available, although in this case it is named `originalRequest`. - -Supposing we wanted to pass a transaction ID from the original (triggering) request and insert it into the JSON request -body sent by the webhook call. - -For an original request body JSON like this: - -```json -{ - "transactionId": "12345" -} -``` - -We could construct a JSON request body in the webhook like this: - -Java: - -{% raw %} - -```java -wm.stubFor(post(urlPathEqualTo("/templating")) - .willReturn(ok()) - .withServeEventListener("webhook", webhook() - .withMethod(POST) - .withUrl("http://my-target-host/callback") - .withHeader("Content-Type", "application/json") - .withBody("{ \"message\": \"success\", \"transactionId\": \"{{jsonPath originalRequest.body '$.transactionId'}}\" }") - ); -``` - -{% endraw %} - -JSON: - -{% raw %} - -```json -{ - "request": { - "urlPath": "/templating", - "method": "POST" - }, - "response": { - "status": 200 - }, - "serveEventListeners": [ - { - "name": "webhook", - "parameters": { - "method": "POST", - "url": "http://my-target-host/callback", - "headers": { - "Content-Type": "application/json" - }, - "body": "{ \"message\": \"success\", \"transactionId\": \"{{jsonPath originalRequest.body '$.transactionId'}}\" }" - } - } - ] -} -``` - -{% endraw %} - -> **note** -> -> Webhook templates currently do not support system or environment variables. - -## Implementing a callback using templating - -To implement the callback pattern, where the original request contains the target to be called on completion of a long-running task, -we can use templating on the URL and method. - -Java: - -{% raw %} - -```java -wm.stubFor(post(urlPathEqualTo("/something-async")) - .willReturn(ok()) - .withServeEventListener("webhook", webhook() - .withMethod("{{jsonPath originalRequest.body '$.callbackMethod'}}") - .withUrl("{{jsonPath originalRequest.body '$.callbackUrl'}}")) - ); -``` - -{% endraw %} - -JSON: - -{% raw %} - -```json -{ - "request": { - "urlPath": "/something-async", - "method": "POST" - }, - "response": { - "status": 200 - }, - "serveEventListeners": [ - { - "name": "webhook", - "parameters": { - "method": "{{jsonPath originalRequest.body '$.callbackMethod'}}", - "url": "{{jsonPath originalRequest.body '$.callbackUrl'}}" - } - } - ] -} -``` - -{% endraw %} - -## Adding delays - -A fixed or random delay can be added before the webhook call is made, using the same style of [delay parameters as stubs](../simulating-faults/). - -### Fixed delays - -Java: - -```java -wm.stubFor(post(urlPathEqualTo("/delayed")) - .willReturn(ok()) - .withServeEventListener("webhook", webhook() - .withFixedDelay(1000) - .withMethod(RequestMethod.GET) - .withUrl("http://my-target-host/callback") - ) -); -``` - -JSON: - -```json -{ - "request": { - "urlPath": "/delayed", - "method": "POST" - }, - "response": { - "status": 200 - }, - "serveEventListeners": [ - { - "name": "webhook", - "parameters": { - "method": "GET", - "url": "http://my-target-host/callback", - "delay": { - "type": "fixed", - "milliseconds": 1000 - } - } - } - ] -} -``` - -### Random delays - -Java: - -```java -wm.stubFor(post(urlPathEqualTo("/delayed")) - .willReturn(ok()) - .withServeEventListener("webhook", webhook() - .withDelay(new UniformDistribution(500, 1000)) - .withMethod(RequestMethod.GET) - .withUrl("http://my-target-host/callback") - ) -); -``` - -JSON: - -```json -{ - "request": { - "urlPath": "/delayed", - "method": "POST" - }, - "response": { - "status": 200 - }, - "serveEventListeners": [ - { - "name": "webhook", - "parameters": { - "method": "GET", - "url": "http://my-target-host/callback", - "delay": { - "type": "uniform", - "lower": 500, - "upper": 1000 - } - } - } - ] -} -``` - -## Extending webhooks - -Webhook behaviour can be further customised in code via an extension point. - -This works in a similar fashion to response transformation. The extension class implements the `WebhookTransformer` interface and is then loaded via -the extension mechanism (see [Extending WireMock](https://wiremock.org/docs/extending-wiremock/)). - -```java -public class MyWebhookTransformer implements WebhookTransformer { - - @Override - public WebhookDefinition transform( - ServeEvent serveEvent, - WebhookDefinition webhookDefinition) { - // build and return a new WebhookDefinition with some custom changes - } -} -``` diff --git a/_docs_theme/assets/stylesheets/static.css b/_docs_theme/assets/stylesheets/static.css new file mode 100644 index 00000000..c489d309 --- /dev/null +++ b/_docs_theme/assets/stylesheets/static.css @@ -0,0 +1,3 @@ +body { + background: red; +} \ No newline at end of file diff --git a/_docs_theme/main.html b/_docs_theme/main.html new file mode 100644 index 00000000..0ced57b1 --- /dev/null +++ b/_docs_theme/main.html @@ -0,0 +1,173 @@ +{% extends "base.html" %} + +{% block header %} +
+
+ + +
+
+{% endblock %} + +{% block tabs %} + {% import "partials/tabs-item.html" as item with context %} + + + +{% endblock %} + + diff --git a/_includes/downloads.html b/_docs_theme/partials/downloads.html similarity index 78% rename from _includes/downloads.html rename to _docs_theme/partials/downloads.html index 9c62ac79..629fafc2 100644 --- a/_includes/downloads.html +++ b/_docs_theme/partials/downloads.html @@ -47,23 +47,23 @@
- Maven + Maven
- Gradle + Gradle
- Kotlin + Kotlin
- SBT + SBT
{% if include.show_standalone %}
- Java + Java
- Docker + Docker
{% endif %}
@@ -91,21 +91,21 @@ test {% endhighlight %} -

Then follow the next steps for JUnit 5+ or plain Java.

+

Then follow the next steps for JUnit 5+ or plain Java.

Add the following to your project's build.gradle:

{% highlight groovy %} testImplementation "org.wiremock:wiremock:{{ site.wiremock_version }}" {% endhighlight %} -

Then follow the next steps for JUnit 5+ or plain Java.

+

Then follow the next steps for JUnit 5+ or plain Java.

Add the following to your project's build.gradle.kts:

{% highlight kotlin %} testImplementation("org.wiremock:wiremock:{{ site.wiremock_version }}") {% endhighlight %} -

Then follow the next steps for JUnit 5+ or plain Java.

+

Then follow the next steps for JUnit 5+ or plain Java.

Add the following to your project’s build.sbt:

@@ -122,7 +122,7 @@ {% highlight bash %} java -jar wiremock-standalone-{{ site.wiremock_version }}.jar {% endhighlight %} -

Learn more in the running standalone guide.

+

Learn more in the running standalone guide.

Run the following in a terminal:

@@ -132,7 +132,7 @@ --name wiremock \ wiremock/wiremock:{{ site.wiremock_version }} {% endhighlight %} -

Learn more in the Docker guide.

+

Learn more in the Docker guide.

diff --git a/_docs_theme/partials/header.html b/_docs_theme/partials/header.html new file mode 100644 index 00000000..ff95e301 --- /dev/null +++ b/_docs_theme/partials/header.html @@ -0,0 +1,145 @@ + +
+
+ {% if staticPage is not defined %} + + + + + + + {% endif %} + + + + + + + {% if ("material/search" in config.plugins) and (staticPage is not defined) %} + + + + {% include "partials/search.html" %} + {% endif %} + + {% if staticPage is defined %} + + {% endif %} + +
+ Go to WM Cloud + Free forever. No credit card needed +
+
+ +
+
\ No newline at end of file diff --git a/_docs_theme/standalone.html b/_docs_theme/standalone.html new file mode 100644 index 00000000..7605bcc0 --- /dev/null +++ b/_docs_theme/standalone.html @@ -0,0 +1,49 @@ +{% import "partials/language.html" as lang with context %} + + + + + + + WireMock - flexible, open source API mocking | WireMock + {% for path in config.theme.css %} + + {% endfor %} {% for path in config.extra_css %} + + {% endfor %} + + + + + {% set staticPage = true %} {% include "partials/header.html" %} {% block + content %} +
{{ page.content }}
+ {% endblock %} + + + + {% for path in config.extra_javascript %} + + {% endfor %} + + diff --git a/_docs_theme/static.html b/_docs_theme/static.html new file mode 100644 index 00000000..f62692d2 --- /dev/null +++ b/_docs_theme/static.html @@ -0,0 +1,45 @@ +{% import "partials/language.html" as lang with context %} + + + + + + + WireMock - flexible, open source API mocking | WireMock + {% for path in config.theme.css %} + + {% endfor %} + {% for path in config.extra_css %} + + {% endfor %} + + + + +{% set staticPage = true %} +{% include "partials/header.html" %} + +{% block content %} + {{ page.content }} +{% endblock %} + + + + +{% for path in config.extra_javascript %} + +{% endfor %} + + + diff --git a/_docs_theme/testing.html b/_docs_theme/testing.html new file mode 100644 index 00000000..e379bfe7 --- /dev/null +++ b/_docs_theme/testing.html @@ -0,0 +1,445 @@ + + +{% import "partials/language.html" as lang with context %} + + + + + + + {% block site_meta %} + + + + + {% if page.meta and page.meta.description %} + + {% elif config.site_description %} + + {% endif %} + + + {% if page.meta and page.meta.author %} + + {% elif config.site_author %} + + {% endif %} + + + {% if page.canonical_url %} + + {% endif %} + + + {% if page.previous_page %} + + {% endif %} + + + {% if page.next_page %} + + {% endif %} + + + {% if "rss" in config.plugins %} + + + {% endif %} + + + + + + + {% endblock %} + + + {% block htmltitle %} + {% if page.meta and page.meta.title %} + {{ page.meta.title }} - {{ config.site_name }} + {% elif page.title and not page.is_homepage %} + {{ page.title | striptags }} - {{ config.site_name }} + {% else %} + {{ config.site_name }} + {% endif %} + {% endblock %} + + + {% block styles %} + + + + {% if config.theme.palette %} + {% set palette = config.theme.palette %} + + {% endif %} + + + {% include "partials/icons.html" %} + {% endblock %} + + + {% block libs %} + {% for script in config.extra.polyfills %} + {{ script | script_tag }} + {% endfor %} + {% endblock %} + + + {% block fonts %} + + + {% if config.theme.font != false %} + {% set text = config.theme.font.get("text", "Roboto") %} + {% set code = config.theme.font.get("code", "Roboto Mono") %} + + + + {% endif %} + {% endblock %} + + + {% for path in config.extra_css %} + + {% endfor %} + + + {% include "partials/javascripts/base.html" %} + + + {% block analytics %} + {% include "partials/integrations/analytics.html" %} + {% endblock %} + + + {% if page.meta and page.meta.meta %} + {% for tag in page.meta.meta %} + + {% endfor %} + {% endif %} + + + {% block extrahead %}{% endblock %} + + + +{% set direction = config.theme.direction or lang.t("direction") %} +{% if config.theme.palette %} +{% set palette = config.theme.palette %} +{% if not palette is mapping %} +{% set palette = palette | first %} +{% endif %} +{% set scheme = palette.scheme | d("default", true) %} +{% set primary = palette.primary | d("indigo", true) %} +{% set accent = palette.accent | d("indigo", true) %} + +{% else %} + +{% endif %} +{% set features = config.theme.features or [] %} + + +{% if not config.theme.palette is mapping %} +{% include "partials/javascripts/palette.html" %} +{% endif %} + + + + + + + + + +
+ {% if page.toc | first is defined %} + {% set skip = page.toc | first %} + + {{ lang.t("action.skip") }} + + {% endif %} +
+ + +
+ {% if self.announce() %} + + {% endif %} +
+ + +{% if config.extra.version %} + +{% endif %} + + +{% block header %} +{% include "partials/header.html" %} +{% endblock %} + + +
+ + + {% block hero %}{% endblock %} + + + {% block tabs %} + {% if "navigation.tabs.sticky" not in features %} + {% if "navigation.tabs" in features %} + {% include "partials/tabs.html" %} + {% endif %} + {% endif %} + {% endblock %} + + +
+
+ + + {% block site_nav %} + + + {% if nav %} + {% if page.meta and page.meta.hide %} + {% set hidden = "hidden" if "navigation" in page.meta.hide %} + {% endif %} + + {% endif %} + + + {% if "toc.integrate" not in features %} + {% if page.meta and page.meta.hide %} + {% set hidden = "hidden" if "toc" in page.meta.hide %} + {% endif %} + + {% endif %} + {% endblock %} + + + {% block container %} +
+
+ {% block content %} + {% include "partials/content.html" %} + {% endblock %} +
+
+ {% endblock %} + + + {% include "partials/javascripts/content.html" %} +
+ + + {% if "navigation.top" in features %} + {% include "partials/top.html" %} + {% endif %} +
+ + + {% block footer %} + {% include "partials/footer.html" %} + {% endblock %} +
+ + +
+
+
+ + +{% if "navigation.instant.progress" in features %} +{% include "partials/progress.html" %} +{% endif %} + + +{% if config.extra.consent %} + + + +{% include "partials/javascripts/consent.html" %} +{% endif %} + + +{% block config %} +{%- set app = { +"base": base_url, +"features": features, +"translations": {}, +"search": "assets/javascripts/workers/search.js" | url +} -%} + + +{%- if config.extra.version -%} +{%- set _ = app.update({ "version": config.extra.version }) -%} +{%- endif -%} + + +{%- if config.extra.tags -%} +{%- set _ = app.update({ "tags": config.extra.tags }) -%} +{%- endif -%} + + +{%- set translations = app.translations -%} +{%- for key in [ +"clipboard.copy", +"clipboard.copied", +"search.result.placeholder", +"search.result.none", +"search.result.one", +"search.result.other", +"search.result.more.one", +"search.result.more.other", +"search.result.term.missing", +"select.version" +] -%} +{%- set _ = translations.update({ key: lang.t(key) }) -%} +{%- endfor -%} + + + +{% endblock %} + + +{% block scripts %} + + + +{% for script in config.extra_javascript %} +{{ script | script_tag }} +{% endfor %} +{% endblock %} + + \ No newline at end of file diff --git a/_includes/analytics-providers/clarity.html b/_includes/analytics-providers/clarity.html deleted file mode 100644 index 0a44c59f..00000000 --- a/_includes/analytics-providers/clarity.html +++ /dev/null @@ -1,9 +0,0 @@ -{% if site.analytics.clarity.enabled %} - -{% endif %} diff --git a/_includes/analytics-providers/custom.html b/_includes/analytics-providers/custom.html deleted file mode 100644 index c34b97ad..00000000 --- a/_includes/analytics-providers/custom.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/_includes/analytics-providers/google-universal.html b/_includes/analytics-providers/google-universal.html deleted file mode 100644 index 3ada6e36..00000000 --- a/_includes/analytics-providers/google-universal.html +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/_includes/analytics-providers/google.html b/_includes/analytics-providers/google.html deleted file mode 100644 index 571cb252..00000000 --- a/_includes/analytics-providers/google.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - diff --git a/_includes/analytics-providers/hotjar.html b/_includes/analytics-providers/hotjar.html deleted file mode 100644 index 7846ed02..00000000 --- a/_includes/analytics-providers/hotjar.html +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/_includes/analytics-providers/plausible.html b/_includes/analytics-providers/plausible.html deleted file mode 100644 index 31a0c565..00000000 --- a/_includes/analytics-providers/plausible.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/_includes/analytics-providers/vwo.html b/_includes/analytics-providers/vwo.html deleted file mode 100644 index 64365eba..00000000 --- a/_includes/analytics-providers/vwo.html +++ /dev/null @@ -1,17 +0,0 @@ -{% if site.analytics.vwo.enabled %} - - - -{% endif %} \ No newline at end of file diff --git a/_includes/analytics.html b/_includes/analytics.html deleted file mode 100644 index e6122ff0..00000000 --- a/_includes/analytics.html +++ /dev/null @@ -1,35 +0,0 @@ -{% if site.analytics and page.analytics != false and jekyll.environment == "production" %} - -{% if site.analytics.google %} - {% include /analytics-providers/google.html %} -{% endif %} - -{% if site.analytics.google-universal %} - {% include /analytics-providers/google-universal.html %} -{% endif %} - -{% if site.analytics.hotjar %} - {% include /analytics-providers/hotjar.html %} -{% endif %} - -{% if site.analytics.clarity %} - {% include /analytics-providers/clarity.html %} -{% endif %} - -{% if site.analytics.plausible %} - {% include /analytics-providers/google-universal.html %} -{% endif %} - -{% if site.analytics.custom %} - {% include /analytics-providers/custom.html %} -{% endif %} - -{% if site.analytics.custom %} - {% include /analytics-providers/custom.html %} -{% endif %} - -{% if site.analytics.vwo %} - {% include /analytics-providers/vwo.html %} -{% endif %} - -{% endif %} diff --git a/_includes/anchor-headings.html b/_includes/anchor-headings.html deleted file mode 100644 index ee5c2a64..00000000 --- a/_includes/anchor-headings.html +++ /dev/null @@ -1,174 +0,0 @@ -{% capture headingsWorkspace %} - {% comment %} - Copyright (c) 2018 Vladimir "allejo" Jimenez - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - {% endcomment %} - {% comment %} - Version 1.0.13 - https://github.com/allejo/jekyll-anchor-headings - - "Be the pull request you wish to see in the world." ~Ben Balter - - Usage: - {% include anchor_headings.html html=content anchorBody="#" %} - - Parameters: - * html (string) - the HTML of compiled markdown generated by kramdown in Jekyll - - Optional Parameters: - * beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content - * headerAttrs (string) : '' - Any custom HTML attributes that will be added to the heading tag; you may NOT use `id`; - the `%heading%` and `%html_id%` placeholders are available - * anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `` tag; you may NOT use `href`, `class` or `title`; - the `%heading%` and `%html_id%` placeholders are available - * anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available - * anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space - * anchorTitle (string) : '' - The `title` attribute that will be used for anchors - * h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored - * h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored - * bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content - * bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content - * generateId (true) : false - Set to true if a header without id should generate an id to use. - - Output: - The original HTML with the addition of anchors inside of all of the h1-h6 headings. - {% endcomment %} - - {% assign minHeader = include.h_min | default: 1 %} - {% assign maxHeader = include.h_max | default: 6 %} - {% assign beforeHeading = include.beforeHeading %} - {% assign headerAttrs = include.headerAttrs %} - {% assign nodes = include.html | split: ' - {% if headerLevel == 0 %} - - {% assign firstChunk = node | split: '>' | first %} - - - {% unless firstChunk contains '<' %} - {% capture node %}{% endcapture %} - {% assign _workspace = node | split: _closingTag %} - {% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %} - {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %} - {% assign escaped_header = header | strip_html | strip %} - - {% assign _classWorkspace = _workspace[0] | split: 'class="' %} - {% assign _classWorkspace = _classWorkspace[1] | split: '"' %} - {% assign _html_class = _classWorkspace[0] %} - - {% if _html_class contains "no_anchor" %} - {% assign skip_anchor = true %} - {% else %} - {% assign skip_anchor = false %} - {% endif %} - - {% assign _idWorkspace = _workspace[0] | split: 'id="' %} - {% if _idWorkspace[1] %} - {% assign _idWorkspace = _idWorkspace[1] | split: '"' %} - {% assign html_id = _idWorkspace[0] %} - {% assign h_attrs = headerAttrs %} - {% elsif include.generateId %} - - {% assign html_id = escaped_header | slugify %} - {% if html_id == "" %} - {% assign html_id = false %} - {% endif %} - - {% capture h_attrs %}{{ headerAttrs }} id="%html_id%"{% endcapture %} - {% endif %} - - - {% capture anchor %}{% endcapture %} - - {% if skip_anchor == false and html_id and headerLevel >= minHeader and headerLevel <= maxHeader %} - {% if h_attrs %} - {% capture _hAttrToStrip %}{{ _hAttrToStrip | split: '>' | first }} {{ h_attrs | strip | replace: '%heading%', escaped_header | replace: '%html_id%', html_id }}>{% endcapture %} - {% endif %} - - {% capture anchor %}href="#{{ html_id }}"{% endcapture %} - - {% if include.anchorClass %} - {% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %} - {% endif %} - - {% if include.anchorTitle %} - {% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', escaped_header }}"{% endcapture %} - {% endif %} - - {% if include.anchorAttrs %} - {% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', escaped_header | replace: '%html_id%', html_id }}{% endcapture %} - {% endif %} - - {% capture anchor %}{{ include.anchorBody | replace: '%heading%', escaped_header | default: '' }}{% endcapture %} - - - {% if beforeHeading %} - {% capture anchor %}{{ anchor }} {% endcapture %} - {% else %} - {% capture anchor %} {{ anchor }}{% endcapture %} - {% endif %} - {% endif %} - - {% capture new_heading %} - - {% endcapture %} - - - {% assign chunkCount = _workspace | size %} - {% if chunkCount > 1 %} - {% capture new_heading %}{{ new_heading }}{{ _workspace | last }}{% endcapture %} - {% endif %} - - {% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %} - {% endfor %} -{% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }} diff --git a/_includes/archive-single.html b/_includes/archive-single.html deleted file mode 100644 index 41e07c75..00000000 --- a/_includes/archive-single.html +++ /dev/null @@ -1,43 +0,0 @@ - -{% if post.header.teaser %} - {% capture teaser %}{{ post.header.teaser }}{% endcapture %} -{% else %} - {% capture teaser %}{{ site.teaser }}{% endcapture %} -{% endif %} - - diff --git a/_includes/author-profile.html b/_includes/author-profile.html deleted file mode 100644 index 607dfd18..00000000 --- a/_includes/author-profile.html +++ /dev/null @@ -1,101 +0,0 @@ - -{% if page.author %} - {% assign author = site.data.authors[page.author] %}{% else %}{% assign author = site.author %} -{% endif %} - -
- -
- {% if author.avatar contains "://" %} - {{ author.name }} - {% else %} - {{ author.name }} - {% endif %} -
- -
-

{{ author.name }}

- {% if author.bio %}

{{ author.bio }}

{% endif %} -
- -
- - -
-
diff --git a/_includes/breadcrumbs.html b/_includes/breadcrumbs.html deleted file mode 100644 index 40898f5a..00000000 --- a/_includes/breadcrumbs.html +++ /dev/null @@ -1,40 +0,0 @@ - -{% case site.categories.type %} - {% when "liquid" %} - {% assign path_type = "#" %} - {% when "jekyll-archives" %} - {% assign path_type = nil %} -{% endcase %} - -{% if page.collection != 'posts' %} - {% assign path_type = nil %} - {% assign crumb_path = '/' %} -{% else %} - {% assign crumb_path = site.categories.path %} -{% endif %} - - \ No newline at end of file diff --git a/_includes/browser-upgrade.html b/_includes/browser-upgrade.html deleted file mode 100644 index e8d8b262..00000000 --- a/_includes/browser-upgrade.html +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/_includes/category-list.html b/_includes/category-list.html deleted file mode 100644 index 2f52c3e4..00000000 --- a/_includes/category-list.html +++ /dev/null @@ -1,27 +0,0 @@ - -{% case site.category_archive.type %} - {% when "liquid" %} - {% assign path_type = "#" %} - {% when "jekyll-archives" %} - {% assign path_type = nil %} -{% endcase %} - -{% if site.category_archive.path %} - {% comment %} - - - {% endcomment %} - {% capture page_categories %}{% for category in page.categories %}{{ category | downcase }}#{{ category }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %} - {% assign category_hashes = (page_categories | split: ',' | sort:0) %} - -

- {{ site.data.ui-text[site.locale].categories_label }} - - {% for hash in category_hashes %} - {% assign keyValue = hash | split: '#' %} - {% capture category_word %}{{ keyValue[1] | strip_newlines }}{% endcapture %} - {% unless forloop.last %}, {% endunless %} - {% endfor %} - -

-{% endif %} \ No newline at end of file diff --git a/_includes/comments-providers/custom.html b/_includes/comments-providers/custom.html deleted file mode 100644 index 90993691..00000000 --- a/_includes/comments-providers/custom.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/_includes/comments-providers/discourse.html b/_includes/comments-providers/discourse.html deleted file mode 100644 index a6527569..00000000 --- a/_includes/comments-providers/discourse.html +++ /dev/null @@ -1,14 +0,0 @@ -{% if site.comments.discourse.server %} - -{% capture canonical %}{% if site.permalink contains '.html' %}{{ page.url | absolute_url }}{% else %}{{ page.url | remove:'index.html' | strip_slash | absolute_url }}{% endif %}{% endcapture %} - - -{% endif %} \ No newline at end of file diff --git a/_includes/comments-providers/disqus.html b/_includes/comments-providers/disqus.html deleted file mode 100644 index c6fc691d..00000000 --- a/_includes/comments-providers/disqus.html +++ /dev/null @@ -1,22 +0,0 @@ -{% if site.comments.disqus.shortname %} - - -{% endif %} \ No newline at end of file diff --git a/_includes/comments-providers/facebook.html b/_includes/comments-providers/facebook.html deleted file mode 100644 index 009dc1c6..00000000 --- a/_includes/comments-providers/facebook.html +++ /dev/null @@ -1,8 +0,0 @@ -
- \ No newline at end of file diff --git a/_includes/comments-providers/google-plus.html b/_includes/comments-providers/google-plus.html deleted file mode 100644 index 0b4ff6b7..00000000 --- a/_includes/comments-providers/google-plus.html +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/_includes/comments-providers/scripts.html b/_includes/comments-providers/scripts.html deleted file mode 100644 index 0da90c5d..00000000 --- a/_includes/comments-providers/scripts.html +++ /dev/null @@ -1,16 +0,0 @@ -{% if site.comments.provider and page.comments %} - -{% case site.comments.provider %} -{% when "disqus" %} - {% include /comments-providers/disqus.html %} -{% when "discourse" %} - {% include /comments-providers/discourse.html %} -{% when "facebook" %} - {% include /comments-providers/facebook.html %} -{% when "google-plus" %} - {% include /comments-providers/google-plus.html %} -{% when "custom" %} - {% include /comments-providers/custom.html %} -{% endcase %} - -{% endif %} \ No newline at end of file diff --git a/_includes/comments.html b/_includes/comments.html deleted file mode 100644 index 3c089c99..00000000 --- a/_includes/comments.html +++ /dev/null @@ -1,14 +0,0 @@ - -
-

{{ site.data.ui-text[site.locale].comments_label }}

- {% case site.comments.provider %} - {% when "disqus" %} -
- {% when "facebook" %} -
- {% when "google-plus" %} -
Loading Google+ Comments ...
- {% when "custom" %} -
- {% endcase %} -
\ No newline at end of file diff --git a/_includes/docs-sidebar.html b/_includes/docs-sidebar.html deleted file mode 100644 index d62ae06c..00000000 --- a/_includes/docs-sidebar.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - diff --git a/_includes/feature_row b/_includes/feature_row deleted file mode 100644 index 2087479b..00000000 --- a/_includes/feature_row +++ /dev/null @@ -1,51 +0,0 @@ - -{% if include.id %} - {% assign feature_row = page.[include.id] %} -{% else %} - {% assign feature_row = page.feature_row %} -{% endif %} - -
- - {% for f in feature_row %} - - {% if f.url contains "://" %} - {% capture f_url %}{{ f.url }}{% endcapture %} - {% else %} - {% capture f_url %}{{ f.url | absolute_url}}{% endcapture %} - {% endif %} - -
-
- {% if f.image_path %} -
- {% if f.alt %}{{ f.alt }}{% endif %} -
- {% endif %} - -
- {% if f.title %} -

{{ f.title }}

- {% endif %} - - {% if f.excerpt %} -
- {{ f.excerpt | markdownify }} -
- {% endif %} - - {% if f.url %} -

{{ f.btn_label | default: site.data.ui-text[site.locale].more_label }}

- {% endif %} -
-
-
- {% endfor %} - -
\ No newline at end of file diff --git a/_includes/footer.html b/_includes/footer.html deleted file mode 100644 index dd46a087..00000000 --- a/_includes/footer.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - diff --git a/_includes/footer/custom.html b/_includes/footer/custom.html deleted file mode 100644 index d512599d..00000000 --- a/_includes/footer/custom.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/_includes/gallery b/_includes/gallery deleted file mode 100644 index cc6b9737..00000000 --- a/_includes/gallery +++ /dev/null @@ -1,50 +0,0 @@ - -{% if include.id %} - {% assign gallery = page.[include.id] %} -{% else %} - {% assign gallery = page.gallery %} -{% endif %} - -{% capture gallery_size %}{{ gallery | size }}{% endcapture %} - -{% if gallery_size == '2' %} - {% assign gallery_layout = 'half' %} -{% elsif gallery_size >= '3' %} - {% assign gallery_layout = 'third' %} -{% else %} - {% assign gallery_layout = '' %} -{% endif %} - - \ No newline at end of file diff --git a/_includes/group-by-array b/_includes/group-by-array deleted file mode 100644 index 251302c7..00000000 --- a/_includes/group-by-array +++ /dev/null @@ -1,47 +0,0 @@ - - - -{% assign __empty_array = '' | split: ',' %} -{% assign group_names = __empty_array %} -{% assign group_items = __empty_array %} - - -{% assign __names = include.collection | map: include.field %} - - -{% assign __names = __names | join: ',' | join: ',' | split: ',' %} - - -{% assign __names = __names | sort %} -{% for name in __names | sort %} - - -{% unless name == previous %} - - -{% assign group_names = group_names | push: name %} -{% endunless %} - -{% assign previous = name %} -{% endfor %} - - - -{% for name in group_names %} - - -{% assign __item = __empty_array %} -{% for __element in include.collection %} -{% if __element[include.field] contains name %} -{% assign __item = __item | push: __element %} -{% endif %} -{% endfor %} - - -{% assign group_items = group_items | push: __item %} -{% endfor %} \ No newline at end of file diff --git a/_includes/head.html b/_includes/head.html deleted file mode 100644 index d378e768..00000000 --- a/_includes/head.html +++ /dev/null @@ -1,29 +0,0 @@ - - - -{% include seo.html %} - -{% include analytics.html %} - - - - - - - - - - - - - - - - - - - - - diff --git a/_includes/head/custom.html b/_includes/head/custom.html deleted file mode 100644 index 01767313..00000000 --- a/_includes/head/custom.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/_includes/masthead.html b/_includes/masthead.html deleted file mode 100644 index e49257ec..00000000 --- a/_includes/masthead.html +++ /dev/null @@ -1,109 +0,0 @@ -
-
- - - -
- - Go to WM Cloud - - Free forever. No credit card needed -
- - -
-
- -
    -
  • - - Go to WM Cloud - -
  • - {% for menuItem in site.data.navigation.main %} - {% if menuItem.link contains 'http' %} - {% assign effectiveLink = menuItem.link %} - {% else %} - {% assign effectiveLink = menuItem.link | absolute_url %} - {% endif %} - -
  • - {% if menuItem.link %} - {% if menuItem.new_window %} - - {% else %} - - {% endif %} - {{ menuItem.title }} - - {% else %} - {{ menuItem.title }} - {% endif %} -
  • - {% endfor %} -
-
-
diff --git a/_includes/nav-breadcrumb-icon.svg b/_includes/nav-breadcrumb-icon.svg deleted file mode 100644 index 74012513..00000000 --- a/_includes/nav-breadcrumb-icon.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/_includes/nav-breadcrumbs.html b/_includes/nav-breadcrumbs.html deleted file mode 100644 index 1ed4bee2..00000000 --- a/_includes/nav-breadcrumbs.html +++ /dev/null @@ -1,94 +0,0 @@ - - - \ No newline at end of file diff --git a/_includes/nav_list b/_includes/nav_list deleted file mode 100644 index ce5b12f0..00000000 --- a/_includes/nav_list +++ /dev/null @@ -1,45 +0,0 @@ -{% assign navigation = site.data.navigation[include.nav] %} - - \ No newline at end of file diff --git a/_includes/page__hero.html b/_includes/page__hero.html deleted file mode 100644 index 0fac7e05..00000000 --- a/_includes/page__hero.html +++ /dev/null @@ -1,54 +0,0 @@ - -{% if page.header.image contains "://" %} - {% capture img_path %}{{ page.header.image }}{% endcapture %} -{% else %} - {% capture img_path %}{{ page.header.image | prepend: "/images/" | absolute_url }}{% endcapture %} -{% endif %} - -{% if page.header.cta_url contains "://" %} - {% capture cta_path %}{{ page.header.cta_url }}{% endcapture %} -{% else %} - {% capture cta_path %}{{ page.header.cta_url | absolute_url }}{% endcapture %} -{% endif %} - -{% if page.header.overlay_image contains "://" %} - {% capture overlay_img_path %}{{ page.header.overlay_image }}{% endcapture %} -{% elsif page.header.overlay_image %} - {% capture overlay_img_path %}{{ page.header.overlay_image | prepend: "/images/" | absolute_url }}{% endcapture %} -{% endif %} - -{% if page.header.overlay_filter contains "rgba" %} - {% capture overlay_filter %}{{ page.header.overlay_filter }}{% endcapture %} -{% elsif page.header.overlay_filter %} - {% capture overlay_filter %}rgba(0, 0, 0, {{ page.header.overlay_filter }}){% endcapture %} -{% endif %} - -
- {% if page.header.overlay_color or page.header.overlay_image %} -
-

- {% if paginator %} - {{ site.title }}{% unless paginator.page == 1 %} {{ site.data.ui-text[site.locale].page }} {{ paginator.page }}{% endunless %} - {% else %} - {{ page.title | default: site.title | markdownify | remove: "

" | remove: "

" }} - {% endif %} -

- {% if page.excerpt %} -

{{ page.excerpt | markdownify | remove: "

" | remove: "

" }}

- {% endif %} - {% if site.read_time and page.read_time %} -

{% include read-time.html %}

- {% endif %} - {% if page.header.cta_url %} -

{{ page.header.cta_label | default: site.data.ui-text[site.locale].more_label }}

- {% endif %} -
- {% else %} - {{ page.title }} - {% endif %} - {% if page.header.caption %} - {{ page.header.caption | markdownify | remove: "

" | remove: "

" }}
- {% endif %} -
\ No newline at end of file diff --git a/_includes/page__taxonomy.html b/_includes/page__taxonomy.html deleted file mode 100644 index 90bdd311..00000000 --- a/_includes/page__taxonomy.html +++ /dev/null @@ -1,8 +0,0 @@ - -{% if site.tag_archive.type and page.tags[0] %} - {% include tag-list.html %} -{% endif %} - -{% if site.category_archive.type and page.categories[0] %} - {% include category-list.html %} -{% endif %} \ No newline at end of file diff --git a/_includes/paginator.html b/_includes/paginator.html deleted file mode 100644 index 0b87ec35..00000000 --- a/_includes/paginator.html +++ /dev/null @@ -1,73 +0,0 @@ - -{% if paginator.total_pages > 1 %} -{% assign blog_base_path = '/blog' | absolute_url %} - - - - -{% endif %} diff --git a/_includes/post_pagination.html b/_includes/post_pagination.html deleted file mode 100644 index c34541af..00000000 --- a/_includes/post_pagination.html +++ /dev/null @@ -1,15 +0,0 @@ - -{% if page.previous or page.next %} - -{% endif %} \ No newline at end of file diff --git a/_includes/read-time.html b/_includes/read-time.html deleted file mode 100644 index 605dc0bc..00000000 --- a/_includes/read-time.html +++ /dev/null @@ -1,17 +0,0 @@ -{% if post.read_time %} - {% assign words = post.content | strip_html | number_of_words %} -{% elsif page.read_time %} - {% assign words = page.content | strip_html | number_of_words %} -{% endif %} - -{% if site.words_per_minute %} - {% if words < 180 %} - {{ site.data.ui-text[site.locale].less_than }} 1 {{ site.data.ui-text[site.locale].minute_read }} - {% elsif words < 360 %} - 1 {{ site.data.ui-text[site.locale].minute_read }} - {% else %} - {{ words | divided_by:site.words_per_minute }} {{ site.data.ui-text[site.locale].minute_read }} - {% endif %} -{% else %} - {{ site.data.ui-text[site.locale].undefined_wpm }} -{% endif %} \ No newline at end of file diff --git a/_includes/scripts.html b/_includes/scripts.html deleted file mode 100644 index 9058db79..00000000 --- a/_includes/scripts.html +++ /dev/null @@ -1,3 +0,0 @@ - - -{% include /comments-providers/scripts.html %} diff --git a/_includes/seo.html b/_includes/seo.html deleted file mode 100644 index 85148348..00000000 --- a/_includes/seo.html +++ /dev/null @@ -1,156 +0,0 @@ - - -{% if site.url %} - {% assign seo_url = site.url | append: site.baseurl %} -{% endif %} -{% assign seo_url = seo_url | default: site.github.url %} - - - -{% if page.meta_title %} - {% assign seo_title = page.meta_title %} -{% else if page.title %} - {% assign seo_title = page.title | append: " " | append: site.title_separator | append: " " | append: site.title %} -{% endif %} - -{% if seo_title %} - {% assign seo_title = seo_title | strip_html | strip_newlines | escape_once %} -{% endif %} - -{% if site.url %} - {% assign canonical_url = page.url | replace: "index.html", "" | prepend: site.url %} -{% endif %} - -{{ seo_title | default: site.title }}{% if paginator %}{% unless paginator.page == 1 %} {{ site.title_separator }} {{ site.data.ui-text[site.locale].page }} {{ paginator.page }}{% endunless %}{% endif %} - -{% assign seo_description = page.description | default: page.excerpt | default: site.description %} -{% if seo_description %} - {% assign seo_description = seo_description | markdownify | strip_html | strip_newlines | escape_once %} -{% endif %} - -{% assign seo_author = page.author | default: page.author[0] | default: site.author[0] %} -{% if seo_author %} - {% if seo_author.twitter %} - {% assign seo_author_twitter = seo_author.twitter %} - {% else %} - {% if site.data.authors and site.data.authors[seo_author] %} - {% assign seo_author_twitter = site.data.authors[seo_author].twitter %} - {% else %} - {% assign seo_author_twitter = seo_author %} - {% endif %} - {% endif %} - {% assign seo_author_twitter = seo_author_twitter | replace: "@", "" %} -{% endif %} - - - - - - - - - - - -{% if seo_url %} - - -{% endif %} - -{% if page.description %} - -{% endif %} - -{% if site.twitter.username %} - - - - - - {% if page.og_image %} - - - {% elsif page.header.image %} - - - {% else %} - - {% if site.og_image %} - - {% endif %} - {% endif %} - - {% if seo_author_twitter %} - - {% endif %} -{% endif %} - -{% if site.facebook %} - {% if site.facebook.publisher %} - - {% endif %} - - {% if site.facebook.app_id %} - - {% endif %} -{% endif %} - -{% if page.og_image %} - -{% elsif page.header.image %} - -{% elsif page.header.overlay_image %} - -{% elsif site.og_image %} - -{% endif %} - -{% if page.date %} - - - {% if page.next.url %} - - {% endif %} - {% if page.previous.url %} - - {% endif %} -{% endif %} - -{% if site.og_image %} - -{% endif %} - -{% if site.social %} - -{% endif %} - -{% if site.google_site_verification %} - -{% endif %} -{% if site.bing_site_verification %} - -{% endif %} -{% if site.alexa_site_verification %} - -{% endif %} -{% if site.yandex_site_verification %} - -{% endif %} - diff --git a/_includes/sidebar.html b/_includes/sidebar.html deleted file mode 100644 index 368d8566..00000000 --- a/_includes/sidebar.html +++ /dev/null @@ -1,25 +0,0 @@ - - -{% if page.author_profile or layout.author_profile or page.sidebar %} - -{% endif %} \ No newline at end of file diff --git a/_includes/social-link-items.html b/_includes/social-link-items.html deleted file mode 100644 index 89ea6904..00000000 --- a/_includes/social-link-items.html +++ /dev/null @@ -1,5 +0,0 @@ -
  • - - - -
  • diff --git a/_includes/social-share.html b/_includes/social-share.html deleted file mode 100644 index a9306b28..00000000 --- a/_includes/social-share.html +++ /dev/null @@ -1,14 +0,0 @@ - - \ No newline at end of file diff --git a/_includes/studio-docs-sidebar.html b/_includes/studio-docs-sidebar.html deleted file mode 100644 index 5dee5ae9..00000000 --- a/_includes/studio-docs-sidebar.html +++ /dev/null @@ -1,29 +0,0 @@ - - diff --git a/_includes/tag-list.html b/_includes/tag-list.html deleted file mode 100644 index 7b733074..00000000 --- a/_includes/tag-list.html +++ /dev/null @@ -1,27 +0,0 @@ - -{% case site.tag_archive.type %} - {% when "liquid" %} - {% assign path_type = "#" %} - {% when "jekyll-archives" %} - {% assign path_type = nil %} -{% endcase %} - -{% if site.tag_archive.path %} - {% comment %} - - - {% endcomment %} - {% capture page_tags %}{% for tag in page.tags %}{{ tag | downcase }}#{{ tag }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %} - {% assign tag_hashes = (page_tags | split: ',' | sort:0) %} - -

    - {{ site.data.ui-text[site.locale].tags_label }} - - {% for hash in tag_hashes %} - {% assign keyValue = hash | split: '#' %} - {% capture tag_word %}{{ keyValue[1] | strip_newlines }}{% endcapture %} - {% unless forloop.last %}, {% endunless %} - {% endfor %} - -

    -{% endif %} \ No newline at end of file diff --git a/_includes/toc b/_includes/toc deleted file mode 100644 index 6ba831c9..00000000 --- a/_includes/toc +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/_layouts/archive-taxonomy.html b/_layouts/archive-taxonomy.html deleted file mode 100644 index 6939122d..00000000 --- a/_layouts/archive-taxonomy.html +++ /dev/null @@ -1,15 +0,0 @@ ---- -layout: default -author_profile: false ---- - -
    - {% include sidebar.html %} - -
    -

    {{ page.title }}

    - {% for post in page.posts %} - {% include archive-single.html %} - {% endfor %} -
    -
    \ No newline at end of file diff --git a/_layouts/archive.html b/_layouts/archive.html deleted file mode 100644 index 22f984c7..00000000 --- a/_layouts/archive.html +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: default ---- - -{% if (page.header.overlay_color or page.header.overlay_image) or page.header.image %} - {% include page__hero.html %} -{% endif %} - -{% if page.url != "/" and site.breadcrumbs %} - {% unless paginator %} - {% include breadcrumbs.html %} - {% endunless %} -{% endif %} - -
    - {% include sidebar.html %} - -
    - {% unless page.header.overlay_color or page.header.overlay_image %} -

    {{ page.title }}

    - {% endunless %} - {{ content }} -
    -
    \ No newline at end of file diff --git a/_layouts/compress.html b/_layouts/compress.html deleted file mode 100644 index 8248010b..00000000 --- a/_layouts/compress.html +++ /dev/null @@ -1,10 +0,0 @@ ---- -# Jekyll layout that compresses HTML -# v3.0.2 -# http://jch.penibelst.de/ -# © 2014–2015 Anatol Broder -# MIT License ---- - -{% capture _LINE_FEED %} -{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd p rt rp optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "" %}{% endif %}{% unless _pre_before contains "" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " ;; ;" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %}
    Step Bytes
    raw {{ content | size }}{% if _profile_endings %}
    endings {{ _profile_endings }}{% endif %}{% if _profile_startings %}
    startings {{ _profile_startings }}{% endif %}{% if _profile_comments %}
    comments {{ _profile_comments }}{% endif %}{% if _profile_collapse %}
    collapse {{ _profile_collapse }}{% endif %}{% if _profile_clippings %}
    clippings {{ _profile_clippings }}{% endif %}
    {% endif %}{% endif %} diff --git a/_layouts/default.html b/_layouts/default.html deleted file mode 100644 index e26b977d..00000000 --- a/_layouts/default.html +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: compress ---- - - - - - {% include head.html %} - {% include head/custom.html %} - - - - {% include browser-upgrade.html %} - {% include masthead.html %} - - {{ content }} - - - - - - {% include scripts.html %} - - - diff --git a/_layouts/docs.html b/_layouts/docs.html deleted file mode 100644 index b533a4d8..00000000 --- a/_layouts/docs.html +++ /dev/null @@ -1,186 +0,0 @@ ---- -layout: default ---- - -
    - - {% if page.collection == 'studio_docs' %} - {% include studio-docs-sidebar.html %} - {% else %} - {% include docs-sidebar.html %} - {% endif %} - - - -
    - {% if page.seo_title %}{% endif %} - {% if page.excerpt %}{% endif %} - {% if page.date %}{% endif %} - {% if page.modified %}{% endif %} - - - - - -
    -
    - {% if page.title %}

    {{ page.title | markdownify | remove: "

    " | remove: "

    " }}

    {% endif %} -
    - - {% if site.wiremock_baseline == site.data.baselines.current.id %} - {% if site.data.baselines.preview.id %} -
    - This document is for the WireMock {{ site.data.baselines.current.id }} baseline. - See the documentation for WireMock {{ site.data.baselines.preview.id }} preview - here -
    - {% endif %} - {% else %} - {% if site.wiremock_baseline == site.data.baselines.preview.id %} -
    - WARNING: - This document is for WireMock {{ site.data.baselines.preview.id }} preview. - See the documentation for the current WireMock {{ site.data.baselines.current.id }} baseline - here. - If you are interested to know more what is planned for WireMock {{ site.data.baselines.preview.id }}, - see - this page. -
    - {% else %} -
    - WARNING: - This document is for an old WireMock {{ site.wiremock_baseline }} baseline. - See the documentation for the current WireMock {{ site.data.baselines.current.id }} baseline - here -
    - {% endif %} - {% endif %} - -
    - - {% include anchor-headings.html html=content anchorBody="#" anchorClass="anchor" %} - {% if page.link %}{% endif %} -
    - - - - {% if page.share %}{% include social-share.html %}{% endif %} -
    - - {% if site.comments.provider and page.comments %} - {% include comments.html %} - {% endif %} -
    - - {% comment %}{% endcomment %} - {% if page.id and page.related and site.related_posts.size > 0 %} - - {% endif %} -
    diff --git a/_layouts/single.html b/_layouts/single.html deleted file mode 100644 index 9037ac97..00000000 --- a/_layouts/single.html +++ /dev/null @@ -1,74 +0,0 @@ ---- -layout: default ---- - -{% if (page.header.overlay_color or page.header.overlay_image) or page.header.image %} - {% include page__hero.html %} -{% endif %} - -{% if page.url != "/" and site.breadcrumbs %} - {% unless paginator %} - {% include breadcrumbs.html %} - {% endunless %} -{% endif %} - -
    - {% include sidebar.html %} - -
    - {% if page.title %}{% endif %} - {% if page.excerpt %}{% endif %} - {% if page.date %}{% endif %} - {% if page.modified %}{% endif %} - -
    - {% unless page.header.overlay_color or page.header.overlay_image %} -
    - {% if page.title %}

    {{ page.title | markdownify | remove: "

    " | remove: "

    " }}

    {% endif %} - {% if page.read_time %} -

    {% include read-time.html %}

    - {% endif %} -
    - {% endunless %} - -
    - {{ content }} - {% if page.link %}{% endif %} -
    - -
    - {% if site.data.ui-text[site.locale].meta_label %} -

    {{ site.data.ui-text[site.locale].meta_label }}

    - {% endif %} - {% include page__taxonomy.html %} - {% if page.modified %} -

    {{ site.data.ui-text[site.locale].date_label }}

    - {% elsif page.date %} -

    {{ site.data.ui-text[site.locale].date_label }}

    - {% endif %} -
    - - {% if page.share %}{% include social-share.html %}{% endif %} - - {% include post_pagination.html %} -
    - - {% if site.comments.provider and page.comments %} - {% include comments.html %} - {% endif %} -
    - - {% comment %}{% endcomment %} - {% if page.id and page.related and site.related_posts.size > 0 %} - - {% endif %} -
    \ No newline at end of file diff --git a/_layouts/solution.html b/_layouts/solution.html deleted file mode 100644 index 39bd4899..00000000 --- a/_layouts/solution.html +++ /dev/null @@ -1,72 +0,0 @@ ---- -layout: docs ---- - - - -{% if page.logo %} -
    -
    - - - -
    -
    -{% endif %} - -{% if page.coming-soon %} -
    -

    - Work in Progress: - This solution page will be published soon. - If you are interested to contribute a patch based on - WireMock Ecosystem, - please submit a pull request! -

    -
    -{% else %} - {% if page.hide-disclaimer %} - - {% else %} -
    -

    - Disclaimer: - This solution page includes resources maintained - by their authors outside the WireMock organization on GitHub. - The info is provided as is without guarantees unless explicitly specified. - Referenced projects and guidelines - might be incompatible with the recent WireMock {{ site.data.baselines.current.id }} releases - or the recent versions of the target technology or framework. -

    -

    - Please use with caution, and submit GitHub issues or pull requests to this page and referenced repositories - if something is missing, broken or needs update. -

    -
    - {% endif %} -{% endif %} - -{{ content }} diff --git a/_layouts/splash.html b/_layouts/splash.html deleted file mode 100644 index 8168a730..00000000 --- a/_layouts/splash.html +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: default ---- - -{% if (page.header.overlay_color or page.header.overlay_image) or page.header.image %} - {% include page__hero.html %} -{% endif %} - -
    -
    - {% if page.title %}{% endif %} - {% if page.excerpt %}{% endif %} - {% if page.date %}{% endif %} - {% if page.modified %}{% endif %} - -
    - {{ content }} -
    -
    -
    \ No newline at end of file diff --git a/_layouts/support.html b/_layouts/support.html deleted file mode 100644 index 1c734e33..00000000 --- a/_layouts/support.html +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: default ---- - -{% if (page.header.overlay_color or page.header.overlay_image) or page.header.image %} - {% include page__hero.html %} -{% endif %} - -
    -
    - {% if page.title %}{% endif %} - {% if page.excerpt %}{% endif %} - {% if page.date %}{% endif %} - {% if page.modified %}{% endif %} - -
    - {{ content }} -
    -
    -
    \ No newline at end of file diff --git a/_pages/404.md b/_pages/404.md deleted file mode 100644 index b273202b..00000000 --- a/_pages/404.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "Page Not Found" -layout: single -excerpt: "Page not found. Your pixels are in another canvas." -sitemap: false -permalink: /404.html ---- - -Sorry, but the page you were trying to view does not exist --- perhaps you can try searching for it below. - - - diff --git a/_plugins/breadcrumbs.rb b/_plugins/breadcrumbs.rb deleted file mode 100644 index 1c70bea5..00000000 --- a/_plugins/breadcrumbs.rb +++ /dev/null @@ -1,82 +0,0 @@ -require_relative 'drops/breadcrumb_item.rb' - -module Jekyll - module Breadcrumbs - @@config = {} - @@siteAddress = "" - @@sideAddresses = {} - - def self.clearAddressCache - @@sideAddresses = {} - end - - def self.loadAddressCache(site) - clearAddressCache - site.documents.each { |page| addAddressItem(page.url, page['crumbtitle'] || page['title'] || '') } # collection files including posts - site.pages.each { |page| addAddressItem(page.url, page['crumbtitle'] || page['title'] || '') } # pages - site.posts.docs.each { |page| addAddressItem(page.url, page['crumbtitle'] || page['title'] || '') } # posts - end - - def self.addAddressItem(url, title) - key = createAddressCacheKey(url) - @@sideAddresses[key] = {:url => url, :title => title} - end - - def self.findAddressItem(path) - key = createAddressCacheKey(path) - @@sideAddresses[key] if key - end - - def self.createAddressCacheKey(path) - path.chomp("/").empty? ? "/" : path.chomp("/") - end - - def self.buildSideBreadcrumbs(side, payload) - payload["breadcrumbs"] = [] - return if side.url == @@siteAddress && root_hide === true - - drop = Jekyll::Drops::BreadcrumbItem - position = 0 - - path = side.url.chomp("/").split(/(?=\/)/) - -1.upto(path.size - 1) do |int| - joined_path = int == -1 ? "" : path[0..int].join - item = findAddressItem(joined_path) - if item - position += 1 - item[:position] = position - item[:root_image] = root_image - payload["breadcrumbs"] << drop.new(item) - end - end - end - - # Config - def self.loadConfig(site) - config = site.config["breadcrumbs"] || {"root" => {"hide" => false, "image" => false}} - root = config["root"] - @@config[:root_hide] = root["hide"] || false - @@config[:root_image] = root["image"] || false - - @@siteAddress = site.config["baseurl"] || "/" - @@siteAddress = "/" if @@siteAddress.empty? - end - - def self.root_hide - @@config[:root_hide] - end - - def self.root_image - @@config[:root_image] - end - end -end - -Jekyll::Hooks.register :site, :pre_render do |site, payload| - Jekyll::Breadcrumbs::loadConfig(site) - Jekyll::Breadcrumbs::loadAddressCache(site) -end - -Jekyll::Hooks.register [:pages, :documents], :pre_render do |side, payload| - Jekyll::Breadcrumbs::buildSideBreadcrumbs(side, payload) -end diff --git a/_plugins/drops/breadcrumb_item.rb b/_plugins/drops/breadcrumb_item.rb deleted file mode 100644 index 8e3b2cf8..00000000 --- a/_plugins/drops/breadcrumb_item.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Jekyll - module Drops - class BreadcrumbItem < Liquid::Drop - extend Forwardable - - def initialize(side) - @side = side - end - - def position - @side[:position] - end - - def title - @side[:title] - end - - def url - @side[:url] - end - - def rootimage - @side[:root_image] - end - - end - end - end - \ No newline at end of file diff --git a/_plugins/jekyll-code-tabs.rb b/_plugins/jekyll-code-tabs.rb deleted file mode 100644 index 6b36d369..00000000 --- a/_plugins/jekyll-code-tabs.rb +++ /dev/null @@ -1 +0,0 @@ -require_relative "../lib/jekyll-code-tabs" diff --git a/_sass/_animations.scss b/_sass/_animations.scss deleted file mode 100644 index a975d021..00000000 --- a/_sass/_animations.scss +++ /dev/null @@ -1,12 +0,0 @@ -/* ========================================================================== - ANIMATIONS - ========================================================================== */ - -@keyframes intro { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} \ No newline at end of file diff --git a/_sass/_archive.scss b/_sass/_archive.scss deleted file mode 100644 index fae3b415..00000000 --- a/_sass/_archive.scss +++ /dev/null @@ -1,243 +0,0 @@ -/* ========================================================================== - ARCHIVE - ========================================================================== */ - -.archive { - margin-bottom: 2em; - - @include breakpoint($medium) { - @include span(12 of 12); - } - - @include breakpoint($large) { - @include span(10 of 12 last); - @include prefix(0.5 of 12); - } - - a { - color: inherit; - text-decoration: none; - } -} - -.archive__subtitle { - margin: 1.414em 0 0; - padding-bottom: 0.5em; - font-size: $type-size-5; - color: mix(#fff, $gray, 25%); - border-bottom: 1px solid $border-color; - - + .list__item .archive__item-title { - margin-top: 0.5em; - } -} - -.archive__item-title { - margin-bottom: 0.75em; - font-family: $sans-serif-narrow; -} - -.archive__item { - - .page__date { - margin-top: 40px; - margin-bottom: -40px; - font-size: $type-size-6; - } -} - -// remove border -.page__content { - - .archive__item-title { - margin-top: 1em; - border-bottom: none; - } -} - -.archive__item-excerpt { - margin-top: 0; - font-size: $type-size-6; - - & + p { - text-indent: 0; - } -} - -.archive__item-teaser { - border-radius: $border-radius; - overflow: hidden; - img { - width: 100%; - } -} - -a:hover { - .archive__item-teaser { - box-shadow: 0 0 10px rgba(#000, 0.25); - } - - .archive__item-title { - text-decoration: underline; - } -} - - -/* - List view - ========================================================================== */ - -.list__item { - @include breakpoint($medium) { - padding-right: $right-sidebar-width-narrow; - } - - @include breakpoint($large) { - padding-right: $right-sidebar-width; - } - - @include breakpoint($x-large) { - padding-right: $right-sidebar-width-wide; - } - - .page__meta { - margin: 0 0 4px; - } -} - - -/* - Grid view - ========================================================================== */ - -.grid__item { - margin-bottom: 2em; - - .page__meta { - margin: 0 0 4px; - } - - .archive__item-title { - margin-top: 0.5em; - font-size: $type-size-5; - } - - .archive__item-excerpt { - display: none; - } - - @include breakpoint($small) { - @include gallery(5 of 10); - .archive__item-teaser { - max-height: 200px; - } - } - - @include breakpoint($medium) { - margin-left: 0; // reset before mixin does its thing - margin-right: 0; // reset before mixin does its thing - @include gallery(2.5 of 10); - - .archive__item-teaser { - max-height: 120px; - } - - .archive__item-excerpt { - display: block; - font-size: $type-size-6; - } - } -} - - -/* - Features - ========================================================================== */ - -.feature__wrapper { - @include clearfix(); - margin-bottom: 2em; - border-bottom: 1px solid $border-color; -} - -.feature__item { - margin-bottom: 2em; - font-size: 1.25rem; - - @include breakpoint($small) { - margin-bottom: 0; - @include gallery(4 of 12); - - .feature__item-teaser { - max-height: 200px; - overflow: hidden; - } - } - - &--left { - @include full(); - font-size: 1.25rem; - - .archive__item-teaser { - margin-bottom: 2em; - } - - @include breakpoint($small) { - .archive__item-teaser { - @include span(5 of 12); - } - - .archive__item-body { - @include span(7 of 12 last); - @include prefix(0.5 of 12); - @include suffix(1 of 12); - } - } - } - - &--right { - @include full(); - font-size: 1.25rem; - - .archive__item-teaser { - margin-bottom: 2em; - } - - @include breakpoint($small) { - text-align: right; - - .archive__item-teaser { - @include span(5 of 12 rtl); - } - - .archive__item-body { - @include span(7 of 12 last rtl); - @include prefix(0.5 of 12); - @include suffix(1 of 12); - } - } - } - - &--center { - @include full(); - font-size: 1.25rem; - - .archive__item-teaser { - margin-bottom: 2em; - } - - @include breakpoint($small) { - text-align: center; - - .archive__item-teaser { - margin: 0 auto; - width: span(5 of 12); - } - - .archive__item-body { - margin: 0 auto; - width: span(7 of 12); - } - } - } -} diff --git a/_sass/_base.scss b/_sass/_base.scss deleted file mode 100644 index 1b859867..00000000 --- a/_sass/_base.scss +++ /dev/null @@ -1,365 +0,0 @@ -/* ========================================================================== - BASE ELEMENTS - ========================================================================== */ - -@font-face { - font-family: "DMSans"; - src: url("/assets/fonts/DMSans-Regular.ttf") format("truetype"); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: "DMSans"; - src: url("/assets/fonts/DMSans-Medium.ttf") format("truetype"); - font-weight: 500; - font-style: normal; -} - -body { - margin: 0; - padding: 0; - color: $text-color; - font-family: $global-font-family; - line-height: 1.5; - - &.overflow--hidden { - /* when primary navigation is visible, the content in the background won't scroll */ - overflow: hidden; - } -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0 0 $p-m 0; - line-height: 1.2; - font-family: $header-font-family; - font-weight: bold; -} - -h1 { - margin-top: 0; - font-size: $type-size-3; -} - -h2 { - font-size: $type-size-4; -} - -h3 { - font-size: $type-size-5; -} - -h4 { - font-size: $type-size-6; -} - -h5 { - font-size: $type-size-6; -} - -h6 { - font-size: $type-size-6; -} - -small, -.small { - font-size: $type-size-6; -} - -p { - margin: 0 0 $p-m; -} - -u, -ins { - text-decoration: none; - border-bottom: 1px solid $text-color; - a { - color: inherit; - } -} - -del a { - color: inherit; -} - -/* reduce orphans and widows when printing */ - -p, -pre, -blockquote, -ul, -ol, -dl, -figure, -table, -fieldset { - orphans: 3; - widows: 3; -} - -/* abbreviations */ - -abbr[title], -abbr[data-original-title] { - text-decoration: none; - cursor: help; - border-bottom: 1px dotted $text-color; -} - -/* blockquotes */ - -blockquote { - margin: 2em 1em 2em 0; - padding-left: 1em; - padding-right: 1em; - font-style: italic; - border-left: 0.25em solid $primary-color; - - cite { - font-style: italic; - - &:before { - content: "\2014"; - padding-right: 5px; - } - } -} - -/* links */ - -// a { -// color: #0f0f0f; -// text-decoration: none; -// -// &:focus { -// @extend %tab-focus; -// } -// -// &:hover, -// &:active { -// outline: 0; -// } -// -// &:hover { -// color: #3f3f3f; -// } -// } - -/* code */ - -tt, -code, -kbd, -samp, -pre { - font-family: $monospace; - text-wrap: balance; - overflow-wrap: anywhere; -} - -pre { - padding: $p-l; - overflow-x: auto; // add scrollbars to wide code blocks -} - -p > code, -a > code, -li > code, -figcaption > code, -td > code { - padding-top: 0.1rem; - padding-bottom: 0.1rem; - font-size: $type-size-6; - background: $code-background-color; - border: 1px solid $lighter-gray; - border-radius: $border-radius; - box-shadow: $box-shadow; - - &:before, - &:after { - letter-spacing: -0.2em; - content: "\00a0"; // non-breaking space - } -} - -/* horizontal rule */ - -hr { - display: block; - margin: 1em 0; - border: 0; - border-top: 1px solid $border-color; -} - -/* lists */ - -ul li, -ol li { - margin-bottom: 0.5em; -} - -li ul, -li ol { - margin-top: 0.5em; -} - -/* - Media and embeds - ========================================================================== */ - -/* Figures and images */ - -figure { - display: flex; - justify-content: space-between; - align-items: flex-start; - flex-wrap: wrap; - margin: 2em 0; - - img, - iframe, - .fluid-width-video-wrapper { - margin-bottom: 1em; - } - - img { - width: 100%; - border-radius: $border-radius; - transition: $global-transition; - } - - > a { - display: block; - } - - &.half { - > a, - > img { - @include breakpoint($small) { - width: calc(50% - 0.5em); - } - } - - figcaption { - width: 100%; - } - } - - &.third { - > a, - > img { - @include breakpoint($small) { - width: calc(33.3333% - 0.5em); - } - } - - figcaption { - width: 100%; - } - } -} - -/* Figure captions */ - -figcaption { - margin-bottom: 0.5em; - color: mix(#fff, $text-color, 25%); - font-family: $caption-font-family; - font-size: $type-size-6; - - a { - color: inherit; - text-decoration: none; - border-bottom: 1px solid $light-gray; - transition: $global-transition; - - &:hover { - color: #000; - border-bottom-color: #000; - } - } -} - -/* Fix IE9 SVG bug */ - -svg:not(:root) { - overflow: hidden; -} - -/* - Navigation lists - ========================================================================== */ - -/** - * Removes margins, padding, and bullet points from navigation lists - * - * Example usage: - * - */ - -nav { - ul { - margin: 0; - padding: 0; - } - - li { - list-style: none; - } - - a { - text-decoration: none; - } - - /* override white-space for nested lists */ - ul li, - ol li { - margin-bottom: 0; - } - - li ul, - li ol { - margin-top: 0; - } -} - -/* - Global animation transition - ========================================================================== */ - -b, -i, -strong, -em, -blockquote, -p, -q, -span, -figure, -img, -h1, -h2, -header, -input, -a, -tr, -td, -form button, -input[type="submit"], -.btn, -.highlight, -.archive__item-teaser { - transition: $global-transition; -} diff --git a/_sass/_buttons.scss b/_sass/_buttons.scss deleted file mode 100644 index c0118d09..00000000 --- a/_sass/_buttons.scss +++ /dev/null @@ -1,151 +0,0 @@ -/* ========================================================================== - BUTTONS - ========================================================================== */ - -/* - Default button - ========================================================================== */ - -.btn { - /* default button */ - display: block; - margin-bottom: 0.25em; - padding: $p-m $p-l; - color: #fff !important; - font-family: $sans-serif; - font-size: var(--font-size, $type-size-6); - font-weight: bold; - text-align: center; - text-decoration: none; - background-color: $dark-blue; - border: 0 !important; - border-radius: $border-radius; - cursor: pointer; - - &:hover { - transform: scale(1.05); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.24); - } - - @include breakpoint($medium) { - display: inline-block; - } - - .icon { - margin-right: 0.5em; - } - - .icon + .hidden { - margin-left: -0.5em; // override for hidden text - } - - /* fills width of parent container */ - - &--block { - display: block; - width: 100%; - - + .btn--block { - margin-top: 0.25em; - } - } - - /* for dark backgrounds */ - - &--inverse { - color: $text-color !important; - border: 1px solid $light-gray !important; // override - background-color: #fff; - } - - /* light outline */ - - &--light-outline { - border: 1px solid #fff !important; // override - background-color: transparent; - } - - /* information */ - - &--info { - background-color: $info-color; - - &:hover { - background-color: mix(#000, $info-color, 20%); - } - } - - /* warning */ - - &--warning { - background-color: $warning-color; - - &:hover { - background-color: mix(#000, $warning-color, 20%); - } - } - - /* success */ - - &--success { - background-color: $success-color; - - &:hover { - background-color: mix(#000, $success-color, 20%); - } - } - - /* danger */ - - &--danger { - background-color: $danger-color; - - &:hover { - background-color: mix(#000, $danger-color, 20%); - } - } - - /* disabled */ - - &--disabled { - pointer-events: none; - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: 0.65; - } - - /* social buttons */ - - $social: (facebook, $facebook-color), (twitter, $twitter-color), - (google-plus, $google-plus-color), (linkedin, $linkedin-color); - - @each $socialnetwork, $color in $social { - &--#{$socialnetwork} { - background-color: $color; - - &:hover { - background-color: mix(#000, $color, 20%); - } - } - } - - /* extra large button */ - - &--x-large { - font-size: $type-size-4; - } - - /* large button */ - - &--large { - font-size: $type-size-5; - } - - /* small button */ - - &--small { - font-size: $type-size-7; - } -} diff --git a/_sass/_code.scss b/_sass/_code.scss deleted file mode 100644 index aca87434..00000000 --- a/_sass/_code.scss +++ /dev/null @@ -1,34 +0,0 @@ -.codeTabDescription { - margin: 0px; - padding: 0px; - font-family: "Ubuntu"; - font-style: normal; - font-weight: normal; - font-size: 16px; - color: #000; -} - -.code-tabs-main-example .highlight { - background: #f0f5ff; - border: 1px solid #d2dff9; - box-sizing: border-box; - border-radius: 0; -} - -.code-tabs-main-example pre { - text-align: left; -} - -.codeSnippet { - display: none; - width: 100%; - position: relative; - - @include breakpoint($medium) { - padding: $p-l; - } - - &.activeCodeSnippet { - display: block; - } -} diff --git a/_sass/_footer.scss b/_sass/_footer.scss deleted file mode 100644 index ea568bac..00000000 --- a/_sass/_footer.scss +++ /dev/null @@ -1,78 +0,0 @@ -/* ========================================================================== - FOOTER - ========================================================================== */ - -@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&family=Open+Sans:wght@300;400;500;600;700;800&family=Roboto:wght@400;500;700&display=swap"); -@font-face { - font-family: SF_Pro; - src: url(../fonts/SF_Pro.ttf); -} - -.page__footer { - @include full(); - @include clearfix; - - color: $dark-milk; - animation: intro 0.3s both; - animation-delay: 0.45s; - background-color: #f8f7f9; - - footer { - @include container; - @include clearfix; - margin-top: 2em; - padding: 0 1em 2em; - - @include breakpoint($x-large) { - max-width: $x-large; - } - } - - a { - color: inherit; - text-decoration: none; - - &:hover { - text-decoration: underline; - } - } - - .fa { - color: mix(#fff, $gray, 25%); - } -} - -.page__footer-copyright { - display: flex; - flex-direction: column; - align-items: center; - - .short-logo { - width: 114px; - height: 39px; - } - - .footer-copyright-description { - margin-top: 0.8rem; - font-size: 14px; - font-family: "Ubuntu"; - font-style: normal; - font-weight: 400; - } - - .footer-social-links { - display: flex; - align-items: center; - list-style: none; - margin: 1.2rem 0 0 0; - padding: 0; - - li { - margin: 0 0 0 15px !important; - - &:first-child { - margin-left: 0 !important; - } - } - } -} diff --git a/_sass/_forms.scss b/_sass/_forms.scss deleted file mode 100644 index d84d1030..00000000 --- a/_sass/_forms.scss +++ /dev/null @@ -1,350 +0,0 @@ -/* ========================================================================== - Forms - ========================================================================== */ - -btnform { - margin: 0 0 5px 0; - - fieldset { - margin-bottom: 5px; - padding: 0; - border-width: 0; - } - - legend { - display: block; - width: 100%; - margin-bottom: 5px * 2; - *margin-left: -7px; - padding: 0; - color: $text-color; - border: 0; - border-bottom: 1px solid mix(#fff, #000, 80%); - white-space: normal; - } - - p { - margin-bottom: 5px / 2; - } - - ul { - list-style-type: none; - margin: 0 0 5px 0; - padding: 0; - } - - br { - display: none; - } -} - -label, -input, -button, -select, -textarea { - vertical-align: baseline; - *vertical-align: middle; -} - -input, -button, -select, -textarea { - font-family: $sans-serif; - box-sizing: border-box; -} - -label { - display: block; - margin-bottom: 10px / 8; - font-weight: bold; - color: $text-color; - cursor: pointer; - - input, - textarea, - select { - display: block; - } -} - -input, -textarea, -select { - display: inline-block; - width: 100%; - padding: 4px; - margin-bottom: 5px / 4; - background-color: #fff; - border: 1px solid mix(#fff, #000, 80%); - color: $text-color; - - &:hover { - border-color: mix(#fff, $primary-color, 50%); - } -} - -.input-mini { - width: 60px; -} - -.input-small { - width: 90px; -} - -input[type="image"], -input[type="checkbox"], -input[type="radio"] { - width: auto; - height: auto; - padding: 0; - margin: 3px 0; - *margin-top: 0; - line-height: normal; - cursor: pointer; - border-radius: 0; - border: 0 \9; -} - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; - padding: 0; - *width: 13px; - *height: 13px; -} - -input[type="image"] { - border: 0; - box-shadow: none; -} - -input[type="file"] { - width: auto; - padding: initial; - line-height: initial; - border: initial; - background-color: transparent; - background-color: initial; - box-shadow: none; -} - -input[type="button"], -input[type="reset"], -input[type="submit"] { - width: auto; - height: auto; - cursor: pointer; - *overflow: visible; -} - -select, -input[type="file"] { - *margin-top: 4px; -} - -select { - width: auto; - background-color: #fff; -} - -select[multiple], -select[size] { - height: auto; -} - -textarea { - resize: vertical; - height: auto; - overflow: auto; - vertical-align: top; -} - -input[type="hidden"] { - display: none; -} - -.radio, -.checkbox { - padding-left: 18px; - font-weight: normal; -} - -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -18px; -} - -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} - -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} - - -/* - Disabled state - ========================================================================== */ - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - opacity: 0.5; - cursor: not-allowed; -} - - -/* - Focus & active state - ========================================================================== */ - -input:focus, -textarea:focus { - border-color: $primary-color; - outline: 0; - outline: thin dotted \9; -} - -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus, -select:focus { - box-shadow: none; -} - - -/* - Help text - ========================================================================== */ - -.help-block, -.help-inline { - color: $info-color; -} - -.help-block { - display: block; - margin-bottom: 1em; - line-height: 1em; -} - -.help-inline { - display: inline-block; - vertical-align: middle; - padding-left: 5px; -} - - -/* - .form-inline - ========================================================================== */ - -.form-inline input, -.form-inline textarea, -.form-inline select { - display: inline-block; - margin-bottom: 0; -} - -.form-inline label { - display: inline-block; -} - -.form-inline .radio, -.form-inline .checkbox, -.form-inline .radio { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-left: 0; - margin-right: 3px; } - - -/* - .form-search - ========================================================================== */ - -.form-search input, -.form-search textarea, -.form-search select { - display: inline-block; - margin-bottom: 0; -} - -.form-search .search-query { - padding-left: 14px; - padding-right: 14px; - margin-bottom: 0; - border-radius: 14px; -} - -.form-search label { - display: inline-block; -} - -.form-search .radio, -.form-search .checkbox, -.form-inline .radio { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"] { - float: left; - margin-left: 0; - margin-right: 3px; -} - - -/* - Google search form - ========================================================================== */ - -#goog-fixurl { - ul { - list-style: none; - margin-left: 0; - padding-left: 0; - li { - list-style-type: none; - } - } -} - -#goog-wm-qt { - width: auto; - margin-right: 10px; - margin-bottom: 20px; - padding: 8px 20px; - display: inline-block; - font-size: $type-size-6; - background-color: #fff; - color: #000; - border-width: 2px !important; - border-style: solid !important; - border-color: lighten(#000,50); - border-radius: $border-radius; -} - -#goog-wm-sb { - @extend .btn; -} \ No newline at end of file diff --git a/_sass/_masthead.scss b/_sass/_masthead.scss deleted file mode 100644 index 4c87615f..00000000 --- a/_sass/_masthead.scss +++ /dev/null @@ -1,392 +0,0 @@ -/* ========================================================================== - MASTHEAD - ========================================================================== */ - -.masthead { - background-color: #fff; - position: relative; - animation: intro 0.3s both; - animation-delay: 0.15s; - z-index: 20; - max-width: 1280px; - margin: 0 auto; - display: grid; - padding: $p-m 0; - grid-template-columns: 254px 1fr auto; - font-size: 16px; - line-height: 24px; - align-items: center; - font-family: "DMSans"; - - @include breakpoint($medium) { - padding: $p-xl 0; - } -} - -.masthead__nav { - display: grid; - - ul { - display: flex; - gap: 24px; - justify-self: center; - } - - .divSubNav a { - display: block; - } -} - -.masthead__logo { - margin-left: 12px; -} - -.masthead__cta { - text-align: center; - display: none; - - @include breakpoint($large) { - display: block; - } - - &-note { - display: block; - font-size: 12px; - color: black; - font-weight: 500; - } -} - -.masthead__menu { - display: flex; - align-items: center; - justify-content: flex-start; - @media (max-width: 1023px) { - justify-content: space-between; - } - - ul { - margin-left: auto; - margin-right: 8em; - padding: 0; - clear: both; - list-style-type: none; - } -} - -.masthead__menu-item { - display: inline-block; - list-style-type: none; - white-space: nowrap; - padding-left: 20px; - - &--lg { - padding-right: 2em; - } -} - -.social-links { - display: flex; - align-items: center; - - li { - margin: 0 0 0 20px; - &:first-child { - margin-left: 0; - } - } - .separator-line-nav { - margin: 0 20px; - } -} - -.schedule-demo-nav, -.schedule-demo-mobile-nav { - cursor: pointer; - background: #f0f5ff; - border: 1px solid rgba(15, 178, 239, 0.5); - border-radius: 4px; - padding: 3px 10px; - color: #0fb2ef; - font-family: "Ubuntu"; - font-style: normal; - font-weight: 700; - font-size: 16px; -} - -schedule-demo-nav-mobile { - margin-bottom: 10px; -} - -.hamburgerMenuIcon { - justify-self: flex-end; - margin-right: 12px; - padding: 0; - background: none; - border: none; - display: none; - - img { - width: 100%; - } -} - -.mobile-menu-wrapper { - display: none; - - a:not(.btn) { - display: block; - padding: $p-m 0; - font-size: $type-size-4; - color: $text-color; - text-decoration: none; - } -} - -.overlay-menu { - display: none; -} - -@media (max-width: 1023px) { - #site-nav, - .social-links { - display: none; - } - - .hamburgerMenuIcon { - display: block; - width: 24px; - height: 24px; - align-self: flex-start; - } - - .closeMenuIcon { - position: absolute; - right: 16px; - top: 16px; - width: 18px; - } - - .mobile-menu-wrapper { - display: block; - background-color: #fff; - position: fixed; - right: -50vw; - top: 0; - height: 100%; - width: 50vw; - border-top-left-radius: 10px; - border-bottom-left-radius: 10px; - z-index: 100; - -webkit-transition: right 0.2s linear; - -moz-transition: right 0.2s linear; - -o-transition: right 0.2s linear; - transition: right 0.2s linear; - padding: 38px 24px; - - &__cta { - display: block; - margin-bottom: 4px; - padding: 14px 24px; - margin-left: auto; - background: #2d69f6; - color: white; - border-radius: 4px; - background-color: #2d69f6; - text-decoration: none; - text-align: center; - - &:hover { - color: #fafafa; - } - } - - ul { - margin: 0; - padding: 0; - list-style: none; - } - - &.active-menu { - display: block; - right: 0; - width: 80vw; - } - } - .overlay-menu { - &.active-overlay { - display: block; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 50; - background-color: rgba(7, 0, 71, 0.5); - } - } - .mobile-social-links { - display: flex; - justify-content: flex-end; - - li { - margin-left: 10px; - &:first-child { - margin-left: 0; - } - } - } -} - -.navlink { - position: relative !important; - padding-bottom: 0; - cursor: pointer; - - &:hover { - & > a { - color: $link-color; - } - } - - a { - padding: 0 !important; - margin: 0 0 5px 0; - width: fit-content !important; - height: 32px; - font-weight: 500; - color: $text-color; - } -} - -.navlink-image { - width: 20px; - filter: invert(47%); - vertical-align: middle; -} - -.divSubNav { - position: relative; - cursor: default; - display: none; - position: absolute; - content: ""; - left: 0; - top: 20px; - width: fit-content; - padding-top: 12px; -} - -.divSubNav__inner { - position: relative; - padding: 10px 15px; - background: #ffffff; - box-shadow: 0px -5px 20px rgba(210, 223, 249, 0.5); - border-radius: 4px; - - &:before { - position: absolute; - content: ""; - left: 15px; - width: 0; - height: 0; - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-bottom: 7px solid #fff; - top: -7px; - } -} - -.divSubNav a { - padding: 0 !important; - margin: 0 0 5px 0; - width: fit-content !important; - - &:hover { - color: $link-color; - } -} - -.divSubNav a:last-child { - margin-bottom: 0; -} - -.divSubNav a::before { - background: none !important; -} - -.navlink:hover > .divSubNav { - display: block; -} - -.navHover::before { - background: unset !important; -} - -.navlink::before { - background: unset !important; -} - -.navlink a::before { - background: unset !important; -} - -.wiremock-cloud-logo-navbar-item { - padding-left: 20px; - padding-top: 0; -} - -.wiremock-cloud-logo-navbar-item div span { - text-align: right; -} - -.wiremock-cloud-logo-navbar { - margin: 0; - background: unset !important; -} - -.wiremock-cloud-logo-navbar div { - border-color: #0fb2ef; - background-color: #e4f0f7; - border-style: solid; - border-radius: 8px; - border-width: 4px; - align-items: center; - justify-content: center; - margin: 0; - height: 45px; - position: relative; -} - -.wiremock-cloud-logo-navbar div img { - vertical-align: middle; - width: 100%; - background-color: #e4f0f7; - height: 36px; - padding: 4px; - padding-left: 12px; - padding-right: 12px; -} - -.wiremock-cloud-logo-navbar div div { - font-size: x-small; - font-weight: bold; - position: absolute; - bottom: 2px; - left: 4px; - border-style: none; - height: fit-content; -} - -.wiremock-cloud-logo-note { - margin-left: auto; - margin-right: 4em; - float: right; - font-size: small; -} - -@media (max-width: 1023px) { - .wiremock-cloud-logo-note { - display: none; - } -} diff --git a/_sass/_mixins.scss b/_sass/_mixins.scss deleted file mode 100644 index 67967e41..00000000 --- a/_sass/_mixins.scss +++ /dev/null @@ -1,52 +0,0 @@ -/* ========================================================================== - MIXINS - ========================================================================== */ - -@use "sass:math"; - -%tab-focus { - // Default - outline: thin dotted $warning-color; - // Webkit - outline: 5px auto $warning-color; - outline-offset: -2px; -} - -/* - em function - ========================================================================== */ - -@function em($target, $context: $doc-font-size) { - @return math.div($target, $context) * 1em; -} - - -/* - Bourbon clearfix - ========================================================================== */ - -// Provides an easy way to include a clearfix for containing floats. -// -// @link http://cssmojo.com/latest_new_clearfix_so_far/ -// -// @example scss - Usage -// .element { -// @include clearfix; -// } -// -// @example css - CSS Output -// .element::after { -// clear: both; -// content: ""; -// display: table; -// } - -@mixin clearfix { - clear: both; - - &::after { - clear: both; - content: ""; - display: table; - } -} \ No newline at end of file diff --git a/_sass/_mocklab-popup.scss b/_sass/_mocklab-popup.scss deleted file mode 100644 index f9af5ddc..00000000 --- a/_sass/_mocklab-popup.scss +++ /dev/null @@ -1,106 +0,0 @@ -.mocklab-popup { - width: 400px !important; - maxwidth: 800px !important; - - @include breakpoint($small) { - width: 600px !important; - } - - .ui-dialog-titlebar { - background: none !important; - border: 0 !important; - } -} - -.mocklab-popup__title { - margin-top: 0; -} - -.mocklab-popup__confirm-button { - border: 1px solid #ffaf0f !important; - background: #ff9800 url("/images/ui-bg_inset-soft_30_FF9800_1x100.png") 50% - 50% repeat-x !important; - - .ui-button-text { - font-weight: bold; - } -} - -.mocklab-callout { - padding: 0.5rem; - padding-left: 70px; - margin-top: 1rem !important; - margin-bottom: 2rem !important; - background-color: #f9fcf5; - border: 1px solid #666; - border-radius: 4px; - background-image: url("/images/mocklab_logo_transparent.png"); - background-size: 46px 46px; - background-repeat: no-repeat; - background-position: 2% 50%; - display: flex; - flex-wrap: nowrap; - justify-content: space-between; - - &__text { - margin: 0 !important; - padding-left: 0.5rem; - padding-right: 0.5rem; - } - - &__learn-more-button { - border: none !important; - border-radius: 5px; - background-color: #036334; - color: white; - padding: 0.5rem; - outline: none; - min-width: 6rem; - max-height: 2.5rem; - margin-top: auto; - margin-bottom: auto; - - &:active, - &:visited, - &:hover { - color: white; - text-decoration: none; - } - } -} - -.mocklab-cta { - border: 3px solid $mocklab-dark-green !important; - border-radius: 5px; - color: white; - text-align: center; - padding: 0.2rem; - outline: none; - min-width: 6rem; - max-height: 2.5rem; - margin-top: auto; - margin-bottom: auto; - margin-right: 15px; - - &:active, - &:visited, - &:hover { - color: white; - text-decoration: none; - } - - &--primary { - background-color: $mocklab-dark-green; - } - - &--secondary { - color: $mocklab-dark-green; - background-color: transparent; - - &:active, - &:visited, - &:hover { - color: $mocklab-dark-green; - } - } -} diff --git a/_sass/_navigation.scss b/_sass/_navigation.scss deleted file mode 100644 index 6323562c..00000000 --- a/_sass/_navigation.scss +++ /dev/null @@ -1,448 +0,0 @@ -/* ========================================================================== - NAVIGATION - ========================================================================== */ - -/* - Breadcrumb navigation links - ========================================================================== */ - -.breadcrumbs { - @include container; - @include clearfix; - margin-top: 0; - margin-bottom: 0; - padding-right: 2em; - font-family: $sans-serif; - animation: intro 0.3s both; - animation-delay: 0.3s; - - @include breakpoint($large) { - padding-right: 1em; - } - - @include breakpoint($x-large) { - max-width: $x-large; - } - - ol { - padding: 0; - list-style: none; - font-size: $type-size-6; - - @include breakpoint($large) { - @include span(10 of 12 last); - float: left; - padding-left: 0; - } - - @include breakpoint($x-large) { - @include prefix(0.5 of 12); - float: left; - padding-left: 0; - } - } - - li { - display: inline; - } - - li a { - display: inline; - color: inherit; - } - - .current { - font-weight: bold; - } -} - -/* - Post pagination navigation links - ========================================================================== */ - -.pagination { - @include full(); - @include clearfix(); - margin-top: 1em; - padding-top: 1em; - - ul { - margin: 0; - padding: 0; - list-style-type: none; - font-family: $sans-serif; - } - - li { - display: block; - float: left; - margin-left: -1px; - - a { - margin-bottom: 0.25em; - padding: 0.5em 1em; - font-family: $sans-serif; - font-size: 14px; - font-weight: bold; - line-height: 1.5; - text-align: center; - text-decoration: none; - color: mix(#fff, $gray, 25%); - border: 1px solid $light-gray; - border-radius: 0; - - &:hover { - color: $link-color-hover; - } - - &.current { - color: #fff; - background: $primary-color; - } - - &.disabled { - color: $light-gray; - pointer-events: none; - cursor: not-allowed; - } - } - - &:first-child { - margin-left: 0; - - a { - border-top-left-radius: $border-radius; - border-bottom-left-radius: $border-radius; - } - } - - &:last-child { - a { - border-top-right-radius: $border-radius; - border-bottom-right-radius: $border-radius; - } - } - } - - /* next/previous buttons */ - &--pager { - display: block; - padding: 1em 2em; - float: left; - width: 50%; - font-family: $sans-serif; - font-size: $type-size-5; - font-weight: bold; - text-align: center; - text-decoration: none; - color: mix(#fff, $gray, 25%); - border: 1px solid $light-gray; - border-radius: $border-radius; - - &:hover { - color: $link-color-hover; - } - - &:first-child { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - - &:last-child { - margin-left: -1px; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - - &.disabled { - color: $light-gray; - pointer-events: none; - cursor: not-allowed; - } - } -} - -.page__content + .pagination, -.page__meta + .pagination, -.page__share + .pagination, -.page__comments + .pagination { - margin-top: 2em; - padding-top: 2em; - border-top: 1px solid $border-color; -} - -/* - Priority plus navigation - ========================================================================== */ - -.greedy-nav { - position: relative; - min-width: 250px; - margin-left: auto; - margin-right: 0; - text-align: center; - align-items: center; - display: flex; - justify-items: center; - margin-top: 0.8%; - a { - display: block; - margin: 0; - padding: 0 0; - color: $head-nav-links; - text-decoration: none; - - &:hover { - color: $masthead-link-color-hover; - } - } - - button { - position: absolute; - height: 100%; - right: 0; - padding: 0 0.5rem; - border: 0; - outline: none; - background-color: $primary-color; - color: #fff; - cursor: pointer; - } - - .visible-links { - margin-left: auto; - margin-right: 2em; - display: table; - - li { - display: table-cell; - vertical-align: top; - padding-top: 10px; - - &:first-child { - font-weight: bold; - - a { - margin-left: 0; - } - } - - &:last-child { - a { - margin-right: 0; - } - } - } - - li:last-child { - float: right; - padding-top: 1px; - padding-bottom: 2px; - } - - a { - position: relative; - - &:before { - content: ""; - position: absolute; - left: 0; - bottom: 0; - height: 4px; - background: mix(#fff, $primary-color, 50%); - width: 100%; - transition: $global-transition; - transform: scaleX(0); // hide - } - - &:hover:before { - transform: scaleX(1); // reveal - } - } - } - - .hidden-links { - position: absolute; - top: 100%; - right: 0; - margin-top: 15px; - padding: 5px; - border: 1px solid $border-color; - border-radius: $border-radius; - background: #fff; - box-shadow: 0 0 10px rgba(#000, 0.25); - - a { - margin: 0; - padding: 10px 20px; - font-size: $type-size-5; - - &:hover { - color: $masthead-link-color-hover; - background: mix(#fff, $primary-color, 75%); - } - } - - &:before { - content: ""; - position: absolute; - top: -11px; - right: 10px; - width: 0; - border-style: solid; - border-width: 0 10px 10px; - border-color: $border-color transparent; - display: block; - z-index: 0; - } - - &:after { - content: ""; - position: absolute; - top: -10px; - right: 10px; - width: 0; - border-style: solid; - border-width: 0 10px 10px; - border-color: #fff transparent; - display: block; - z-index: 1; - } - - li { - display: block; - border-bottom: 1px solid $border-color; - - &:last-child { - border-bottom: none; - } - } - } -} - -/* - Navigation list - ========================================================================== */ - -.nav__list { - padding-top: 10px; - font-size: 1.25rem; - - ul { - margin-bottom: 1em; - } - - a { - display: block; - padding: 0.125em 0; - // color: $info-color; - - &:hover { - text-decoration: underline; - } - } - - .active { - margin-left: -0.5em; - padding-left: 0.5em; - padding-right: 0.5em; - color: #fff; - font-weight: bold; - background: $primary-color; - border-radius: $border-radius; - - &:hover { - color: #fff; - } - } -} - -.nav__list-item--selected { - font-weight: bold; - color: $light-blue; -} - -.nav__title { - margin: 0; - padding: 0.5rem 1rem; - font-family: $sans-serif-narrow; - font-size: $type-size-5; - font-weight: bold; -} - -.nav__sub-title { - display: block; - margin: 0.5rem 0; - padding: 0.5rem 0; - font-family: $sans-serif-narrow; - font-size: $type-size-6; - font-weight: bold; - text-transform: uppercase; - border-bottom: 1px solid $border-color; -} - -/* - Table of contents navigation - ========================================================================== */ - -.toc { - font-family: $sans-serif-narrow; - color: $gray; - text-transform: uppercase; - letter-spacing: 1px; - background-color: #fff; - border: 1px solid $border-color; - border-radius: $border-radius; - box-shadow: $box-shadow; - - .nav__title { - color: #fff; - font-size: $type-size-6; - background: $primary-color; - border-top-left-radius: $border-radius; - border-top-right-radius: $border-radius; - } -} - -.toc__menu { - margin: 0; - padding: 0; - width: 100%; - list-style: none; - font-size: 0.8rem; - - a { - display: block; - padding: 0.5rem 1rem; - color: $gray; - font-size: $type-size-7; - font-weight: bold; - line-height: 1.5; - border-bottom: 1px solid $border-color; - - &:hover { - color: #000; - background: $lighter-gray; - } - } - - > li:last-child { - a { - border-bottom: none; - } - } - - li ul > li a { - padding-left: 2rem; - font-weight: normal; - } - - // hide sub sub links on small screens - li > ul li { - display: none; - - @include breakpoint($medium) { - display: block; - } - } -} diff --git a/_sass/_notices.scss b/_sass/_notices.scss deleted file mode 100644 index ec7dd256..00000000 --- a/_sass/_notices.scss +++ /dev/null @@ -1,99 +0,0 @@ -/* ========================================================================== - NOTICE TEXT BLOCKS - ========================================================================== */ - -/** - * Default Kramdown usage (no indents!): - *
    - * #### Headline for the Notice - * Text for the notice - *
    - */ - -@mixin notice($notice-color) { - margin: 2em 0 !important; // override - padding: 1em; - font-family: $global-font-family; - font-size: $type-size-6 !important; - text-indent: initial; // override - background-color: mix(#fff, $notice-color, 90%); - border-radius: $border-radius; - box-shadow: 0 1px 1px rgba($notice-color, 0.25); - - h4 { - margin-top: 0 !important; // override - margin-bottom: 0.75em; - } - - @at-root .page__content #{&} h4 { - // using at-root to override .page-content h4 font size - margin-bottom: 0; - font-size: 1em; - } - - p { - &:last-child { - margin-bottom: 0 !important; // override - } - } - - h4 + p { - // remove space above paragraphs that appear directly after notice headline - margin-top: 0; - padding-top: 0; - } - - a { - color: $notice-color; - - &:hover { - color: mix(#000, $notice-color, 40%); - } - } - - code { - background-color: mix(#fff, $notice-color, 95%) - } - - ul { - &:last-child { - margin-bottom: 0; // override - } - } -} - -/* Default notice */ - -.notice { - @include notice($light-gray); -} - -/* Primary notice */ - -.notice--primary { - @include notice($primary-color); -} - -/* Info notice */ - -.notice--info { - @include notice($info-color); -} - -/* Warning notice */ - -.notice--warning { - @include notice($warning-color); -} - -/* Success notice */ - -.notice--success { - @include notice($success-color); -} - -/* Danger notice */ - -.notice--danger { - @include notice($danger-color); -} \ No newline at end of file diff --git a/_sass/_notify.scss b/_sass/_notify.scss deleted file mode 100644 index 8996b074..00000000 --- a/_sass/_notify.scss +++ /dev/null @@ -1,18 +0,0 @@ -.notifyjs-corner { - position: absolute !important; - top: 0; - margin: 0 !important; - right: 0; - - .notifyjs-wrapper, - .notifyjs-container { - margin: 0 !important; - } - - .notifyjs-wiremock_notification_with_link-info { - border: none !important; - border-radius: 0 !important; - background-image: none !important; - text-align: center; - } -} diff --git a/_sass/_page.scss b/_sass/_page.scss deleted file mode 100644 index 8ac250ef..00000000 --- a/_sass/_page.scss +++ /dev/null @@ -1,351 +0,0 @@ -/* ========================================================================== - SINGLE PAGE/POST - ========================================================================== */ - -#main { - @include container; - @include clearfix; - margin-top: 2em; - padding-left: 1em; - padding-right: 1em; - animation: intro 0.3s both; - animation-delay: 0.35s; - - @include breakpoint($x-large) { - max-width: $x-large; - } - - @include breakpoint($x2-large) { - max-width: $x2-large; - } -} - -.custom-doc-wrapper { - height: 100vh; -} - -.page { - @include breakpoint($large) { - @include span(10 of 12 last); - @include prefix(0.5 of 12); - @include suffix(2 of 12); - } - - .page__inner-wrap { - @include full(); - - .page__content, - .page__meta, - .page__share { - @include full(); - } - } -} - -.page-wide { - @extend .page; - @include suffix(0 of 12); -} - -.page__title { - margin-top: 0; - line-height: 1; - color: #0fb2ef; - - & + .page__meta { - margin-top: -0.5em; - } -} - -.page__lead { - font-family: $global-font-family; - font-size: $type-size-4; -} - -.page__content { - h2 { - padding-bottom: 0.5em; - border-bottom: 1px solid $border-color; - color: #0fb2ef; - } - - p, - li, - dl { - font-size: 1em; - } - - /* paragraph indents */ - p { - margin: 0 0 $indent-var; - - // sibling indentation - @if $paragraph-indent == true { - & + p { - text-indent: $indent-var; - margin-top: -($indent-var); - } - } - } - - a { - text-decoration: none; - - &:hover { - text-decoration: underline; - } - } - - dt { - margin-top: 1em; - font-family: $sans-serif; - font-weight: bold; - } - - dd { - margin-left: 1em; - font-family: $sans-serif; - font-size: $type-size-6; - } - - .small { - font-size: $type-size-6; - } - - /* blockquote citations */ - blockquote + .small { - margin-top: -1.5em; - padding-left: 1.25rem; - } - - [class^="language-"] { - margin-bottom: $p-l; - } -} - -.page__hero { - position: relative; - margin-bottom: 2em; - @include clearfix; - animation: intro 0.3s both; - animation-delay: 0.25s; - - &--overlay { - position: relative; - margin-bottom: 2em; - padding: 3em 0; - @include clearfix; - background-size: cover; - background-repeat: no-repeat; - background-position: center; - animation: intro 0.3s both; - animation-delay: 0.25s; - - a { - color: #fff; - } - - .wrapper { - padding-left: 1em; - padding-right: 1em; - - @include breakpoint($x-large) { - max-width: $x-large; - } - - @include breakpoint($x2-large) { - max-width: $x2-large; - } - } - - .page__title, - .page__meta, - .page__lead, - .btn { - color: $very-light-blue; - text-shadow: 1px 1px 4px rgba(#000, 0.5); - } - - .page__lead { - max-width: $large; - } - - .page__title { - font-size: $type-size-2; - - @include breakpoint($small) { - font-size: $type-size-1; - } - } - } -} - -.page__hero-image { - width: 100%; - height: auto; - -ms-interpolation-mode: bicubic; -} - -.page__hero-caption { - position: absolute; - bottom: 0; - right: 0; - margin: 0 auto; - padding: 2px 5px; - color: #fff; - font-family: $caption-font-family; - font-size: $type-size-7; - background: #000; - text-align: right; - z-index: 5; - opacity: 0.5; - border-radius: $border-radius 0 $border-radius 0; - - @include breakpoint($large) { - padding: 5px 10px; - } - - a { - color: #fff; - text-decoration: none; - } -} - -/* - Social sharing - ========================================================================== */ - -.page__share { - margin-top: 2em; - padding-top: 1em; - border-top: 1px solid $border-color; - - @include breakpoint(max-width $small) { - .btn span { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - } - } -} - -.page__share-title { - margin-bottom: 10px; - font-size: $type-size-6; - text-transform: uppercase; -} - -/* - Page meta - ========================================================================== */ - -.page__meta { - margin-top: 2em; - margin-bottom: $p-l; - color: mix(#fff, $gray, 25%); - font-family: $sans-serif; - font-size: $type-size-6; - - p { - margin: 0; - } - - a { - color: inherit; - } -} - -.page__meta-title { - font-size: small; - text-transform: uppercase; - padding-bottom: 20px; - - &:not(:first-child) { - padding-left: 20px; - } -} - -/* - Page taxonomy - ========================================================================== */ - -.page__taxonomy { - .sep { - display: none; - } - - strong { - margin-right: 10px; - } -} - -.page__taxonomy-item { - display: inline-block; - margin-right: 5px; - margin-bottom: 8px; - padding: 5px 10px; - text-decoration: none; - border: 1px solid $light-gray; - border-radius: $border-radius; - - &:hover { - text-decoration: none; - color: $link-color-hover; - } -} - -/* - Comments - ========================================================================== */ - -.page__comments { - @include full(); -} - -.page__comments-title { - margin-top: 2rem; - margin-bottom: 10px; - padding-top: 2rem; - font-size: $type-size-6; - border-top: 1px solid $border-color; - text-transform: uppercase; -} - -/* - Related - ========================================================================== */ - -.page__related { - margin-top: 2em; - padding-top: 1em; - border-top: 1px solid $border-color; - @include clearfix(); - float: left; - - @include breakpoint($large) { - @include pre(2.5 of 12); - } - - a { - color: inherit; - text-decoration: none; - } -} - -.page__related-title { - margin-bottom: 10px; - font-size: $type-size-6; - text-transform: uppercase; -} - -.boxed-image { - border: solid 1px $lighter-gray; - padding: 0.5rem; - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} diff --git a/_sass/_print.scss b/_sass/_print.scss deleted file mode 100644 index 09bdb1d8..00000000 --- a/_sass/_print.scss +++ /dev/null @@ -1,18 +0,0 @@ -/* ========================================================================== - PRINT STYLES - ========================================================================== */ - -/* - Hide the following elements on print - ========================================================================== */ - -@media print { - .masthead, - .toc, - .page__share, - .page__related, - .ads, - .page__footer { - display: none; - } -} diff --git a/_sass/_reset.scss b/_sass/_reset.scss deleted file mode 100644 index 6fe5780c..00000000 --- a/_sass/_reset.scss +++ /dev/null @@ -1,174 +0,0 @@ -/* ========================================================================== - STYLE RESETS - ========================================================================== */ - -@include border-box-sizing; - -html { - /* apply a natural box layout model to all elements */ - box-sizing: border-box; - background-color: $background-color; - font-size: 16px; - - @include breakpoint($medium) { - font-size: 18px; - } - - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -/* Remove margin */ - -body { margin: 0; } - -/* Selected elements */ - -::selection { - color: #fff; - background: #000; -} - -/* Display HTML5 elements in IE6-9 and FF3 */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section { - display: block; -} - -/* Display block in IE6-9 and FF3 */ - -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} - -/* Prevents modern browsers from displaying 'audio' without controls */ - -audio:not([controls]) { - display: none; -} - -a { - color: $link-color; -} - -/* Apply focus state */ - -a:focus { - @extend %tab-focus; -} - -/* Remove outline from links */ - -a:hover, -a:active { - outline: 0; -} - -/* Prevent sub and sup affecting line-height in all browsers */ - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* img border in anchor's and image quality */ - -img { - /* Responsive images (ensure images don't scale beyond their parents) */ - max-width: 100%; // part 1: Set a maximum relative to the parent - width: auto\9; // IE7-8 need help adjusting responsive images - height: auto; // part 2: Scale the height according to the width, otherwise you get stretching - - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} - -/* Prevent max-width from affecting Google Maps */ - -#map_canvas img, -.google-maps img { - max-width: none; -} - -/* Consistent form font size in all browsers, margin changes, misc */ - -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} - -button, -input { - *overflow: visible; // inner spacing ie IE6/7 - line-height: normal; // FF3/4 have !important on line-height in UA stylesheet -} - -button::-moz-focus-inner, -input::-moz-focus-inner { // inner padding and border oddities in FF3/4 - padding: 0; - border: 0; -} - -button, -html input[type="button"], // avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; // corrects inability to style clickable `input` types in iOS - cursor: pointer; // improves usability and consistency of cursor style between image-type `input` and others -} - -label, -select, -button, -input[type="button"], -input[type="reset"], -input[type="submit"], -input[type="radio"], -input[type="checkbox"] { - cursor: pointer; // improves usability and consistency of cursor style between image-type `input` and others -} - -input[type="search"] { // Appearance in Safari/Chrome - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; // inner-padding issues in Chrome OSX, Safari 5 -} - -textarea { - overflow: auto; // remove vertical scrollbar in IE6-9 - vertical-align: top; // readability and alignment cross-browser -} \ No newline at end of file diff --git a/_sass/_sidebar-docs.scss b/_sass/_sidebar-docs.scss deleted file mode 100644 index bcf9bea4..00000000 --- a/_sass/_sidebar-docs.scss +++ /dev/null @@ -1,39 +0,0 @@ -.sidebar { - opacity: 1 !important; - margin-top: 25px; - - :hover { - opacity: 1 !important; - } -} -.doc-category { - color: #18253d !important; - margin-bottom: 10px; - :last-of-type { - margin-bottom: 0; - } - - &__title { - user-select: none; - cursor: pointer; - position: relative; - font-size: 16px; - color: #18253d; - } - - &__sub-nav { - margin-left: 10px; - font-size: 18px; - } - &__sub-nav--active { - display: block; - } - &__li a { - text-decoration: none !important; - color: #18253d; - font-weight: unset; - } - &__li--selected a { - font-weight: bold; - } -} diff --git a/_sass/_sidebar.scss b/_sass/_sidebar.scss deleted file mode 100644 index ae84f90d..00000000 --- a/_sass/_sidebar.scss +++ /dev/null @@ -1,231 +0,0 @@ -/* ========================================================================== - SIDEBAR - ========================================================================== */ - -/* - Default - ========================================================================== */ - -.sidebar { - @include clearfix(); - margin-bottom: 1em; - - @include breakpoint($large) { - @include span(2 of 12); - opacity: 0.75; - transition: opacity 0.2s ease-in-out; - - &:hover { - opacity: 1; - } - } - - @include breakpoint($x-large) { - padding-right: 0; - } - - h2, h3, h4, h5, h6 { - margin-bottom: 0; - font-family: $sans-serif-narrow; - } - - h3, h4 { - font-size: $type-size-5; - } - - p, li { - font-family: $sans-serif; - font-size: $type-size-6; - line-height: 1.5; - } - - img { - width: 100%; - } -} - -.sidebar__right { - margin-bottom: 1em; - - @include breakpoint($large) { - position: relative; - float: right; - width: $right-sidebar-width-narrow; - margin-left: span(0.5 of 12); - z-index: 10; - } - - @include breakpoint($x-large) { - width: $right-sidebar-width; - } -} - -/* - Author profile and links - ========================================================================== */ - -.author__avatar { - display: table-cell; - vertical-align: top; - width: 36px; - height: 36px; - - @include breakpoint($large) { - display: block; - width: auto; - height: auto; - } - - img { - max-width: 110px; - border-radius: 50%; - - @include breakpoint($large) { - padding: 5px; - border: 1px solid $border-color; - } - } -} - -.author__content { - display: table-cell; - vertical-align: top; - padding-left: 15px; - padding-right: 25px; - line-height: 1; - - @include breakpoint($large) { - display: block; - width: 100%; - padding-left: 0; - padding-right: 0; - } -} - -.author__name { - margin: 0; - - @include breakpoint($large) { - margin-top: 10px; - margin-bottom: 10px; - } -} -.sidebar .author__name { - font-family: $sans-serif; - font-size: $type-size-5; -} - -.author__bio { - margin: 0; - - @include breakpoint($large) { - margin-top: 10px; - margin-bottom: 20px; - } -} - -.author__urls-wrapper { - position: relative; - display: table-cell; - vertical-align: middle; - font-family: $sans-serif; - z-index: 10; - position: relative; - cursor: pointer; - - li:last-child { - a { - margin-bottom: 0; - } - } - - @include breakpoint($large) { - display: block; - } - - button { - margin-bottom: 0; - - @include breakpoint($large) { - display: none; - } - } -} - -.author__urls { - display: none; - position: absolute; - right: 0; - margin-top: 15px; - padding: 10px; - list-style-type: none; - border: 1px solid $border-color; - border-radius: $border-radius; - background: #fff; - z-index: -1; - box-shadow: 0 0 10px rgba(#000, 0.25); - cursor: default; - - @include breakpoint($large) { - display: block; - position: relative; - margin: 0; - padding: 0; - border: 0; - background: transparent; - box-shadow: none; - } - - &:before { - display: block; - content: ""; - position: absolute; - top: -11px; - left: calc(50% - 10px); - width: 0; - border-style: solid; - border-width: 0 10px 10px; - border-color: $border-color transparent; - z-index: 0; - - @include breakpoint($large) { - display: none; - } - } - - &:after { - display: block; - content: ""; - position: absolute; - top: -10px; - left: calc(50% - 10px); - width: 0; - border-style: solid; - border-width: 0 10px 10px; - border-color: #fff transparent; - z-index: 1; - - @include breakpoint($large) { - display: none; - } - } - - li { - white-space: nowrap; - } - - a { - display: block; - margin-bottom: 5px; - padding-right: 5px; - padding-top: 2px; - padding-bottom: 2px; - color: inherit; - font-size: $type-size-5; - text-decoration: none; - - &:hover { - text-decoration: underline; - } - } -} \ No newline at end of file diff --git a/_sass/_splash.scss b/_sass/_splash.scss deleted file mode 100644 index d99c9a49..00000000 --- a/_sass/_splash.scss +++ /dev/null @@ -1,95 +0,0 @@ -.splash, -.resources-container { - h1, - h2, - h3, - h4, - ul, - p { - margin: 0 !important; - padding: 0 !important; - border: none !important; - } - - @include breakpoint($large) { - padding: 50px 0; - } - - @include breakpoint($x-large) { - width: $x-large; - } - - @include breakpoint($x2-large) { - width: $x2-large; - } - - margin-left: auto; - margin-right: auto; - - - h1 { - font-family: "Ubuntu"; - font-style: normal; - font-weight: bold; - font-size: 2.8rem; - color: #18253d; - border: none !important; - - &:hover { - border: none !important; - } - } - - h2 { - font-family: "Ubuntu"; - font-style: normal; - font-weight: bold; - font-size: 2rem; - color: #18253d; - border: none !important; - margin-top: 30px; - - &:hover { - border: none !important; - } - } - - p { - font-family: "Ubuntu"; - font-style: normal; - font-weight: normal; - font-size: 18px; - color: #18253d; - margin-top: 10px !important; - } - - h4 { - font-family: "Ubuntu"; - font-style: normal; - font-weight: 400; - font-size: 32px; - color: #18253d; - margin-top: 30px !important; - } -} - -.splash { - min-height: 100vh; - padding: 0; -} - -.margin-top-zero { - margin-top: 0 !important; -} - -@media (max-width: 1000px) { - .resources-container { - width: 90%; - padding-left: 20px; - padding-right: 20px; - - a { - word-break: break-word; - } - } -} diff --git a/_sass/_studio.scss b/_sass/_studio.scss deleted file mode 100644 index 0c4e29eb..00000000 --- a/_sass/_studio.scss +++ /dev/null @@ -1,318 +0,0 @@ -.wiremock-cloud-header { - h1, - h2, - h3, - h4, - ul, - p { - margin: 0 !important; - padding: 0 !important; - border: none !important; - } - - background: $general-background; - - display: flex; - align-items: center; - justify-content: center; - flex: 1; - background-image: url(../../images/wiremockStudioLeft.png), - url(../../images/wiremockStudioRight.png); - background-position: 0% 50%, 100% 50%; - background-repeat: no-repeat, no-repeat; - background-size: 420px 450px, 420px 450px; - height: 600px; - - .wiremock-cloud-header__intro { - display: flex; - flex-direction: column; - align-items: center; - width: 560px; - - .wiremockBIG { - width: 346px; - margin-right: 15px; - } - - h2 { - font-family: "Ubuntu"; - font-style: normal; - font-weight: bold; - color: #18253d; - font-size: 60px; - text-align: center; - } - - p { - font-family: "Ubuntu"; - font-style: normal; - font-weight: normal; - font-size: 16px; - text-align: center; - color: #18253d; - margin: 30px 0 !important; - width: 75%; - } - .getStartedHeader { - display: flex; - align-items: center; - } - .getStartedLink { - font-family: "Ubuntu"; - font-style: normal; - font-weight: 700; - font-size: 16px; - color: #f59121; - margin-right: 5px; - text-decoration: none; - border-bottom: 2px solid; - } - } - - .wiremock-cloud-header-middle { - display: flex; - align-items: center; - } -} - -.wiremock-cloud-container { - width: 880px; - margin-left: auto; - margin-right: auto; - padding: 0 1em; -} - -.responsive-img-studio { - width: 100%; - height: auto; - margin: 30px 0; -} - -.main-wrapper-studio { - h1, - h2, - h3, - h4, - ul, - p { - margin: 0 !important; - padding: 0 !important; - border: none !important; - } - - padding: 60px 0; - - .h4Studio { - font-family: "Ubuntu"; - font-style: normal; - font-weight: bold; - font-size: 32px; - color: #18253d; - margin: 45px 0 20px 0 !important; - } - - .pstudio { - font-family: "Ubuntu"; - font-style: normal; - font-weight: normal; - font-size: 18px; - color: #18253d; - - a { - color: #3db2ef; - } - } - - .pMargin { - margin-bottom: 15px !important; - } - - .titleTXT-main-wrapper { - color: #18253d; - font-style: normal; - font-weight: bold; - font-family: "Ubuntu"; - font-size: 40px; - } - - .wiremockBYUP9 { - width: 440px; - margin: 20px 0; - } - .highlight { - background: #f0f5ff; - border: 1px solid #d2dff9; - box-sizing: border-box; - border-radius: 8px; - } -} - -.otherWiremockProducts { - padding: 0 0 60px 0; - - .h2Studio { - font-family: "Ubuntu"; - font-style: normal; - font-weight: bold; - font-size: 50px; - color: #18253d; - padding: 0; - margin: 0 0 0 0 !important; - border: none; - } - - .pstudio { - font-family: "Ubuntu"; - font-style: normal; - font-weight: normal; - font-size: 12px; - color: #18253d; - } - - .customTXTFooter { - font-size: 16px; - } - - .otherWiremockIMG { - width: 168px; - } - - .h4Studio { - font-family: "Ubuntu"; - font-style: normal; - padding: 0; - margin: 0 0 10px 0; - font-size: 36px; - color: #000; - } - - .otherWiremockP { - margin-top: 40px !important; - } -} - -.otherWiremockProducts-container { - display: flex; - justify-content: space-between; - width: 1100px; - margin-left: auto; - margin-right: auto; - background: #f0f5ff; - border-radius: 50px; - padding: 50px; -} - -.otherWiremockProductsLeft { - width: 294px; -} - -.otherWiremockCardWrapper { - display: flex; - justify-content: space-between; - width: 626px; -} - -.otherWiremockCard { - display: flex; - flex-direction: column; - justify-content: space-between; - padding: 20px; - width: 288px; - height: 286px; - background: rgba(255, 255, 255, 0.5); - border: 1px solid #d2dff9; - box-sizing: border-box; - border-radius: 8px; -} -.wiremock-cloud-mobile-subtitle { - display: none; - font-size: 30px !important; -} - -@media (max-width: 1410px) { - .wiremock-cloud-subtitle { - display: none; - } - .wiremockBIG { - width: 180px !important; - } - .wiremock-cloud-header__intro { - h2 { - font-size: 30px !important; - } - } - .wiremock-cloud-mobile-subtitle { - display: block; - } -} - -@media (max-width: 1305px) { - .wiremock-cloud-header { - background-size: 350px 400px, 350px 400px; - } - .wiremock-cloud-header__intro { - width: 370px !important; - } -} - -@media (max-width: 1130px) { - .otherWiremockProducts-container { - width: 900px; - padding: 40px; - } - .otherWiremockCard { - width: 265px; - height: unset; - } -} - -@media (max-width: 1080px) { - .wiremock-cloud-header__intro { - width: 320px !important; - } -} - -@media (max-width: 1023px) { - .wiremock-cloud-header__intro { - padding: 0 20px; - } - .wiremock-cloud-header { - background-image: unset; - } - .wiremock-cloud-container { - width: 90%; - } - .otherWiremockProducts-container { - width: 90%; - flex-direction: column; - align-items: center; - } - .otherWiremockProductsLeft { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - } - .otherWiremockCardWrapper { - flex-direction: column; - align-items: center; - width: unset; - } - .otherWiremockCard { - margin-bottom: 20px; - &:last-child { - margin-bottom: 0; - } - } - .otherWiremockProducts { - .otherWiremockP { - margin-top: 20px !important; - } - } -} - -@media (max-width: 340px) { - .wiremockBIG { - width: 165px !important; - } -} diff --git a/_sass/_tables.scss b/_sass/_tables.scss deleted file mode 100644 index d31dc24a..00000000 --- a/_sass/_tables.scss +++ /dev/null @@ -1,38 +0,0 @@ -/* ========================================================================== - TABLES - ========================================================================== */ - -table { - margin-bottom: 1em; - width: 100%; - font-family: $global-font-family; - font-size: $type-size-6; - border-collapse: collapse; - border: 1px solid $light-gray; - - & + table { - margin-top: 1em; - } -} - -thead { - background-color: $lighter-gray; - border-bottom: 1px solid $light-gray; -} - -th { - padding: 0.5em; - font-weight: bold; - text-align: left; - border-right: 1px solid $light-gray; -} - -td { - padding: 0.5em; - border-bottom: 1px solid $light-gray; - border-right: 1px solid $light-gray; -} - -tr, td, th { - vertical-align: middle; -} \ No newline at end of file diff --git a/_sass/_utilities.scss b/_sass/_utilities.scss deleted file mode 100644 index cc2cb500..00000000 --- a/_sass/_utilities.scss +++ /dev/null @@ -1,399 +0,0 @@ -/* ========================================================================== - UTILITY CLASSES - ========================================================================== */ - -/* - Visibility - ========================================================================== */ - -/* http://www.456bereastreet.com/archive/200711/screen_readers_sometimes_ignore_displaynone/ */ - -.hidden { - display: none; - visibility: hidden; -} - -/* for preloading images */ - -.load { - display: none; -} - -.transparent { - opacity: 0; -} - -/* https://developer.yahoo.com/blogs/ydn/clip-hidden-content-better-accessibility-53456.html */ - -.visually-hidden, -.screen-reader-text, -.screen-reader-text span, -.screen-reader-shortcut { - position: absolute !important; - clip: rect(1px, 1px, 1px, 1px); - height: 1px !important; - width: 1px !important; - border: 0 !important; - overflow: hidden; -} - -body:hover .visually-hidden a, -body:hover .visually-hidden input, -body:hover .visually-hidden button { - display: none !important; -} - -/* screen readers */ - -.screen-reader-text:focus, -.screen-reader-shortcut:focus { - clip: auto !important; - height: auto !important; - width: auto !important; - display: block; - font-size: 1em; - font-weight: bold; - padding: 15px 23px 14px; - background: #fff; - z-index: 100000; - text-decoration: none; - box-shadow: 0 0 2px 2px rgba(0,0,0,.6); -} - - -/* - Skip links - ========================================================================== */ - -.skip-link { - position: fixed; - z-index: 20; - margin: 0; - font-family: $sans-serif; - white-space: nowrap; -} - -.skip-link li { - height: 0; - width: 0; - list-style: none; -} - - -/* - Type - ========================================================================== */ - -.text-left { - text-align: left; -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.text-justify { - text-align: justify; -} - -.text-nowrap { - white-space: nowrap; -} - - -/* - Alignment - ========================================================================== */ - -/* clearfix */ - -.cf { clear: both; } - -.wrapper { - @include container(); -} - - -/* - Images - ========================================================================== */ - -/* image align left */ - -.align-left { - display: block; - margin-left: auto; - margin-right: auto; - - @include breakpoint($small) { - float: left; - margin-right: 1em; - } -} - -/* image align right */ - -.align-right { - display: block; - margin-left: auto; - margin-right: auto; - - @include breakpoint($small) { - float: right; - margin-left: 1em; - } -} - -/* image align center */ - -.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -/* file page content container */ - -.full { - @include breakpoint($large){ - margin-right: -1 * span(2.5 of 12) !important; - } -} - -/* - Icons - ========================================================================== */ - -.icon { - display: inline-block; - fill: currentColor; - width: 1em; - height: 1.1em; - line-height: 1; - position: relative; - top: -0.1em; - vertical-align: middle; -} - -// social icons - -.social-icons { - .fa { - color: #000; - } - - .fa-behance, - .fa-behance-square { - color: $behance-color; - } - - .fa-dribbble { - color: $dribbble-color; - } - - .fa-facebook, - .fa-facebook-square { - color: $facebook-color; - } - - .fa-flickr { - color: $flickr-color; - } - - .fa-foursquare { - color: $foursquare-color; - } - - .fa-github, - .fa-github-alt, - .fa-github-square { - color: $github-color; - } - - .fa-google-plus, - .fa-google-plus-square { - color: $google-plus-color; - } - - .fa-instagram { - color: $instagram-color; - } - - .fa-lastfm, - .fa-lastfm-square { - color: $lastfm-color; - } - - .fa-linkedin, - .fa-linkedin-square { - color: $linkedin-color; - } - - .fa-pinterest, - .fa-pinterest-p, - .fa-pinterest-square { - color: $pinterest-color; - } - - .fa-rss, - .fa-rss-square { - color: $rss-color; - } - - .fa-soundcloud { - color: $soundcloud-color; - } - - .fa-stack-exchange, - .fa-stack-overflow { - color: $stackoverflow-color; - } - - .fa-tumblr, - .fa-tumblr-square { - color: $tumblr-color; - } - - .fa-twitter, - .fa-twitter-square { - color: $twitter-color; - } - - .fa-vimeo, - .fa-vimeo-square { - color: $vimeo-color; - } - - .fa-vine { - color: $vine-color; - } - - .fa-youtube, - .fa-youtube-square, - .fa-youtube-play { - color: $youtube-color; - } - - .fa-xing, - .fa-xing-square { - color: $xing-color; - } -} - - -/* - Navicons - ========================================================================== */ - -.navicon { - position: relative; - width: $navicon-width; - height: $navicon-height; - background: #fff; - margin: auto; - transition: 0.3s; - - &:before, - &:after { - content: ""; - position: absolute; - left: 0; - width: $navicon-width; - height: $navicon-height; - background: #fff; - transition: 0.3s; - } - - &:before { - top: (-2 * $navicon-height); - } - - &:after { - bottom: (-2 * $navicon-height); - } -} - -.close .navicon { - // hide the middle line - background: transparent; - - // overlay the lines by setting both their top values to 0 - &:before, &:after{ - transform-origin: 50% 50%; - top: 0; - width: $navicon-width; - } - - // rotate the lines to form the x shape - &:before{ - transform: rotate3d(0,0,1,45deg); - } - &:after{ - transform: rotate3d(0,0,1,-45deg); - } -} - - -/* - Sticky, fixed to top content - ========================================================================== */ - -.sticky { - @include breakpoint($large) { - @include clearfix(); - position: -webkit-sticky; - position: sticky; - top: 2em; - - > * { - display: block; - } - } -} - - -/* - Wells - ========================================================================== */ - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: $border-radius; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - - -/* - Footnotes - ========================================================================== */ - -.footnote { - color: mix(#fff, $gray, 25%); - text-decoration: none; -} - -.footnotes { - color: mix(#fff, $gray, 25%); - - ol, li, p { - margin-bottom: 0; - font-size: $type-size-6; - } -} - -a.reversefootnote { - color: $gray; - text-decoration: none; - - &:hover { - text-decoration: underline; - } -} \ No newline at end of file diff --git a/_sass/_variables.scss b/_sass/_variables.scss deleted file mode 100644 index 052ab0c5..00000000 --- a/_sass/_variables.scss +++ /dev/null @@ -1,180 +0,0 @@ -/* ========================================================================== - Variables - ========================================================================== */ - -/* - Typography - ========================================================================== */ - -$doc-font-size: 16; - -/* paragraph indention */ -$paragraph-indent: false; // true, false (default) -$indent-var: 1.3em; - -/* system typefaces */ -$serif: Georgia, Times, serif; -$sans-serif: "DMSans", "Segoe UI", "Helvetica Neue", "Lucida Grande", Arial, - sans-serif; -$monospace: "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace; - -/* sans serif typefaces */ -$sans-serif-narrow: $sans-serif; -$helvetica: Helvetica, "Helvetica Neue", Arial, sans-serif; - -/* serif typefaces */ -$georgia: Georgia, serif; -$times: Times, serif; -$bodoni: "Bodoni MT", serif; -$calisto: "Calisto MT", serif; -$garamond: Garamond, serif; - -$global-font-family: $sans-serif; -$header-font-family: $sans-serif; -$caption-font-family: $serif; - -/* type scale */ -$type-size-1: 2.441em; // ~39.056px -$type-size-2: 1.953em; // ~31.248px -$type-size-3: 1.563em; // ~25.008px -$type-size-4: 1.25em; // ~20px -$type-size-5: 1em; // ~16px -$type-size-6: 0.75em; // ~12px -$type-size-7: 0.6875em; // ~11px -$type-size-8: 0.625em; // ~10px - -$type-sizes: $type-size-1, $type-size-2, $type-size-3, $type-size-4, - $type-size-5, $type-size-6, $type-size-7, $type-size-8; - -@for $i from 1 through length($type-sizes) { - $size: nth($type-sizes, $i); - - .t-#{$i + 1} { - --font-size: #{$size}; - font-size: #{$size}; - } -} - -/* - Colors - ========================================================================== */ - -$general-background: #f0f5ff; -$dark-milk: #7d93bd; -$dark-blue: #2d69f6; -$light-blue: #7e8aa2; -$lighter-blue: #c3ecfb; -$very-light-blue: #becdea; -$orange: #ff9800; - -// header border-bottom -$head-border-bottom: #f0f5ff; - -// $gray : #7a8288; -$gray: #666666; -$dark-gray: mix(#000, $gray, 40%); -$darker-gray: mix(#000, $gray, 60%); -$light-gray: #f8f7f9; -$lighter-gray: mix(#fff, $gray, 90%); -$blue: #2d69f6; - -$body-color: #fff; -$background-color: #fff; -$code-background-color: #fafafa; -$code-background-color-dark: $light-gray; -$text-color: #0f0f0f; -$border-color: $lighter-gray; - -$primary-color: $gray; -$success-color: #62c462; -$warning-color: #f89406; -$danger-color: #ee5f5b; -$info-color: #52adc8; - -/* brands */ -$behance-color: #1769ff; -$dribbble-color: #ea4c89; -$facebook-color: #3b5998; -$flickr-color: #ff0084; -$foursquare-color: #0072b1; -$github-color: #171516; -$google-plus-color: #dd4b39; -$instagram-color: #517fa4; -$lastfm-color: #d51007; -$linkedin-color: #007bb6; -$pinterest-color: #cb2027; -$rss-color: #fa9b39; -$soundcloud-color: #ff3300; -$stackoverflow-color: #fe7a15; -$tumblr-color: #32506d; -$twitter-color: #55acee; -$vimeo-color: #1ab7ea; -$vine-color: #00bf8f; -$youtube-color: #bb0000; -$xing-color: #006567; - -$mocklab-light-green: #f9fcf5; -$mocklab-dark-green: #036334; - -/* links */ -$head-nav-links: #7d93bd; -$link-color: $blue; -$link-color-hover: mix(#000, $link-color, 25%); -$link-color-visited: mix(#fff, $link-color, 25%); -$masthead-link-color: $orange; -$masthead-link-color-hover: mix(#000, $gray, 25%); - -/* - Breakpoints - ========================================================================== */ - -@include breakpoint-set("to ems", true); - -$small: 600px; -$medium: 768px; -$medium-wide: 900px; -$large: 1024px; -$x-large: 1280px; -$x2-large: 1920px; - -/* - Grid - ========================================================================== */ - -$right-sidebar-width-narrow: 200px; -$right-sidebar-width: 300px; -$right-sidebar-width-wide: 400px; - -$susy: ( - columns: 12, - // column-width: 90px, - gutters: 1 * 0.25, - math: fluid, - output: float, - gutter-position: after, - container: $large, - global-box-sizing: border-box, - // debug: ( - // image: show, - // color: blue, - // output: overlay, - // toggle: top right, - // ),,,,,,,,,,,,,,,,,,,,,,,,,,, -); - -/* - Other - ========================================================================== */ - -$border-radius: 4px; -$box-shadow: 0 1px 1px rgba(0, 0, 0, 0.125); -$navicon-width: 28px; -$navicon-height: 4px; -$global-transition: all 0.2s ease-in-out; - -$p-s: 6px; -$p-m: 12px; -$p-l: 24px; -$p-xl: 36px; -$p-2xl: 48px; -$p-3xl: 72px; diff --git a/_sass/support.scss b/_sass/support.scss deleted file mode 100644 index 7c240ef5..00000000 --- a/_sass/support.scss +++ /dev/null @@ -1,46 +0,0 @@ -.support { - width: 950px; - height: 100vh; - margin-left: auto; - margin-right: auto; - padding: 0 0 50px 0; - - @media (max-width: 990px) { - width: 90%; - } - - h1, - h2, - h3, - h4 { - font-family: "Ubuntu"; - font-style: normal; - font-weight: bold; - color: #18253d; - border: none !important; - } - h1 { - font-size: 2.8rem; - margin-top: 0px; - margin-bottom: 0px; - } - h2 { - margin-top: 30px; - margin-bottom: 0px; - font-size: 2rem; - padding-bottom: 10px; - :first-child { - padding-top: 0px !important; - margin-top: 0px !important; - } - } - p { - font-family: "Ubuntu"; - font-style: normal; - font-weight: normal; - font-size: 18px; - color: #18253d; - margin-top: 0px !important; - margin-bottom: 0; - } -} diff --git a/_sass/vendor/_jquery-ui.scss b/_sass/vendor/_jquery-ui.scss deleted file mode 100644 index 3086e999..00000000 --- a/_sass/vendor/_jquery-ui.scss +++ /dev/null @@ -1,764 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2016-07-05 -* http://jqueryui.com -* Includes: core.css, draggable.css, resizable.css, button.css, dialog.css, tabs.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=%22Lato%22%2C%20%22Segoe%20UI%22%2C%20%22Helvetica%20Neue%22%2C%20%22Lucida%20Grande%22%2C%20Arial%2C%20sans-serif%3B&fsDefault=1em&fwDefault=normal&cornerRadius=5px&bgColorHeader=%23333333&bgTextureHeader=gloss_wave&borderColorHeader=%23333333&fcHeader=%23ffffff&iconColorHeader=%23ffffff&bgColorContent=%23000000&bgTextureContent=inset_soft&borderColorContent=%23666666&fcContent=%23ffffff&iconColorContent=%23cccccc&bgColorDefault=%23555555&bgTextureDefault=glass&borderColorDefault=%23666666&fcDefault=%23eeeeee&iconColorDefault=%23cccccc&bgColorHover=%237E8AA2&bgTextureHover=glass&borderColorHover=%2359b4d4&fcHover=%23ffffff&iconColorHover=%23ffffff&bgColorActive=%23FF9800&bgTextureActive=inset_soft&borderColorActive=%23ffaf0f&fcActive=%23ffffff&iconColorActive=%23222222&bgColorHighlight=%23eeeeee&bgTextureHighlight=highlight_soft&borderColorHighlight=%23cccccc&fcHighlight=%232e7db2&iconColorHighlight=%234b8e0b&bgColorError=%23ffc73d&bgTextureError=glass&borderColorError=%23ffb73d&fcError=%23111111&iconColorError=%23a83300&bgColorOverlay=%235c5c5c&bgTextureOverlay=flat&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=%23cccccc&bgTextureShadow=flat&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px&bgImgOpacityHeader=25&bgImgOpacityContent=25&bgImgOpacityDefault=20&bgImgOpacityHover=40&bgImgOpacityActive=30&bgImgOpacityHighlight=80&bgImgOpacityError=40 -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { - display: none; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix:before, -.ui-helper-clearfix:after { - content: ""; - display: table; - border-collapse: collapse; -} -.ui-helper-clearfix:after { - clear: both; -} -.ui-helper-clearfix { - min-height: 0; /* support: IE7 */ -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter:Alpha(Opacity=0); /* support: IE8 */ -} - -.ui-front { - z-index: 100; -} - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { - cursor: default !important; -} - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-draggable-handle { - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; - -ms-touch-action: none; - touch-action: none; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-button { - display: inline-block; - position: relative; - padding: 0; - line-height: normal; - margin-right: .1em; - cursor: pointer; - vertical-align: middle; - text-align: center; - overflow: visible; /* removes extra width in IE */ -} -.ui-button, -.ui-button:link, -.ui-button:visited, -.ui-button:hover, -.ui-button:active { - text-decoration: none; -} -/* to make room for the icon, a width needs to be set here */ -.ui-button-icon-only { - width: 2.2em; -} -/* button elements seem to need a little more width */ -button.ui-button-icon-only { - width: 2.4em; -} -.ui-button-icons-only { - width: 3.4em; -} -button.ui-button-icons-only { - width: 3.7em; -} - -/* button text element */ -.ui-button .ui-button-text { - display: block; - line-height: normal; -} -.ui-button-text-only .ui-button-text { - padding: .4em 1em; -} -.ui-button-icon-only .ui-button-text, -.ui-button-icons-only .ui-button-text { - padding: .4em; - text-indent: -9999999px; -} -.ui-button-text-icon-primary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 1em .4em 2.1em; -} -.ui-button-text-icon-secondary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 2.1em .4em 1em; -} -.ui-button-text-icons .ui-button-text { - padding-left: 2.1em; - padding-right: 2.1em; -} -/* no icon support for input elements, provide padding by default */ -input.ui-button { - padding: .4em 1em; -} - -/* button icon element(s) */ -.ui-button-icon-only .ui-icon, -.ui-button-text-icon-primary .ui-icon, -.ui-button-text-icon-secondary .ui-icon, -.ui-button-text-icons .ui-icon, -.ui-button-icons-only .ui-icon { - position: absolute; - top: 50%; - margin-top: -8px; -} -.ui-button-icon-only .ui-icon { - left: 50%; - margin-left: -8px; -} -.ui-button-text-icon-primary .ui-button-icon-primary, -.ui-button-text-icons .ui-button-icon-primary, -.ui-button-icons-only .ui-button-icon-primary { - left: .5em; -} -.ui-button-text-icon-secondary .ui-button-icon-secondary, -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; -} - -/* button sets */ -.ui-buttonset { - margin-right: 7px; -} -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: -.3em; -} - -/* workarounds */ -/* reset extra padding in Firefox, see h5bp.com/l */ -input.ui-button::-moz-focus-inner, -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; -} -.ui-dialog { - overflow: hidden; - position: absolute; - top: 0; - left: 0; - padding: .2em; - outline: 0; -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative; -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 0; - white-space: nowrap; - width: 90%; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 20px; - margin: -10px 0 0 0; - padding: 1px; - height: 20px; -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin-top: .5em; - padding: .3em 1em .5em .4em; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; -} -.ui-dialog .ui-resizable-se { - width: 12px; - height: 12px; - right: -5px; - bottom: -5px; - background-position: 16px 16px; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-tabs { - position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ - padding: .2em; -} -.ui-tabs .ui-tabs-nav { - margin: 0; - padding: .2em .2em 0; -} -.ui-tabs .ui-tabs-nav li { - list-style: none; - float: left; - position: relative; - top: 0; - margin: 1px .2em 0 0; - border-bottom-width: 0; - padding: 0; - white-space: nowrap; -} -.ui-tabs .ui-tabs-nav .ui-tabs-anchor { - float: left; - padding: .5em 1em; - text-decoration: none; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active { - margin-bottom: -1px; - padding-bottom: 1px; -} -.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, -.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { - cursor: text; -} -.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { - cursor: pointer; -} -.ui-tabs .ui-tabs-panel { - display: block; - border-width: 0; - padding: 1em 1.4em; - background: none; -} - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: "Lato", "Segoe UI", "Helvetica Neue", "Lucida Grande", Arial, sans-serif;; - font-size: 1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: "Lato", "Segoe UI", "Helvetica Neue", "Lucida Grande", Arial, sans-serif;; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #666666; - background: #000000 url("/images/ui-bg_inset-soft_25_000000_1x100.png") 50% bottom repeat-x; - color: #ffffff; -} -.ui-widget-content a { - color: #ffffff; -} -.ui-widget-header { - border: 1px solid #333333; - background: #333333 url("/images/ui-bg_gloss-wave_25_333333_500x100.png") 50% 50% repeat-x; - color: #ffffff; - font-weight: bold; -} -.ui-widget-header a { - color: #ffffff; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #666666; - background: #555555 url("/images/ui-bg_glass_20_555555_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #eeeeee; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #eeeeee; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #59b4d4; - background: #7E8AA2 url("/images/ui-bg_glass_40_7E8AA2_1x400.png") 50% 50% repeat-x; - font-weight: normal; - color: #ffffff; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #ffffff; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #ffaf0f; - background: #FF9800 url("/images/ui-bg_inset-soft_30_FF9800_1x100.png") 50% 50% repeat-x; - font-weight: normal; - color: #ffffff; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #ffffff; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #cccccc; - background: #eeeeee url("/images/ui-bg_highlight-soft_80_eeeeee_1x100.png") 50% top repeat-x; - color: #2e7db2; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #2e7db2; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #ffb73d; - background: #ffc73d url("/images/ui-bg_glass_40_ffc73d_1x400.png") 50% 50% repeat-x; - color: #111111; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #111111; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #111111; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("/images/ui-icons_cccccc_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("/images/ui-icons_ffffff_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("/images/ui-icons_cccccc_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("/images/ui-icons_ffffff_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("/images/ui-icons_222222_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("/images/ui-icons_4b8e0b_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("/images/ui-icons_a83300_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 5px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 5px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 5px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 5px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #5c5c5c; - opacity: .8; - filter: Alpha(Opacity=80); /* support: IE8 */ -} -.ui-widget-shadow { - margin: -7px 0 0 -7px; - padding: 7px; - background: #cccccc; - opacity: .6; - filter: Alpha(Opacity=60); /* support: IE8 */ - border-radius: 8px; -} diff --git a/_sass/vendor/breakpoint/_breakpoint.scss b/_sass/vendor/breakpoint/_breakpoint.scss deleted file mode 100644 index a0528eb8..00000000 --- a/_sass/vendor/breakpoint/_breakpoint.scss +++ /dev/null @@ -1,114 +0,0 @@ -////////////////////////////// -// Default Variables -////////////////////////////// -$Breakpoint-Settings: ( - 'default media': all, - 'default feature': min-width, - 'default pair': width, - - 'force all media type': false, - 'to ems': false, - 'transform resolutions': true, - - 'no queries': false, - 'no query fallbacks': false, - - 'base font size': 16px, - - 'legacy syntax': false -); - -$breakpoint: () !default; - -////////////////////////////// -// Imports -////////////////////////////// -@import "settings"; -@import "context"; -@import "helpers"; -@import "parsers"; -@import "no-query"; - -@import "respond-to"; - -@import "legacy-settings"; - -////////////////////////////// -// Breakpoint Mixin -////////////////////////////// - -@mixin breakpoint($query, $no-query: false) { - @include legacy-settings-warning; - - // Reset contexts - @include private-breakpoint-reset-contexts(); - - $breakpoint: breakpoint($query, false); - - $query-string: map-get($breakpoint, 'query'); - $query-fallback: map-get($breakpoint, 'fallback'); - - $private-breakpoint-context-holder: map-get($breakpoint, 'context holder') !global; - $private-breakpoint-query-count: map-get($breakpoint, 'query count') !global; - - // Allow for an as-needed override or usage of no query fallback. - @if $no-query != false { - $query-fallback: $no-query; - } - - @if $query-fallback != false { - $context-setter: private-breakpoint-set-context('no-query', $query-fallback); - } - - // Print Out Query String - @if not breakpoint-get('no queries') { - @media #{$query-string} { - @content; - } - } - - @if breakpoint-get('no query fallbacks') != false or breakpoint-get('no queries') == true { - - $type: type-of(breakpoint-get('no query fallbacks')); - $print: false; - - @if ($type == 'bool') { - $print: true; - } - @else if ($type == 'string') { - @if $query-fallback == breakpoint-get('no query fallbacks') { - $print: true; - } - } - @else if ($type == 'list') { - @each $wrapper in breakpoint-get('no query fallbacks') { - @if $query-fallback == $wrapper { - $print: true; - } - } - } - - // Write Fallback - @if ($query-fallback != false) and ($print == true) { - $type-fallback: type-of($query-fallback); - - @if ($type-fallback != 'bool') { - #{$query-fallback} & { - @content; - } - } - @else { - @content; - } - } - } - - @include private-breakpoint-reset-contexts(); -} - - -@mixin mq($query, $no-query: false) { - @include breakpoint($query, $no-query) { - @content; - } -} diff --git a/_sass/vendor/breakpoint/_context.scss b/_sass/vendor/breakpoint/_context.scss deleted file mode 100644 index 57947f5c..00000000 --- a/_sass/vendor/breakpoint/_context.scss +++ /dev/null @@ -1,95 +0,0 @@ -////////////////////////////// -// Private Breakpoint Variables -////////////////////////////// -$private-breakpoint-context-holder: (); -$private-breakpoint-query-count: 0 !default; - -////////////////////////////// -// Breakpoint Has Context -// Returns whether or not you are inside a Breakpoint query -////////////////////////////// -@function breakpoint-has-context() { - @if length($private-breakpoint-query-count) { - @return true; - } - @else { - @return false; - } -} - -////////////////////////////// -// Breakpoint Get Context -// $feature: Input feature to get it's current MQ context. Returns false if no context -////////////////////////////// -@function breakpoint-get-context($feature) { - @if map-has-key($private-breakpoint-context-holder, $feature) { - $get: map-get($private-breakpoint-context-holder, $feature); - // Special handling of no-query from get side so /false/ prepends aren't returned - @if $feature == 'no-query' { - @if type-of($get) == 'list' and length($get) > 1 and nth($get, 1) == false { - $get: nth($get, length($get)); - } - } - @return $get; - } - @else { - @if breakpoint-has-context() and $feature == 'media' { - @return breakpoint-get('default media'); - } - @else { - @return false; - } - } -} - -////////////////////////////// -// Private function to set context -////////////////////////////// -@function private-breakpoint-set-context($feature, $value) { - @if $value == 'monochrome' { - $feature: 'monochrome'; - } - - $current: map-get($private-breakpoint-context-holder, $feature); - @if $current and length($current) == $private-breakpoint-query-count { - @warn "You have already queried against `#{$feature}`. Unexpected things may happen if you query against the same feature more than once in the same `and` query. Breakpoint is overwriting the current context with `#{$value}`"; - } - - @if not map-has-key($private-breakpoint-context-holder, $feature) { - $v-holder: (); - @for $i from 1 to $private-breakpoint-query-count { - @if $feature == 'media' { - $v-holder: append($v-holder, breakpoint-get('default media')); - } - @else { - $v-holder: append($v-holder, false); - } - } - $v-holder: append($v-holder, $value); - $private-breakpoint-context-holder: map-merge($private-breakpoint-context-holder, ($feature: $v-holder)) !global; - } - @else { - $v-holder: map-get($private-breakpoint-context-holder, $feature); - $length: length($v-holder); - @for $i from $length to $private-breakpoint-query-count - 1 { - @if $feature == 'media' { - $v-holder: append($v-holder, breakpoint-get('default media')); - } - @else { - $v-holder: append($v-holder, false); - } - } - $v-holder: append($v-holder, $value); - $private-breakpoint-context-holder: map-merge($private-breakpoint-context-holder, ($feature: $v-holder)) !global; - } - - @return true; -} - -////////////////////////////// -// Private function to reset context -////////////////////////////// -@mixin private-breakpoint-reset-contexts { - $private-breakpoint-context-holder: () !global; - $private-breakpoint-query-count: 0 !global; -} \ No newline at end of file diff --git a/_sass/vendor/breakpoint/_helpers.scss b/_sass/vendor/breakpoint/_helpers.scss deleted file mode 100644 index 1accfe9e..00000000 --- a/_sass/vendor/breakpoint/_helpers.scss +++ /dev/null @@ -1,153 +0,0 @@ -////////////////////////////// -// Converts the input value to Base EMs -////////////////////////////// -@use "sass:math"; - -@function breakpoint-to-base-em($value) { - $value-unit: unit($value); - - // Will convert relative EMs into root EMs. - @if breakpoint-get('base font size') and type-of(breakpoint-get('base font size')) == 'number' and $value-unit == 'em' { - $base-unit: unit(breakpoint-get('base font size')); - - @if $base-unit == 'px' or $base-unit == '%' or $base-unit == 'em' or $base-unit == 'pt' { - @return math.div(base-conversion($value), base-conversion(breakpoint-get('base font size'))) * 1em; - } - @else { - @warn '#{breakpoint-get(\'base font size\')} is not set in valid units for font size!'; - @return false; - } - } - @else { - @return base-conversion($value); - } -} - -@function base-conversion($value) { - $unit: unit($value); - - @if $unit == 'px' { - @return math.div($value, 16px) * 1em; - } - @else if $unit == '%' { - @return math.div($value, 100%) * 1em; - } - @else if $unit == 'em' { - @return $value; - } - @else if $unit == 'pt' { - @return math.div($value, 12pt) * 1em; - } - @else { - @return $value; -// @warn 'Everything is terrible! What have you done?!'; - } -} - -////////////////////////////// -// Returns whether the feature can have a min/max pair -////////////////////////////// -$breakpoint-min-max-features: 'color', - 'color-index', - 'aspect-ratio', - 'device-aspect-ratio', - 'device-height', - 'device-width', - 'height', - 'monochrome', - 'resolution', - 'width'; - -@function breakpoint-min-max($feature) { - @each $item in $breakpoint-min-max-features { - @if $feature == $item { - @return true; - } - } - @return false; -} - -////////////////////////////// -// Returns whether the feature can have a string value -////////////////////////////// -$breakpoint-string-features: 'orientation', - 'scan', - 'color', - 'aspect-ratio', - 'device-aspect-ratio', - 'pointer', - 'luminosity'; - -@function breakpoint-string-value($feature) { - @each $item in $breakpoint-string-features { - @if breakpoint-min-max($item) { - @if $feature == 'min-#{$item}' or $feature == 'max-#{$item}' { - @return true; - } - } - @else if $feature == $item { - @return true; - } - } - @return false; -} - -////////////////////////////// -// Returns whether the feature is a media type -////////////////////////////// -$breakpoint-media-types: 'all', - 'braille', - 'embossed', - 'handheld', - 'print', - 'projection', - 'screen', - 'speech', - 'tty', - 'tv'; - -@function breakpoint-is-media($feature) { - @each $media in $breakpoint-media-types { - @if ($feature == $media) or ($feature == 'not #{$media}') or ($feature == 'only #{$media}') { - @return true; - } - } - - @return false; -} - -////////////////////////////// -// Returns whether the feature can stand alone -////////////////////////////// -$breakpoint-single-string-features: 'color', - 'color-index', - 'grid', - 'monochrome'; - -@function breakpoint-single-string($feature) { - @each $item in $breakpoint-single-string-features { - @if $feature == $item { - @return true; - } - } - @return false; -} - -////////////////////////////// -// Returns whether the feature -////////////////////////////// -@function breakpoint-is-resolution($feature) { - $resolutions: 'device-pixel-ratio', 'dpr'; - - @if breakpoint-get('transform resolutions') { - $resolutions: append($resolutions, 'resolution'); - } - - @each $reso in $resolutions { - @if index($feature, $reso) or index($feature, 'min-#{$reso}') or index($feature, 'max-#{$reso}') { - @return true; - } - } - - @return false; -} diff --git a/_sass/vendor/breakpoint/_legacy-settings.scss b/_sass/vendor/breakpoint/_legacy-settings.scss deleted file mode 100644 index e060ebe3..00000000 --- a/_sass/vendor/breakpoint/_legacy-settings.scss +++ /dev/null @@ -1,50 +0,0 @@ -@mixin legacy-settings-warning { - $legacyVars: ( - 'default-media': 'default media', - 'default-feature': 'default feature', - 'force-media-all': 'force all media type', - 'to-ems': 'to ems', - 'resolutions': 'transform resolutions', - 'no-queries': 'no queries', - 'no-query-fallbacks': 'no query fallbacks', - 'base-font-size': 'base font size', - 'legacy-syntax': 'legacy syntax' - ); - - @each $legacy, $new in $legacyVars { - @if global-variable-exists('breakpoint-' + $legacy) { - @warn "In order to avoid variable namspace collisions, we have updated the way to change settings for Breakpoint. Please change all instances of `$breakpoint-#{$legacy}: {{setting}}` to `@include breakpoint-set('#{$new}', {{setting}})`. Variable settings, as well as this warning will be deprecated in a future release." - } - }; - - ////////////////////////////// - // Hand correct each setting - ////////////////////////////// - @if global-variable-exists('breakpoint-default-media') and $breakpoint-default-media != breakpoint-get('default media') { - @include breakpoint-set('default media', $breakpoint-default-media); - } - @if global-variable-exists('breakpoint-default-feature') and $breakpoint-default-feature != breakpoint-get('default feature') { - @include breakpoint-set('default feature', $breakpoint-default-feature); - } - @if global-variable-exists('breakpoint-force-media-all') and $breakpoint-force-media-all != breakpoint-get('force all media type') { - @include breakpoint-set('force all media type', $breakpoint-force-media-all); - } - @if global-variable-exists('breakpoint-to-ems') and $breakpoint-to-ems != breakpoint-get('to ems') { - @include breakpoint-set('to ems', $breakpoint-to-ems); - } - @if global-variable-exists('breakpoint-resolutions') and $breakpoint-resolutions != breakpoint-get('transform resolutions') { - @include breakpoint-set('transform resolutions', $breakpoint-resolutions); - } - @if global-variable-exists('breakpoint-no-queries') and $breakpoint-no-queries != breakpoint-get('no queries') { - @include breakpoint-set('no queries', $breakpoint-no-queries); - } - @if global-variable-exists('breakpoint-no-query-fallbacks') and $breakpoint-no-query-fallbacks != breakpoint-get('no query fallbacks') { - @include breakpoint-set('no query fallbacks', $breakpoint-no-query-fallbacks); - } - @if global-variable-exists('breakpoint-base-font-size') and $breakpoint-base-font-size != breakpoint-get('base font size') { - @include breakpoint-set('base font size', $breakpoint-base-font-size); - } - @if global-variable-exists('breakpoint-legacy-syntax') and $breakpoint-legacy-syntax != breakpoint-get('legacy syntax') { - @include breakpoint-set('legacy syntax', $breakpoint-legacy-syntax); - } -} \ No newline at end of file diff --git a/_sass/vendor/breakpoint/_no-query.scss b/_sass/vendor/breakpoint/_no-query.scss deleted file mode 100644 index 0b5a81f6..00000000 --- a/_sass/vendor/breakpoint/_no-query.scss +++ /dev/null @@ -1,15 +0,0 @@ -@function breakpoint-no-query($query) { - @if type-of($query) == 'list' { - $keyword: nth($query, 1); - - @if type-of($keyword) == 'string' and ($keyword == 'no-query' or $keyword == 'no query' or $keyword == 'fallback') { - @return nth($query, 2); - } - @else { - @return false; - } - } - @else { - @return false; - } -} diff --git a/_sass/vendor/breakpoint/_parsers.scss b/_sass/vendor/breakpoint/_parsers.scss deleted file mode 100644 index f0b053fe..00000000 --- a/_sass/vendor/breakpoint/_parsers.scss +++ /dev/null @@ -1,215 +0,0 @@ -////////////////////////////// -// Import Parser Pieces -////////////////////////////// -@import "parsers/query"; -@import "parsers/single"; -@import "parsers/double"; -@import "parsers/triple"; -@import "parsers/resolution"; - -$Memo-Exists: function-exists(memo-get) and function-exists(memo-set); - -////////////////////////////// -// Breakpoint Function -////////////////////////////// -@function breakpoint($query, $contexts...) { - $run: true; - $return: (); - - // Grab the Memo Output if Memoization can be a thing - @if $Memo-Exists { - $return: memo-get(breakpoint, breakpoint $query $contexts); - - @if $return != null { - $run: false; - } - } - - @if not $Memo-Exists or $run { - // Internal Variables - $query-string: ''; - $query-fallback: false; - $return: (); - - // Reserve Global Private Breakpoint Context - $holder-context: $private-breakpoint-context-holder; - $holder-query-count: $private-breakpoint-query-count; - - // Reset Global Private Breakpoint Context - $private-breakpoint-context-holder: () !global; - $private-breakpoint-query-count: 0 !global; - - - // Test to see if it's a comma-separated list - $or-list: if(list-separator($query) == 'comma', true, false); - - - @if ($or-list == false and breakpoint-get('legacy syntax') == false) { - $query-string: breakpoint-parse($query); - } - @else { - $length: length($query); - - $last: nth($query, $length); - $query-fallback: breakpoint-no-query($last); - - @if ($query-fallback != false) { - $length: $length - 1; - } - - @if (breakpoint-get('legacy syntax') == true) { - $mq: (); - - @for $i from 1 through $length { - $mq: append($mq, nth($query, $i), comma); - } - - $query-string: breakpoint-parse($mq); - } - @else { - $query-string: ''; - @for $i from 1 through $length { - $query-string: $query-string + if($i == 1, '', ', ') + breakpoint-parse(nth($query, $i)); - } - } - } - - $return: ('query': $query-string, - 'fallback': $query-fallback, - 'context holder': $private-breakpoint-context-holder, - 'query count': $private-breakpoint-query-count - ); - @if length($contexts) > 0 and nth($contexts, 1) != false { - @if $query-fallback != false { - $context-setter: private-breakpoint-set-context('no-query', $query-fallback); - } - $context-map: (); - @each $context in $contexts { - $context-map: map-merge($context-map, ($context: breakpoint-get-context($context))); - } - $return: map-merge($return, (context: $context-map)); - } - - // Reset Global Private Breakpoint Context - $private-breakpoint-context-holder: () !global; - $private-breakpoint-query-count: 0 !global; - - @if $Memo-Exists { - $holder: memo-set(breakpoint, breakpoint $query $contexts, $return); - } - } - - @return $return; -} - -////////////////////////////// -// General Breakpoint Parser -////////////////////////////// -@function breakpoint-parse($query) { - // Increase number of 'and' queries - $private-breakpoint-query-count: $private-breakpoint-query-count + 1 !global; - - // Set up Media Type - $query-print: ''; - - $force-all: ((breakpoint-get('force all media type') == true) and (breakpoint-get('default media') == 'all')); - $empty-media: true; - @if ($force-all == true) or (breakpoint-get('default media') != 'all') { - // Force the print of the default media type if (force all is true and default media type is all) or (default media type is not all) - $query-print: breakpoint-get('default media'); - $empty-media: false; - } - - - $query-resolution: false; - - $query-holder: breakpoint-parse-query($query); - - - - // Loop over each parsed out query and write it to $query-print - $first: true; - - @each $feature in $query-holder { - $length: length($feature); - - // Parse a single feature - @if ($length == 1) { - // Feature is currently a list, grab the actual value - $feature: nth($feature, 1); - - // Media Type must by convention be the first item, so it's safe to flat override $query-print, which right now should only be the default media type - @if (breakpoint-is-media($feature)) { - @if ($force-all == true) or ($feature != 'all') { - // Force the print of the default media type if (force all is true and default media type is all) or (default media type is not all) - $query-print: $feature; - $empty-media: false; - - // Set Context - $context-setter: private-breakpoint-set-context(media, $query-print); - } - } - @else { - $parsed: breakpoint-parse-single($feature, $empty-media, $first); - $query-print: '#{$query-print} #{$parsed}'; - $first: false; - } - } - // Parse a double feature - @else if ($length == 2) { - @if (breakpoint-is-resolution($feature) != false) { - $query-resolution: $feature; - } - @else { - $parsed: null; - // If it's a string/number pair, - // we check to see if one is a single-string value, - // then we parse it as a normal double - $alpha: nth($feature, 1); - $beta: nth($feature, 2); - @if breakpoint-single-string($alpha) or breakpoint-single-string($beta) { - $parsed: breakpoint-parse-single($alpha, $empty-media, $first); - $query-print: '#{$query-print} #{$parsed}'; - $first: false; - $parsed: breakpoint-parse-single($beta, $empty-media, $first); - $query-print: '#{$query-print} #{$parsed}'; - } - @else { - $parsed: breakpoint-parse-double($feature, $empty-media, $first); - $query-print: '#{$query-print} #{$parsed}'; - $first: false; - } - } - } - // Parse a triple feature - @else if ($length == 3) { - $parsed: breakpoint-parse-triple($feature, $empty-media, $first); - $query-print: '#{$query-print} #{$parsed}'; - $first: false; - } - - } - - @if ($query-resolution != false) { - $query-print: breakpoint-build-resolution($query-print, $query-resolution, $empty-media, $first); - } - - // Loop through each feature that's been detected so far and append 'false' to the the value list to increment their counters - @each $f, $v in $private-breakpoint-context-holder { - $v-holder: $v; - $length: length($v-holder); - @if length($v-holder) < $private-breakpoint-query-count { - @for $i from $length to $private-breakpoint-query-count { - @if $f == 'media' { - $v-holder: append($v-holder, breakpoint-get('default media')); - } - @else { - $v-holder: append($v-holder, false); - } - } - } - $private-breakpoint-context-holder: map-merge($private-breakpoint-context-holder, ($f: $v-holder)) !global; - } - - @return $query-print; -} diff --git a/_sass/vendor/breakpoint/_respond-to.scss b/_sass/vendor/breakpoint/_respond-to.scss deleted file mode 100644 index e2462c5f..00000000 --- a/_sass/vendor/breakpoint/_respond-to.scss +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////// -// Default the Breakpoints variable -//////////////////////// -$breakpoints: () !default; -$BREAKPOINTS: () !default; - -//////////////////////// -// Respond-to API Mixin -//////////////////////// -@mixin respond-to($context, $no-query: false) { - @if length($breakpoints) > 0 and length($BREAKPOINTS) == 0 { - @warn "In order to avoid variable namespace collisions, we have updated the way to add breakpoints for respond-to. Please change all instances of `$breakpoints: add-breakpoint()` to `@include add-breakpoint()`. The `add-breakpoint()` function will be deprecated in a future release."; - $BREAKPOINTS: $breakpoints !global; - $breakpoints: () !global; - } - - @if type-of($BREAKPOINTS) != 'map' { - // Just in case someone writes gibberish to the $breakpoints variable. - @warn "Your breakpoints aren't a map! `respond-to` expects a map. Please check the value of $BREAKPOINTS variable."; - @content; - } - @else if map-has-key($BREAKPOINTS, $context) { - @include breakpoint(map-get($BREAKPOINTS, $context), $no-query) { - @content; - } - } - @else if not map-has-key($BREAKPOINTS, $context) { - @warn "`#{$context}` isn't a defined breakpoint! Please add it using `$breakpoints: add-breakpoint(`#{$context}`, $value);`"; - @content; - } - @else { - @warn "You haven't created any breakpoints yet! Make some already! `@include add-breakpoint($name, $bkpt)`"; - @content; - } -} - -////////////////////////////// -// Add Breakpoint to Breakpoints -// TODO: Remove function in next release -////////////////////////////// -@function add-breakpoint($name, $bkpt, $overwrite: false) { - $output: ($name: $bkpt); - - @if length($breakpoints) == 0 { - @return $output; - } - @else { - @if map-has-key($breakpoints, $name) and $overwrite != true { - @warn "You already have a breakpoint named `#{$name}`, please choose another breakpoint name, or pass in `$overwrite: true` to overwrite the previous breakpoint."; - @return $breakpoints; - } - @else if not map-has-key($breakpoints, $name) or $overwrite == true { - @return map-merge($breakpoints, $output); - } - } -} - -@mixin add-breakpoint($name, $bkpt, $overwrite: false) { - $output: ($name: $bkpt); - - @if length($BREAKPOINTS) == 0 { - $BREAKPOINTS: $output !global; - } - @else { - @if map-has-key($BREAKPOINTS, $name) and $overwrite != true { - @warn "You already have a breakpoint named `#{$name}`, please choose another breakpoint name, or pass in `$overwrite: true` to overwrite the previous breakpoint."; - $BREAKPOINTS: $BREAKPOINTS !global; - } - @else if not map-has-key($BREAKPOINTS, $name) or $overwrite == true { - $BREAKPOINTS: map-merge($BREAKPOINTS, $output) !global; - } - } -} - -@function get-breakpoint($name: false) { - @if $name == false { - @return $BREAKPOINTS; - } - @else { - @return map-get($BREAKPOINTS, $name); - } -} diff --git a/_sass/vendor/breakpoint/_settings.scss b/_sass/vendor/breakpoint/_settings.scss deleted file mode 100644 index 05ee6894..00000000 --- a/_sass/vendor/breakpoint/_settings.scss +++ /dev/null @@ -1,71 +0,0 @@ -////////////////////////////// -// Has Setting -////////////////////////////// -@function breakpoint-has($setting) { - @if map-has-key($breakpoint, $setting) { - @return true; - } - @else { - @return false; - } -} - -////////////////////////////// -// Get Settings -////////////////////////////// -@function breakpoint-get($setting) { - @if breakpoint-has($setting) { - @return map-get($breakpoint, $setting); - } - @else { - @return map-get($Breakpoint-Settings, $setting); - } -} - -////////////////////////////// -// Set Settings -////////////////////////////// -@function breakpoint-set($setting, $value) { - @if (str-index($setting, '-') or str-index($setting, '_')) and str-index($setting, ' ') == null { - @warn "Words in Breakpoint settings should be separated by spaces, not dashes or underscores. Please replace dashes and underscores between words with spaces. Settings will not work as expected until changed."; - } - $breakpoint: map-merge($breakpoint, ($setting: $value)) !global; - @return true; -} - -@mixin breakpoint-change($setting, $value) { - $breakpoint-change: breakpoint-set($setting, $value); -} - -@mixin breakpoint-set($setting, $value) { - @include breakpoint-change($setting, $value); -} - -@mixin bkpt-change($setting, $value) { - @include breakpoint-change($setting, $value); -} -@mixin bkpt-set($setting, $value) { - @include breakpoint-change($setting, $value); -} - -////////////////////////////// -// Remove Setting -////////////////////////////// -@function breakpoint-reset($settings...) { - @if length($settings) == 1 { - $settings: nth($settings, 1); - } - - @each $setting in $settings { - $breakpoint: map-remove($breakpoint, $setting) !global; - } - @return true; -} - -@mixin breakpoint-reset($settings...) { - $breakpoint-reset: breakpoint-reset($settings); -} - -@mixin bkpt-reset($settings...) { - $breakpoint-reset: breakpoint-reset($settings); -} \ No newline at end of file diff --git a/_sass/vendor/breakpoint/parsers/_double.scss b/_sass/vendor/breakpoint/parsers/_double.scss deleted file mode 100644 index 24580c15..00000000 --- a/_sass/vendor/breakpoint/parsers/_double.scss +++ /dev/null @@ -1,33 +0,0 @@ -////////////////////////////// -// Import Pieces -////////////////////////////// -@import "double/default-pair"; -@import "double/double-string"; -@import "double/default"; - -@function breakpoint-parse-double($feature, $empty-media, $first) { - $parsed: ''; - $leader: ''; - // If we're forcing - @if not ($empty-media) or not ($first) { - $leader: 'and '; - } - - $first: nth($feature, 1); - $second: nth($feature, 2); - - // If we've got two numbers, we know we need to use the default pair because there are no media queries that has a media feature that is a number - @if type-of($first) == 'number' and type-of($second) == 'number' { - $parsed: breakpoint-parse-default-pair($first, $second); - } - // If they are both strings, we send it through the string parser - @else if type-of($first) == 'string' and type-of($second) == 'string' { - $parsed: breakpoint-parse-double-string($first, $second); - } - // If it's a string/number pair, we parse it as a normal double - @else { - $parsed: breakpoint-parse-double-default($first, $second); - } - - @return $leader + $parsed; -} diff --git a/_sass/vendor/breakpoint/parsers/_query.scss b/_sass/vendor/breakpoint/parsers/_query.scss deleted file mode 100644 index b138b393..00000000 --- a/_sass/vendor/breakpoint/parsers/_query.scss +++ /dev/null @@ -1,82 +0,0 @@ -@function breakpoint-parse-query($query) { - // Parse features out of an individual query - $feature-holder: (); - $query-holder: (); - $length: length($query); - - @if $length == 2 { - // If we've got a string/number, number/string, check to see if it's a valid string/number pair or two singles - @if (type-of(nth($query, 1)) == 'string' and type-of(nth($query, 2)) == 'number') or (type-of(nth($query, 1)) == 'number' and type-of(nth($query, 2)) == 'string') { - - $number: ''; - $value: ''; - - @if type-of(nth($query, 1)) == 'string' { - $number: nth($query, 2); - $value: nth($query, 1); - } - @else { - $number: nth($query, 1); - $value: nth($query, 2); - } - - // If the string value can be a single value, check to see if the number passed in is a valid input for said single value. Fortunately, all current single-value options only accept unitless numbers, so this check is easy. - @if breakpoint-single-string($value) { - @if unitless($number) { - $feature-holder: append($value, $number, space); - $query-holder: append($query-holder, $feature-holder, comma); - @return $query-holder; - } - } - // If the string is a media type, split the query - @if breakpoint-is-media($value) { - $query-holder: append($query-holder, nth($query, 1)); - $query-holder: append($query-holder, nth($query, 2)); - @return $query-holder; - } - // If it's not a single feature, we're just going to assume it's a proper string/value pair, and roll with it. - @else { - $feature-holder: append($value, $number, space); - $query-holder: append($query-holder, $feature-holder, comma); - @return $query-holder; - } - - } - // If they're both numbers, we assume it's a double and roll with that - @else if (type-of(nth($query, 1)) == 'number' and type-of(nth($query, 2)) == 'number') { - $feature-holder: append(nth($query, 1), nth($query, 2), space); - $query-holder: append($query-holder, $feature-holder, comma); - @return $query-holder; - } - // If they're both strings and neither are singles, we roll with that. - @else if (type-of(nth($query, 1)) == 'string' and type-of(nth($query, 2)) == 'string') { - @if not breakpoint-single-string(nth($query, 1)) and not breakpoint-single-string(nth($query, 2)) { - $feature-holder: append(nth($query, 1), nth($query, 2), space); - $query-holder: append($query-holder, $feature-holder, comma); - @return $query-holder; - } - } - } - @else if $length == 3 { - // If we've got three items and none is a list, we check to see - @if type-of(nth($query, 1)) != 'list' and type-of(nth($query, 2)) != 'list' and type-of(nth($query, 3)) != 'list' { - // If none of the items are single string values and none of the values are media values, we're good. - @if (not breakpoint-single-string(nth($query, 1)) and not breakpoint-single-string(nth($query, 2)) and not breakpoint-single-string(nth($query, 3))) and ((not breakpoint-is-media(nth($query, 1)) and not breakpoint-is-media(nth($query, 2)) and not breakpoint-is-media(nth($query, 3)))) { - $feature-holder: append(nth($query, 1), nth($query, 2), space); - $feature-holder: append($feature-holder, nth($query, 3), space); - $query-holder: append($query-holder, $feature-holder, comma); - @return $query-holder; - } - // let's check to see if the first item is a media type - @else if breakpoint-is-media(nth($query, 1)) { - $query-holder: append($query-holder, nth($query, 1)); - $feature-holder: append(nth($query, 2), nth($query, 3), space); - $query-holder: append($query-holder, $feature-holder); - @return $query-holder; - } - } - } - - // If it's a single item, or if it's not a special case double or triple, we can simply return the query. - @return $query; -} diff --git a/_sass/vendor/breakpoint/parsers/_resolution.scss b/_sass/vendor/breakpoint/parsers/_resolution.scss deleted file mode 100644 index 19769adf..00000000 --- a/_sass/vendor/breakpoint/parsers/_resolution.scss +++ /dev/null @@ -1,31 +0,0 @@ -@import "resolution/resolution"; - -@function breakpoint-build-resolution($query-print, $query-resolution, $empty-media, $first) { - $leader: ''; - // If we're forcing - @if not ($empty-media) or not ($first) { - $leader: 'and '; - } - - @if breakpoint-get('transform resolutions') and $query-resolution { - $resolutions: breakpoint-make-resolutions($query-resolution); - $length: length($resolutions); - $query-holder: ''; - - @for $i from 1 through $length { - $query: '#{$query-print} #{$leader}#{nth($resolutions, $i)}'; - @if $i == 1 { - $query-holder: $query; - } - @else { - $query-holder: '#{$query-holder}, #{$query}'; - } - } - - @return $query-holder; - } - @else { - // Return with attached resolution - @return $query-print; - } -} diff --git a/_sass/vendor/breakpoint/parsers/_single.scss b/_sass/vendor/breakpoint/parsers/_single.scss deleted file mode 100644 index d9fd764a..00000000 --- a/_sass/vendor/breakpoint/parsers/_single.scss +++ /dev/null @@ -1,26 +0,0 @@ -////////////////////////////// -// Import Pieces -////////////////////////////// -@import "single/default"; - -@function breakpoint-parse-single($feature, $empty-media, $first) { - $parsed: ''; - $leader: ''; - // If we're forcing - @if not ($empty-media) or not ($first) { - $leader: 'and '; - } - - // If it's a single feature that can stand alone, we let it - @if (breakpoint-single-string($feature)) { - $parsed: $feature; - // Set Context - $context-setter: private-breakpoint-set-context($feature, $feature); - } - // If it's not a stand alone feature, we pass it off to the default handler. - @else { - $parsed: breakpoint-parse-default($feature); - } - - @return $leader + '(' + $parsed + ')'; -} diff --git a/_sass/vendor/breakpoint/parsers/_triple.scss b/_sass/vendor/breakpoint/parsers/_triple.scss deleted file mode 100644 index e2732067..00000000 --- a/_sass/vendor/breakpoint/parsers/_triple.scss +++ /dev/null @@ -1,36 +0,0 @@ -////////////////////////////// -// Import Pieces -////////////////////////////// -@import "triple/default"; - -@function breakpoint-parse-triple($feature, $empty-media, $first) { - $parsed: ''; - $leader: ''; - - // If we're forcing - @if not ($empty-media) or not ($first) { - $leader: 'and '; - } - - // separate the string features from the value numbers - $string: null; - $numbers: null; - @each $val in $feature { - @if type-of($val) == string { - $string: $val; - } - @else { - @if type-of($numbers) == 'null' { - $numbers: $val; - } - @else { - $numbers: append($numbers, $val); - } - } - } - - $parsed: breakpoint-parse-triple-default($string, nth($numbers, 1), nth($numbers, 2)); - - @return $leader + $parsed; - -} diff --git a/_sass/vendor/breakpoint/parsers/double/_default-pair.scss b/_sass/vendor/breakpoint/parsers/double/_default-pair.scss deleted file mode 100644 index f88432cc..00000000 --- a/_sass/vendor/breakpoint/parsers/double/_default-pair.scss +++ /dev/null @@ -1,21 +0,0 @@ -@function breakpoint-parse-default-pair($first, $second) { - $default: breakpoint-get('default pair'); - $min: ''; - $max: ''; - - // Sort into min and max - $min: min($first, $second); - $max: max($first, $second); - - // Set Context - $context-setter: private-breakpoint-set-context(min-#{$default}, $min); - $context-setter: private-breakpoint-set-context(max-#{$default}, $max); - - // Make them EMs if need be - @if (breakpoint-get('to ems') == true) { - $min: breakpoint-to-base-em($min); - $max: breakpoint-to-base-em($max); - } - - @return '(min-#{$default}: #{$min}) and (max-#{$default}: #{$max})'; -} diff --git a/_sass/vendor/breakpoint/parsers/double/_default.scss b/_sass/vendor/breakpoint/parsers/double/_default.scss deleted file mode 100644 index 73190ed5..00000000 --- a/_sass/vendor/breakpoint/parsers/double/_default.scss +++ /dev/null @@ -1,22 +0,0 @@ -@function breakpoint-parse-double-default($first, $second) { - $feature: ''; - $value: ''; - - @if type-of($first) == 'string' { - $feature: $first; - $value: $second; - } - @else { - $feature: $second; - $value: $first; - } - - // Set Context - $context-setter: private-breakpoint-set-context($feature, $value); - - @if (breakpoint-get('to ems') == true) { - $value: breakpoint-to-base-em($value); - } - - @return '(#{$feature}: #{$value})' -} diff --git a/_sass/vendor/breakpoint/parsers/double/_double-string.scss b/_sass/vendor/breakpoint/parsers/double/_double-string.scss deleted file mode 100644 index c6fd0cb0..00000000 --- a/_sass/vendor/breakpoint/parsers/double/_double-string.scss +++ /dev/null @@ -1,22 +0,0 @@ -@function breakpoint-parse-double-string($first, $second) { - $feature: ''; - $value: ''; - - // Test to see which is the feature and which is the value - @if (breakpoint-string-value($first) == true) { - $feature: $first; - $value: $second; - } - @else if (breakpoint-string-value($second) == true) { - $feature: $second; - $value: $first; - } - @else { - @warn "Neither #{$first} nor #{$second} is a valid media query name."; - } - - // Set Context - $context-setter: private-breakpoint-set-context($feature, $value); - - @return '(#{$feature}: #{$value})'; -} \ No newline at end of file diff --git a/_sass/vendor/breakpoint/parsers/resolution/_resolution.scss b/_sass/vendor/breakpoint/parsers/resolution/_resolution.scss deleted file mode 100644 index 205e25cd..00000000 --- a/_sass/vendor/breakpoint/parsers/resolution/_resolution.scss +++ /dev/null @@ -1,62 +0,0 @@ -@use "sass:math"; - -@function breakpoint-make-resolutions($resolution) { - $length: length($resolution); - - $output: (); - - @if $length == 2 { - $feature: ''; - $value: ''; - - // Find which is number - @if type-of(nth($resolution, 1)) == 'number' { - $value: nth($resolution, 1); - } - @else { - $value: nth($resolution, 2); - } - - // Determine min/max/standard - @if index($resolution, 'min-resolution') { - $feature: 'min-'; - } - @else if index($resolution, 'max-resolution') { - $feature: 'max-'; - } - - $standard: '(#{$feature}resolution: #{$value})'; - - // If we're not dealing with dppx, - @if unit($value) != 'dppx' { - $base: 96dpi; - @if unit($value) == 'dpcm' { - $base: 243.84dpcm; - } - // Write out feature tests - $webkit: ''; - $moz: ''; - $webkit: '(-webkit-#{$feature}device-pixel-ratio: #{math.div($value, $base)})'; - $moz: '(#{$feature}-moz-device-pixel-ratio: #{math.div($value, $base)})'; - // Append to output - $output: append($output, $standard, space); - $output: append($output, $webkit, space); - $output: append($output, $moz, space); - } - @else { - $webkit: ''; - $moz: ''; - $webkit: '(-webkit-#{$feature}device-pixel-ratio: #{math.div($value, 1dppx)})'; - $moz: '(#{$feature}-moz-device-pixel-ratio: #{math.div($value, 1dppx)})'; - $fallback: '(#{$feature}resolution: #{math.div($value, 1dppx) * 96dpi})'; - // Append to output - $output: append($output, $standard, space); - $output: append($output, $webkit, space); - $output: append($output, $moz, space); - $output: append($output, $fallback, space); - } - - } - - @return $output; -} diff --git a/_sass/vendor/breakpoint/parsers/single/_default.scss b/_sass/vendor/breakpoint/parsers/single/_default.scss deleted file mode 100644 index 503ef427..00000000 --- a/_sass/vendor/breakpoint/parsers/single/_default.scss +++ /dev/null @@ -1,13 +0,0 @@ -@function breakpoint-parse-default($feature) { - $default: breakpoint-get('default feature'); - - // Set Context - $context-setter: private-breakpoint-set-context($default, $feature); - - @if (breakpoint-get('to ems') == true) and (type-of($feature) == 'number') { - @return '#{$default}: #{breakpoint-to-base-em($feature)}'; - } - @else { - @return '#{$default}: #{$feature}'; - } -} diff --git a/_sass/vendor/breakpoint/parsers/triple/_default.scss b/_sass/vendor/breakpoint/parsers/triple/_default.scss deleted file mode 100644 index 7fa418dd..00000000 --- a/_sass/vendor/breakpoint/parsers/triple/_default.scss +++ /dev/null @@ -1,18 +0,0 @@ -@function breakpoint-parse-triple-default($feature, $first, $second) { - - // Sort into min and max - $min: min($first, $second); - $max: max($first, $second); - - // Set Context - $context-setter: private-breakpoint-set-context(min-#{$feature}, $min); - $context-setter: private-breakpoint-set-context(max-#{$feature}, $max); - - // Make them EMs if need be - @if (breakpoint-get('to ems') == true) { - $min: breakpoint-to-base-em($min); - $max: breakpoint-to-base-em($max); - } - - @return '(min-#{$feature}: #{$min}) and (max-#{$feature}: #{$max})'; -} diff --git a/_sass/vendor/font-awesome/_animated.scss b/_sass/vendor/font-awesome/_animated.scss deleted file mode 100644 index 8a020dbf..00000000 --- a/_sass/vendor/font-awesome/_animated.scss +++ /dev/null @@ -1,34 +0,0 @@ -// Spinning Icons -// -------------------------- - -.#{$fa-css-prefix}-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} - -.#{$fa-css-prefix}-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} diff --git a/_sass/vendor/font-awesome/_bordered-pulled.scss b/_sass/vendor/font-awesome/_bordered-pulled.scss deleted file mode 100644 index d4b85a02..00000000 --- a/_sass/vendor/font-awesome/_bordered-pulled.scss +++ /dev/null @@ -1,25 +0,0 @@ -// Bordered & Pulled -// ------------------------- - -.#{$fa-css-prefix}-border { - padding: .2em .25em .15em; - border: solid .08em $fa-border-color; - border-radius: .1em; -} - -.#{$fa-css-prefix}-pull-left { float: left; } -.#{$fa-css-prefix}-pull-right { float: right; } - -.#{$fa-css-prefix} { - &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } - &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } -} - -/* Deprecated as of 4.4.0 */ -.pull-right { float: right; } -.pull-left { float: left; } - -.#{$fa-css-prefix} { - &.pull-left { margin-right: .3em; } - &.pull-right { margin-left: .3em; } -} diff --git a/_sass/vendor/font-awesome/_core.scss b/_sass/vendor/font-awesome/_core.scss deleted file mode 100644 index 04ab1e5e..00000000 --- a/_sass/vendor/font-awesome/_core.scss +++ /dev/null @@ -1,14 +0,0 @@ -// Base Class Definition -// ------------------------- - -@use "sass:list"; - -.#{$fa-css-prefix} { - display: inline-block; - font: normal normal normal list.slash($fa-font-size-base, $fa-line-height-base) FontAwesome; // shortening font declaration - font-size: inherit; // can't have font-size inherit on line above, so need to override - text-rendering: auto; // optimizelegibility throws things off #1094 - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -} diff --git a/_sass/vendor/font-awesome/_fixed-width.scss b/_sass/vendor/font-awesome/_fixed-width.scss deleted file mode 100644 index 5411f953..00000000 --- a/_sass/vendor/font-awesome/_fixed-width.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Fixed Width Icons -// ------------------------- -@use "sass:math"; - -.#{$fa-css-prefix}-fw { - width: math.div(18em, 14); - text-align: center; -} diff --git a/_sass/vendor/font-awesome/_font-awesome.scss b/_sass/vendor/font-awesome/_font-awesome.scss deleted file mode 100644 index a19d664c..00000000 --- a/_sass/vendor/font-awesome/_font-awesome.scss +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ - -@import "variables"; -@import "mixins"; -@import "path"; -@import "core"; -@import "larger"; -@import "fixed-width"; -@import "list"; -@import "bordered-pulled"; -@import "animated"; -@import "rotated-flipped"; -@import "stacked"; -@import "icons"; -@import "screen-reader"; diff --git a/_sass/vendor/font-awesome/_icons.scss b/_sass/vendor/font-awesome/_icons.scss deleted file mode 100644 index b64017ae..00000000 --- a/_sass/vendor/font-awesome/_icons.scss +++ /dev/null @@ -1,724 +0,0 @@ -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ - -.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; } -.#{$fa-css-prefix}-music:before { content: $fa-var-music; } -.#{$fa-css-prefix}-search:before { content: $fa-var-search; } -.#{$fa-css-prefix}-envelope-o:before { content: $fa-var-envelope-o; } -.#{$fa-css-prefix}-heart:before { content: $fa-var-heart; } -.#{$fa-css-prefix}-star:before { content: $fa-var-star; } -.#{$fa-css-prefix}-star-o:before { content: $fa-var-star-o; } -.#{$fa-css-prefix}-user:before { content: $fa-var-user; } -.#{$fa-css-prefix}-film:before { content: $fa-var-film; } -.#{$fa-css-prefix}-th-large:before { content: $fa-var-th-large; } -.#{$fa-css-prefix}-th:before { content: $fa-var-th; } -.#{$fa-css-prefix}-th-list:before { content: $fa-var-th-list; } -.#{$fa-css-prefix}-check:before { content: $fa-var-check; } -.#{$fa-css-prefix}-remove:before, -.#{$fa-css-prefix}-close:before, -.#{$fa-css-prefix}-times:before { content: $fa-var-times; } -.#{$fa-css-prefix}-search-plus:before { content: $fa-var-search-plus; } -.#{$fa-css-prefix}-search-minus:before { content: $fa-var-search-minus; } -.#{$fa-css-prefix}-power-off:before { content: $fa-var-power-off; } -.#{$fa-css-prefix}-signal:before { content: $fa-var-signal; } -.#{$fa-css-prefix}-gear:before, -.#{$fa-css-prefix}-cog:before { content: $fa-var-cog; } -.#{$fa-css-prefix}-trash-o:before { content: $fa-var-trash-o; } -.#{$fa-css-prefix}-home:before { content: $fa-var-home; } -.#{$fa-css-prefix}-file-o:before { content: $fa-var-file-o; } -.#{$fa-css-prefix}-clock-o:before { content: $fa-var-clock-o; } -.#{$fa-css-prefix}-road:before { content: $fa-var-road; } -.#{$fa-css-prefix}-download:before { content: $fa-var-download; } -.#{$fa-css-prefix}-arrow-circle-o-down:before { content: $fa-var-arrow-circle-o-down; } -.#{$fa-css-prefix}-arrow-circle-o-up:before { content: $fa-var-arrow-circle-o-up; } -.#{$fa-css-prefix}-inbox:before { content: $fa-var-inbox; } -.#{$fa-css-prefix}-play-circle-o:before { content: $fa-var-play-circle-o; } -.#{$fa-css-prefix}-rotate-right:before, -.#{$fa-css-prefix}-repeat:before { content: $fa-var-repeat; } -.#{$fa-css-prefix}-refresh:before { content: $fa-var-refresh; } -.#{$fa-css-prefix}-list-alt:before { content: $fa-var-list-alt; } -.#{$fa-css-prefix}-lock:before { content: $fa-var-lock; } -.#{$fa-css-prefix}-flag:before { content: $fa-var-flag; } -.#{$fa-css-prefix}-headphones:before { content: $fa-var-headphones; } -.#{$fa-css-prefix}-volume-off:before { content: $fa-var-volume-off; } -.#{$fa-css-prefix}-volume-down:before { content: $fa-var-volume-down; } -.#{$fa-css-prefix}-volume-up:before { content: $fa-var-volume-up; } -.#{$fa-css-prefix}-qrcode:before { content: $fa-var-qrcode; } -.#{$fa-css-prefix}-barcode:before { content: $fa-var-barcode; } -.#{$fa-css-prefix}-tag:before { content: $fa-var-tag; } -.#{$fa-css-prefix}-tags:before { content: $fa-var-tags; } -.#{$fa-css-prefix}-book:before { content: $fa-var-book; } -.#{$fa-css-prefix}-bookmark:before { content: $fa-var-bookmark; } -.#{$fa-css-prefix}-print:before { content: $fa-var-print; } -.#{$fa-css-prefix}-camera:before { content: $fa-var-camera; } -.#{$fa-css-prefix}-font:before { content: $fa-var-font; } -.#{$fa-css-prefix}-bold:before { content: $fa-var-bold; } -.#{$fa-css-prefix}-italic:before { content: $fa-var-italic; } -.#{$fa-css-prefix}-text-height:before { content: $fa-var-text-height; } -.#{$fa-css-prefix}-text-width:before { content: $fa-var-text-width; } -.#{$fa-css-prefix}-align-left:before { content: $fa-var-align-left; } -.#{$fa-css-prefix}-align-center:before { content: $fa-var-align-center; } -.#{$fa-css-prefix}-align-right:before { content: $fa-var-align-right; } -.#{$fa-css-prefix}-align-justify:before { content: $fa-var-align-justify; } -.#{$fa-css-prefix}-list:before { content: $fa-var-list; } -.#{$fa-css-prefix}-dedent:before, -.#{$fa-css-prefix}-outdent:before { content: $fa-var-outdent; } -.#{$fa-css-prefix}-indent:before { content: $fa-var-indent; } -.#{$fa-css-prefix}-video-camera:before { content: $fa-var-video-camera; } -.#{$fa-css-prefix}-photo:before, -.#{$fa-css-prefix}-image:before, -.#{$fa-css-prefix}-picture-o:before { content: $fa-var-picture-o; } -.#{$fa-css-prefix}-pencil:before { content: $fa-var-pencil; } -.#{$fa-css-prefix}-map-marker:before { content: $fa-var-map-marker; } -.#{$fa-css-prefix}-adjust:before { content: $fa-var-adjust; } -.#{$fa-css-prefix}-tint:before { content: $fa-var-tint; } -.#{$fa-css-prefix}-edit:before, -.#{$fa-css-prefix}-pencil-square-o:before { content: $fa-var-pencil-square-o; } -.#{$fa-css-prefix}-share-square-o:before { content: $fa-var-share-square-o; } -.#{$fa-css-prefix}-check-square-o:before { content: $fa-var-check-square-o; } -.#{$fa-css-prefix}-arrows:before { content: $fa-var-arrows; } -.#{$fa-css-prefix}-step-backward:before { content: $fa-var-step-backward; } -.#{$fa-css-prefix}-fast-backward:before { content: $fa-var-fast-backward; } -.#{$fa-css-prefix}-backward:before { content: $fa-var-backward; } -.#{$fa-css-prefix}-play:before { content: $fa-var-play; } -.#{$fa-css-prefix}-pause:before { content: $fa-var-pause; } -.#{$fa-css-prefix}-stop:before { content: $fa-var-stop; } -.#{$fa-css-prefix}-forward:before { content: $fa-var-forward; } -.#{$fa-css-prefix}-fast-forward:before { content: $fa-var-fast-forward; } -.#{$fa-css-prefix}-step-forward:before { content: $fa-var-step-forward; } -.#{$fa-css-prefix}-eject:before { content: $fa-var-eject; } -.#{$fa-css-prefix}-chevron-left:before { content: $fa-var-chevron-left; } -.#{$fa-css-prefix}-chevron-right:before { content: $fa-var-chevron-right; } -.#{$fa-css-prefix}-plus-circle:before { content: $fa-var-plus-circle; } -.#{$fa-css-prefix}-minus-circle:before { content: $fa-var-minus-circle; } -.#{$fa-css-prefix}-times-circle:before { content: $fa-var-times-circle; } -.#{$fa-css-prefix}-check-circle:before { content: $fa-var-check-circle; } -.#{$fa-css-prefix}-question-circle:before { content: $fa-var-question-circle; } -.#{$fa-css-prefix}-info-circle:before { content: $fa-var-info-circle; } -.#{$fa-css-prefix}-crosshairs:before { content: $fa-var-crosshairs; } -.#{$fa-css-prefix}-times-circle-o:before { content: $fa-var-times-circle-o; } -.#{$fa-css-prefix}-check-circle-o:before { content: $fa-var-check-circle-o; } -.#{$fa-css-prefix}-ban:before { content: $fa-var-ban; } -.#{$fa-css-prefix}-arrow-left:before { content: $fa-var-arrow-left; } -.#{$fa-css-prefix}-arrow-right:before { content: $fa-var-arrow-right; } -.#{$fa-css-prefix}-arrow-up:before { content: $fa-var-arrow-up; } -.#{$fa-css-prefix}-arrow-down:before { content: $fa-var-arrow-down; } -.#{$fa-css-prefix}-mail-forward:before, -.#{$fa-css-prefix}-share:before { content: $fa-var-share; } -.#{$fa-css-prefix}-expand:before { content: $fa-var-expand; } -.#{$fa-css-prefix}-compress:before { content: $fa-var-compress; } -.#{$fa-css-prefix}-plus:before { content: $fa-var-plus; } -.#{$fa-css-prefix}-minus:before { content: $fa-var-minus; } -.#{$fa-css-prefix}-asterisk:before { content: $fa-var-asterisk; } -.#{$fa-css-prefix}-exclamation-circle:before { content: $fa-var-exclamation-circle; } -.#{$fa-css-prefix}-gift:before { content: $fa-var-gift; } -.#{$fa-css-prefix}-leaf:before { content: $fa-var-leaf; } -.#{$fa-css-prefix}-fire:before { content: $fa-var-fire; } -.#{$fa-css-prefix}-eye:before { content: $fa-var-eye; } -.#{$fa-css-prefix}-eye-slash:before { content: $fa-var-eye-slash; } -.#{$fa-css-prefix}-warning:before, -.#{$fa-css-prefix}-exclamation-triangle:before { content: $fa-var-exclamation-triangle; } -.#{$fa-css-prefix}-plane:before { content: $fa-var-plane; } -.#{$fa-css-prefix}-calendar:before { content: $fa-var-calendar; } -.#{$fa-css-prefix}-random:before { content: $fa-var-random; } -.#{$fa-css-prefix}-comment:before { content: $fa-var-comment; } -.#{$fa-css-prefix}-magnet:before { content: $fa-var-magnet; } -.#{$fa-css-prefix}-chevron-up:before { content: $fa-var-chevron-up; } -.#{$fa-css-prefix}-chevron-down:before { content: $fa-var-chevron-down; } -.#{$fa-css-prefix}-retweet:before { content: $fa-var-retweet; } -.#{$fa-css-prefix}-shopping-cart:before { content: $fa-var-shopping-cart; } -.#{$fa-css-prefix}-folder:before { content: $fa-var-folder; } -.#{$fa-css-prefix}-folder-open:before { content: $fa-var-folder-open; } -.#{$fa-css-prefix}-arrows-v:before { content: $fa-var-arrows-v; } -.#{$fa-css-prefix}-arrows-h:before { content: $fa-var-arrows-h; } -.#{$fa-css-prefix}-bar-chart-o:before, -.#{$fa-css-prefix}-bar-chart:before { content: $fa-var-bar-chart; } -.#{$fa-css-prefix}-twitter-square:before { content: $fa-var-twitter-square; } -.#{$fa-css-prefix}-facebook-square:before { content: $fa-var-facebook-square; } -.#{$fa-css-prefix}-camera-retro:before { content: $fa-var-camera-retro; } -.#{$fa-css-prefix}-key:before { content: $fa-var-key; } -.#{$fa-css-prefix}-gears:before, -.#{$fa-css-prefix}-cogs:before { content: $fa-var-cogs; } -.#{$fa-css-prefix}-comments:before { content: $fa-var-comments; } -.#{$fa-css-prefix}-thumbs-o-up:before { content: $fa-var-thumbs-o-up; } -.#{$fa-css-prefix}-thumbs-o-down:before { content: $fa-var-thumbs-o-down; } -.#{$fa-css-prefix}-star-half:before { content: $fa-var-star-half; } -.#{$fa-css-prefix}-heart-o:before { content: $fa-var-heart-o; } -.#{$fa-css-prefix}-sign-out:before { content: $fa-var-sign-out; } -.#{$fa-css-prefix}-linkedin-square:before { content: $fa-var-linkedin-square; } -.#{$fa-css-prefix}-thumb-tack:before { content: $fa-var-thumb-tack; } -.#{$fa-css-prefix}-external-link:before { content: $fa-var-external-link; } -.#{$fa-css-prefix}-sign-in:before { content: $fa-var-sign-in; } -.#{$fa-css-prefix}-trophy:before { content: $fa-var-trophy; } -.#{$fa-css-prefix}-github-square:before { content: $fa-var-github-square; } -.#{$fa-css-prefix}-upload:before { content: $fa-var-upload; } -.#{$fa-css-prefix}-lemon-o:before { content: $fa-var-lemon-o; } -.#{$fa-css-prefix}-phone:before { content: $fa-var-phone; } -.#{$fa-css-prefix}-square-o:before { content: $fa-var-square-o; } -.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; } -.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; } -.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; } -.#{$fa-css-prefix}-facebook-f:before, -.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; } -.#{$fa-css-prefix}-github:before { content: $fa-var-github; } -.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; } -.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; } -.#{$fa-css-prefix}-feed:before, -.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; } -.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; } -.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; } -.#{$fa-css-prefix}-bell:before { content: $fa-var-bell; } -.#{$fa-css-prefix}-certificate:before { content: $fa-var-certificate; } -.#{$fa-css-prefix}-hand-o-right:before { content: $fa-var-hand-o-right; } -.#{$fa-css-prefix}-hand-o-left:before { content: $fa-var-hand-o-left; } -.#{$fa-css-prefix}-hand-o-up:before { content: $fa-var-hand-o-up; } -.#{$fa-css-prefix}-hand-o-down:before { content: $fa-var-hand-o-down; } -.#{$fa-css-prefix}-arrow-circle-left:before { content: $fa-var-arrow-circle-left; } -.#{$fa-css-prefix}-arrow-circle-right:before { content: $fa-var-arrow-circle-right; } -.#{$fa-css-prefix}-arrow-circle-up:before { content: $fa-var-arrow-circle-up; } -.#{$fa-css-prefix}-arrow-circle-down:before { content: $fa-var-arrow-circle-down; } -.#{$fa-css-prefix}-globe:before { content: $fa-var-globe; } -.#{$fa-css-prefix}-wrench:before { content: $fa-var-wrench; } -.#{$fa-css-prefix}-tasks:before { content: $fa-var-tasks; } -.#{$fa-css-prefix}-filter:before { content: $fa-var-filter; } -.#{$fa-css-prefix}-briefcase:before { content: $fa-var-briefcase; } -.#{$fa-css-prefix}-arrows-alt:before { content: $fa-var-arrows-alt; } -.#{$fa-css-prefix}-group:before, -.#{$fa-css-prefix}-users:before { content: $fa-var-users; } -.#{$fa-css-prefix}-chain:before, -.#{$fa-css-prefix}-link:before { content: $fa-var-link; } -.#{$fa-css-prefix}-cloud:before { content: $fa-var-cloud; } -.#{$fa-css-prefix}-flask:before { content: $fa-var-flask; } -.#{$fa-css-prefix}-cut:before, -.#{$fa-css-prefix}-scissors:before { content: $fa-var-scissors; } -.#{$fa-css-prefix}-copy:before, -.#{$fa-css-prefix}-files-o:before { content: $fa-var-files-o; } -.#{$fa-css-prefix}-paperclip:before { content: $fa-var-paperclip; } -.#{$fa-css-prefix}-save:before, -.#{$fa-css-prefix}-floppy-o:before { content: $fa-var-floppy-o; } -.#{$fa-css-prefix}-square:before { content: $fa-var-square; } -.#{$fa-css-prefix}-navicon:before, -.#{$fa-css-prefix}-reorder:before, -.#{$fa-css-prefix}-bars:before { content: $fa-var-bars; } -.#{$fa-css-prefix}-list-ul:before { content: $fa-var-list-ul; } -.#{$fa-css-prefix}-list-ol:before { content: $fa-var-list-ol; } -.#{$fa-css-prefix}-strikethrough:before { content: $fa-var-strikethrough; } -.#{$fa-css-prefix}-underline:before { content: $fa-var-underline; } -.#{$fa-css-prefix}-table:before { content: $fa-var-table; } -.#{$fa-css-prefix}-magic:before { content: $fa-var-magic; } -.#{$fa-css-prefix}-truck:before { content: $fa-var-truck; } -.#{$fa-css-prefix}-pinterest:before { content: $fa-var-pinterest; } -.#{$fa-css-prefix}-pinterest-square:before { content: $fa-var-pinterest-square; } -.#{$fa-css-prefix}-google-plus-square:before { content: $fa-var-google-plus-square; } -.#{$fa-css-prefix}-google-plus:before { content: $fa-var-google-plus; } -.#{$fa-css-prefix}-money:before { content: $fa-var-money; } -.#{$fa-css-prefix}-caret-down:before { content: $fa-var-caret-down; } -.#{$fa-css-prefix}-caret-up:before { content: $fa-var-caret-up; } -.#{$fa-css-prefix}-caret-left:before { content: $fa-var-caret-left; } -.#{$fa-css-prefix}-caret-right:before { content: $fa-var-caret-right; } -.#{$fa-css-prefix}-columns:before { content: $fa-var-columns; } -.#{$fa-css-prefix}-unsorted:before, -.#{$fa-css-prefix}-sort:before { content: $fa-var-sort; } -.#{$fa-css-prefix}-sort-down:before, -.#{$fa-css-prefix}-sort-desc:before { content: $fa-var-sort-desc; } -.#{$fa-css-prefix}-sort-up:before, -.#{$fa-css-prefix}-sort-asc:before { content: $fa-var-sort-asc; } -.#{$fa-css-prefix}-envelope:before { content: $fa-var-envelope; } -.#{$fa-css-prefix}-linkedin:before { content: $fa-var-linkedin; } -.#{$fa-css-prefix}-rotate-left:before, -.#{$fa-css-prefix}-undo:before { content: $fa-var-undo; } -.#{$fa-css-prefix}-legal:before, -.#{$fa-css-prefix}-gavel:before { content: $fa-var-gavel; } -.#{$fa-css-prefix}-dashboard:before, -.#{$fa-css-prefix}-tachometer:before { content: $fa-var-tachometer; } -.#{$fa-css-prefix}-comment-o:before { content: $fa-var-comment-o; } -.#{$fa-css-prefix}-comments-o:before { content: $fa-var-comments-o; } -.#{$fa-css-prefix}-flash:before, -.#{$fa-css-prefix}-bolt:before { content: $fa-var-bolt; } -.#{$fa-css-prefix}-sitemap:before { content: $fa-var-sitemap; } -.#{$fa-css-prefix}-umbrella:before { content: $fa-var-umbrella; } -.#{$fa-css-prefix}-paste:before, -.#{$fa-css-prefix}-clipboard:before { content: $fa-var-clipboard; } -.#{$fa-css-prefix}-lightbulb-o:before { content: $fa-var-lightbulb-o; } -.#{$fa-css-prefix}-exchange:before { content: $fa-var-exchange; } -.#{$fa-css-prefix}-cloud-download:before { content: $fa-var-cloud-download; } -.#{$fa-css-prefix}-cloud-upload:before { content: $fa-var-cloud-upload; } -.#{$fa-css-prefix}-user-md:before { content: $fa-var-user-md; } -.#{$fa-css-prefix}-stethoscope:before { content: $fa-var-stethoscope; } -.#{$fa-css-prefix}-suitcase:before { content: $fa-var-suitcase; } -.#{$fa-css-prefix}-bell-o:before { content: $fa-var-bell-o; } -.#{$fa-css-prefix}-coffee:before { content: $fa-var-coffee; } -.#{$fa-css-prefix}-cutlery:before { content: $fa-var-cutlery; } -.#{$fa-css-prefix}-file-text-o:before { content: $fa-var-file-text-o; } -.#{$fa-css-prefix}-building-o:before { content: $fa-var-building-o; } -.#{$fa-css-prefix}-hospital-o:before { content: $fa-var-hospital-o; } -.#{$fa-css-prefix}-ambulance:before { content: $fa-var-ambulance; } -.#{$fa-css-prefix}-medkit:before { content: $fa-var-medkit; } -.#{$fa-css-prefix}-fighter-jet:before { content: $fa-var-fighter-jet; } -.#{$fa-css-prefix}-beer:before { content: $fa-var-beer; } -.#{$fa-css-prefix}-h-square:before { content: $fa-var-h-square; } -.#{$fa-css-prefix}-plus-square:before { content: $fa-var-plus-square; } -.#{$fa-css-prefix}-angle-double-left:before { content: $fa-var-angle-double-left; } -.#{$fa-css-prefix}-angle-double-right:before { content: $fa-var-angle-double-right; } -.#{$fa-css-prefix}-angle-double-up:before { content: $fa-var-angle-double-up; } -.#{$fa-css-prefix}-angle-double-down:before { content: $fa-var-angle-double-down; } -.#{$fa-css-prefix}-angle-left:before { content: $fa-var-angle-left; } -.#{$fa-css-prefix}-angle-right:before { content: $fa-var-angle-right; } -.#{$fa-css-prefix}-angle-up:before { content: $fa-var-angle-up; } -.#{$fa-css-prefix}-angle-down:before { content: $fa-var-angle-down; } -.#{$fa-css-prefix}-desktop:before { content: $fa-var-desktop; } -.#{$fa-css-prefix}-laptop:before { content: $fa-var-laptop; } -.#{$fa-css-prefix}-tablet:before { content: $fa-var-tablet; } -.#{$fa-css-prefix}-mobile-phone:before, -.#{$fa-css-prefix}-mobile:before { content: $fa-var-mobile; } -.#{$fa-css-prefix}-circle-o:before { content: $fa-var-circle-o; } -.#{$fa-css-prefix}-quote-left:before { content: $fa-var-quote-left; } -.#{$fa-css-prefix}-quote-right:before { content: $fa-var-quote-right; } -.#{$fa-css-prefix}-spinner:before { content: $fa-var-spinner; } -.#{$fa-css-prefix}-circle:before { content: $fa-var-circle; } -.#{$fa-css-prefix}-mail-reply:before, -.#{$fa-css-prefix}-reply:before { content: $fa-var-reply; } -.#{$fa-css-prefix}-github-alt:before { content: $fa-var-github-alt; } -.#{$fa-css-prefix}-folder-o:before { content: $fa-var-folder-o; } -.#{$fa-css-prefix}-folder-open-o:before { content: $fa-var-folder-open-o; } -.#{$fa-css-prefix}-smile-o:before { content: $fa-var-smile-o; } -.#{$fa-css-prefix}-frown-o:before { content: $fa-var-frown-o; } -.#{$fa-css-prefix}-meh-o:before { content: $fa-var-meh-o; } -.#{$fa-css-prefix}-gamepad:before { content: $fa-var-gamepad; } -.#{$fa-css-prefix}-keyboard-o:before { content: $fa-var-keyboard-o; } -.#{$fa-css-prefix}-flag-o:before { content: $fa-var-flag-o; } -.#{$fa-css-prefix}-flag-checkered:before { content: $fa-var-flag-checkered; } -.#{$fa-css-prefix}-terminal:before { content: $fa-var-terminal; } -.#{$fa-css-prefix}-code:before { content: $fa-var-code; } -.#{$fa-css-prefix}-mail-reply-all:before, -.#{$fa-css-prefix}-reply-all:before { content: $fa-var-reply-all; } -.#{$fa-css-prefix}-star-half-empty:before, -.#{$fa-css-prefix}-star-half-full:before, -.#{$fa-css-prefix}-star-half-o:before { content: $fa-var-star-half-o; } -.#{$fa-css-prefix}-location-arrow:before { content: $fa-var-location-arrow; } -.#{$fa-css-prefix}-crop:before { content: $fa-var-crop; } -.#{$fa-css-prefix}-code-fork:before { content: $fa-var-code-fork; } -.#{$fa-css-prefix}-unlink:before, -.#{$fa-css-prefix}-chain-broken:before { content: $fa-var-chain-broken; } -.#{$fa-css-prefix}-question:before { content: $fa-var-question; } -.#{$fa-css-prefix}-info:before { content: $fa-var-info; } -.#{$fa-css-prefix}-exclamation:before { content: $fa-var-exclamation; } -.#{$fa-css-prefix}-superscript:before { content: $fa-var-superscript; } -.#{$fa-css-prefix}-subscript:before { content: $fa-var-subscript; } -.#{$fa-css-prefix}-eraser:before { content: $fa-var-eraser; } -.#{$fa-css-prefix}-puzzle-piece:before { content: $fa-var-puzzle-piece; } -.#{$fa-css-prefix}-microphone:before { content: $fa-var-microphone; } -.#{$fa-css-prefix}-microphone-slash:before { content: $fa-var-microphone-slash; } -.#{$fa-css-prefix}-shield:before { content: $fa-var-shield; } -.#{$fa-css-prefix}-calendar-o:before { content: $fa-var-calendar-o; } -.#{$fa-css-prefix}-fire-extinguisher:before { content: $fa-var-fire-extinguisher; } -.#{$fa-css-prefix}-rocket:before { content: $fa-var-rocket; } -.#{$fa-css-prefix}-maxcdn:before { content: $fa-var-maxcdn; } -.#{$fa-css-prefix}-chevron-circle-left:before { content: $fa-var-chevron-circle-left; } -.#{$fa-css-prefix}-chevron-circle-right:before { content: $fa-var-chevron-circle-right; } -.#{$fa-css-prefix}-chevron-circle-up:before { content: $fa-var-chevron-circle-up; } -.#{$fa-css-prefix}-chevron-circle-down:before { content: $fa-var-chevron-circle-down; } -.#{$fa-css-prefix}-html5:before { content: $fa-var-html5; } -.#{$fa-css-prefix}-css3:before { content: $fa-var-css3; } -.#{$fa-css-prefix}-anchor:before { content: $fa-var-anchor; } -.#{$fa-css-prefix}-unlock-alt:before { content: $fa-var-unlock-alt; } -.#{$fa-css-prefix}-bullseye:before { content: $fa-var-bullseye; } -.#{$fa-css-prefix}-ellipsis-h:before { content: $fa-var-ellipsis-h; } -.#{$fa-css-prefix}-ellipsis-v:before { content: $fa-var-ellipsis-v; } -.#{$fa-css-prefix}-rss-square:before { content: $fa-var-rss-square; } -.#{$fa-css-prefix}-play-circle:before { content: $fa-var-play-circle; } -.#{$fa-css-prefix}-ticket:before { content: $fa-var-ticket; } -.#{$fa-css-prefix}-minus-square:before { content: $fa-var-minus-square; } -.#{$fa-css-prefix}-minus-square-o:before { content: $fa-var-minus-square-o; } -.#{$fa-css-prefix}-level-up:before { content: $fa-var-level-up; } -.#{$fa-css-prefix}-level-down:before { content: $fa-var-level-down; } -.#{$fa-css-prefix}-check-square:before { content: $fa-var-check-square; } -.#{$fa-css-prefix}-pencil-square:before { content: $fa-var-pencil-square; } -.#{$fa-css-prefix}-external-link-square:before { content: $fa-var-external-link-square; } -.#{$fa-css-prefix}-share-square:before { content: $fa-var-share-square; } -.#{$fa-css-prefix}-compass:before { content: $fa-var-compass; } -.#{$fa-css-prefix}-toggle-down:before, -.#{$fa-css-prefix}-caret-square-o-down:before { content: $fa-var-caret-square-o-down; } -.#{$fa-css-prefix}-toggle-up:before, -.#{$fa-css-prefix}-caret-square-o-up:before { content: $fa-var-caret-square-o-up; } -.#{$fa-css-prefix}-toggle-right:before, -.#{$fa-css-prefix}-caret-square-o-right:before { content: $fa-var-caret-square-o-right; } -.#{$fa-css-prefix}-euro:before, -.#{$fa-css-prefix}-eur:before { content: $fa-var-eur; } -.#{$fa-css-prefix}-gbp:before { content: $fa-var-gbp; } -.#{$fa-css-prefix}-dollar:before, -.#{$fa-css-prefix}-usd:before { content: $fa-var-usd; } -.#{$fa-css-prefix}-rupee:before, -.#{$fa-css-prefix}-inr:before { content: $fa-var-inr; } -.#{$fa-css-prefix}-cny:before, -.#{$fa-css-prefix}-rmb:before, -.#{$fa-css-prefix}-yen:before, -.#{$fa-css-prefix}-jpy:before { content: $fa-var-jpy; } -.#{$fa-css-prefix}-ruble:before, -.#{$fa-css-prefix}-rouble:before, -.#{$fa-css-prefix}-rub:before { content: $fa-var-rub; } -.#{$fa-css-prefix}-won:before, -.#{$fa-css-prefix}-krw:before { content: $fa-var-krw; } -.#{$fa-css-prefix}-bitcoin:before, -.#{$fa-css-prefix}-btc:before { content: $fa-var-btc; } -.#{$fa-css-prefix}-file:before { content: $fa-var-file; } -.#{$fa-css-prefix}-file-text:before { content: $fa-var-file-text; } -.#{$fa-css-prefix}-sort-alpha-asc:before { content: $fa-var-sort-alpha-asc; } -.#{$fa-css-prefix}-sort-alpha-desc:before { content: $fa-var-sort-alpha-desc; } -.#{$fa-css-prefix}-sort-amount-asc:before { content: $fa-var-sort-amount-asc; } -.#{$fa-css-prefix}-sort-amount-desc:before { content: $fa-var-sort-amount-desc; } -.#{$fa-css-prefix}-sort-numeric-asc:before { content: $fa-var-sort-numeric-asc; } -.#{$fa-css-prefix}-sort-numeric-desc:before { content: $fa-var-sort-numeric-desc; } -.#{$fa-css-prefix}-thumbs-up:before { content: $fa-var-thumbs-up; } -.#{$fa-css-prefix}-thumbs-down:before { content: $fa-var-thumbs-down; } -.#{$fa-css-prefix}-youtube-square:before { content: $fa-var-youtube-square; } -.#{$fa-css-prefix}-youtube:before { content: $fa-var-youtube; } -.#{$fa-css-prefix}-xing:before { content: $fa-var-xing; } -.#{$fa-css-prefix}-xing-square:before { content: $fa-var-xing-square; } -.#{$fa-css-prefix}-youtube-play:before { content: $fa-var-youtube-play; } -.#{$fa-css-prefix}-dropbox:before { content: $fa-var-dropbox; } -.#{$fa-css-prefix}-stack-overflow:before { content: $fa-var-stack-overflow; } -.#{$fa-css-prefix}-instagram:before { content: $fa-var-instagram; } -.#{$fa-css-prefix}-flickr:before { content: $fa-var-flickr; } -.#{$fa-css-prefix}-adn:before { content: $fa-var-adn; } -.#{$fa-css-prefix}-bitbucket:before { content: $fa-var-bitbucket; } -.#{$fa-css-prefix}-bitbucket-square:before { content: $fa-var-bitbucket-square; } -.#{$fa-css-prefix}-tumblr:before { content: $fa-var-tumblr; } -.#{$fa-css-prefix}-tumblr-square:before { content: $fa-var-tumblr-square; } -.#{$fa-css-prefix}-long-arrow-down:before { content: $fa-var-long-arrow-down; } -.#{$fa-css-prefix}-long-arrow-up:before { content: $fa-var-long-arrow-up; } -.#{$fa-css-prefix}-long-arrow-left:before { content: $fa-var-long-arrow-left; } -.#{$fa-css-prefix}-long-arrow-right:before { content: $fa-var-long-arrow-right; } -.#{$fa-css-prefix}-apple:before { content: $fa-var-apple; } -.#{$fa-css-prefix}-windows:before { content: $fa-var-windows; } -.#{$fa-css-prefix}-android:before { content: $fa-var-android; } -.#{$fa-css-prefix}-linux:before { content: $fa-var-linux; } -.#{$fa-css-prefix}-dribbble:before { content: $fa-var-dribbble; } -.#{$fa-css-prefix}-skype:before { content: $fa-var-skype; } -.#{$fa-css-prefix}-foursquare:before { content: $fa-var-foursquare; } -.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; } -.#{$fa-css-prefix}-female:before { content: $fa-var-female; } -.#{$fa-css-prefix}-male:before { content: $fa-var-male; } -.#{$fa-css-prefix}-gittip:before, -.#{$fa-css-prefix}-gratipay:before { content: $fa-var-gratipay; } -.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; } -.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; } -.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; } -.#{$fa-css-prefix}-bug:before { content: $fa-var-bug; } -.#{$fa-css-prefix}-vk:before { content: $fa-var-vk; } -.#{$fa-css-prefix}-weibo:before { content: $fa-var-weibo; } -.#{$fa-css-prefix}-renren:before { content: $fa-var-renren; } -.#{$fa-css-prefix}-pagelines:before { content: $fa-var-pagelines; } -.#{$fa-css-prefix}-stack-exchange:before { content: $fa-var-stack-exchange; } -.#{$fa-css-prefix}-arrow-circle-o-right:before { content: $fa-var-arrow-circle-o-right; } -.#{$fa-css-prefix}-arrow-circle-o-left:before { content: $fa-var-arrow-circle-o-left; } -.#{$fa-css-prefix}-toggle-left:before, -.#{$fa-css-prefix}-caret-square-o-left:before { content: $fa-var-caret-square-o-left; } -.#{$fa-css-prefix}-dot-circle-o:before { content: $fa-var-dot-circle-o; } -.#{$fa-css-prefix}-wheelchair:before { content: $fa-var-wheelchair; } -.#{$fa-css-prefix}-vimeo-square:before { content: $fa-var-vimeo-square; } -.#{$fa-css-prefix}-turkish-lira:before, -.#{$fa-css-prefix}-try:before { content: $fa-var-try; } -.#{$fa-css-prefix}-plus-square-o:before { content: $fa-var-plus-square-o; } -.#{$fa-css-prefix}-space-shuttle:before { content: $fa-var-space-shuttle; } -.#{$fa-css-prefix}-slack:before { content: $fa-var-slack; } -.#{$fa-css-prefix}-envelope-square:before { content: $fa-var-envelope-square; } -.#{$fa-css-prefix}-wordpress:before { content: $fa-var-wordpress; } -.#{$fa-css-prefix}-openid:before { content: $fa-var-openid; } -.#{$fa-css-prefix}-institution:before, -.#{$fa-css-prefix}-bank:before, -.#{$fa-css-prefix}-university:before { content: $fa-var-university; } -.#{$fa-css-prefix}-mortar-board:before, -.#{$fa-css-prefix}-graduation-cap:before { content: $fa-var-graduation-cap; } -.#{$fa-css-prefix}-yahoo:before { content: $fa-var-yahoo; } -.#{$fa-css-prefix}-google:before { content: $fa-var-google; } -.#{$fa-css-prefix}-reddit:before { content: $fa-var-reddit; } -.#{$fa-css-prefix}-reddit-square:before { content: $fa-var-reddit-square; } -.#{$fa-css-prefix}-stumbleupon-circle:before { content: $fa-var-stumbleupon-circle; } -.#{$fa-css-prefix}-stumbleupon:before { content: $fa-var-stumbleupon; } -.#{$fa-css-prefix}-delicious:before { content: $fa-var-delicious; } -.#{$fa-css-prefix}-digg:before { content: $fa-var-digg; } -.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; } -.#{$fa-css-prefix}-pied-piper-alt:before { content: $fa-var-pied-piper-alt; } -.#{$fa-css-prefix}-drupal:before { content: $fa-var-drupal; } -.#{$fa-css-prefix}-joomla:before { content: $fa-var-joomla; } -.#{$fa-css-prefix}-language:before { content: $fa-var-language; } -.#{$fa-css-prefix}-fax:before { content: $fa-var-fax; } -.#{$fa-css-prefix}-building:before { content: $fa-var-building; } -.#{$fa-css-prefix}-child:before { content: $fa-var-child; } -.#{$fa-css-prefix}-paw:before { content: $fa-var-paw; } -.#{$fa-css-prefix}-spoon:before { content: $fa-var-spoon; } -.#{$fa-css-prefix}-cube:before { content: $fa-var-cube; } -.#{$fa-css-prefix}-cubes:before { content: $fa-var-cubes; } -.#{$fa-css-prefix}-behance:before { content: $fa-var-behance; } -.#{$fa-css-prefix}-behance-square:before { content: $fa-var-behance-square; } -.#{$fa-css-prefix}-steam:before { content: $fa-var-steam; } -.#{$fa-css-prefix}-steam-square:before { content: $fa-var-steam-square; } -.#{$fa-css-prefix}-recycle:before { content: $fa-var-recycle; } -.#{$fa-css-prefix}-automobile:before, -.#{$fa-css-prefix}-car:before { content: $fa-var-car; } -.#{$fa-css-prefix}-cab:before, -.#{$fa-css-prefix}-taxi:before { content: $fa-var-taxi; } -.#{$fa-css-prefix}-tree:before { content: $fa-var-tree; } -.#{$fa-css-prefix}-spotify:before { content: $fa-var-spotify; } -.#{$fa-css-prefix}-deviantart:before { content: $fa-var-deviantart; } -.#{$fa-css-prefix}-soundcloud:before { content: $fa-var-soundcloud; } -.#{$fa-css-prefix}-database:before { content: $fa-var-database; } -.#{$fa-css-prefix}-file-pdf-o:before { content: $fa-var-file-pdf-o; } -.#{$fa-css-prefix}-file-word-o:before { content: $fa-var-file-word-o; } -.#{$fa-css-prefix}-file-excel-o:before { content: $fa-var-file-excel-o; } -.#{$fa-css-prefix}-file-powerpoint-o:before { content: $fa-var-file-powerpoint-o; } -.#{$fa-css-prefix}-file-photo-o:before, -.#{$fa-css-prefix}-file-picture-o:before, -.#{$fa-css-prefix}-file-image-o:before { content: $fa-var-file-image-o; } -.#{$fa-css-prefix}-file-zip-o:before, -.#{$fa-css-prefix}-file-archive-o:before { content: $fa-var-file-archive-o; } -.#{$fa-css-prefix}-file-sound-o:before, -.#{$fa-css-prefix}-file-audio-o:before { content: $fa-var-file-audio-o; } -.#{$fa-css-prefix}-file-movie-o:before, -.#{$fa-css-prefix}-file-video-o:before { content: $fa-var-file-video-o; } -.#{$fa-css-prefix}-file-code-o:before { content: $fa-var-file-code-o; } -.#{$fa-css-prefix}-vine:before { content: $fa-var-vine; } -.#{$fa-css-prefix}-codepen:before { content: $fa-var-codepen; } -.#{$fa-css-prefix}-jsfiddle:before { content: $fa-var-jsfiddle; } -.#{$fa-css-prefix}-life-bouy:before, -.#{$fa-css-prefix}-life-buoy:before, -.#{$fa-css-prefix}-life-saver:before, -.#{$fa-css-prefix}-support:before, -.#{$fa-css-prefix}-life-ring:before { content: $fa-var-life-ring; } -.#{$fa-css-prefix}-circle-o-notch:before { content: $fa-var-circle-o-notch; } -.#{$fa-css-prefix}-ra:before, -.#{$fa-css-prefix}-rebel:before { content: $fa-var-rebel; } -.#{$fa-css-prefix}-ge:before, -.#{$fa-css-prefix}-empire:before { content: $fa-var-empire; } -.#{$fa-css-prefix}-git-square:before { content: $fa-var-git-square; } -.#{$fa-css-prefix}-git:before { content: $fa-var-git; } -.#{$fa-css-prefix}-y-combinator-square:before, -.#{$fa-css-prefix}-yc-square:before, -.#{$fa-css-prefix}-hacker-news:before { content: $fa-var-hacker-news; } -.#{$fa-css-prefix}-tencent-weibo:before { content: $fa-var-tencent-weibo; } -.#{$fa-css-prefix}-qq:before { content: $fa-var-qq; } -.#{$fa-css-prefix}-wechat:before, -.#{$fa-css-prefix}-weixin:before { content: $fa-var-weixin; } -.#{$fa-css-prefix}-send:before, -.#{$fa-css-prefix}-paper-plane:before { content: $fa-var-paper-plane; } -.#{$fa-css-prefix}-send-o:before, -.#{$fa-css-prefix}-paper-plane-o:before { content: $fa-var-paper-plane-o; } -.#{$fa-css-prefix}-history:before { content: $fa-var-history; } -.#{$fa-css-prefix}-circle-thin:before { content: $fa-var-circle-thin; } -.#{$fa-css-prefix}-header:before { content: $fa-var-header; } -.#{$fa-css-prefix}-paragraph:before { content: $fa-var-paragraph; } -.#{$fa-css-prefix}-sliders:before { content: $fa-var-sliders; } -.#{$fa-css-prefix}-share-alt:before { content: $fa-var-share-alt; } -.#{$fa-css-prefix}-share-alt-square:before { content: $fa-var-share-alt-square; } -.#{$fa-css-prefix}-bomb:before { content: $fa-var-bomb; } -.#{$fa-css-prefix}-soccer-ball-o:before, -.#{$fa-css-prefix}-futbol-o:before { content: $fa-var-futbol-o; } -.#{$fa-css-prefix}-tty:before { content: $fa-var-tty; } -.#{$fa-css-prefix}-binoculars:before { content: $fa-var-binoculars; } -.#{$fa-css-prefix}-plug:before { content: $fa-var-plug; } -.#{$fa-css-prefix}-slideshare:before { content: $fa-var-slideshare; } -.#{$fa-css-prefix}-twitch:before { content: $fa-var-twitch; } -.#{$fa-css-prefix}-yelp:before { content: $fa-var-yelp; } -.#{$fa-css-prefix}-newspaper-o:before { content: $fa-var-newspaper-o; } -.#{$fa-css-prefix}-wifi:before { content: $fa-var-wifi; } -.#{$fa-css-prefix}-calculator:before { content: $fa-var-calculator; } -.#{$fa-css-prefix}-paypal:before { content: $fa-var-paypal; } -.#{$fa-css-prefix}-google-wallet:before { content: $fa-var-google-wallet; } -.#{$fa-css-prefix}-cc-visa:before { content: $fa-var-cc-visa; } -.#{$fa-css-prefix}-cc-mastercard:before { content: $fa-var-cc-mastercard; } -.#{$fa-css-prefix}-cc-discover:before { content: $fa-var-cc-discover; } -.#{$fa-css-prefix}-cc-amex:before { content: $fa-var-cc-amex; } -.#{$fa-css-prefix}-cc-paypal:before { content: $fa-var-cc-paypal; } -.#{$fa-css-prefix}-cc-stripe:before { content: $fa-var-cc-stripe; } -.#{$fa-css-prefix}-bell-slash:before { content: $fa-var-bell-slash; } -.#{$fa-css-prefix}-bell-slash-o:before { content: $fa-var-bell-slash-o; } -.#{$fa-css-prefix}-trash:before { content: $fa-var-trash; } -.#{$fa-css-prefix}-copyright:before { content: $fa-var-copyright; } -.#{$fa-css-prefix}-at:before { content: $fa-var-at; } -.#{$fa-css-prefix}-eyedropper:before { content: $fa-var-eyedropper; } -.#{$fa-css-prefix}-paint-brush:before { content: $fa-var-paint-brush; } -.#{$fa-css-prefix}-birthday-cake:before { content: $fa-var-birthday-cake; } -.#{$fa-css-prefix}-area-chart:before { content: $fa-var-area-chart; } -.#{$fa-css-prefix}-pie-chart:before { content: $fa-var-pie-chart; } -.#{$fa-css-prefix}-line-chart:before { content: $fa-var-line-chart; } -.#{$fa-css-prefix}-lastfm:before { content: $fa-var-lastfm; } -.#{$fa-css-prefix}-lastfm-square:before { content: $fa-var-lastfm-square; } -.#{$fa-css-prefix}-toggle-off:before { content: $fa-var-toggle-off; } -.#{$fa-css-prefix}-toggle-on:before { content: $fa-var-toggle-on; } -.#{$fa-css-prefix}-bicycle:before { content: $fa-var-bicycle; } -.#{$fa-css-prefix}-bus:before { content: $fa-var-bus; } -.#{$fa-css-prefix}-ioxhost:before { content: $fa-var-ioxhost; } -.#{$fa-css-prefix}-angellist:before { content: $fa-var-angellist; } -.#{$fa-css-prefix}-cc:before { content: $fa-var-cc; } -.#{$fa-css-prefix}-shekel:before, -.#{$fa-css-prefix}-sheqel:before, -.#{$fa-css-prefix}-ils:before { content: $fa-var-ils; } -.#{$fa-css-prefix}-meanpath:before { content: $fa-var-meanpath; } -.#{$fa-css-prefix}-buysellads:before { content: $fa-var-buysellads; } -.#{$fa-css-prefix}-connectdevelop:before { content: $fa-var-connectdevelop; } -.#{$fa-css-prefix}-dashcube:before { content: $fa-var-dashcube; } -.#{$fa-css-prefix}-forumbee:before { content: $fa-var-forumbee; } -.#{$fa-css-prefix}-leanpub:before { content: $fa-var-leanpub; } -.#{$fa-css-prefix}-sellsy:before { content: $fa-var-sellsy; } -.#{$fa-css-prefix}-shirtsinbulk:before { content: $fa-var-shirtsinbulk; } -.#{$fa-css-prefix}-simplybuilt:before { content: $fa-var-simplybuilt; } -.#{$fa-css-prefix}-skyatlas:before { content: $fa-var-skyatlas; } -.#{$fa-css-prefix}-cart-plus:before { content: $fa-var-cart-plus; } -.#{$fa-css-prefix}-cart-arrow-down:before { content: $fa-var-cart-arrow-down; } -.#{$fa-css-prefix}-diamond:before { content: $fa-var-diamond; } -.#{$fa-css-prefix}-ship:before { content: $fa-var-ship; } -.#{$fa-css-prefix}-user-secret:before { content: $fa-var-user-secret; } -.#{$fa-css-prefix}-motorcycle:before { content: $fa-var-motorcycle; } -.#{$fa-css-prefix}-street-view:before { content: $fa-var-street-view; } -.#{$fa-css-prefix}-heartbeat:before { content: $fa-var-heartbeat; } -.#{$fa-css-prefix}-venus:before { content: $fa-var-venus; } -.#{$fa-css-prefix}-mars:before { content: $fa-var-mars; } -.#{$fa-css-prefix}-mercury:before { content: $fa-var-mercury; } -.#{$fa-css-prefix}-intersex:before, -.#{$fa-css-prefix}-transgender:before { content: $fa-var-transgender; } -.#{$fa-css-prefix}-transgender-alt:before { content: $fa-var-transgender-alt; } -.#{$fa-css-prefix}-venus-double:before { content: $fa-var-venus-double; } -.#{$fa-css-prefix}-mars-double:before { content: $fa-var-mars-double; } -.#{$fa-css-prefix}-venus-mars:before { content: $fa-var-venus-mars; } -.#{$fa-css-prefix}-mars-stroke:before { content: $fa-var-mars-stroke; } -.#{$fa-css-prefix}-mars-stroke-v:before { content: $fa-var-mars-stroke-v; } -.#{$fa-css-prefix}-mars-stroke-h:before { content: $fa-var-mars-stroke-h; } -.#{$fa-css-prefix}-neuter:before { content: $fa-var-neuter; } -.#{$fa-css-prefix}-genderless:before { content: $fa-var-genderless; } -.#{$fa-css-prefix}-facebook-official:before { content: $fa-var-facebook-official; } -.#{$fa-css-prefix}-pinterest-p:before { content: $fa-var-pinterest-p; } -.#{$fa-css-prefix}-whatsapp:before { content: $fa-var-whatsapp; } -.#{$fa-css-prefix}-server:before { content: $fa-var-server; } -.#{$fa-css-prefix}-user-plus:before { content: $fa-var-user-plus; } -.#{$fa-css-prefix}-user-times:before { content: $fa-var-user-times; } -.#{$fa-css-prefix}-hotel:before, -.#{$fa-css-prefix}-bed:before { content: $fa-var-bed; } -.#{$fa-css-prefix}-viacoin:before { content: $fa-var-viacoin; } -.#{$fa-css-prefix}-train:before { content: $fa-var-train; } -.#{$fa-css-prefix}-subway:before { content: $fa-var-subway; } -.#{$fa-css-prefix}-medium:before { content: $fa-var-medium; } -.#{$fa-css-prefix}-yc:before, -.#{$fa-css-prefix}-y-combinator:before { content: $fa-var-y-combinator; } -.#{$fa-css-prefix}-optin-monster:before { content: $fa-var-optin-monster; } -.#{$fa-css-prefix}-opencart:before { content: $fa-var-opencart; } -.#{$fa-css-prefix}-expeditedssl:before { content: $fa-var-expeditedssl; } -.#{$fa-css-prefix}-battery-4:before, -.#{$fa-css-prefix}-battery-full:before { content: $fa-var-battery-full; } -.#{$fa-css-prefix}-battery-3:before, -.#{$fa-css-prefix}-battery-three-quarters:before { content: $fa-var-battery-three-quarters; } -.#{$fa-css-prefix}-battery-2:before, -.#{$fa-css-prefix}-battery-half:before { content: $fa-var-battery-half; } -.#{$fa-css-prefix}-battery-1:before, -.#{$fa-css-prefix}-battery-quarter:before { content: $fa-var-battery-quarter; } -.#{$fa-css-prefix}-battery-0:before, -.#{$fa-css-prefix}-battery-empty:before { content: $fa-var-battery-empty; } -.#{$fa-css-prefix}-mouse-pointer:before { content: $fa-var-mouse-pointer; } -.#{$fa-css-prefix}-i-cursor:before { content: $fa-var-i-cursor; } -.#{$fa-css-prefix}-object-group:before { content: $fa-var-object-group; } -.#{$fa-css-prefix}-object-ungroup:before { content: $fa-var-object-ungroup; } -.#{$fa-css-prefix}-sticky-note:before { content: $fa-var-sticky-note; } -.#{$fa-css-prefix}-sticky-note-o:before { content: $fa-var-sticky-note-o; } -.#{$fa-css-prefix}-cc-jcb:before { content: $fa-var-cc-jcb; } -.#{$fa-css-prefix}-cc-diners-club:before { content: $fa-var-cc-diners-club; } -.#{$fa-css-prefix}-clone:before { content: $fa-var-clone; } -.#{$fa-css-prefix}-balance-scale:before { content: $fa-var-balance-scale; } -.#{$fa-css-prefix}-hourglass-o:before { content: $fa-var-hourglass-o; } -.#{$fa-css-prefix}-hourglass-1:before, -.#{$fa-css-prefix}-hourglass-start:before { content: $fa-var-hourglass-start; } -.#{$fa-css-prefix}-hourglass-2:before, -.#{$fa-css-prefix}-hourglass-half:before { content: $fa-var-hourglass-half; } -.#{$fa-css-prefix}-hourglass-3:before, -.#{$fa-css-prefix}-hourglass-end:before { content: $fa-var-hourglass-end; } -.#{$fa-css-prefix}-hourglass:before { content: $fa-var-hourglass; } -.#{$fa-css-prefix}-hand-grab-o:before, -.#{$fa-css-prefix}-hand-rock-o:before { content: $fa-var-hand-rock-o; } -.#{$fa-css-prefix}-hand-stop-o:before, -.#{$fa-css-prefix}-hand-paper-o:before { content: $fa-var-hand-paper-o; } -.#{$fa-css-prefix}-hand-scissors-o:before { content: $fa-var-hand-scissors-o; } -.#{$fa-css-prefix}-hand-lizard-o:before { content: $fa-var-hand-lizard-o; } -.#{$fa-css-prefix}-hand-spock-o:before { content: $fa-var-hand-spock-o; } -.#{$fa-css-prefix}-hand-pointer-o:before { content: $fa-var-hand-pointer-o; } -.#{$fa-css-prefix}-hand-peace-o:before { content: $fa-var-hand-peace-o; } -.#{$fa-css-prefix}-trademark:before { content: $fa-var-trademark; } -.#{$fa-css-prefix}-registered:before { content: $fa-var-registered; } -.#{$fa-css-prefix}-creative-commons:before { content: $fa-var-creative-commons; } -.#{$fa-css-prefix}-gg:before { content: $fa-var-gg; } -.#{$fa-css-prefix}-gg-circle:before { content: $fa-var-gg-circle; } -.#{$fa-css-prefix}-tripadvisor:before { content: $fa-var-tripadvisor; } -.#{$fa-css-prefix}-odnoklassniki:before { content: $fa-var-odnoklassniki; } -.#{$fa-css-prefix}-odnoklassniki-square:before { content: $fa-var-odnoklassniki-square; } -.#{$fa-css-prefix}-get-pocket:before { content: $fa-var-get-pocket; } -.#{$fa-css-prefix}-wikipedia-w:before { content: $fa-var-wikipedia-w; } -.#{$fa-css-prefix}-safari:before { content: $fa-var-safari; } -.#{$fa-css-prefix}-chrome:before { content: $fa-var-chrome; } -.#{$fa-css-prefix}-firefox:before { content: $fa-var-firefox; } -.#{$fa-css-prefix}-opera:before { content: $fa-var-opera; } -.#{$fa-css-prefix}-internet-explorer:before { content: $fa-var-internet-explorer; } -.#{$fa-css-prefix}-tv:before, -.#{$fa-css-prefix}-television:before { content: $fa-var-television; } -.#{$fa-css-prefix}-contao:before { content: $fa-var-contao; } -.#{$fa-css-prefix}-500px:before { content: $fa-var-500px; } -.#{$fa-css-prefix}-amazon:before { content: $fa-var-amazon; } -.#{$fa-css-prefix}-calendar-plus-o:before { content: $fa-var-calendar-plus-o; } -.#{$fa-css-prefix}-calendar-minus-o:before { content: $fa-var-calendar-minus-o; } -.#{$fa-css-prefix}-calendar-times-o:before { content: $fa-var-calendar-times-o; } -.#{$fa-css-prefix}-calendar-check-o:before { content: $fa-var-calendar-check-o; } -.#{$fa-css-prefix}-industry:before { content: $fa-var-industry; } -.#{$fa-css-prefix}-map-pin:before { content: $fa-var-map-pin; } -.#{$fa-css-prefix}-map-signs:before { content: $fa-var-map-signs; } -.#{$fa-css-prefix}-map-o:before { content: $fa-var-map-o; } -.#{$fa-css-prefix}-map:before { content: $fa-var-map; } -.#{$fa-css-prefix}-commenting:before { content: $fa-var-commenting; } -.#{$fa-css-prefix}-commenting-o:before { content: $fa-var-commenting-o; } -.#{$fa-css-prefix}-houzz:before { content: $fa-var-houzz; } -.#{$fa-css-prefix}-vimeo:before { content: $fa-var-vimeo; } -.#{$fa-css-prefix}-black-tie:before { content: $fa-var-black-tie; } -.#{$fa-css-prefix}-fonticons:before { content: $fa-var-fonticons; } -.#{$fa-css-prefix}-reddit-alien:before { content: $fa-var-reddit-alien; } -.#{$fa-css-prefix}-edge:before { content: $fa-var-edge; } -.#{$fa-css-prefix}-credit-card-alt:before { content: $fa-var-credit-card-alt; } -.#{$fa-css-prefix}-codiepie:before { content: $fa-var-codiepie; } -.#{$fa-css-prefix}-modx:before { content: $fa-var-modx; } -.#{$fa-css-prefix}-fort-awesome:before { content: $fa-var-fort-awesome; } -.#{$fa-css-prefix}-usb:before { content: $fa-var-usb; } -.#{$fa-css-prefix}-product-hunt:before { content: $fa-var-product-hunt; } -.#{$fa-css-prefix}-mixcloud:before { content: $fa-var-mixcloud; } -.#{$fa-css-prefix}-scribd:before { content: $fa-var-scribd; } -.#{$fa-css-prefix}-pause-circle:before { content: $fa-var-pause-circle; } -.#{$fa-css-prefix}-pause-circle-o:before { content: $fa-var-pause-circle-o; } -.#{$fa-css-prefix}-stop-circle:before { content: $fa-var-stop-circle; } -.#{$fa-css-prefix}-stop-circle-o:before { content: $fa-var-stop-circle-o; } -.#{$fa-css-prefix}-shopping-bag:before { content: $fa-var-shopping-bag; } -.#{$fa-css-prefix}-shopping-basket:before { content: $fa-var-shopping-basket; } -.#{$fa-css-prefix}-hashtag:before { content: $fa-var-hashtag; } -.#{$fa-css-prefix}-bluetooth:before { content: $fa-var-bluetooth; } -.#{$fa-css-prefix}-bluetooth-b:before { content: $fa-var-bluetooth-b; } -.#{$fa-css-prefix}-percent:before { content: $fa-var-percent; } -.#{$fa-css-prefix}-gitlab:before { content: $fa-var-gitlab; } -.#{$fa-css-prefix}-wpbeginner:before { content: $fa-var-wpbeginner; } -.#{$fa-css-prefix}-wpforms:before { content: $fa-var-wpforms; } -.#{$fa-css-prefix}-envira:before { content: $fa-var-envira; } -.#{$fa-css-prefix}-universal-access:before { content: $fa-var-universal-access; } -.#{$fa-css-prefix}-wheelchair-alt:before { content: $fa-var-wheelchair-alt; } -.#{$fa-css-prefix}-question-circle-o:before { content: $fa-var-question-circle-o; } -.#{$fa-css-prefix}-blind:before { content: $fa-var-blind; } -.#{$fa-css-prefix}-audio-description:before { content: $fa-var-audio-description; } -.#{$fa-css-prefix}-volume-control-phone:before { content: $fa-var-volume-control-phone; } -.#{$fa-css-prefix}-braille:before { content: $fa-var-braille; } -.#{$fa-css-prefix}-assistive-listening-systems:before { content: $fa-var-assistive-listening-systems; } -.#{$fa-css-prefix}-asl-interpreting:before, -.#{$fa-css-prefix}-american-sign-language-interpreting:before { content: $fa-var-american-sign-language-interpreting; } -.#{$fa-css-prefix}-deafness:before, -.#{$fa-css-prefix}-hard-of-hearing:before, -.#{$fa-css-prefix}-deaf:before { content: $fa-var-deaf; } -.#{$fa-css-prefix}-glide:before { content: $fa-var-glide; } -.#{$fa-css-prefix}-glide-g:before { content: $fa-var-glide-g; } -.#{$fa-css-prefix}-signing:before, -.#{$fa-css-prefix}-sign-language:before { content: $fa-var-sign-language; } -.#{$fa-css-prefix}-low-vision:before { content: $fa-var-low-vision; } -.#{$fa-css-prefix}-viadeo:before { content: $fa-var-viadeo; } -.#{$fa-css-prefix}-viadeo-square:before { content: $fa-var-viadeo-square; } -.#{$fa-css-prefix}-snapchat:before { content: $fa-var-snapchat; } -.#{$fa-css-prefix}-snapchat-ghost:before { content: $fa-var-snapchat-ghost; } -.#{$fa-css-prefix}-snapchat-square:before { content: $fa-var-snapchat-square; } diff --git a/_sass/vendor/font-awesome/_larger.scss b/_sass/vendor/font-awesome/_larger.scss deleted file mode 100644 index a4065941..00000000 --- a/_sass/vendor/font-awesome/_larger.scss +++ /dev/null @@ -1,15 +0,0 @@ -// Icon Sizes -// ------------------------- - -/* makes the font 33% larger relative to the icon container */ -@use "sass:math"; - -.#{$fa-css-prefix}-lg { - font-size: math.div(4em, 3); - line-height: (3em * 0.25); - vertical-align: -15%; -} -.#{$fa-css-prefix}-2x { font-size: 2em; } -.#{$fa-css-prefix}-3x { font-size: 3em; } -.#{$fa-css-prefix}-4x { font-size: 4em; } -.#{$fa-css-prefix}-5x { font-size: 5em; } diff --git a/_sass/vendor/font-awesome/_list.scss b/_sass/vendor/font-awesome/_list.scss deleted file mode 100644 index 988e6f87..00000000 --- a/_sass/vendor/font-awesome/_list.scss +++ /dev/null @@ -1,21 +0,0 @@ -// List Icons -// ------------------------- - -@use "sass:math"; - -.#{$fa-css-prefix}-ul { - padding-left: 0; - margin-left: $fa-li-width; - list-style-type: none; - > li { position: relative; } -} -.#{$fa-css-prefix}-li { - position: absolute; - left: -$fa-li-width; - width: $fa-li-width; - top: math.div(2em, 14); - text-align: center; - &.#{$fa-css-prefix}-lg { - left: -$fa-li-width + math.div(4em, 14); - } -} diff --git a/_sass/vendor/font-awesome/_mixins.scss b/_sass/vendor/font-awesome/_mixins.scss deleted file mode 100644 index 86f51385..00000000 --- a/_sass/vendor/font-awesome/_mixins.scss +++ /dev/null @@ -1,62 +0,0 @@ -// Mixins -// -------------------------- - -@use "sass:list"; - -@mixin fa-icon() { - display: inline-block; - font: normal normal normal list.slash($fa-font-size-base, $fa-line-height-base) FontAwesome; // shortening font declaration - font-size: inherit; // can't have font-size inherit on line above, so need to override - text-rendering: auto; // optimizelegibility throws things off #1094 - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -} - -@mixin fa-icon-rotate($degrees, $rotation) { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; - -webkit-transform: rotate($degrees); - -ms-transform: rotate($degrees); - transform: rotate($degrees); -} - -@mixin fa-icon-flip($horiz, $vert, $rotation) { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; - -webkit-transform: scale($horiz, $vert); - -ms-transform: scale($horiz, $vert); - transform: scale($horiz, $vert); -} - - -// Only display content to screen readers. A la Bootstrap 4. -// -// See: http://a11yproject.com/posts/how-to-hide-content/ - -@mixin sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0,0,0,0); - border: 0; -} - -// Use in conjunction with .sr-only to only display content when it's focused. -// -// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 -// -// Credit: HTML5 Boilerplate - -@mixin sr-only-focusable { - &:active, - &:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; - } -} diff --git a/_sass/vendor/font-awesome/_path.scss b/_sass/vendor/font-awesome/_path.scss deleted file mode 100644 index bb457c23..00000000 --- a/_sass/vendor/font-awesome/_path.scss +++ /dev/null @@ -1,15 +0,0 @@ -/* FONT PATH - * -------------------------- */ - -@font-face { - font-family: 'FontAwesome'; - src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); - src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), - url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), - url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), - url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), - url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); -// src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts - font-weight: normal; - font-style: normal; -} diff --git a/_sass/vendor/font-awesome/_rotated-flipped.scss b/_sass/vendor/font-awesome/_rotated-flipped.scss deleted file mode 100644 index a3558fd0..00000000 --- a/_sass/vendor/font-awesome/_rotated-flipped.scss +++ /dev/null @@ -1,20 +0,0 @@ -// Rotated & Flipped Icons -// ------------------------- - -.#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } -.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } -.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } - -.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } -.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } - -// Hook for IE8-9 -// ------------------------- - -:root .#{$fa-css-prefix}-rotate-90, -:root .#{$fa-css-prefix}-rotate-180, -:root .#{$fa-css-prefix}-rotate-270, -:root .#{$fa-css-prefix}-flip-horizontal, -:root .#{$fa-css-prefix}-flip-vertical { - filter: none; -} diff --git a/_sass/vendor/font-awesome/_screen-reader.scss b/_sass/vendor/font-awesome/_screen-reader.scss deleted file mode 100644 index 637426f0..00000000 --- a/_sass/vendor/font-awesome/_screen-reader.scss +++ /dev/null @@ -1,5 +0,0 @@ -// Screen Readers -// ------------------------- - -.sr-only { @include sr-only(); } -.sr-only-focusable { @include sr-only-focusable(); } diff --git a/_sass/vendor/font-awesome/_stacked.scss b/_sass/vendor/font-awesome/_stacked.scss deleted file mode 100644 index aef74036..00000000 --- a/_sass/vendor/font-awesome/_stacked.scss +++ /dev/null @@ -1,20 +0,0 @@ -// Stacked Icons -// ------------------------- - -.#{$fa-css-prefix}-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.#{$fa-css-prefix}-stack-1x { line-height: inherit; } -.#{$fa-css-prefix}-stack-2x { font-size: 2em; } -.#{$fa-css-prefix}-inverse { color: $fa-inverse; } diff --git a/_sass/vendor/font-awesome/_variables.scss b/_sass/vendor/font-awesome/_variables.scss deleted file mode 100644 index 2826e022..00000000 --- a/_sass/vendor/font-awesome/_variables.scss +++ /dev/null @@ -1,737 +0,0 @@ -// Variables -// -------------------------- - -@use "sass:math"; - -$fa-font-path: "../fonts" !default; -$fa-font-size-base: 14px !default; -$fa-line-height-base: 1 !default; -//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.6.1/fonts" !default; // for referencing Bootstrap CDN font files directly -$fa-css-prefix: fa !default; -$fa-version: "4.6.1" !default; -$fa-border-color: #eee !default; -$fa-inverse: #fff !default; -$fa-li-width: math.div(30em, 14) !default; - -$fa-var-500px: "\f26e"; -$fa-var-adjust: "\f042"; -$fa-var-adn: "\f170"; -$fa-var-align-center: "\f037"; -$fa-var-align-justify: "\f039"; -$fa-var-align-left: "\f036"; -$fa-var-align-right: "\f038"; -$fa-var-amazon: "\f270"; -$fa-var-ambulance: "\f0f9"; -$fa-var-american-sign-language-interpreting: "\f2a3"; -$fa-var-anchor: "\f13d"; -$fa-var-android: "\f17b"; -$fa-var-angellist: "\f209"; -$fa-var-angle-double-down: "\f103"; -$fa-var-angle-double-left: "\f100"; -$fa-var-angle-double-right: "\f101"; -$fa-var-angle-double-up: "\f102"; -$fa-var-angle-down: "\f107"; -$fa-var-angle-left: "\f104"; -$fa-var-angle-right: "\f105"; -$fa-var-angle-up: "\f106"; -$fa-var-apple: "\f179"; -$fa-var-archive: "\f187"; -$fa-var-area-chart: "\f1fe"; -$fa-var-arrow-circle-down: "\f0ab"; -$fa-var-arrow-circle-left: "\f0a8"; -$fa-var-arrow-circle-o-down: "\f01a"; -$fa-var-arrow-circle-o-left: "\f190"; -$fa-var-arrow-circle-o-right: "\f18e"; -$fa-var-arrow-circle-o-up: "\f01b"; -$fa-var-arrow-circle-right: "\f0a9"; -$fa-var-arrow-circle-up: "\f0aa"; -$fa-var-arrow-down: "\f063"; -$fa-var-arrow-left: "\f060"; -$fa-var-arrow-right: "\f061"; -$fa-var-arrow-up: "\f062"; -$fa-var-arrows: "\f047"; -$fa-var-arrows-alt: "\f0b2"; -$fa-var-arrows-h: "\f07e"; -$fa-var-arrows-v: "\f07d"; -$fa-var-asl-interpreting: "\f2a3"; -$fa-var-assistive-listening-systems: "\f2a2"; -$fa-var-asterisk: "\f069"; -$fa-var-at: "\f1fa"; -$fa-var-audio-description: "\f29e"; -$fa-var-automobile: "\f1b9"; -$fa-var-backward: "\f04a"; -$fa-var-balance-scale: "\f24e"; -$fa-var-ban: "\f05e"; -$fa-var-bank: "\f19c"; -$fa-var-bar-chart: "\f080"; -$fa-var-bar-chart-o: "\f080"; -$fa-var-barcode: "\f02a"; -$fa-var-bars: "\f0c9"; -$fa-var-battery-0: "\f244"; -$fa-var-battery-1: "\f243"; -$fa-var-battery-2: "\f242"; -$fa-var-battery-3: "\f241"; -$fa-var-battery-4: "\f240"; -$fa-var-battery-empty: "\f244"; -$fa-var-battery-full: "\f240"; -$fa-var-battery-half: "\f242"; -$fa-var-battery-quarter: "\f243"; -$fa-var-battery-three-quarters: "\f241"; -$fa-var-bed: "\f236"; -$fa-var-beer: "\f0fc"; -$fa-var-behance: "\f1b4"; -$fa-var-behance-square: "\f1b5"; -$fa-var-bell: "\f0f3"; -$fa-var-bell-o: "\f0a2"; -$fa-var-bell-slash: "\f1f6"; -$fa-var-bell-slash-o: "\f1f7"; -$fa-var-bicycle: "\f206"; -$fa-var-binoculars: "\f1e5"; -$fa-var-birthday-cake: "\f1fd"; -$fa-var-bitbucket: "\f171"; -$fa-var-bitbucket-square: "\f172"; -$fa-var-bitcoin: "\f15a"; -$fa-var-black-tie: "\f27e"; -$fa-var-blind: "\f29d"; -$fa-var-bluetooth: "\f293"; -$fa-var-bluetooth-b: "\f294"; -$fa-var-bold: "\f032"; -$fa-var-bolt: "\f0e7"; -$fa-var-bomb: "\f1e2"; -$fa-var-book: "\f02d"; -$fa-var-bookmark: "\f02e"; -$fa-var-bookmark-o: "\f097"; -$fa-var-braille: "\f2a1"; -$fa-var-briefcase: "\f0b1"; -$fa-var-btc: "\f15a"; -$fa-var-bug: "\f188"; -$fa-var-building: "\f1ad"; -$fa-var-building-o: "\f0f7"; -$fa-var-bullhorn: "\f0a1"; -$fa-var-bullseye: "\f140"; -$fa-var-bus: "\f207"; -$fa-var-buysellads: "\f20d"; -$fa-var-cab: "\f1ba"; -$fa-var-calculator: "\f1ec"; -$fa-var-calendar: "\f073"; -$fa-var-calendar-check-o: "\f274"; -$fa-var-calendar-minus-o: "\f272"; -$fa-var-calendar-o: "\f133"; -$fa-var-calendar-plus-o: "\f271"; -$fa-var-calendar-times-o: "\f273"; -$fa-var-camera: "\f030"; -$fa-var-camera-retro: "\f083"; -$fa-var-car: "\f1b9"; -$fa-var-caret-down: "\f0d7"; -$fa-var-caret-left: "\f0d9"; -$fa-var-caret-right: "\f0da"; -$fa-var-caret-square-o-down: "\f150"; -$fa-var-caret-square-o-left: "\f191"; -$fa-var-caret-square-o-right: "\f152"; -$fa-var-caret-square-o-up: "\f151"; -$fa-var-caret-up: "\f0d8"; -$fa-var-cart-arrow-down: "\f218"; -$fa-var-cart-plus: "\f217"; -$fa-var-cc: "\f20a"; -$fa-var-cc-amex: "\f1f3"; -$fa-var-cc-diners-club: "\f24c"; -$fa-var-cc-discover: "\f1f2"; -$fa-var-cc-jcb: "\f24b"; -$fa-var-cc-mastercard: "\f1f1"; -$fa-var-cc-paypal: "\f1f4"; -$fa-var-cc-stripe: "\f1f5"; -$fa-var-cc-visa: "\f1f0"; -$fa-var-certificate: "\f0a3"; -$fa-var-chain: "\f0c1"; -$fa-var-chain-broken: "\f127"; -$fa-var-check: "\f00c"; -$fa-var-check-circle: "\f058"; -$fa-var-check-circle-o: "\f05d"; -$fa-var-check-square: "\f14a"; -$fa-var-check-square-o: "\f046"; -$fa-var-chevron-circle-down: "\f13a"; -$fa-var-chevron-circle-left: "\f137"; -$fa-var-chevron-circle-right: "\f138"; -$fa-var-chevron-circle-up: "\f139"; -$fa-var-chevron-down: "\f078"; -$fa-var-chevron-left: "\f053"; -$fa-var-chevron-right: "\f054"; -$fa-var-chevron-up: "\f077"; -$fa-var-child: "\f1ae"; -$fa-var-chrome: "\f268"; -$fa-var-circle: "\f111"; -$fa-var-circle-o: "\f10c"; -$fa-var-circle-o-notch: "\f1ce"; -$fa-var-circle-thin: "\f1db"; -$fa-var-clipboard: "\f0ea"; -$fa-var-clock-o: "\f017"; -$fa-var-clone: "\f24d"; -$fa-var-close: "\f00d"; -$fa-var-cloud: "\f0c2"; -$fa-var-cloud-download: "\f0ed"; -$fa-var-cloud-upload: "\f0ee"; -$fa-var-cny: "\f157"; -$fa-var-code: "\f121"; -$fa-var-code-fork: "\f126"; -$fa-var-codepen: "\f1cb"; -$fa-var-codiepie: "\f284"; -$fa-var-coffee: "\f0f4"; -$fa-var-cog: "\f013"; -$fa-var-cogs: "\f085"; -$fa-var-columns: "\f0db"; -$fa-var-comment: "\f075"; -$fa-var-comment-o: "\f0e5"; -$fa-var-commenting: "\f27a"; -$fa-var-commenting-o: "\f27b"; -$fa-var-comments: "\f086"; -$fa-var-comments-o: "\f0e6"; -$fa-var-compass: "\f14e"; -$fa-var-compress: "\f066"; -$fa-var-connectdevelop: "\f20e"; -$fa-var-contao: "\f26d"; -$fa-var-copy: "\f0c5"; -$fa-var-copyright: "\f1f9"; -$fa-var-creative-commons: "\f25e"; -$fa-var-credit-card: "\f09d"; -$fa-var-credit-card-alt: "\f283"; -$fa-var-crop: "\f125"; -$fa-var-crosshairs: "\f05b"; -$fa-var-css3: "\f13c"; -$fa-var-cube: "\f1b2"; -$fa-var-cubes: "\f1b3"; -$fa-var-cut: "\f0c4"; -$fa-var-cutlery: "\f0f5"; -$fa-var-dashboard: "\f0e4"; -$fa-var-dashcube: "\f210"; -$fa-var-database: "\f1c0"; -$fa-var-deaf: "\f2a4"; -$fa-var-deafness: "\f2a4"; -$fa-var-dedent: "\f03b"; -$fa-var-delicious: "\f1a5"; -$fa-var-desktop: "\f108"; -$fa-var-deviantart: "\f1bd"; -$fa-var-diamond: "\f219"; -$fa-var-digg: "\f1a6"; -$fa-var-dollar: "\f155"; -$fa-var-dot-circle-o: "\f192"; -$fa-var-download: "\f019"; -$fa-var-dribbble: "\f17d"; -$fa-var-dropbox: "\f16b"; -$fa-var-drupal: "\f1a9"; -$fa-var-edge: "\f282"; -$fa-var-edit: "\f044"; -$fa-var-eject: "\f052"; -$fa-var-ellipsis-h: "\f141"; -$fa-var-ellipsis-v: "\f142"; -$fa-var-empire: "\f1d1"; -$fa-var-envelope: "\f0e0"; -$fa-var-envelope-o: "\f003"; -$fa-var-envelope-square: "\f199"; -$fa-var-envira: "\f299"; -$fa-var-eraser: "\f12d"; -$fa-var-eur: "\f153"; -$fa-var-euro: "\f153"; -$fa-var-exchange: "\f0ec"; -$fa-var-exclamation: "\f12a"; -$fa-var-exclamation-circle: "\f06a"; -$fa-var-exclamation-triangle: "\f071"; -$fa-var-expand: "\f065"; -$fa-var-expeditedssl: "\f23e"; -$fa-var-external-link: "\f08e"; -$fa-var-external-link-square: "\f14c"; -$fa-var-eye: "\f06e"; -$fa-var-eye-slash: "\f070"; -$fa-var-eyedropper: "\f1fb"; -$fa-var-facebook: "\f09a"; -$fa-var-facebook-f: "\f09a"; -$fa-var-facebook-official: "\f230"; -$fa-var-facebook-square: "\f082"; -$fa-var-fast-backward: "\f049"; -$fa-var-fast-forward: "\f050"; -$fa-var-fax: "\f1ac"; -$fa-var-feed: "\f09e"; -$fa-var-female: "\f182"; -$fa-var-fighter-jet: "\f0fb"; -$fa-var-file: "\f15b"; -$fa-var-file-archive-o: "\f1c6"; -$fa-var-file-audio-o: "\f1c7"; -$fa-var-file-code-o: "\f1c9"; -$fa-var-file-excel-o: "\f1c3"; -$fa-var-file-image-o: "\f1c5"; -$fa-var-file-movie-o: "\f1c8"; -$fa-var-file-o: "\f016"; -$fa-var-file-pdf-o: "\f1c1"; -$fa-var-file-photo-o: "\f1c5"; -$fa-var-file-picture-o: "\f1c5"; -$fa-var-file-powerpoint-o: "\f1c4"; -$fa-var-file-sound-o: "\f1c7"; -$fa-var-file-text: "\f15c"; -$fa-var-file-text-o: "\f0f6"; -$fa-var-file-video-o: "\f1c8"; -$fa-var-file-word-o: "\f1c2"; -$fa-var-file-zip-o: "\f1c6"; -$fa-var-files-o: "\f0c5"; -$fa-var-film: "\f008"; -$fa-var-filter: "\f0b0"; -$fa-var-fire: "\f06d"; -$fa-var-fire-extinguisher: "\f134"; -$fa-var-firefox: "\f269"; -$fa-var-flag: "\f024"; -$fa-var-flag-checkered: "\f11e"; -$fa-var-flag-o: "\f11d"; -$fa-var-flash: "\f0e7"; -$fa-var-flask: "\f0c3"; -$fa-var-flickr: "\f16e"; -$fa-var-floppy-o: "\f0c7"; -$fa-var-folder: "\f07b"; -$fa-var-folder-o: "\f114"; -$fa-var-folder-open: "\f07c"; -$fa-var-folder-open-o: "\f115"; -$fa-var-font: "\f031"; -$fa-var-fonticons: "\f280"; -$fa-var-fort-awesome: "\f286"; -$fa-var-forumbee: "\f211"; -$fa-var-forward: "\f04e"; -$fa-var-foursquare: "\f180"; -$fa-var-frown-o: "\f119"; -$fa-var-futbol-o: "\f1e3"; -$fa-var-gamepad: "\f11b"; -$fa-var-gavel: "\f0e3"; -$fa-var-gbp: "\f154"; -$fa-var-ge: "\f1d1"; -$fa-var-gear: "\f013"; -$fa-var-gears: "\f085"; -$fa-var-genderless: "\f22d"; -$fa-var-get-pocket: "\f265"; -$fa-var-gg: "\f260"; -$fa-var-gg-circle: "\f261"; -$fa-var-gift: "\f06b"; -$fa-var-git: "\f1d3"; -$fa-var-git-square: "\f1d2"; -$fa-var-github: "\f09b"; -$fa-var-github-alt: "\f113"; -$fa-var-github-square: "\f092"; -$fa-var-gitlab: "\f296"; -$fa-var-gittip: "\f184"; -$fa-var-glass: "\f000"; -$fa-var-glide: "\f2a5"; -$fa-var-glide-g: "\f2a6"; -$fa-var-globe: "\f0ac"; -$fa-var-google: "\f1a0"; -$fa-var-google-plus: "\f0d5"; -$fa-var-google-plus-square: "\f0d4"; -$fa-var-google-wallet: "\f1ee"; -$fa-var-graduation-cap: "\f19d"; -$fa-var-gratipay: "\f184"; -$fa-var-group: "\f0c0"; -$fa-var-h-square: "\f0fd"; -$fa-var-hacker-news: "\f1d4"; -$fa-var-hand-grab-o: "\f255"; -$fa-var-hand-lizard-o: "\f258"; -$fa-var-hand-o-down: "\f0a7"; -$fa-var-hand-o-left: "\f0a5"; -$fa-var-hand-o-right: "\f0a4"; -$fa-var-hand-o-up: "\f0a6"; -$fa-var-hand-paper-o: "\f256"; -$fa-var-hand-peace-o: "\f25b"; -$fa-var-hand-pointer-o: "\f25a"; -$fa-var-hand-rock-o: "\f255"; -$fa-var-hand-scissors-o: "\f257"; -$fa-var-hand-spock-o: "\f259"; -$fa-var-hand-stop-o: "\f256"; -$fa-var-hard-of-hearing: "\f2a4"; -$fa-var-hashtag: "\f292"; -$fa-var-hdd-o: "\f0a0"; -$fa-var-header: "\f1dc"; -$fa-var-headphones: "\f025"; -$fa-var-heart: "\f004"; -$fa-var-heart-o: "\f08a"; -$fa-var-heartbeat: "\f21e"; -$fa-var-history: "\f1da"; -$fa-var-home: "\f015"; -$fa-var-hospital-o: "\f0f8"; -$fa-var-hotel: "\f236"; -$fa-var-hourglass: "\f254"; -$fa-var-hourglass-1: "\f251"; -$fa-var-hourglass-2: "\f252"; -$fa-var-hourglass-3: "\f253"; -$fa-var-hourglass-end: "\f253"; -$fa-var-hourglass-half: "\f252"; -$fa-var-hourglass-o: "\f250"; -$fa-var-hourglass-start: "\f251"; -$fa-var-houzz: "\f27c"; -$fa-var-html5: "\f13b"; -$fa-var-i-cursor: "\f246"; -$fa-var-ils: "\f20b"; -$fa-var-image: "\f03e"; -$fa-var-inbox: "\f01c"; -$fa-var-indent: "\f03c"; -$fa-var-industry: "\f275"; -$fa-var-info: "\f129"; -$fa-var-info-circle: "\f05a"; -$fa-var-inr: "\f156"; -$fa-var-instagram: "\f16d"; -$fa-var-institution: "\f19c"; -$fa-var-internet-explorer: "\f26b"; -$fa-var-intersex: "\f224"; -$fa-var-ioxhost: "\f208"; -$fa-var-italic: "\f033"; -$fa-var-joomla: "\f1aa"; -$fa-var-jpy: "\f157"; -$fa-var-jsfiddle: "\f1cc"; -$fa-var-key: "\f084"; -$fa-var-keyboard-o: "\f11c"; -$fa-var-krw: "\f159"; -$fa-var-language: "\f1ab"; -$fa-var-laptop: "\f109"; -$fa-var-lastfm: "\f202"; -$fa-var-lastfm-square: "\f203"; -$fa-var-leaf: "\f06c"; -$fa-var-leanpub: "\f212"; -$fa-var-legal: "\f0e3"; -$fa-var-lemon-o: "\f094"; -$fa-var-level-down: "\f149"; -$fa-var-level-up: "\f148"; -$fa-var-life-bouy: "\f1cd"; -$fa-var-life-buoy: "\f1cd"; -$fa-var-life-ring: "\f1cd"; -$fa-var-life-saver: "\f1cd"; -$fa-var-lightbulb-o: "\f0eb"; -$fa-var-line-chart: "\f201"; -$fa-var-link: "\f0c1"; -$fa-var-linkedin: "\f0e1"; -$fa-var-linkedin-square: "\f08c"; -$fa-var-linux: "\f17c"; -$fa-var-list: "\f03a"; -$fa-var-list-alt: "\f022"; -$fa-var-list-ol: "\f0cb"; -$fa-var-list-ul: "\f0ca"; -$fa-var-location-arrow: "\f124"; -$fa-var-lock: "\f023"; -$fa-var-long-arrow-down: "\f175"; -$fa-var-long-arrow-left: "\f177"; -$fa-var-long-arrow-right: "\f178"; -$fa-var-long-arrow-up: "\f176"; -$fa-var-low-vision: "\f2a8"; -$fa-var-magic: "\f0d0"; -$fa-var-magnet: "\f076"; -$fa-var-mail-forward: "\f064"; -$fa-var-mail-reply: "\f112"; -$fa-var-mail-reply-all: "\f122"; -$fa-var-male: "\f183"; -$fa-var-map: "\f279"; -$fa-var-map-marker: "\f041"; -$fa-var-map-o: "\f278"; -$fa-var-map-pin: "\f276"; -$fa-var-map-signs: "\f277"; -$fa-var-mars: "\f222"; -$fa-var-mars-double: "\f227"; -$fa-var-mars-stroke: "\f229"; -$fa-var-mars-stroke-h: "\f22b"; -$fa-var-mars-stroke-v: "\f22a"; -$fa-var-maxcdn: "\f136"; -$fa-var-meanpath: "\f20c"; -$fa-var-medium: "\f23a"; -$fa-var-medkit: "\f0fa"; -$fa-var-meh-o: "\f11a"; -$fa-var-mercury: "\f223"; -$fa-var-microphone: "\f130"; -$fa-var-microphone-slash: "\f131"; -$fa-var-minus: "\f068"; -$fa-var-minus-circle: "\f056"; -$fa-var-minus-square: "\f146"; -$fa-var-minus-square-o: "\f147"; -$fa-var-mixcloud: "\f289"; -$fa-var-mobile: "\f10b"; -$fa-var-mobile-phone: "\f10b"; -$fa-var-modx: "\f285"; -$fa-var-money: "\f0d6"; -$fa-var-moon-o: "\f186"; -$fa-var-mortar-board: "\f19d"; -$fa-var-motorcycle: "\f21c"; -$fa-var-mouse-pointer: "\f245"; -$fa-var-music: "\f001"; -$fa-var-navicon: "\f0c9"; -$fa-var-neuter: "\f22c"; -$fa-var-newspaper-o: "\f1ea"; -$fa-var-object-group: "\f247"; -$fa-var-object-ungroup: "\f248"; -$fa-var-odnoklassniki: "\f263"; -$fa-var-odnoklassniki-square: "\f264"; -$fa-var-opencart: "\f23d"; -$fa-var-openid: "\f19b"; -$fa-var-opera: "\f26a"; -$fa-var-optin-monster: "\f23c"; -$fa-var-outdent: "\f03b"; -$fa-var-pagelines: "\f18c"; -$fa-var-paint-brush: "\f1fc"; -$fa-var-paper-plane: "\f1d8"; -$fa-var-paper-plane-o: "\f1d9"; -$fa-var-paperclip: "\f0c6"; -$fa-var-paragraph: "\f1dd"; -$fa-var-paste: "\f0ea"; -$fa-var-pause: "\f04c"; -$fa-var-pause-circle: "\f28b"; -$fa-var-pause-circle-o: "\f28c"; -$fa-var-paw: "\f1b0"; -$fa-var-paypal: "\f1ed"; -$fa-var-pencil: "\f040"; -$fa-var-pencil-square: "\f14b"; -$fa-var-pencil-square-o: "\f044"; -$fa-var-percent: "\f295"; -$fa-var-phone: "\f095"; -$fa-var-phone-square: "\f098"; -$fa-var-photo: "\f03e"; -$fa-var-picture-o: "\f03e"; -$fa-var-pie-chart: "\f200"; -$fa-var-pied-piper: "\f1a7"; -$fa-var-pied-piper-alt: "\f1a8"; -$fa-var-pinterest: "\f0d2"; -$fa-var-pinterest-p: "\f231"; -$fa-var-pinterest-square: "\f0d3"; -$fa-var-plane: "\f072"; -$fa-var-play: "\f04b"; -$fa-var-play-circle: "\f144"; -$fa-var-play-circle-o: "\f01d"; -$fa-var-plug: "\f1e6"; -$fa-var-plus: "\f067"; -$fa-var-plus-circle: "\f055"; -$fa-var-plus-square: "\f0fe"; -$fa-var-plus-square-o: "\f196"; -$fa-var-power-off: "\f011"; -$fa-var-print: "\f02f"; -$fa-var-product-hunt: "\f288"; -$fa-var-puzzle-piece: "\f12e"; -$fa-var-qq: "\f1d6"; -$fa-var-qrcode: "\f029"; -$fa-var-question: "\f128"; -$fa-var-question-circle: "\f059"; -$fa-var-question-circle-o: "\f29c"; -$fa-var-quote-left: "\f10d"; -$fa-var-quote-right: "\f10e"; -$fa-var-ra: "\f1d0"; -$fa-var-random: "\f074"; -$fa-var-rebel: "\f1d0"; -$fa-var-recycle: "\f1b8"; -$fa-var-reddit: "\f1a1"; -$fa-var-reddit-alien: "\f281"; -$fa-var-reddit-square: "\f1a2"; -$fa-var-refresh: "\f021"; -$fa-var-registered: "\f25d"; -$fa-var-remove: "\f00d"; -$fa-var-renren: "\f18b"; -$fa-var-reorder: "\f0c9"; -$fa-var-repeat: "\f01e"; -$fa-var-reply: "\f112"; -$fa-var-reply-all: "\f122"; -$fa-var-retweet: "\f079"; -$fa-var-rmb: "\f157"; -$fa-var-road: "\f018"; -$fa-var-rocket: "\f135"; -$fa-var-rotate-left: "\f0e2"; -$fa-var-rotate-right: "\f01e"; -$fa-var-rouble: "\f158"; -$fa-var-rss: "\f09e"; -$fa-var-rss-square: "\f143"; -$fa-var-rub: "\f158"; -$fa-var-ruble: "\f158"; -$fa-var-rupee: "\f156"; -$fa-var-safari: "\f267"; -$fa-var-save: "\f0c7"; -$fa-var-scissors: "\f0c4"; -$fa-var-scribd: "\f28a"; -$fa-var-search: "\f002"; -$fa-var-search-minus: "\f010"; -$fa-var-search-plus: "\f00e"; -$fa-var-sellsy: "\f213"; -$fa-var-send: "\f1d8"; -$fa-var-send-o: "\f1d9"; -$fa-var-server: "\f233"; -$fa-var-share: "\f064"; -$fa-var-share-alt: "\f1e0"; -$fa-var-share-alt-square: "\f1e1"; -$fa-var-share-square: "\f14d"; -$fa-var-share-square-o: "\f045"; -$fa-var-shekel: "\f20b"; -$fa-var-sheqel: "\f20b"; -$fa-var-shield: "\f132"; -$fa-var-ship: "\f21a"; -$fa-var-shirtsinbulk: "\f214"; -$fa-var-shopping-bag: "\f290"; -$fa-var-shopping-basket: "\f291"; -$fa-var-shopping-cart: "\f07a"; -$fa-var-sign-in: "\f090"; -$fa-var-sign-language: "\f2a7"; -$fa-var-sign-out: "\f08b"; -$fa-var-signal: "\f012"; -$fa-var-signing: "\f2a7"; -$fa-var-simplybuilt: "\f215"; -$fa-var-sitemap: "\f0e8"; -$fa-var-skyatlas: "\f216"; -$fa-var-skype: "\f17e"; -$fa-var-slack: "\f198"; -$fa-var-sliders: "\f1de"; -$fa-var-slideshare: "\f1e7"; -$fa-var-smile-o: "\f118"; -$fa-var-snapchat: "\f2ab"; -$fa-var-snapchat-ghost: "\f2ac"; -$fa-var-snapchat-square: "\f2ad"; -$fa-var-soccer-ball-o: "\f1e3"; -$fa-var-sort: "\f0dc"; -$fa-var-sort-alpha-asc: "\f15d"; -$fa-var-sort-alpha-desc: "\f15e"; -$fa-var-sort-amount-asc: "\f160"; -$fa-var-sort-amount-desc: "\f161"; -$fa-var-sort-asc: "\f0de"; -$fa-var-sort-desc: "\f0dd"; -$fa-var-sort-down: "\f0dd"; -$fa-var-sort-numeric-asc: "\f162"; -$fa-var-sort-numeric-desc: "\f163"; -$fa-var-sort-up: "\f0de"; -$fa-var-soundcloud: "\f1be"; -$fa-var-space-shuttle: "\f197"; -$fa-var-spinner: "\f110"; -$fa-var-spoon: "\f1b1"; -$fa-var-spotify: "\f1bc"; -$fa-var-square: "\f0c8"; -$fa-var-square-o: "\f096"; -$fa-var-stack-exchange: "\f18d"; -$fa-var-stack-overflow: "\f16c"; -$fa-var-star: "\f005"; -$fa-var-star-half: "\f089"; -$fa-var-star-half-empty: "\f123"; -$fa-var-star-half-full: "\f123"; -$fa-var-star-half-o: "\f123"; -$fa-var-star-o: "\f006"; -$fa-var-steam: "\f1b6"; -$fa-var-steam-square: "\f1b7"; -$fa-var-step-backward: "\f048"; -$fa-var-step-forward: "\f051"; -$fa-var-stethoscope: "\f0f1"; -$fa-var-sticky-note: "\f249"; -$fa-var-sticky-note-o: "\f24a"; -$fa-var-stop: "\f04d"; -$fa-var-stop-circle: "\f28d"; -$fa-var-stop-circle-o: "\f28e"; -$fa-var-street-view: "\f21d"; -$fa-var-strikethrough: "\f0cc"; -$fa-var-stumbleupon: "\f1a4"; -$fa-var-stumbleupon-circle: "\f1a3"; -$fa-var-subscript: "\f12c"; -$fa-var-subway: "\f239"; -$fa-var-suitcase: "\f0f2"; -$fa-var-sun-o: "\f185"; -$fa-var-superscript: "\f12b"; -$fa-var-support: "\f1cd"; -$fa-var-table: "\f0ce"; -$fa-var-tablet: "\f10a"; -$fa-var-tachometer: "\f0e4"; -$fa-var-tag: "\f02b"; -$fa-var-tags: "\f02c"; -$fa-var-tasks: "\f0ae"; -$fa-var-taxi: "\f1ba"; -$fa-var-television: "\f26c"; -$fa-var-tencent-weibo: "\f1d5"; -$fa-var-terminal: "\f120"; -$fa-var-text-height: "\f034"; -$fa-var-text-width: "\f035"; -$fa-var-th: "\f00a"; -$fa-var-th-large: "\f009"; -$fa-var-th-list: "\f00b"; -$fa-var-thumb-tack: "\f08d"; -$fa-var-thumbs-down: "\f165"; -$fa-var-thumbs-o-down: "\f088"; -$fa-var-thumbs-o-up: "\f087"; -$fa-var-thumbs-up: "\f164"; -$fa-var-ticket: "\f145"; -$fa-var-times: "\f00d"; -$fa-var-times-circle: "\f057"; -$fa-var-times-circle-o: "\f05c"; -$fa-var-tint: "\f043"; -$fa-var-toggle-down: "\f150"; -$fa-var-toggle-left: "\f191"; -$fa-var-toggle-off: "\f204"; -$fa-var-toggle-on: "\f205"; -$fa-var-toggle-right: "\f152"; -$fa-var-toggle-up: "\f151"; -$fa-var-trademark: "\f25c"; -$fa-var-train: "\f238"; -$fa-var-transgender: "\f224"; -$fa-var-transgender-alt: "\f225"; -$fa-var-trash: "\f1f8"; -$fa-var-trash-o: "\f014"; -$fa-var-tree: "\f1bb"; -$fa-var-trello: "\f181"; -$fa-var-tripadvisor: "\f262"; -$fa-var-trophy: "\f091"; -$fa-var-truck: "\f0d1"; -$fa-var-try: "\f195"; -$fa-var-tty: "\f1e4"; -$fa-var-tumblr: "\f173"; -$fa-var-tumblr-square: "\f174"; -$fa-var-turkish-lira: "\f195"; -$fa-var-tv: "\f26c"; -$fa-var-twitch: "\f1e8"; -$fa-var-twitter: "\f099"; -$fa-var-twitter-square: "\f081"; -$fa-var-umbrella: "\f0e9"; -$fa-var-underline: "\f0cd"; -$fa-var-undo: "\f0e2"; -$fa-var-universal-access: "\f29a"; -$fa-var-university: "\f19c"; -$fa-var-unlink: "\f127"; -$fa-var-unlock: "\f09c"; -$fa-var-unlock-alt: "\f13e"; -$fa-var-unsorted: "\f0dc"; -$fa-var-upload: "\f093"; -$fa-var-usb: "\f287"; -$fa-var-usd: "\f155"; -$fa-var-user: "\f007"; -$fa-var-user-md: "\f0f0"; -$fa-var-user-plus: "\f234"; -$fa-var-user-secret: "\f21b"; -$fa-var-user-times: "\f235"; -$fa-var-users: "\f0c0"; -$fa-var-venus: "\f221"; -$fa-var-venus-double: "\f226"; -$fa-var-venus-mars: "\f228"; -$fa-var-viacoin: "\f237"; -$fa-var-viadeo: "\f2a9"; -$fa-var-viadeo-square: "\f2aa"; -$fa-var-video-camera: "\f03d"; -$fa-var-vimeo: "\f27d"; -$fa-var-vimeo-square: "\f194"; -$fa-var-vine: "\f1ca"; -$fa-var-vk: "\f189"; -$fa-var-volume-control-phone: "\f2a0"; -$fa-var-volume-down: "\f027"; -$fa-var-volume-off: "\f026"; -$fa-var-volume-up: "\f028"; -$fa-var-warning: "\f071"; -$fa-var-wechat: "\f1d7"; -$fa-var-weibo: "\f18a"; -$fa-var-weixin: "\f1d7"; -$fa-var-whatsapp: "\f232"; -$fa-var-wheelchair: "\f193"; -$fa-var-wheelchair-alt: "\f29b"; -$fa-var-wifi: "\f1eb"; -$fa-var-wikipedia-w: "\f266"; -$fa-var-windows: "\f17a"; -$fa-var-won: "\f159"; -$fa-var-wordpress: "\f19a"; -$fa-var-wpbeginner: "\f297"; -$fa-var-wpforms: "\f298"; -$fa-var-wrench: "\f0ad"; -$fa-var-xing: "\f168"; -$fa-var-xing-square: "\f169"; -$fa-var-y-combinator: "\f23b"; -$fa-var-y-combinator-square: "\f1d4"; -$fa-var-yahoo: "\f19e"; -$fa-var-yc: "\f23b"; -$fa-var-yc-square: "\f1d4"; -$fa-var-yelp: "\f1e9"; -$fa-var-yen: "\f157"; -$fa-var-youtube: "\f167"; -$fa-var-youtube-play: "\f16a"; -$fa-var-youtube-square: "\f166"; - diff --git a/_sass/vendor/magnific-popup/_magnific-popup.scss b/_sass/vendor/magnific-popup/_magnific-popup.scss deleted file mode 100644 index 45826fb3..00000000 --- a/_sass/vendor/magnific-popup/_magnific-popup.scss +++ /dev/null @@ -1,651 +0,0 @@ -/* Magnific Popup CSS */ - -@use "sass:math"; - -@import "settings"; - -//////////////////////// -// -// Contents: -// -// 1. Default Settings -// 2. General styles -// - Transluscent overlay -// - Containers, wrappers -// - Cursors -// - Helper classes -// 3. Appearance -// - Preloader & text that displays error messages -// - CSS reset for buttons -// - Close icon -// - "1 of X" counter -// - Navigation (left/right) arrows -// - Iframe content type styles -// - Image content type styles -// - Media query where size of arrows is reduced -// - IE7 support -// -//////////////////////// - - - -//////////////////////// -// 1. Default Settings -//////////////////////// - -$mfp-overlay-color: #0b0b0b !default; -$mfp-overlay-opacity: 0.8 !default; -$mfp-shadow: 0 0 8px rgba(0, 0, 0, 0.6) !default; // shadow on image or iframe -$mfp-popup-padding-left: 8px !default; // Padding from left and from right side -$mfp-popup-padding-left-mobile: 6px !default; // Same as above, but is applied when width of window is less than 800px - -$mfp-z-index-base: 1040 !default; // Base z-index of popup -$mfp-include-arrows: true !default; // include styles for nav arrows -$mfp-controls-opacity: 0.65 !default; -$mfp-controls-color: #FFF !default; -$mfp-controls-border-color: #3F3F3F !default; -$mfp-inner-close-icon-color: #333 !default; -$mfp-controls-text-color: #CCC !default; // Color of preloader and "1 of X" indicator -$mfp-controls-text-color-hover: #FFF !default; -$mfp-IE7support: true !default; // Very basic IE7 support - -// Iframe-type options -$mfp-include-iframe-type: true !default; -$mfp-iframe-padding-top: 40px !default; -$mfp-iframe-background: #000 !default; -$mfp-iframe-max-width: 900px !default; -$mfp-iframe-ratio: math.div(9, 16) !default; - -// Image-type options -$mfp-include-image-type: true !default; -$mfp-image-background: #444 !default; -$mfp-image-padding-top: 40px !default; -$mfp-image-padding-bottom: 40px !default; -$mfp-include-mobile-layout-for-image: true !default; // Removes paddings from top and bottom - -// Image caption options -$mfp-caption-title-color: #F3F3F3 !default; -$mfp-caption-subtitle-color: #BDBDBD !default; - -// A11y -$mfp-use-visuallyhidden: false !default; // Hide content from browsers, but make it available for screen readers - - - -//////////////////////// -// 2. General styles -//////////////////////// - -// Transluscent overlay -.mfp-bg { - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: $mfp-z-index-base + 2; - overflow: hidden; - position: fixed; - - background: $mfp-overlay-color; - opacity: $mfp-overlay-opacity; - @if $mfp-IE7support { - filter: unquote("alpha(opacity=#{$mfp-overlay-opacity*100})"); - } -} - -// Wrapper for popup -.mfp-wrap { - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: $mfp-z-index-base + 3; - position: fixed; - outline: none !important; - -webkit-backface-visibility: hidden; // fixes webkit bug that can cause "false" scrollbar -} - -// Root container -.mfp-container { - text-align: center; - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - padding: 0 $mfp-popup-padding-left; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -// Vertical centerer helper -.mfp-container { - &:before { - content: ''; - display: inline-block; - height: 100%; - vertical-align: middle; - } -} - -// Remove vertical centering when popup has class `mfp-align-top` -.mfp-align-top { - .mfp-container { - &:before { - display: none; - } - } -} - -// Popup content holder -.mfp-content { - position: relative; - display: inline-block; - vertical-align: middle; - margin: 0 auto; - text-align: left; - z-index: $mfp-z-index-base + 5; -} -.mfp-inline-holder, -.mfp-ajax-holder { - .mfp-content { - width: 100%; - cursor: auto; - } -} - -// Cursors -.mfp-ajax-cur { - cursor: progress; -} -.mfp-zoom-out-cur { - &, .mfp-image-holder .mfp-close { - cursor: -moz-zoom-out; - cursor: -webkit-zoom-out; - cursor: zoom-out; - } -} -.mfp-zoom { - cursor: pointer; - cursor: -webkit-zoom-in; - cursor: -moz-zoom-in; - cursor: zoom-in; -} -.mfp-auto-cursor { - .mfp-content { - cursor: auto; - } -} - -.mfp-close, -.mfp-arrow, -.mfp-preloader, -.mfp-counter { - -webkit-user-select:none; - -moz-user-select: none; - user-select: none; -} - -// Hide the image during the loading -.mfp-loading { - &.mfp-figure { - display: none; - } -} - -// Helper class that hides stuff -@if $mfp-use-visuallyhidden { - // From HTML5 Boilerplate https://github.com/h5bp/html5-boilerplate/blob/v4.2.0/doc/css.md#visuallyhidden - .mfp-hide { - border: 0 !important; - clip: rect(0 0 0 0) !important; - height: 1px !important; - margin: -1px !important; - overflow: hidden !important; - padding: 0 !important; - position: absolute !important; - width: 1px !important; - } -} @else { - .mfp-hide { - display: none !important; - } -} - - -//////////////////////// -// 3. Appearance -//////////////////////// - -// Preloader and text that displays error messages -.mfp-preloader { - color: $mfp-controls-text-color; - position: absolute; - top: 50%; - width: auto; - text-align: center; - margin-top: -0.8em; - left: 8px; - right: 8px; - z-index: $mfp-z-index-base + 4; - a { - color: $mfp-controls-text-color; - &:hover { - color: $mfp-controls-text-color-hover; - } - } -} - -// Hide preloader when content successfully loaded -.mfp-s-ready { - .mfp-preloader { - display: none; - } -} - -// Hide content when it was not loaded -.mfp-s-error { - .mfp-content { - display: none; - } -} - -// CSS-reset for buttons -button { - &.mfp-close, - &.mfp-arrow { - overflow: visible; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; - display: block; - outline: none; - padding: 0; - z-index: $mfp-z-index-base + 6; - -webkit-box-shadow: none; - box-shadow: none; - } - &::-moz-focus-inner { - padding: 0; - border: 0 - } -} - - -// Close icon -.mfp-close { - width: 44px; - height: 44px; - line-height: 44px; - - position: absolute; - right: 0; - top: 0; - text-decoration: none; - text-align: center; - opacity: $mfp-controls-opacity; - @if $mfp-IE7support { - filter: unquote("alpha(opacity=#{$mfp-controls-opacity*100})"); - } - padding: 0 0 18px 10px; - color: $mfp-controls-color; - - font-style: normal; - font-size: 28px; - font-family: $serif; - - &:hover, - &:focus { - opacity: 1; - @if $mfp-IE7support { - filter: unquote("alpha(opacity=#{1*100})"); - } - } - - &:active { - top: 1px; - } -} -.mfp-close-btn-in { - .mfp-close { - color: $mfp-inner-close-icon-color; - } -} -.mfp-image-holder, -.mfp-iframe-holder { - .mfp-close { - color: $mfp-controls-color; - right: -6px; - text-align: right; - padding-right: 6px; - width: 100%; - } -} - -// "1 of X" counter -.mfp-counter { - position: absolute; - top: 0; - right: 0; - color: $mfp-controls-text-color; - font-size: 12px; - line-height: 18px; -} - -// Navigation arrows -@if $mfp-include-arrows { - .mfp-arrow { - position: absolute; - opacity: $mfp-controls-opacity; - @if $mfp-IE7support { - filter: unquote("alpha(opacity=#{$mfp-controls-opacity*100})"); - } - margin: 0; - top: 50%; - margin-top: -55px; - padding: 0; - width: 90px; - height: 110px; - -webkit-tap-highlight-color: rgba(0,0,0,0); - &:active { - margin-top: -54px; - } - &:hover, - &:focus { - opacity: 1; - @if $mfp-IE7support { - filter: unquote("alpha(opacity=#{1*100})"); - } - } - &:before, - &:after, - .mfp-b, - .mfp-a { - content: ''; - display: block; - width: 0; - height: 0; - position: absolute; - left: 0; - top: 0; - margin-top: 35px; - margin-left: 35px; - border: medium inset transparent; - } - - &:after, - .mfp-a { - - border-top-width: 13px; - border-bottom-width: 13px; - top:8px; - } - - &:before, - .mfp-b { - border-top-width: 21px; - border-bottom-width: 21px; - opacity: 0.7; - } - - } - - .mfp-arrow-left { - left: 0; - - &:after, - .mfp-a { - border-right: 17px solid $mfp-controls-color; - margin-left: 31px; - } - &:before, - .mfp-b { - margin-left: 25px; - border-right: 27px solid $mfp-controls-border-color; - } - } - - .mfp-arrow-right { - right: 0; - &:after, - .mfp-a { - border-left: 17px solid $mfp-controls-color; - margin-left: 39px - } - &:before, - .mfp-b { - border-left: 27px solid $mfp-controls-border-color; - } - } -} - - - -// Iframe content type -@if $mfp-include-iframe-type { - .mfp-iframe-holder { - padding-top: $mfp-iframe-padding-top; - padding-bottom: $mfp-iframe-padding-top; - .mfp-content { - line-height: 0; - width: 100%; - max-width: $mfp-iframe-max-width; - } - .mfp-close { - top: -40px; - } - } - .mfp-iframe-scaler { - width: 100%; - height: 0; - overflow: hidden; - padding-top: $mfp-iframe-ratio * 100%; - iframe { - position: absolute; - display: block; - top: 0; - left: 0; - width: 100%; - height: 100%; - box-shadow: $mfp-shadow; - background: $mfp-iframe-background; - } - } -} - - - -// Image content type -@if $mfp-include-image-type { - - /* Main image in popup */ - img { - &.mfp-img { - width: auto; - max-width: 100%; - height: auto; - display: block; - line-height: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: $mfp-image-padding-top 0 $mfp-image-padding-bottom; - margin: 0 auto; - } - } - - /* The shadow behind the image */ - .mfp-figure { - line-height: 0; - &:after { - content: ''; - position: absolute; - left: 0; - top: $mfp-image-padding-top; - bottom: $mfp-image-padding-bottom; - display: block; - right: 0; - width: auto; - height: auto; - z-index: -1; - box-shadow: $mfp-shadow; - background: $mfp-image-background; - } - small { - color: $mfp-caption-subtitle-color; - display: block; - font-size: 12px; - line-height: 14px; - } - figure { - margin: 0; - } - figcaption { - margin-top: 0; - margin-bottom: 0; // reset for bottom spacing - } - } - .mfp-bottom-bar { - margin-top: -$mfp-image-padding-bottom + 4; - position: absolute; - top: 100%; - left: 0; - width: 100%; - cursor: auto; - } - .mfp-title { - text-align: left; - line-height: 18px; - color: $mfp-caption-title-color; - word-wrap: break-word; - padding-right: 36px; // leave some space for counter at right side - } - - .mfp-image-holder { - .mfp-content { - max-width: 100%; - } - } - - .mfp-gallery { - .mfp-image-holder { - .mfp-figure { - cursor: pointer; - } - } - } - - - @if $mfp-include-mobile-layout-for-image { - @media screen and (max-width: 800px) and (orientation:landscape), screen and (max-height: 300px) { - /** - * Remove all paddings around the image on small screen - */ - .mfp-img-mobile { - .mfp-image-holder { - padding-left: 0; - padding-right: 0; - } - img { - &.mfp-img { - padding: 0; - } - } - .mfp-figure { - // The shadow behind the image - &:after { - top: 0; - bottom: 0; - } - small { - display: inline; - margin-left: 5px; - } - } - .mfp-bottom-bar { - background: rgba(0,0,0,0.6); - bottom: 0; - margin: 0; - top: auto; - padding: 3px 5px; - position: fixed; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - &:empty { - padding: 0; - } - } - .mfp-counter { - right: 5px; - top: 3px; - } - .mfp-close { - top: 0; - right: 0; - width: 35px; - height: 35px; - line-height: 35px; - background: rgba(0, 0, 0, 0.6); - position: fixed; - text-align: center; - padding: 0; - } - } - } - } -} - - - -// Scale navigation arrows and reduce padding from sides -@media all and (max-width: 900px) { - .mfp-arrow { - -webkit-transform: scale(0.75); - transform: scale(0.75); - } - .mfp-arrow-left { - -webkit-transform-origin: 0; - transform-origin: 0; - } - .mfp-arrow-right { - -webkit-transform-origin: 100%; - transform-origin: 100%; - } - .mfp-container { - padding-left: $mfp-popup-padding-left-mobile; - padding-right: $mfp-popup-padding-left-mobile; - } -} - - - -// IE7 support -// Styles that make popup look nicier in old IE -@if $mfp-IE7support { - .mfp-ie7 { - .mfp-img { - padding: 0; - } - .mfp-bottom-bar { - width: 600px; - left: 50%; - margin-left: -300px; - margin-top: 5px; - padding-bottom: 5px; - } - .mfp-container { - padding: 0; - } - .mfp-content { - padding-top: 44px; - } - .mfp-close { - top: 0; - right: 0; - padding-top: 0; - } - } -} diff --git a/_sass/vendor/magnific-popup/_settings.scss b/_sass/vendor/magnific-popup/_settings.scss deleted file mode 100644 index 9f912c3d..00000000 --- a/_sass/vendor/magnific-popup/_settings.scss +++ /dev/null @@ -1,48 +0,0 @@ -//////////////////////// -// Settings // -//////////////////////// - -// overlay -@use "sass:math"; - -$mfp-overlay-color: #000; // Color of overlay screen -$mfp-overlay-opacity: 0.8; // Opacity of overlay screen -$mfp-shadow: 0 0 8px rgba(0, 0, 0, 0.6); // Shadow on image or iframe - -// spacing -$mfp-popup-padding-left: 8px; // Padding from left and from right side -$mfp-popup-padding-left-mobile: 6px; // Same as above, but is applied when width of window is less than 800px - -$mfp-z-index-base: 1040; // Base z-index of popup - -// controls -$mfp-include-arrows: true; // Include styles for nav arrows -$mfp-controls-opacity: 1; // Opacity of controls -$mfp-controls-color: #fff; // Color of controls -$mfp-controls-border-color: #fff; // Border color of controls -$mfp-inner-close-icon-color: #fff; // Color of close button when inside -$mfp-controls-text-color: #ccc; // Color of preloader and "1 of X" indicator -$mfp-controls-text-color-hover: #fff; // Hover color of preloader and "1 of X" indicator -$mfp-IE7support: true; // Very basic IE7 support - -// Iframe-type options -$mfp-include-iframe-type: true; // Enable Iframe-type popups -$mfp-iframe-padding-top: 40px; // Iframe padding top -$mfp-iframe-background: #000; // Background color of iframes -$mfp-iframe-max-width: 900px; // Maximum width of iframes -$mfp-iframe-ratio: math.div(9, 16); // Ratio of iframe (9/16 = widescreen, 3/4 = standard, etc.) - -// Image-type options -$mfp-include-image-type: true; // Enable Image-type popups -$mfp-image-background: #444 !default; -$mfp-image-padding-top: 40px; // Image padding top -$mfp-image-padding-bottom: 40px; // Image padding bottom -$mfp-include-mobile-layout-for-image: true; // Removes paddings from top and bottom - -// Image caption options -$mfp-caption-title-color: #f3f3f3; // Caption title color -$mfp-caption-subtitle-color: #bdbdbd; // Caption subtitle color -.mfp-counter { font-family: $serif; } // Caption font family - -// A11y -$mfp-use-visuallyhidden: false; diff --git a/_sass/vendor/susy/_su.scss b/_sass/vendor/susy/_su.scss deleted file mode 100644 index 83386adb..00000000 --- a/_sass/vendor/susy/_su.scss +++ /dev/null @@ -1,4 +0,0 @@ -// Su -// == - -@import 'susy/su'; diff --git a/_sass/vendor/susy/_susy.scss b/_sass/vendor/susy/_susy.scss deleted file mode 100644 index 224e98ad..00000000 --- a/_sass/vendor/susy/_susy.scss +++ /dev/null @@ -1,4 +0,0 @@ -// Susy -// ==== - -@import 'susy/language/susy'; diff --git a/_sass/vendor/susy/_susyone.scss b/_sass/vendor/susy/_susyone.scss deleted file mode 100644 index 5b934c68..00000000 --- a/_sass/vendor/susy/_susyone.scss +++ /dev/null @@ -1,4 +0,0 @@ -// Susy -// ==== - -@import 'susy/language/susyone'; diff --git a/_sass/vendor/susy/susy/_su.scss b/_sass/vendor/susy/susy/_su.scss deleted file mode 100644 index a1454157..00000000 --- a/_sass/vendor/susy/susy/_su.scss +++ /dev/null @@ -1,7 +0,0 @@ -// Su -// == - -@import "su/utilities"; -@import "su/settings"; -@import "su/validation"; -@import "su/grid"; diff --git a/_sass/vendor/susy/susy/language/_susy.scss b/_sass/vendor/susy/susy/language/_susy.scss deleted file mode 100644 index 0ee9cae2..00000000 --- a/_sass/vendor/susy/susy/language/_susy.scss +++ /dev/null @@ -1,24 +0,0 @@ -// Susy Next Syntax -// ================ - -$susy-version: 2.1; - -@import "../su"; -@import "../output/float"; - -@import "susy/settings"; -@import "susy/validation"; -@import "susy/grids"; -@import "susy/box-sizing"; -@import "susy/context"; -@import "susy/background"; -@import "susy/container"; -@import "susy/span"; -@import "susy/gutters"; -@import "susy/isolate"; -@import "susy/gallery"; -@import "susy/rows"; -@import "susy/margins"; -@import "susy/padding"; -@import "susy/bleed"; -@import "susy/breakpoint-plugin"; diff --git a/_sass/vendor/susy/susy/language/_susyone.scss b/_sass/vendor/susy/susy/language/_susyone.scss deleted file mode 100644 index a783d3a8..00000000 --- a/_sass/vendor/susy/susy/language/_susyone.scss +++ /dev/null @@ -1,13 +0,0 @@ -// --------------------------------------------------------------------------- -// Partials - -$susy-version: 1.5; - -@import "susyone/settings"; -@import "susyone/functions"; -@import "susyone/grid"; -@import "susyone/isolation"; -@import "susyone/padding"; -@import "susyone/margin"; -@import "susyone/media"; -@import "susyone/background"; diff --git a/_sass/vendor/susy/susy/language/susy/_background.scss b/_sass/vendor/susy/susy/language/susy/_background.scss deleted file mode 100644 index 752b0d36..00000000 --- a/_sass/vendor/susy/susy/language/susy/_background.scss +++ /dev/null @@ -1,387 +0,0 @@ -// Background Grid Syntax -// ====================== - -@use "sass:math"; - -$susy-overlay-grid-head-exists: false; - - -// Show Grid/s -// ----------- -// Show grid on any element using either background or overlay. -// - [$grid] : -@mixin show-grid( - $grid: $susy -) { - $inspect: $grid; - $_output: debug-get(output, $grid); - - @include susy-inspect(show-grid, $inspect); - @if $_output == overlay and susy-get(debug image, $grid) != hide { - @include overlay-grid($grid); - } @else { - @include background-grid($grid); - } -} - -@mixin show-grids( - $grid: $susy -) { - @include show-grid($grid); -} - -// Background Grid -// --------------- -// Show a grid background on any element. -// - [$grid] : -@mixin background-grid( - $grid: $susy -) { - $inspect : $grid; - $_output : get-background($grid); - - @if length($_output) > 0 { - $_flow: susy-get(flow, $grid); - - $_image: (); - @each $name, $layer in map-get($_output, image) { - $_direction: if($name == baseline, to bottom, to to($_flow)); - $_image: append($_image, linear-gradient($_direction, $layer), comma); - } - $_output: map-merge($_output, (image: $_image)); - - @include background-grid-output($_output...); - @include susy-inspect(background-grid, $inspect); - } -} - - -// Overlay Grid -// ------------ -// Generate an icon to trigger grid-overlays on any given elements. -// $grids... : [] [, ]* -@mixin overlay-grid ( - $grid: $susy -) { - @if not($susy-overlay-grid-head-exists) { - @at-root head { @include overlay-head($grid); } - @at-root head:before { @include overlay-trigger; } - @at-root head:hover { @include overlay-trigger-hover; } - $susy-overlay-grid-head-exists: true !global; - } - - head:hover ~ &, - head:hover ~ body & { - position: relative; - &:before { - @include grid-overlay-base; - @include background-grid($grid); - } - } -} - - -// [Private] Overlay Trigger -// ------------------------- -@mixin overlay-trigger { - content: "|||"; - display: block; - padding: 5px 10px; - font: { - family: sans-serif; - size: 16px; - weight: bold; - } -} - - -// [Private] Overlay Trigger Hover -// ------------------------------- -@mixin overlay-trigger-hover { - background: rgba(white, .5); - color: red; -} - - -// [Private] Overlay Head -// ---------------------- -// styles to create grid overlay toggle -@mixin overlay-head ( - $grid: $susy -) { - $_toggle: debug-get(toggle, $grid); - $_horz: null; - $_vert: null; - - @each $side in $_toggle { - $_horz: if($side == left or $side == right, $side, $_horz); - $_vert: if($side == top or $side == bottom, $side, $_vert); - } - - display: block; - position: fixed; - #{$_horz}: 10px; - #{$_vert}: 10px; - z-index: 999; - color: #333; - background: rgba(white, .25); -} - - -// [Private] Grid Overlay Base -// --------------------------- -// Base styles for generating a grid overlay -@mixin grid-overlay-base() { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - content: " "; - z-index: 998; -} - - -// Get Symmetrical Background -// -------------------------- -// - $grid: -@function get-background-sym( - $grid -) { - $grid : parse-grid($grid); - $_gutters : susy-get(gutters, $grid); - $_column-width : susy-get(column-width, $grid); - $_math : susy-get(math, $grid); - - $_color : debug-get(color); - $_trans : transparent; - $_light : lighten($_color, 15%); - - $_end : 1 + $_gutters; - $_after : percentage(math.div(1, $_end)); - $_stops : (); - $_size : span(1 $grid wide); - - @if is-inside($grid) { - $_stops: $_color, $_light; - } @else if is-split($grid) { - $_split: $_gutters*0.5; - $_before: percentage(math.div($_split, $_end)); - $_after: percentage(math.div(1 + $_split, $_end)); - $_stops: $_trans $_before, $_color $_before, $_light $_after, $_trans $_after; - } @else { - $_stops: $_color, $_light $_after, $_trans $_after; - } - - @if $_math == static { - $_size: valid-column-math($_math, $_column-width) * $_end; - } - - $_output: ( - image: (columns: $_stops), - size: $_size, - ); - - @return $_output; -} - - -// Get Asymmetrical Inside -// ----------------------- -// - $grid: -@function get-asym-inside( - $grid -) { - $grid : parse-grid($grid); - $_columns : susy-get(columns, $grid); - - $_color : debug-get(color); - $_light : lighten($_color, 15%); - $_stops : (); - - @for $location from 1 through susy-count($_columns) { - $this-stop: (); - - @if $location == 1 { - $this-stop: append($this-stop, $_color, comma); - } @else { - $start: parse-span(1 at $location $grid); - $start: get-isolation($start); - $this-stop: append($this-stop, $_color $start, comma); - } - - @if $location == susy-count($_columns) { - $this-stop: append($this-stop, $_light, comma); - } @else { - $_end: parse-span(1 at ($location + 1) $grid); - $_end: get-isolation($_end); - $this-stop: append($this-stop, $_light $_end, comma); - } - - $_stops: join($_stops, $this-stop, comma); - } - - @return $_stops; -} - - -// Get Asymmetrical Split -// ---------------------- -// - $grid: -@function get-asym-split( - $grid -) { - $grid : parse-grid($grid); - $_columns : susy-get(columns, $grid); - - $_color : debug-get(color); - $_light : lighten($_color, 15%); - $_stops : (); - - @for $location from 1 through susy-count($_columns) { - $this-stop: (); - - $start: parse-span(1 at $location $grid); - $start: get-isolation($start); - $this-stop: append($this-stop, transparent $start, comma); - $this-stop: append($this-stop, $_color $start, comma); - - $_end: $start + span(1 at $location $grid); - $this-stop: append($this-stop, $_light $_end, comma); - $this-stop: append($this-stop, transparent $_end, comma); - - $_stops: join($_stops, $this-stop, comma); - } - - @return $_stops; -} - - -// Get Asymmetrical Outside -// ------------------------ -// - $grid: -@function get-asym-outside( - $grid -) { - $grid : parse-grid($grid); - $_columns : susy-get(columns, $grid); - - $_color : debug-get(color); - $_light : lighten($_color, 15%); - $_trans : transparent; - $_stops : (); - - @for $location from 1 through susy-count($_columns) { - $this-stop: (); - - @if $location == 1 { - $this-stop: append($this-stop, $_color, comma); - } @else { - $start: parse-span(1 at $location $grid); - $start: get-isolation($start); - $this-stop: append($this-stop, $_color $start, comma); - } - - @if $location == susy-count($_columns) { - $this-stop: append($this-stop, $_light, comma); - } @else { - $gutter: get-span-width(first $location $grid); - - $_end: parse-span(1 at ($location + 1) $grid); - $_end: get-isolation($_end); - - $gutter: $_light $gutter, $_trans $gutter, $_trans $_end; - $this-stop: join($this-stop, $gutter, comma); - } - - $_stops: join($_stops, $this-stop, comma); - } - - @return $_stops; -} - - -// Get Asymmetrical Background -// --------------------------- -// - $grid: -@function get-background-asym( - $grid -) { - $_stops: (); - - @if is-inside($grid) { - $_stops: get-asym-inside($grid); - } @else if is-split($grid) { - $_stops: get-asym-split($grid); - } @else { - $_stops: get-asym-outside($grid); - } - - @return (image: (columns: $_stops)); -} - - -// Get Background -// -------------- -// - $grid: -@function get-background( - $grid -) { - $grid : parse-grid($grid); - $_show : susy-get(debug image, $grid); - $_return : (); - - @if $_show and $_show != 'hide' { - $_columns: susy-get(columns, $grid); - - @if $_show != 'show-baseline' { - $_sym: is-symmetrical($_columns); - $_return: if($_sym, get-background-sym($grid), get-background-asym($grid)); - $_return: map-merge($_return, (clip: content-box)); - } - - @if $_show != 'show-columns' - and global-variable-exists(base-line-height) - and type-of($base-line-height) == 'number' - and not unitless($base-line-height) { - $_color: variable-exists('grid-background-baseline-color'); - $_color: if($_color, $grid-background-baseline-color, #000); - - $_image: map-get($_return, image); - $_size: map-get($_return, size); - $_baseline: (baseline: ($_color 1px, transparent 1px)); - $_baseline-size: 100% $base-line-height; - - $_return: map-merge($_return, ( - image: if($_image, map-merge($_image, $_baseline), $_baseline), - size: if($_size, ($_size, $_baseline-size), $_baseline-size), - )); - - @if $_show == 'show' { - $_clip: map-get($_return, clip); - $_return: map-merge($_return, (clip: join($_clip, border-box, comma))); - } - } @else if $_show == 'show-baseline' { - @warn 'Please provide a $base-line-height with the desired height and units'; - } - } - - @if map-get($_return, image) { - $_return: map-merge($_return, (flow: susy-get(flow, $grid))); - } - - @return $_return; -} - - -// Get Debug -// --------- -// Return the value of a debug setting -// - $key: -@function debug-get( - $key, - $grid: $susy -) { - $key: join(debug, $key, space); - @return susy-get($key, $grid); -} diff --git a/_sass/vendor/susy/susy/language/susy/_bleed.scss b/_sass/vendor/susy/susy/language/susy/_bleed.scss deleted file mode 100644 index 8ef59743..00000000 --- a/_sass/vendor/susy/susy/language/susy/_bleed.scss +++ /dev/null @@ -1,200 +0,0 @@ -// Bleed Syntax -// ============ - -// Bleed -// ----- -// Add negative margins, and equal positive padding to create bleed. -// - $bleed : -@mixin bleed( - $bleed: 0 gutter() -) { - $inspect : $bleed; - $output : get-bleed($bleed); - - @if susy-get(global-box-sizing) != content-box { - $output: map-merge((box-sizing: content-box), $output); - } - - @include susy-inspect(bleed, $inspect); - @include output($output); -} - - -// Bleed-x -// ------- -// Shortcut for horizontal bleed. -// - $bleed : -@mixin bleed-x( - $bleed: gutter() -) { - $bleed : parse-span($bleed); - $trbl : susy-get(span, $bleed); - - @if length($trbl) == 1 { - $bleed: map-merge($bleed, (span: 0 nth($trbl, 1))); - } @else if length($trbl) == 2 { - $bleed: map-merge($bleed, (span: 0 nth($trbl, 2) 0 nth($trbl, 1))); - } @else { - @warn 'bleed-x only takes 2 lengths, but #{length($trbl)} were passed.'; - } - - @include bleed($bleed); -} - - -// Bleed-y -// ------- -// Shortcut for vertical bleed. -// - $bleed : -@mixin bleed-y( - $bleed: if(function-exists(rhythm), rhythm(1), 1em) -) { - $bleed : parse-span($bleed); - $trbl : susy-get(span, $bleed); - - @if length($trbl) == 1 { - $bleed: map-merge($bleed, (span: nth($trbl, 1) 0)); - } @else if length($trbl) == 2 { - $bleed: map-merge($bleed, (span: nth($trbl, 1) 0 nth($trbl, 2) 0)); - } @else { - @warn 'bleed-y only takes 2 lengths, but #{length($trbl)} were passed.'; - } - - @include bleed($bleed); -} - - -// Get Bleed -// --------- -// Return bleed output values -// - $bleed: -@function get-bleed( - $bleed -) { - $bleed : map-merge((spread: wide), parse-span($bleed)); - $trbl : susy-get(span, $bleed); - $short : null; - $output : (); - - @for $i from 1 through length($trbl) { - $this: nth($trbl, $i); - $new: (); - $margin: null; - $padding: null; - $padding-x: null; - - @if $this > 0 { - $this: map-merge($bleed, (span: $this)); - $margin: span($this); - $padding: $margin; - $padding-x: $padding; - } - - @if $margin and $margin > 0 { - $margin: - $margin; - - @if is-inside($this) { - $gutter: gutter($this); - $join: if($gutter and comparable($padding, $gutter), true, false); - $padding-x: if($join and $padding > 0, $padding + $gutter, $padding); - } - } - - @if $i == 1 { - $new: ( - margin-top: $margin, - padding-top: $padding, - margin-right: $margin, - padding-right: $padding-x, - margin-bottom: $margin, - padding-bottom: $padding, - margin-left: $margin, - padding-left: $padding-x, - ); - } @else if $i == 2 { - $new: ( - margin-right: $margin, - padding-right: $padding-x, - margin-left: $margin, - padding-left: $padding-x, - ); - } @else if $i == 3 { - $new: ( - margin-bottom: $margin, - padding-bottom: $padding, - ); - } @else if $i == 4 { - $new: ( - margin-left: $margin, - padding-left: $padding-x, - ); - } - - $output: map-merge($output, $new); - } - - @each $prop, $value in $output { - $output: if($value == 0, map-merge($output, ($prop: null)), $output); - } - - @return bleed-shorthand($output); -} - -// Bleed Shorthand -// --------------- -// Convert bleed output into shorthand when possible. -// - $bleed: -@function bleed-shorthand( - $bleed -) { - $margin: (); - $padding: (); - $return: (); - - @each $key, $value in $bleed { - @if str-index($key, margin) { - $margin: map-merge($margin, ($key: $value)); - } @else if str-index($key, padding) > 0 { - $padding: map-merge($padding, ($key: $value)); - } - } - - $props: ( - margin: $margin, - padding: $padding, - ); - - @each $name, $map in $props { - $four: if(length(map-keys($map)) == 4, true, false); - $null: if(index(map-values($map), null), true, false); - - @if $four and not($null) { - $top: map-get($map, '#{$name}-top'); - $right: map-get($map, '#{$name}-right'); - $bottom: map-get($map, '#{$name}-bottom'); - $left: map-get($map, '#{$name}-left'); - - $tb: if($top == $bottom, $top, null); - $rl: if($right == $left, $right, null); - $all: if($tb == $rl, $tb, null); - - $new: if($all, $all, null); - - @if not($new) { - @if $tb and $rl { - $new: $tb $rl; - } @else if $rl { - $new: $top $rl $bottom; - } @else { - $new: $top $right $bottom $left; - } - } - - $return: map-merge($return, ($name: $new)); - } @else { - $return: map-merge($return, $map); - } - } - - @return $return; -} diff --git a/_sass/vendor/susy/susy/language/susy/_box-sizing.scss b/_sass/vendor/susy/susy/language/susy/_box-sizing.scss deleted file mode 100644 index f551241d..00000000 --- a/_sass/vendor/susy/susy/language/susy/_box-sizing.scss +++ /dev/null @@ -1,47 +0,0 @@ -// Susy Box Sizing -// ================= - -// Global Box Sizing -// ----------------- -// Set a box model globally on all elements. -// - [$box]: border-box | content-box -// - [$inherit]: true | false -@mixin global-box-sizing( - $box: susy-get(global-box-sizing), - $inherit: false -) { - $inspect: $box; - - @if $inherit { - @at-root { - html { @include output((box-sizing: $box)); } - *, *:before, *:after { box-sizing: inherit; } - } - } @else { - *, *:before, *:after { @include output((box-sizing: $box)); } - } - - @include susy-inspect(global-box-sizing, $inspect); - @include update-box-model($box); -} - -// Border Box Sizing -// ----------------- -// A legacy shortcut... -// - [$inherit]: true | false -@mixin border-box-sizing( - $inherit: false -) { - @include global-box-sizing(border-box, $inherit); -} - -// Update Box Model -// ---------------- -// PRIVATE: Updates global box model setting -@mixin update-box-model( - $box -) { - @if $box != susy-get(global-box-sizing) { - @include susy-set(global-box-sizing, $box); - } -} diff --git a/_sass/vendor/susy/susy/language/susy/_breakpoint-plugin.scss b/_sass/vendor/susy/susy/language/susy/_breakpoint-plugin.scss deleted file mode 100644 index 30de288b..00000000 --- a/_sass/vendor/susy/susy/language/susy/_breakpoint-plugin.scss +++ /dev/null @@ -1,185 +0,0 @@ -// Breakpoint Integration -// ====================== - -$susy-media: () !default; -$susy-media-fallback: false !default; - -$_susy-media-context: (); - - -// Susy Breakpoint -// --------------- -// Change grids at different media query breakpoints. -// - $query : [] | | -// - $layout : -// - $no-query : | -@mixin susy-breakpoint( - $query, - $layout: false, - $no-query: $susy-media-fallback -) { - @include susy-media-router($query, $no-query) { - @if $layout { - @include with-layout($layout) { - @content; - } - } @else { - @content; - } - } -} - - -// Susy Media -// ---------- -// - $query: [] | -// - $no-query: | -@mixin susy-media( - $query, - $no-query: $susy-media-fallback -) { - $old-context: $_susy-media-context; - $name: if(map-has-key($susy-media, $query), $query, null); - $query: susy-get-media($query); - $query: susy-parse-media($query); - - @include susy-media-context($query, $name); - - @if $no-query and type-of($no-query) != string { - @content; - } @else { - @media #{susy-render-media($query)} { - @content; - } - - @if type-of($no-query) == string { - #{$no-query} & { - @content; - } - } - } - - @include susy-media-context($old-context, $clean: true); -} - - -// Media Router -// ------------ -// Rout media arguments to the correct mixin. -@mixin susy-media-router( - $query, - $no-query: $susy-media-fallback -) { - @if susy-support(breakpoint, (mixin: breakpoint), $warn: false) { - @include breakpoint($query, $no-query) { - @content; - } - } @else { - @include susy-media($query, $no-query) { - @content; - } - } -} - - -// Update Context -// ------------- -// Set the new media context -@mixin susy-media-context( - $query, - $name: null, - $clean: false -) { - $query: map-merge((name: $name), $query); - - @if $clean { - $_susy-media-context: $query !global; - } @else { - $_susy-media-context: map-merge($_susy-media-context, $query) !global; - } -} - - -// Media Context -// ------------- -// Return the full media context, or a single media property (e.g. min-width) -@function susy-media-context( - $property: false -) { - @if $property { - @return map-get($_susy-media-context, $property); - } @else { - @return $_susy-media-context; - } -} - - -// Get Media -// --------- -// Return a named media-query from $susy-media. -// - $name: -@function susy-get-media( - $name -) { - @if map-has-key($susy-media, $name) { - $map-value: map-get($susy-media, $name); - @if ($name == $map-value) { - $name: $map-value; - } @else { - $name: susy-get-media($map-value); - } - } - - @return $name; -} - - -// Render Media -// ------------ -// Build a media-query string from various media settings -@function susy-render-media( - $query -) { - $output: null; - @each $property, $value in $query { - $string: null; - - @if $property == media { - $string: $value; - } @else { - $string: '(#{$property}: #{$value})'; - } - - $output: if($output, '#{$output} and #{$string}', $string); - } - - @return $output; -} - - -// Parse Media -// ----------- -// Return parsed media-query settings based on shorthand -@function susy-parse-media( - $query -) { - $mq: null; - @if type-of($query) == map { - $mq: $query; - } @else if type-of($query) == number { - $mq: (min-width: $query); - } @else if type-of($query) == list and length($query) == 2 { - @if type-of(nth($query, 1)) == number { - $mq: ( - min-width: min($query...), - max-width: max($query...), - ); - } @else { - $mq: (nth($query, 1): nth($query, 2)); - } - } @else { - $mq: (media: '#{$query}'); - } - - @return $mq; -} diff --git a/_sass/vendor/susy/susy/language/susy/_container.scss b/_sass/vendor/susy/susy/language/susy/_container.scss deleted file mode 100644 index e5f4a858..00000000 --- a/_sass/vendor/susy/susy/language/susy/_container.scss +++ /dev/null @@ -1,81 +0,0 @@ -// Container Syntax -// ================ - -// Container [mixin] -// ----------------- -// Set a container element -// - [$layout] : -@mixin container( - $layout: $susy -) { - $inspect : $layout; - $layout : parse-grid($layout); - - $_width : get-container-width($layout); - $_justify : parse-container-position(susy-get(container-position, $layout)); - $_property : if(susy-get(math, $layout) == static, width, max-width); - - $_box : susy-get(box-sizing, $layout); - - @if $_box { - @include output((box-sizing: $_box)); - } - - @include susy-inspect(container, $inspect); - @include float-container($_width, $_justify, $_property); - @include show-grid($layout); -} - -// Container [function] -// -------------------- -// Return container width -// - [$layout] : -@function container( - $layout: $susy -) { - $layout: parse-grid($layout); - @return get-container-width($layout); -} - -// Get Container Width -// ------------------- -// Calculate the container width -// - [$layout]: -@function get-container-width( - $layout: $susy -) { - $layout : parse-grid($layout); - $_width : susy-get(container, $layout); - $_column-width : susy-get(column-width, $layout); - $_math : susy-get(math, $layout); - - @if not($_width) or $_width == auto { - @if valid-column-math($_math, $_column-width) { - $_columns : susy-get(columns, $layout); - $_gutters : susy-get(gutters, $layout); - $_spread : if(is-split($layout), wide, narrow); - $_width : susy-sum($_columns, $_gutters, $_spread) * $_column-width; - } @else { - $_width: 100%; - } - } - - @return $_width; -} - -// Parse Container Position -// ------------------------ -// Parse the $container-position into margin values. -// - [$justify] : left | center | right | [] -@function parse-container-position( - $justify: map-get($susy-defaults, container-position) -) { - $_return: if($justify == left, 0, auto) if($justify == right, 0, auto); - - @if not(index(left right center, $justify)) { - $_return: nth($justify, 1); - $_return: $_return if(length($justify) > 1, nth($justify, 2), $_return); - } - - @return $_return; -} diff --git a/_sass/vendor/susy/susy/language/susy/_context.scss b/_sass/vendor/susy/susy/language/susy/_context.scss deleted file mode 100644 index 52e12a6c..00000000 --- a/_sass/vendor/susy/susy/language/susy/_context.scss +++ /dev/null @@ -1,36 +0,0 @@ -// Context Syntax -// ============== - -// Nested [function] -// ----------------- -// Return a subset grid for nested context. -// - $context : -@function nested( - $context -) { - $context : parse-span($context); - $span : susy-get(span, $context); - $location : get-location($context); - $columns : susy-get(columns, $context); - - @return susy-slice($span, $location, $columns); -} - -// Nested [mixin] -// -------------- -// Use a subset grid for a nested context -// - $context : -// - @content : -@mixin nested( - $context -) { - $inspect : $context; - $context : parse-span($context); - $old : susy-get(columns); - $susy : map-merge($susy, (columns: nested($context))) !global; - - @include susy-inspect(nested, $inspect); - @content; - - $susy : map-merge($susy, (columns: $old)) !global; -} diff --git a/_sass/vendor/susy/susy/language/susy/_gallery.scss b/_sass/vendor/susy/susy/language/susy/_gallery.scss deleted file mode 100644 index 9d2f0c1b..00000000 --- a/_sass/vendor/susy/susy/language/susy/_gallery.scss +++ /dev/null @@ -1,96 +0,0 @@ -// Gallery Syntax -// ============== - -// Gallery -// ------- -// Create an isolated gallery -// - $span : -// - [$selector] : child | of-type -@use "sass:math"; - -@mixin gallery( - $span, - $selector: child -) { - $inspect : $span; - $span : parse-span($span); - $span : map-merge($span, (location: 1)); - - $n : susy-get(span, $span); - $columns : susy-get(columns, $span); - $context : susy-count($columns); - $flow : susy-get(flow, $span); - - $inside : is-inside($span); - $from : from($flow); - $line : floor(math.div($context, $n)); - $symmetrical : is-symmetrical($columns); - - $output: ( - width : null, - float : from, - margin-before : null, - margin-after : null, - padding-before : null, - padding-after : null, - flow : $flow, - ); - - @if $inside { - $gutters: get-gutters($span); - $output: map-merge($output, ( - padding-before: map-get($gutters, before), - padding-after: map-get($gutters, after), - )); - } - - @if $symmetrical { - $output: map-merge($output, (width: get-span-width($span))); - } - - $box : susy-get(box-sizing, $span); - $global-box : if(susy-get(global-box-sizing) == 'border-box', true, false); - - @include susy-inspect(gallery, $inspect); - - // Collective Output - @if $box == border-box or ($inside and not($box) and not($global-box)) { - @include output((box-sizing: border-box)); - } @else if $box == content-box { - @include output((box-sizing: content-box)); - } - - @include float-span-output($output...); - - // Individual Loop - @for $item from 1 through $line { - $nth: '#{$line}n + #{$item}'; - &:nth-#{$selector}(#{$nth}) { - // Individual Prep - $output: ( - width : if($symmetrical, null, get-span-width($span)), - float : null, - margin-before : get-isolation($span), - margin-after : -100%, - padding-before : null, - padding-after : null, - flow : $flow, - ); - - // Individual Output - @include float-span-output($output...); - - @if get-edge($span) == first { - @include break; - @include first($span); - } @else { - @include nobreak; - } - - // Individual Location Increment - $location: get-location($span) + $n; - $location: if($location > $context, 1, $location); - $span: map-merge($span, (location: $location)); - } - } -} diff --git a/_sass/vendor/susy/susy/language/susy/_grids.scss b/_sass/vendor/susy/susy/language/susy/_grids.scss deleted file mode 100644 index 4fa72edc..00000000 --- a/_sass/vendor/susy/susy/language/susy/_grids.scss +++ /dev/null @@ -1,64 +0,0 @@ -// Grid Syntax -// =========== - - -// Layout -// ------ -// Set a new layout using a shorthand -// - $layout: -// - $clean: boolean -@mixin layout( - $layout, - $clean: false -) { - $inspect : $layout; - $susy : _get-layout($layout, $clean) !global; - - @include susy-inspect(layout, $inspect); -} - - -// Use Grid -// -------- -// Use an arbitrary layout for a section of code -// - $layout: -// - $clean: boolean -@mixin with-layout( - $layout, - $clean: false -) { - $inspect : $layout; - $old : $susy; - $susy : _get-layout($layout, $clean) !global; - - @include susy-inspect(with-layout, $inspect); - - @content; - - $susy: $old !global; -} - - -// Layout -// ------ -// Return a parsed layout map based on shorthand syntax -// - $layout: -@function layout( - $layout: $susy -) { - @return parse-grid($layout); -} - - -// Get Layout -// ---------- -// Return a new layout based on current and given settings -// - $layout: -// - $clean: boolean -@function _get-layout( - $layout, - $clean: false -) { - $layout: layout($layout); - @return if($clean, $layout, _susy-deep-merge($susy, $layout)); -} diff --git a/_sass/vendor/susy/susy/language/susy/_gutters.scss b/_sass/vendor/susy/susy/language/susy/_gutters.scss deleted file mode 100644 index c11211c4..00000000 --- a/_sass/vendor/susy/susy/language/susy/_gutters.scss +++ /dev/null @@ -1,156 +0,0 @@ -// Gutter Syntax -// ============= - - -// Gutters -// ------- -// Set gutters on an element. -// - [$span] : -@use "sass:math"; - -@mixin gutters( - $span: $susy -) { - $inspect : $span; - $span : parse-gutters($span); - $_gutters : get-gutters($span); - - $_output: ( - before: map-get($_gutters, before), - after: map-get($_gutters, after), - flow: susy-get(flow, $span), - ); - - @include susy-inspect(gutters, $inspect); - - @if is-inside($span) { - @include padding-output($_output...); - } @else { - @include margin-output($_output...); - } -} - -@mixin gutter( - $span: $susy -) { - @include gutters($span); -} - - -// Gutter -// ------ -// Return the width of a gutter. -// - [$span] : -@function gutter( - $span: $susy -) { - $span: parse-gutters($span); - - $_gutters: get-gutters($span); - $_gutters: map-get($_gutters, before) or map-get($_gutters, after); - - @return $_gutters; -} - -@function gutters( - $span: $susy -) { - @return gutter($span); -} - - -// Get Gutter Width -// ---------------- -// Return gutter width. -// - [$context]: -@function get-gutter-width( - $context: $susy -) { - $context : parse-gutters($context); - - $_gutters : susy-get(gutters, $context); - $_gutter : susy-get(gutter-override, $context); - - @if $_gutters and ($_gutters > 0) and not($_gutter) { - $_column-width: susy-get(column-width, $context); - $_math: gutter-math($context); - @if $_math == static { - $_gutter: $_gutters * valid-column-math($_math, $_column-width); - } @else { - $_columns : susy-get(columns, $context); - $_spread : if(is-split($context), wide, susy-get(spread, $context)); - $_gutter : percentage(math.div($_gutters, susy-sum($_columns, $_gutters, $_spread))); - } - } - - $_gutter: if($_gutter == 'no-gutters' or $_gutter == 'no-gutter', null, $_gutter); - - @return $_gutter; -} - - -// Get Gutters -// ----------- -// Return before and after gutter values. -// - [$context]: -@function get-gutters( - $context: $susy -) { - $context : parse-gutters($context); - - $_gutter-position : susy-get(gutter-position, $context); - $_gutter : get-gutter-width($context); - - $_return : (before: null, after: null); - - @if is-split($context) and $_gutter { - $_gutter: $_gutter * 0.5; - $_return: map-merge($_return, (before: $_gutter, after: $_gutter)); - } @else { - $_return: map-merge($_return, ($_gutter-position: $_gutter)); - } - - @return $_return; -} - - -// Is Inside -// --------- -// Returns true if gutters are inside. -// $context: -@function is-inside( - $context -) { - $_inside: inside inside-static; - $_gutter-position: susy-get(gutter-position, $context); - - @return if(index($_inside, $_gutter-position), true, false); -} - - -// Is Split -// -------- -// Returns true if gutters are split. -// $context: -@function is-split( - $context -) { - $_split: split inside inside-static; - $_gutter-position: susy-get(gutter-position, $context); - - @return if(index($_split, $_gutter-position), true, false); -} - - -// Gutter Math -// ----------- -// Return the math to use for gutter calculations -// $context: -@function gutter-math( - $context: $susy -) { - $_return : susy-get(math, $context); - $_return : if(susy-get(gutter-position, $context) == inside-static, static, $_return); - - @return $_return; -} diff --git a/_sass/vendor/susy/susy/language/susy/_isolate.scss b/_sass/vendor/susy/susy/language/susy/_isolate.scss deleted file mode 100644 index 7ddfd7f5..00000000 --- a/_sass/vendor/susy/susy/language/susy/_isolate.scss +++ /dev/null @@ -1,77 +0,0 @@ -// Isolation Syntax -// ================ - - -// Isolate [Mixin] -// --------------- -// Set isolation as an override. -// - $location: -@mixin isolate( - $isolate: 1 -) { - $inspect: $isolate; - - $output: ( - push: isolate($isolate), - flow: susy-get(flow, $isolate), - ); - - @include susy-inspect(isolate, $inspect); - @include isolate-output($output...); -} - - -// Isolate [function] -// ------------------ -// Return an isolation offset width. -// - $location: -@function isolate( - $isolate: 1 -) { - $isolate: parse-span($isolate); - $isolation: susy-get(span, $isolate); - - @if $isolation and not(get-location($isolate)) { - $new: ( - span: null, - location: $isolation, - ); - $isolate: map-merge($isolate, $new); - } - - @return get-isolation($isolate); -} - - -// Get Isolation -// ------------- -// Return the isolation offset width -// - $input: -@function get-isolation( - $input -) { - $location : get-location($input); - $columns : susy-get(columns, $input); - $width : null; - - @if type-of($location) == number and not(unitless($location)) { - $width: $location; - } @else if $location { - $push: $location - 1; - @if $push > 0 { - $push: map-merge($input, ( - span: $push, - location: 1, - spread: wide, - )); - $width: get-span-width($push); - } - } - - @if susy-get(gutter-position, $input) == split - and susy-get(gutters, $input) > 0 { - $width: if($width == null, gutters($input), $width + gutters($input)); - } - - @return $width or 0; -} diff --git a/_sass/vendor/susy/susy/language/susy/_margins.scss b/_sass/vendor/susy/susy/language/susy/_margins.scss deleted file mode 100644 index cb368399..00000000 --- a/_sass/vendor/susy/susy/language/susy/_margins.scss +++ /dev/null @@ -1,94 +0,0 @@ -// Margin Syntax -// ============= - -// Pre -// --- -// Add spanning-margins before an element. -// - $span : -@mixin pre( - $span -) { - $inspect: $span; - $span : map-merge((spread: wide), parse-span($span)); - $flow : susy-get(flow, $span); - $split : if(susy-get(gutter-position, $span) == split, true, false); - $gutter : gutter($span); - $span : span($span); - $width : if($split and $gutter, $span + $gutter, $span); - - @include susy-inspect(pre, $inspect); - @include margin-output($width, null, $flow); -} - -// Post -// ---- -// Add spanning-margins after an element. -// - $span : -@mixin post( - $span -) { - $inspect : $span; - $span : map-merge((spread: wide), parse-span($span)); - $flow : susy-get(flow, $span); - $split : if(susy-get(gutter-position, $span) == split, true, false); - $width : if($split, span($span) + gutter($span), span($span)); - - @include susy-inspect(post, $inspect); - @include margin-output(null, $width, $flow); -} - -// Push -// ---- -// Simple synonymn for pre. -// - $span : -@mixin push( - $span -) { - @include pre($span); -} - -// Pull -// ---- -// Add negative spanning-margins before an element. -// - $span : -@mixin pull( - $span -) { - $inspect : $span; - $span : map-merge((spread: wide), parse-span($span)); - $flow : susy-get(flow, $span); - $split : if(susy-get(gutter-position, $span) == split, true, false); - $width : if($split, 0 - span($span) + gutter($span), 0 - span($span)); - - @include susy-inspect(pull, $inspect); - @include margin-output($width, null, $flow); -} - -// Squish -// ------ -// Add spanning-margins before and after an element. -// - $pre : -// - [$post] : -@mixin squish( - $pre, - $post: false -) { - $inspect : ($pre, $post); - $pre : map-merge((spread: wide), parse-span($pre)); - - @if $post { - $post: map-merge((spread: wide), parse-span($post)); - } @else { - $span: susy-get(span, $pre); - @if length($span) > 1 { - $pre: map-merge($pre, (span: nth($span, 1))); - $post: map-merge($pre, (span: nth($span, 2))); - } @else { - $post: $pre; - } - } - - @include susy-inspect(squish, $inspect); - @include pre($pre); - @include post($post); -} diff --git a/_sass/vendor/susy/susy/language/susy/_padding.scss b/_sass/vendor/susy/susy/language/susy/_padding.scss deleted file mode 100644 index cdf75c8b..00000000 --- a/_sass/vendor/susy/susy/language/susy/_padding.scss +++ /dev/null @@ -1,74 +0,0 @@ -// Padding Syntax -// ============== - -// Prefix -// ------ -// Add spanning-padding before an element. -// - $span : -@mixin prefix( - $span -) { - $inspect : $span; - $span : map-merge((spread: wide), parse-span($span)); - $flow : susy-get(flow, $span); - $width : span($span); - - @if is-inside($span) { - $gutter: gutter($span); - $width: if($gutter and comparable($width, $gutter), $width + $gutter, $width); - } - - @include susy-inspect(prefix, $inspect); - @include padding-output($width, null, $flow); -} - -// Suffix -// ------ -// Add spanning-padding after an element. -// - $span : -@mixin suffix( - $span -) { - $inspect : $span; - $span : map-merge((spread: wide), parse-span($span)); - $flow : susy-get(flow, $span); - $width : span($span); - - @if is-inside($span) { - $gutter: gutter($span); - $width: if($gutter and comparable($width, $gutter), $width + $gutter, $width); - } - - @include susy-inspect(suffix, $inspect); - @include padding-output(null, $width, $flow); -} - -// Pad -// --- -// Add spanning-padding before and after an element. -// - $pre : -// - [$post] : -@mixin pad( - $pre, - $post: false -) { - $inspect : ($pre, $post); - $pre : map-merge((spread: wide), parse-span($pre)); - - @if $post { - $post: map-merge((spread: wide), parse-span($post)); - } @else { - $span: susy-get(span, $pre); - @if length($span) > 1 { - $pre: map-merge($pre, (span: nth($span, 1))); - $post: map-merge($pre, (span: nth($span, 2))); - } @else { - $post: $pre; - } - } - - @include susy-inspect(pad, $inspect); - @include prefix($pre); - @include suffix($post); - -} diff --git a/_sass/vendor/susy/susy/language/susy/_rows.scss b/_sass/vendor/susy/susy/language/susy/_rows.scss deleted file mode 100644 index d7264313..00000000 --- a/_sass/vendor/susy/susy/language/susy/_rows.scss +++ /dev/null @@ -1,138 +0,0 @@ -// Row Start & End -// =============== - -// Break -// ----- -// Apply to any element that should force a line break. -@mixin break { - @include output((clear: both)); -} - - -// NoBreak -// ------- -// Cancel the break() effect, e.g. when using media queries. -@mixin nobreak { - @include output((clear: none)); -} - - -// Full -// ---- -// - [$context]: -@mixin full( - $context: $susy -) { - $inspect : $context; - @include susy-inspect(full, $inspect); - @include span(full of parse-grid($context) break); -} - - -// First -// ----- -// - [$context]: -@mixin first( - $context: $susy -) { - $inspect : $context; - $context : parse-grid($context); - $flow : susy-get(flow, $context); - - @include susy-inspect(first, $inspect); - @if not(is-split($context)) { - @include float-first($flow); - } -} - -@mixin alpha( - $context: $susy -) { - @include first($context); -} - - -// Last -// ---- -// - [$context]: -@mixin last( - $context: $susy -) { - $inspect : $context; - $context : parse-grid($context); - - @include susy-inspect(last, $inspect); - - $output: ( - flow: susy-get(flow, $context), - last-flow: susy-get(last-flow, $context), - margin: if(is-split($context), null, 0), - ); - - @include float-last($output...); -} - -@mixin omega( - $context: $susy -) { - @include last($context); -} - - -// Get Edge -// -------- -// Calculate edge value based on location, if possible -@function get-edge( - $span -) { - $span : parse-span($span); - $edge : susy-get(edge, $span); - - @if not($edge) { - $count: susy-count(susy-get(columns, $span)); - $location: susy-get(location, $span); - $n: susy-get(span, $span); - - $number: if(type-of($location) == number, true, false); - $index: if($number and unitless($location), true, false); - - @if $n == $count { - $edge: full; - } @else if $location and $n and $index { - @if $location == 1 { - $edge: if($n == $count, full, first); - } @else if $location + $n - 1 == $count { - $edge: last; - } - } - } - - @if $edge == alpha or $edge == omega { - $edge: if($edge == alpha, first, last); - } - - @return $edge; -} - - -// Get Location -// ------------ -// Calculate location value based on edge, if possible -@function get-location( - $span -) { - $span : parse-span($span); - $location : susy-get(location, $span); - $edge : get-edge($span); - $n : susy-get(span, $span); - - @if $edge and not($location) and type-of($n) == number and unitless($n) { - @if $edge == first { - $location: 1; - } @else if $edge == last { - $location: susy-count(susy-get(columns, $span)) - $n + 1; - } - } - - @return $location -} diff --git a/_sass/vendor/susy/susy/language/susy/_settings.scss b/_sass/vendor/susy/susy/language/susy/_settings.scss deleted file mode 100644 index bec4a411..00000000 --- a/_sass/vendor/susy/susy/language/susy/_settings.scss +++ /dev/null @@ -1,218 +0,0 @@ -// Susy Settings -// ============= - -// Susy Language Defaults -// ---------------------- -// - PRIVATE -@use "sass:math"; - -@include susy-defaults(( - container: auto, - math: fluid, - output: float, - container-position: center, - gutter-position: after, - global-box-sizing: content-box, - debug: ( - image: hide, - color: rgba(#66f, .25), - output: background, - toggle: top right, - ), -)); - - -// Valid Keyword Values -// -------------------- -// - PRIVATE: DONT'T TOUCH -$susy-keywords: ( - container: auto, - math: static fluid, - output: isolate float, - container-position: left center right, - flow: ltr rtl, - gutter-position: before after split inside inside-static, - box-sizing: border-box content-box, - span: full, - edge: first alpha last omega full, - spread: narrow wide wider, - gutter-override: no-gutters no-gutter, - role: nest, - clear: break nobreak, - debug image: show hide show-columns show-baseline, - debug output: background overlay, -); - - -// Parse Susy Keywords and Maps -// ---------------------------- -@function parse-settings( - $short: $susy -) { - $_return: (); - - @if type-of($short) == map { - $_return: $short; - } @else { - @each $item in $short { - // strings - @if type-of($item) == string { - @each $key, $value in $susy-keywords { - @if index($value, $item) { - $_key-value: append($key, $item); - $_return: _susy-deep-set($_return, $_key-value...); - } - } - // maps - } @else if type-of($item) == map { - $_return: map-merge($_return, $item); - } - } - } - - @return $_return; -} - - -// Parse Columns & Gutters -// ----------------------- -@function parse-layout( - $short -) { - $_return: (); - $_columns: (); - $_gutters: null; - - @if not(unitless(nth(nth($short, 1), 1))) { - $_gutters: nth($short, 1); - } @else { - $_columns: (columns: nth($short, 1)); - $_gutters: if(length($short) > 1, nth($short, 2), $_gutters); - } - - @if type-of($_gutters) == list and length($_gutters) > 0 { - $_gutters: ( - gutters: math.div(nth($_gutters, 2), nth($_gutters, 1)), - column-width: nth($_gutters, 1), - ); - } @else { - $_gutters: if($_gutters, (gutters: $_gutters), ()); - } - - $_return: map-merge($_return, $_columns); - $_return: map-merge($_return, $_gutters); - - @return $_return; -} - - -// Parse Grid/Context -// ------------------ -@function parse-grid( - $short: $susy -) { - $_return: parse-settings($short); - $_layout: (); - - @if type-of($short) == map { - $_return: $short; - } @else { - @each $item in $short { - // number or list - @if type-of($item) == number or type-of($item) == list { - @if type-of($item) == list or unitless($item) { - $_layout: append($_layout, $item); - } @else { - $_return: map-merge($_return, (container: $item)); - } - } - } - - $_layout: if(length($_layout) > 0, parse-layout($_layout), $_layout); - } - - @return map-merge($_return, $_layout); -} - - -// Parse Span -// ---------- -@function parse-span( - $short, - $key: span -) { - $_return: (); - - @if type-of($short) == map { - $_return: $short; - } @else { - $_at: index($short, at); - - @if $_at { - $_loci: $_at + 1; - $_location: nth($short, $_loci); - $_return: map-merge($_return, (location: $_location)); - $short: set-nth($short, $_at, null); - $short: set-nth($short, $_loci, null); - } - - $_i: 1; - $_span: (); - - @while $_i <= length($short) { - $_this: nth($short, $_i); - - @if type-of($_this) == number { - $_span: append($_span, $_this); - $short: set-nth($short, $_i, null); - } @else if $_this == of { - $short: set-nth($short, $_i, null); - $_i: length($short) + 1; - } - - $_i: $_i + 1; - } - - @if length($_span) > 0 { - $_span: if(length($_span) == 1, nth($_span, 1), $_span); - $_return: map-merge($_return, ($key: $_span)); - } - - $_return: map-merge($_return, parse-grid($short)); - } - - @return $_return; -} - - -// Parse Gutters -// ------------- -@function parse-gutters( - $short: $susy -) { - $_gutters: parse-span($short, gutter-override); - $_span: susy-get(gutter-override, $_gutters); - - @if $_span and not(map-get($_gutters, columns)) { - $_context: (); - $_new: (); - - @each $item in $_span { - @if type-of($item) == number and unitless($item) { - $_context: append($_context, $item); - } @else { - $_new: append($_new, $item); - } - } - - $_context: parse-grid($_context); - $_new: if(length($_new) == 0, null, $_new); - $_new: if(length($_new) == 1, nth($_new, 1), $_new); - $_new: (gutter-override: if($_new != $_span, $_new, $_span)); - - $_gutters: map-merge($_gutters, $_new); - $_gutters: map-merge($_gutters, $_context); - } - - @return $_gutters; -} diff --git a/_sass/vendor/susy/susy/language/susy/_span.scss b/_sass/vendor/susy/susy/language/susy/_span.scss deleted file mode 100644 index 4e9f6463..00000000 --- a/_sass/vendor/susy/susy/language/susy/_span.scss +++ /dev/null @@ -1,165 +0,0 @@ -// Span Syntax -// =========== - -// Span [mixin] -// ------------ -// Set a spanning element using shorthand syntax. -// - $span : -@use "sass:math"; - -@mixin span( - $span -) { - $inspect: $span; - $span: parse-span($span); - $output: span-math($span); - $nesting: susy-get(span, $span); - $clear: susy-get(clear, $span); - - $box: susy-get(box-sizing, $span); - $content-box: if(susy-get(global-box-sizing) != 'border-box', true, false); - $box: $box or if(is-inside($span) and $content-box, border-box, null); - - @if $clear == break { - @include break; - } @else if $clear == nobreak { - @include nobreak; - } - - @include susy-inspect(span, $inspect); - @include output((box-sizing: $box)); - @include float-span-output($output...); - - @if valid-columns($nesting, silent) { - @include nested($span) { @content; } - } @else { - @content; - } -} - -// Span [function] -// --------------- -// Return the width of a span. -// - $span : -@function span( - $span -) { - @return get-span-width($span); -} - -// Span Math -// --------- -// Get all the span results. -// - $span: -@function span-math( - $span -) { - $nest : if(susy-get(role, $span) == nest, true, false); - $split-nest : if(is-split($span) and $nest, true, false); - $edge : get-edge($span); - $location : get-location($span); - - $float : from; - $padding-before : null; - $padding-after : null; - $margin-before : null; - $margin-after : null; - - // calculate widths - $spread: index(map-values($span), spread); - $span: if($split-nest and not($spread), map-merge($span, (spread: wide)), $span); - $width: get-span-width($span); - $gutters: get-gutters($span); - - // apply gutters - @if is-inside($span) { - @if not(susy-get(role, $span)) { - $padding-before: map-get($gutters, before); - $padding-after: map-get($gutters, after); - } - } @else { - @if not($split-nest) { - $margin-before: map-get($gutters, before); - $margin-after: map-get($gutters, after); - } - } - - // special margin handling - @if susy-get(output, $span) == isolate and $location { - $margin-before: get-isolation($span); - $margin-after: -100%; - } @else if $edge { - $is-split: is-split($span); - $pos: susy-get(gutter-position, $span); - - @if $edge == last { - $float: susy-get(last-flow, $span); - } - - @if not($is-split) { - @if $edge == full or ($edge == first and $pos == before) { - $margin-before: 0; - } - @if $edge == full or ($edge == last and $pos == after) { - $margin-after: 0; - } - } - - } - - @return ( - width : $width, - float : $float, - margin-before : $margin-before, - margin-after : $margin-after, - padding-before : $padding-before, - padding-after : $padding-after, - flow : susy-get(flow, $span), - ); -} - -// Get Span Width -// -------------- -// Return span width. -// - $span: -@function get-span-width( - $span -) { - $span : parse-span($span); - - $n : susy-get(span, $span); - $location : get-location($span); - $columns : susy-get(columns, $span); - $gutters : susy-get(gutters, $span); - $spread : susy-get(spread, $span); - - $context : null; - $span-sum : null; - $width : null; - - @if $n == 'full' { - $pos: susy-get(gutter-position, $span); - $role: susy-get(role, $span); - $n: if($pos == split and $role != nest, susy-count($columns), 100%); - } - - @if type-of($n) != number { - @warn "(#{type-of($n)}) #{$n} is not a valid span."; - } @else if unitless($n) { - $context: susy-sum($columns, $gutters, if(is-split($span), wide, narrow)); - $spread: if(is-inside($span), $spread or wide, $spread); - $span-sum: susy($n, $location, $columns, $gutters, $spread); - - $_math: susy-get(math, $span); - $_column-width: susy-get(column-width, $span); - @if $_math == static { - $width: $span-sum * valid-column-math($_math, $_column-width); - } @else { - $width: percentage(math.div($span-sum, $context)); - } - } @else { - $width: $n; - } - - @return $width; -} diff --git a/_sass/vendor/susy/susy/language/susy/_validation.scss b/_sass/vendor/susy/susy/language/susy/_validation.scss deleted file mode 100644 index a235b176..00000000 --- a/_sass/vendor/susy/susy/language/susy/_validation.scss +++ /dev/null @@ -1,16 +0,0 @@ -// Validation -// ========== - - -// Validate Column Math -// -------------------- -@function valid-column-math( - $math, - $column-width -) { - @if $math == static and not($column-width) { - @error 'Static math requires a valid column-width setting.'; - } - - @return $column-width; -} diff --git a/_sass/vendor/susy/susy/language/susyone/_background.scss b/_sass/vendor/susy/susy/language/susyone/_background.scss deleted file mode 100644 index 38c6726b..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_background.scss +++ /dev/null @@ -1,18 +0,0 @@ -// --------------------------------------------------------------------------- -// Imports - -@import "compass/layout/grid-background"; -@import "compass/css3/background-origin"; -@import "compass/css3/background-clip"; - -// --------------------------------------------------------------------------- -// Susy Grid Background -// -// A wrapper for the compass "column-grid-background" mixin -// Uses all your settings to create a grid background for a container element. -// Note: Sub-pixel rounding can lead to several pixels of variation between browsers. -@mixin susy-grid-background(){ - @include column-grid-background($total-columns, column(), gutter(), 0); - @include background-origin(content-box); - @include background-clip(content-box); -} diff --git a/_sass/vendor/susy/susy/language/susyone/_functions.scss b/_sass/vendor/susy/susy/language/susyone/_functions.scss deleted file mode 100644 index 381e5003..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_functions.scss +++ /dev/null @@ -1,379 +0,0 @@ -// --------------------------------------------------------------------------- -// Imports - -// We need access to some basic font settings for handling media-queries. -@use "sass:math"; - -@import "compass/typography/vertical_rhythm"; - -// For now, we also need this... -$browser-default-font-size-px : 16px; -$browser-default-font-size-percent : 100%; -$browser-default-font-size-pt : 12pt; - -$rem-with-px-fallback : true !default; - -// --------------------------------------------------------------------------- -// Sass list Functions - -// Return a list with specific items removed -// -// filter($list, $target) -// - $list : The list to filter. -// - $target : An item to be removed from the list. -@function filter($list, $target) { - $clean: compact(); - @if index($list, $target) { - @each $item in $list { - $clean: if($item == $target, $clean, append($clean, $item)); - } - } @else { $clean: $list; } - @return $clean; -} - -// --------------------------------------------------------------------------- -// Don't use static output when it will break things - -// Switch element-level output to fluid, when container-width is wrong for static -// -// fix-static-misalignment([$style, $width]) -// - $style: $container-style. -// - $width: $container-width. -@function fix-static-misalignment( - $style: $container-style, - $width: $container-width -) { - @if $container-width and $container-width != container-outer-width($width: false) { - $style: fluid; - } - @return $style; -} - -// --------------------------------------------------------------------------- -// Grid Functions - -// Returns the full width of a grid based on your grid settings. -// -// $columns : The number of columns to get width for. -@function columns-width( - $columns : $total-columns -) { - @if round($columns) != $columns { - @warn "Susy works best with integer column-spans." + - "For partial-columns, you may need to finesse the math by hand using functions directly."; - } - @return ($columns * $column-width) + (if($columns >= 1, ceil($columns - 1), 0) * $gutter-width); -} - -// Return the grid width after adding or subtracting grid padding -// -// $width : the width of the grid without padding; -// $operation : ( add | subtract ) if padding should be added or subtracted; -@function handle-grid-padding( - $width, - $operation : subtract -) { - $pad: $grid-padding*2; - - @if comparable($width, $grid-padding) { - $width: if($operation == subtract, $width - $pad, $width + $pad); - } @else { - @warn "$grid-padding must be set in units comparable to the container width."; - } - - @return $width; -} - -// Return the full outer width of a Container element. -// -// $columns : The number of columns in the Grid Layout. -@function container-outer-width( - $columns : $total-columns, - $width : $container-width -) { - $outerwidth: if($width, $width, columns-width($columns)); - - @if $width { - @if not($border-box-sizing) { $outerwidth: handle-grid-padding($outerwidth, subtract); } - } @else { - @if $border-box-sizing { $outerwidth: handle-grid-padding($outerwidth, add); } - } - - @return $outerwidth; -} - -// Return the percentage width of a single column in a given 'context'. -// -// $context : The grid context in columns, if nested. -// $style : The container style to use. -@function column( - $context : $total-columns, - $style : fix-static-misalignment() -) { - @return if($style == static, $column-width, relative-width($column-width, $context)); -} - -// Return the percentage width of multiple 'columns' in a given 'context'. -// -// $columns : The number of columns to get relative width for. -// $context : The grid context in columns, if nested. -// $style : The container style to use. -@function columns( - $columns, - $context : $total-columns, - $style : fix-static-misalignment() -) { - @return if($style == static, columns-width($columns), relative-width(columns-width($columns), $context)); -} - -// Return the percentage width of a single gutter in a given 'context'. -// -// $context : The grid context in columns, if nested. -// $style : The container style to use. -@function gutter( - $context : $total-columns, - $style : fix-static-misalignment() -) { - @return if($style == static, $gutter-width, relative-width($gutter-width, $context)); -} - -// Return the percentage width of a given value in a given 'context'. -// -// $width : Any given width value. -// $context : The grid context in columns, if nested. -@function relative-width( - $width, - $context : $total-columns -) { - @return percentage(math.div($width, columns-width($context))); -} - -// Return the total space occupied by multiple columns and associated gutters. -// Useful for adding padding or margins (prefix, suffix, push, pull, etc.) -// -// $columns : The number of columns to get relative space for. -// $context : The grid context in columns, if nested. -// $style : The container style to use. -@function space( - $columns, - $context : $total-columns, - $style : fix-static-misalignment() -) { - @return columns($columns, $context, $style) + if($columns >= 1, gutter($context, $style), 0); -} - -// Accept a list including column-count and (optional) position. -// Return either the column count or the position alone. -// -// $columns : the list to split and interprate. -// $request : The value to return, either 'columns' or 'position'. -@function split-columns-value( - $columns, - $request : columns -) { - $pos : false; - $cols : false; - - @each $var in $columns { - @if (type-of($var) == 'string') { - $pos: $var; - } @else { - @if (type-of($var) == 'number') and (unitless($var)) { - $cols: $var; - } @else { - @warn '"#{$var}" is not a valid part of "$columns: #{$columns}" in the columns() mixin.'; - } - } - } - - @if $request == 'columns' { - @return $cols; - } @else { - @if $request == 'position' { - @return $pos; - } @else { - @warn '"#{$request}" is not a valid value for $request'; - } - } -} - -// Accept nth-selector variables, and format them as a valid CSS3 selector. -// -// $n : [first | only | last | ] -// $selector : [child | last-child | of-type | last-of-type ] -@function format-nth( - $n : last, - $selector : child -) { - @if ($n == 'last') or ($n =='first') or ($n =='only') { - $selector: '#{$n}-#{$selector}'; - } @else { - $selector: 'nth-#{$selector}(#{$n})'; - } - @return $selector; -} - -// --------------------------------------------------------------------------- -// Media Functions - -// Return an em value adjusted to match the browser default font size. -// Note: This only works if actual sizes are set relative to browser defaults. -// -// $ems : The initial value to be converted. -// $font-size : The current font-size in. -@function base-ems( - $ems, - $font-size: $base-font-size -){ - $font-size : if(unit($ems) == 'rem', $base-font-size, $font-size); - $unit : unit($font-size); - $mult : math.div($ems, $ems * 0 + 1); - - @if $unit == 'px' { - @return math.div($font-size, $browser-default-font-size-px) * $mult * 1em; - } - @else if $unit == '%' { - @return math.div($font-size, $browser-default-font-size-percent) * $mult * 1em; - } - @else if $unit == 'em' { - @return math.div($font-size, 1em) * $mult * 1em; - } - @else if $unit == 'pt' { - @return math.div($font-size, $browser-default-font-size-pt) * $mult * 1em; - } - @else { - @warn 'Variable $base-font-size does not have a valid font unit. Valid units for fonts in CSS are px, pt, em, and %.'; - } -} - -// This name will be deprecated... -@function absolute-ems( - $ems, - $font-size: $base-font-size -){ - @return base-ems( $ems, $font-size); - } - -// Return a length, after any em-values have been sent through absolute-ems(). -// -// $length : The length value to be checked and adjusted if necessary. -// $font-size : The current font-size in px. -@function fix-ems( - $length, - $font-size: $base-font-size -){ - @if $length { - @if (unit($length) == 'em') or (unit($length) == 'rem') { - $length: absolute-ems($length,$font-size); - } - } - @return $length; -} - -// Sort a list of arguments into "$min $layout $max $ie" order, and return the list. -// -// $media-layout : a list of values [$min $layout $max $ie] including... -// : - one unitless number (columns in a layout) -// : - two optional lengths (min and max-width media-query breakpoints). -// : - one optional boolean or string to trigger fallback support for IE. -// $font-size : [optional] The base font-size of your layout, if you are using ems. -// : - defaults to $base-font-size -@function medialayout( - $media-layout, - $font-size: $base-font-size -) { - $media : false; - $min : false; - $layout : false; - $max : false; - $ie : false; - $has-layout : false; - - @each $val in $media-layout { - @if (type-of($val) == "number") { - @if unitless($val) { - $layout : $val; - $has-layout : true; - } @else { - @if ($has-layout) and not($media) { - $max: $val; - } @else { - @if $media { - $media: join($media,$val); - } @else { - $media: $val; - } - } - } - } @else { - $ie: $val; - } - } - @if (length($media) > 0) { - @if (length($media) == 1) { - $min: nth($media,1); - } @else { - $min: nth($media,1); - $max: nth($media,2); - @if comparable($min, $max) { - @if ($min > $max) { - $max: nth($media,1); - $min: nth($media,2); - } - } @else { - @warn "Can't compare incompatible units." + - "Using #{$min} for min-width, and #{$max} for max-width"; - } - @if (length($media) > 2) { - @warn "You can only send two lengths: a min-width and an (optional) max-width." + - "You sent #{length($media)}: #{$media}"; - } - } - } - - // media-queries must be set in ems relative to the browser default - // rather than the font-size set in CSS. - $min: fix-ems($min,$font-size); - $max: fix-ems($max,$font-size); - - @return $min $layout $max $ie; -} - -// Return the nearest layout (column-count) above a given breakpoint. -// -// $min : The min-width media-query breakpoint above which to establish a new layout. -@function get-layout( - $min -) { - $min : fix-ems($min); - $return : false; - - @if comparable($min, $column-width) { - $return : ceil(math.div($min + $gutter-width, $column-width + $gutter-width)); - } @else { - @warn "Can't determine a layout, becuse #{$min} and #{$column-width} are not comparable."; - } - - @return $return; -} - -// Check to see if a given $media-layout list is simply the default. -// -// $media-layout : a list of values including - -// : One unitless number (columns in a layout) -// : Two optional lengths (min and max-width media-query breakpoints). -// : One optional boolean or string to trigger fallback support for IE. -@function is-default-layout( - $media-layout -) { - $media-layout : medialayout($media-layout); - $min : nth($media-layout,1); - $layout-cols : nth($media-layout,2); - $max : nth($media-layout,3); - - @if $min or $max { - @return false; - } @else { - @return if($layout-cols == $total-columns,true,false); - } -} diff --git a/_sass/vendor/susy/susy/language/susyone/_grid.scss b/_sass/vendor/susy/susy/language/susyone/_grid.scss deleted file mode 100644 index 491c6229..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_grid.scss +++ /dev/null @@ -1,312 +0,0 @@ -// --------------------------------------------------------------------------- -// Imports - -@import "compass/utilities/general/clearfix"; -@import "compass/css3/box-sizing"; - -// --------------------------------------------------------------------------- -// Border-Box Sizing - -// Apply the border-box sizing model to all elements -// and adjust the grid math appropriately. -@mixin border-box-sizing { - $border-box-sizing: true !global; - * { @include box-sizing(border-box); } -} - -// --------------------------------------------------------------------------- -// Container - -// Set the width of a container -// -// $columns : The number of columns in the Grid Layout. -@mixin set-container-width( - $columns : $total-columns, - $style : $container-style, - $px-vals : $pixel-values-only -){ - $width: container-outer-width($columns); - - @if $style == 'static' { - @if $px-vals == true { - width: round(convert-length($width, px)); - } @else { - @include rem(width, $width); - } - } @else { - @if $style == 'fluid' { - @if unit($width) == '%' { - @if $px-vals == true { - width: round(convert-length($width, px)); - } @else { - @include rem(width, $width); - } - } - } @else { - @if $px-vals == true { - max-width: round(convert-length($width, px)); - } @else { - @include rem(max-width, $width); - } - - @include for-legacy-browser(ie,"6") { - @if unit($width) == 'rem' { - _width: round(convert-length($width, px)); - } @else { - _width: $width; - } - } - } - } -} - -// Set the outer grid-containing element(s). -// -// $columns : The number of columns in the container. -@mixin apply-container( - $columns : $total-columns, - $px-vals : $pixel-values-only -){ - @include pie-clearfix; - @include set-container-width($columns); - @if $px-vals == true { - padding-left: round(convert-length($grid-padding, px)); - padding-right: round(convert-length($grid-padding, px)); - } @else { - @include rem(padding-left, $grid-padding); - @include rem(padding-right, $grid-padding); - } - margin: { left: auto; right: auto; } -} - -// Set one or more layouts on a grid-containing element at any number of media-query breakpoints. -// -// $media-layout-1 : [default:$total-columns] A list of values including - -// : One unitless number (representing columns in a layout) -// : Two optional lengths (representing min and max-width media-query breakpoints). -// $media-layout-2 ...-10 : [optional] Same as $media-layout-1 -@mixin container( - $media-layouts... -){ - $media-layouts: if(length($media-layouts) > 0, $media-layouts, $total-columns); - - @each $ml in $media-layouts { - @if is-default-layout($ml) { - @include apply-container; - } @else { - @include at-breakpoint($ml) { - @include apply-container; - } - } - } -} - -// --------------------------------------------------------------------------- -// Columns - -// Create a grid element spanning any number of 'columns' in a grid 'context'. -// $columns : The number of columns to span. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $padding : [optional] Padding applied to the inside of individual grid columns. -// : Padding is only output if one or two values are specified (e.g. 1em or 10px 20px) -// : Padding values are applied only on the horizontal axis in from-to order -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin span-columns( - $columns, - $context : $total-columns, - $padding : false, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - $to : opposite-position($from); - $pos : split-columns-value($columns,position); - $cols : split-columns-value($columns,columns); - $pad-from : if($style == static, 0 * $gutter-width, relative-width(0 * $gutter-width, $context)); - $pad-to : if($style == static, 0 * $gutter-width, relative-width(0 * $gutter-width, $context)); - - @if $padding != false { - $pad-from : nth($padding, 1); - - @if length($padding) > 1 { - $pad-to: nth($padding, 2); - } @else { - $pad-to: $pad-from; - } - - $pad-from : if($style == static, $pad-from, relative-width($pad-from, $context)); - $pad-to : if($style == static, $pad-to, relative-width($pad-to, $context)); - - padding-#{$from}: $pad-from; - padding-#{$to}: $pad-to; - } - - width: columns($cols, $context, $style) - if($border-box-sizing, 0, $pad-to + $pad-from); - - @if ($pos == 'omega') { - @include omega($from); - } @else { - float: $from; - margin-#{$to}: gutter($context, $style); - @include for-legacy-browser(ie, "6") { - display: inline; - } - } -} - -// Apply to elements spanning the last column, to account for the page edge. -// Only needed as an override. Normally 'omega' can just be called by `columns`. -// -// $from : The start-direction for your document. -@mixin omega( - $from : $from-direction -) { - $from : unquote($from); - $to : opposite-position($from); - $hack : opposite-position($omega-float); - - float: $omega-float; - margin-#{$to}: 0; - - @include for-legacy-browser(ie, "6", "7") { - *margin-#{$hack}: - $gutter-width; - @include for-legacy-browser(ie, "6") { - display: inline; - } - } -} - -// Shortcut to apply omega to a specific subset of elements. -// -// $n : [first | only | last | ] -// $selector : [child | last-child | of-type | last-of-type ] -// $from : The start-direction for your document. -@mixin nth-omega( - $n : last, - $selector : child, - $from : $from-direction -) { - $from : unquote($from); - - &:#{format-nth($n,$selector)} { - @if $n == "first" { - @include omega($from); - } @else { - @include with-browser-ranges(css-sel3) { - @include omega($from); - } - } - } -} - - - -// --------------------------------------------------------------------------- -// Resets - -// Reset a '+columns' grid element to default block behavior -// -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -@mixin reset-columns( - $from: $from-direction -) { - $from : unquote($from); - $to : opposite-position($from); - $hack : opposite-position($omega-float); - - float: none; - width: auto; - margin-#{$to}: auto; - - @include for-legacy-browser(ie, "6", "7") { - *margin-#{$hack}: auto; - @include for-legacy-browser(ie, "6") { - display: block; - } - } -} - -// Apply to elements previously set as omega. -// This will return floats and margins back to non-omega settigns. -// -// $context : [optional] The context (columns spanned by parent). -// $from : The start-direction for your document. -// $style : The container style to use. -@mixin remove-omega( - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - $to : opposite-position($from); - $hack : opposite-position($omega-float); - - float: $from; - margin-#{$to}: gutter($context, $style); - - @include for-legacy-browser(ie, "6", "7") { - *margin-#{$hack}: auto; - } -} - -// Shortcut to apply remove-omega to a specific subset of elements. -// -// $n : [first | only | last | ] -// $selector : [child | last-child | of-type | last-of-type ] -// $context : [optional] The context (columns spanned by parent). -// $from : The start-direction for your document. -// $style : The container style to use. -@mixin remove-nth-omega( - $n : last, - $selector : child, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - - &:#{format-nth($n,$selector)} { - @if $n == "first" { - @include remove-omega($context, $from, $style); - } @else { - @include with-browser-ranges(css-sel3) { - @include remove-omega($context, $from, $style); - } - } - } -} - - -// --------------------------------------------------------------------------- -// Change Settings - -@mixin with-grid-settings( - $columns: $total-columns, - $width: $column-width, - $gutter: $gutter-width, - $padding: $grid-padding -) { - // keep the defaults around - $default-columns: $total-columns; - $default-width: $column-width; - $default-gutter: $gutter-width; - $default-padding: $grid-padding; - - // use the new settings - $total-columns: $columns !global; - $column-width: $width !global; - $gutter-width: $gutter !global; - $grid-padding: $padding !global; - - // apply to contents - @content; - - // re-instate the defaults - $total-columns: $default-columns !global; - $column-width: $default-width !global; - $gutter-width: $default-gutter !global; - $grid-padding: $default-padding !global; -} diff --git a/_sass/vendor/susy/susy/language/susyone/_isolation.scss b/_sass/vendor/susy/susy/language/susyone/_isolation.scss deleted file mode 100644 index 378bb1a4..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_isolation.scss +++ /dev/null @@ -1,53 +0,0 @@ -// --------------------------------------------------------------------------- -// Isolation - -// Isolate the position of a grid element (use in addition to span-columns) -// -// $location : The grid column to isolate in, relative to the container; -// $context : [optional] The context (columns spanned by parent). -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -@use "sass:math"; - -@mixin isolate( - $location, - $context: $total-columns, - $from: $from-direction, - $style: fix-static-misalignment() -) { - $to: opposite-position($from); - margin-#{$to}: -100%; - margin-#{$from}: space($location - 1, $context, $style); -} - -// Isolate a group of elements in a grid, using nth-child selectors -// -// $columns : The column-width of each item on the grid; -// $context : [optional] The context (columns spanned by parent). -// $selector : [child | of-type | last-of-type ] (default is 'child') -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -@mixin isolate-grid( - $columns, - $context: $total-columns, - $selector: 'child', - $from: $from-direction, - $style: fix-static-misalignment() -) { - $to: opposite-position($from); - $location: 1; - $line: floor(math.div($context, $columns)); - - @include span-columns($columns, $context, $from: $from, $style: $style); - margin-#{$to}: -100%; - - @for $item from 1 through $line { - $nth: '#{$line}n + #{$item}'; - &:#{format-nth($nth,$selector)} { - margin-#{$from}: space($location - 1, $context, $style); - @if $location == 1 { clear: $from; } - @else { clear: none; } - - $location: $location + $columns; - @if $location > $context { $location: 1; } - } - } -} diff --git a/_sass/vendor/susy/susy/language/susyone/_margin.scss b/_sass/vendor/susy/susy/language/susyone/_margin.scss deleted file mode 100644 index accbbe65..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_margin.scss +++ /dev/null @@ -1,93 +0,0 @@ -// --------------------------------------------------------------------------- -// Margin Mixins - -// Apply 'columns' margin before an element to push it along the grid. -// -// $columns : The number of columns to span. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin pre( - $columns, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - margin-#{$from}: space($columns, $context, $style); -} - -// 'push' is a synonymn for 'pre' -@mixin push( - $columns, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - @include pre($columns, $context, $from, $style); -} - -// Apply negative 'columns' margin before an element to pull it along the grid. -// -// $columns : The number of columns to span. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin pull( - $columns, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - margin-#{$from}: 0 - space($columns, $context, $style); -} - -// Apply 'columns' margin after an element to contain it in a grid. -// -// $columns : The number of columns to span. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin post( - $columns, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - $to : opposite-position($from); - margin-#{$to}: space($columns, $context, $style); -} - -// Apply 'columns' before and/or after an element to contain it on a grid. -// -// $pre : The number of columns to add as margin before. -// $post : The number of columns to add as margin after. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin squish( - $pre : false, - $post : false, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - @if $pre { - @include pre($pre, $context, $from, $style) - } - @if $post { - @include post($post, $context, $from, $style) - } -} diff --git a/_sass/vendor/susy/susy/language/susyone/_media.scss b/_sass/vendor/susy/susy/language/susyone/_media.scss deleted file mode 100644 index ca860fc9..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_media.scss +++ /dev/null @@ -1,105 +0,0 @@ -// --------------------------------------------------------------------------- -// Media Mixins - -// Create a new layout context for (@content) descendants. -// -// $layout-cols : a (unitless) number of columns to use for this layout. -@mixin layout( - $layout-cols -) { - // store default $total-columns setting for later, then change it. - $default-layout : $total-columns; - $total-columns : $layout-cols !global; - - // apply children in this new layout context. - @content; - - // return to default $total-columns setting. - $total-columns : $default-layout !global; -} - -// Nest a block of code inside a new media-query and layout context. -// -// $media-layout : a list of values [$min $layout $max $ie] including... -// : - one unitless number (columns in a layout) -// : - two optional lengths (min and max-width media-query breakpoints). -// : - one optional boolean or string to trigger fallback support for IE. -// $font-size : [optional] The base font-size of your layout, if you are using ems. -// : - defaults to $base-font-size -@mixin at-breakpoint( - $media-layout, - $font-size: $base-font-size -) { - $media-layout : medialayout($media-layout,$font-size); - $min : nth($media-layout,1); - $layout : nth($media-layout,2); - $max : nth($media-layout,3); - $ie : nth($media-layout,4); - - @if not($breakpoint-media-output) and not($breakpoint-ie-output) and not($breakpoint-raw-output) { - @warn "Either $breakpoint-media-output, $breakpoint-ie-output, or $breakpoint-raw-output must be true for at-breakpoint to work."; - } - - // We need to have either a min-width breakpoint or a layout in order to proceed. - @if $min or $layout or $max { - - // If we don't have a layout, we create one based on the min-width. - @if not($layout) { - $layout: get-layout($min); - } - - // If we still don't have a layout, we have a problem. - @if $layout { - // Set our new layout context. - @include layout($layout) { - @if $breakpoint-media-output { - @include with-browser-ranges(css-mediaqueries) { - @if $min and $max { - // Both $min and $max - @media (min-width: $min) and (max-width: $max) { - @content; - } - } @else { - @if not($min) and not($max) { - // Neither $min nor $max: - // We can create a breakpoint based on the number of columns in the layout. - $min: fix-ems(container-outer-width($width: false)); - } - @if $min { - // Min only: - @media (min-width: $min) { - @content; - } - } @else { - // Max only: - @media (max-width: $max) { - @content; - } - } - } - } - } - // Set an IE fallback - @if $ie and $breakpoint-ie-output { - @if (type-of($ie) == 'bool') { - $ie: 'lt-ie9'; - } - .#{$ie} & { - @content; - } - } - - @if $breakpoint-raw-output { - @content; - } - } - } @else { - @warn "We were unable to determine a layout for your breakpoint."; - } - - } @else { - @warn "You need to provide either a valid layout (number of columns)" - + "or a valid media-query min-width breakpoint (length)."; - } - -} diff --git a/_sass/vendor/susy/susy/language/susyone/_padding.scss b/_sass/vendor/susy/susy/language/susyone/_padding.scss deleted file mode 100644 index 8e6394a4..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_padding.scss +++ /dev/null @@ -1,92 +0,0 @@ -// --------------------------------------------------------------------------- -// Padding Mixins - -// add empty colums as padding before an element. -// $columns : The number of columns to prefix. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin prefix( - $columns, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - padding-#{$from}: space($columns, $context, $style); -} - -// add empty colums as padding after an element. -// $columns : The number of columns to suffix. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin suffix( - $columns, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - $to : opposite-position($from); - padding-#{$to}: space($columns, $context, $style); -} - -// add empty colums as padding before and after an element. -// $columns : The number of columns to pad. -// $context : [optional] The context (columns spanned by parent). -// : Context is required on any nested elements. -// : Context MUST NOT be declared on a root element. -// $from : The start direction of your layout (e.g. 'left' for ltr languages) -// $style : The container style to use. -@mixin pad( - $prefix : false, - $suffix : false, - $context : $total-columns, - $from : $from-direction, - $style : fix-static-misalignment() -) { - $from : unquote($from); - @if $prefix { - @include prefix($prefix, $context, $from, $style); - } - @if $suffix { - @include suffix($suffix, $context, $from, $style); - } -} - -// Bleed into colums with margin/padding on any side of an element. -// $width : The side of the bleed. -// : Any unit-length will be used directly. -// : Any unitless number will be used as a column-count. -// : Use "2 of 6" format to represent 2 cals in a 6-col nested context. -// $sides : One or more sides to bleed [ top | right | bottom | left | all ]. -// $style : The container style to use. -@mixin bleed( - $width: $grid-padding, - $sides: left right, - $style: fix-static-misalignment() -) { - @if $border-box-sizing { @include box-sizing(content-box) } - - @if type-of($width) == 'list' { - $width: filter($width, of); - $width: space(nth($width,1), nth($width,2), $style); - } @else if unitless($width) { - $width: space($width, $style: $style); - } - - @if $sides == 'all' { - margin: - $width; - padding: $width; - } @else { - @each $side in $sides { - margin-#{$side}: - $width; - padding-#{$side}: $width; - } - } -} diff --git a/_sass/vendor/susy/susy/language/susyone/_settings.scss b/_sass/vendor/susy/susy/language/susyone/_settings.scss deleted file mode 100644 index e8ff9c84..00000000 --- a/_sass/vendor/susy/susy/language/susyone/_settings.scss +++ /dev/null @@ -1,60 +0,0 @@ -// --------------------------------------------------------------------------- -// Susy Settings - -// The total number of columns in the grid -$total-columns : 12 !default; - -// The width of columns and gutters. -// These must all be set with the comparable units. -$column-width : 4em !default; -$gutter-width : 1em !default; - -// Padding on the left and right of a Grid Container. -$grid-padding : $gutter-width !default; - -// --------------------------------------------------------------------------- -// Advanced Settings - -// From Direction: -// Controls for right-to-left or bi-directional sites. -$from-direction : left !default; - -// Omega Float Direction: -// The direction that +omega elements are floated by deafult. -$omega-float : opposite-position($from-direction) !default; - -// Container Width: -// Override the total width of your grid, using any length (50em, 75%, etc.) -$container-width : false !default; - -// Container Style: -// 'magic' - Static (fixed or elastic) when there's enough space, -// fluid when there isn't. This is the SUSY MAGIC SAUCE(TM). -// 'static' - Forces the grid container to remain static at all times. -// 'fluid' - Forces the grid to remain fluid at all times. -// (this will overrule any static $container-width settings) -$container-style : magic !default; - -// Border-Box Sizing -// Adjust the grid math appropriately for box-sizing: border-box; -// Warning: This does not actually apply the new box model! -// In most cases you can ignore this setting, -// and simply apply the border-box-sizing mixin. -$border-box-sizing : false !default; - -// Pixel Values only: -// Make sure only pixel values are set for the container width. -$pixel-values-only : false !default; - -// --------------------------------------------------------------------------- -// IE Settings - -// When you are using a seperate IE stylesheet, -// you can use these settings to control the output of at-breakpoint. -// By default, at-breakpoint will output media-queries as well as -// any defined ie-fallback classes. -$breakpoint-media-output : true !default; -$breakpoint-ie-output : true !default; - -// Danger Zone! Only set as 'true' in IE-specific style sheets. -$breakpoint-raw-output : false !default; diff --git a/_sass/vendor/susy/susy/output/_float.scss b/_sass/vendor/susy/susy/output/_float.scss deleted file mode 100644 index 9c24051c..00000000 --- a/_sass/vendor/susy/susy/output/_float.scss +++ /dev/null @@ -1,9 +0,0 @@ -// Float API -// ========= - -@import "shared"; - -@import "float/container"; -@import "float/span"; -@import "float/end"; -@import "float/isolate"; diff --git a/_sass/vendor/susy/susy/output/_shared.scss b/_sass/vendor/susy/susy/output/_shared.scss deleted file mode 100644 index dd9df4ed..00000000 --- a/_sass/vendor/susy/susy/output/_shared.scss +++ /dev/null @@ -1,15 +0,0 @@ -// Shared API -// ========== - -@import "support"; - -@import "shared/inspect"; -@import "shared/output"; -@import "shared/direction"; -@import "shared/background"; -@import "shared/container"; -@import "shared/margins"; -@import "shared/padding"; - - - diff --git a/_sass/vendor/susy/susy/output/_support.scss b/_sass/vendor/susy/susy/output/_support.scss deleted file mode 100644 index 53dbc9c3..00000000 --- a/_sass/vendor/susy/susy/output/_support.scss +++ /dev/null @@ -1,9 +0,0 @@ -// Susy Browser Support -// ==================== - -@import "support/support"; -@import "support/prefix"; -@import "support/background"; -@import "support/box-sizing"; -@import "support/rem"; -@import "support/clearfix"; diff --git a/_sass/vendor/susy/susy/output/float/_container.scss b/_sass/vendor/susy/susy/output/float/_container.scss deleted file mode 100644 index 121eb11a..00000000 --- a/_sass/vendor/susy/susy/output/float/_container.scss +++ /dev/null @@ -1,16 +0,0 @@ -// Float Container API -// =================== - -// Float Container -// --------------- -// - [$width] : -// - [$justify] : left | center | right -// - [$math] : fluid | static -@mixin float-container( - $width, - $justify: auto auto, - $property: max-width -) { - @include susy-clearfix; - @include container-output($width, $justify, $property); -} diff --git a/_sass/vendor/susy/susy/output/float/_end.scss b/_sass/vendor/susy/susy/output/float/_end.scss deleted file mode 100644 index 3369997f..00000000 --- a/_sass/vendor/susy/susy/output/float/_end.scss +++ /dev/null @@ -1,40 +0,0 @@ -// Float Ends API -// ============== - -// Susy End Defaults -// ----------------- -// - PRIVATE -@include susy-defaults(( - last-flow: to, -)); - -// Float Last -// ---------- -// - [$flow] : ltr | rtl -@mixin float-last( - $flow: map-get($susy-defaults, flow), - $last-flow: map-get($susy-defaults, last-flow), - $margin: 0 -) { - $to: to($flow); - - $output: ( - float: if($last-flow == to, $to, null), - margin-#{$to}: $margin, - ); - - @include output($output); -} - -// Float First -// ----------- -// - [$flow] : ltr | rtl -@mixin float-first( - $flow: map-get($susy-defaults, flow) -) { - $output: ( - margin-#{from($flow)}: 0, - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/float/_isolate.scss b/_sass/vendor/susy/susy/output/float/_isolate.scss deleted file mode 100644 index 4dd3c230..00000000 --- a/_sass/vendor/susy/susy/output/float/_isolate.scss +++ /dev/null @@ -1,22 +0,0 @@ -// Float Isolation API -// =================== - -// Isolate Output -// -------------- -// - $push : -// - [$flow] : ltr | rtl -@mixin isolate-output( - $push, - $flow: map-get($susy-defaults, flow) -) { - $to: to($flow); - $from: from($flow); - - $output: ( - float: $from, - margin-#{$from}: $push, - margin-#{$to}: -100%, - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/float/_span.scss b/_sass/vendor/susy/susy/output/float/_span.scss deleted file mode 100644 index 5b732ccb..00000000 --- a/_sass/vendor/susy/susy/output/float/_span.scss +++ /dev/null @@ -1,35 +0,0 @@ -// Float Span API -// ============== - -// Float Span Output -// ----------------- -// - $width : -// - [$float] : from | to -// - [$margin-before] : -// - [$margin-after] : -// - [$padding-before] : -// - [$padding-after] : -// - [$flow] : ltr | rtl -@mixin float-span-output( - $width, - $float : from, - $margin-before : null, - $margin-after : null, - $padding-before : null, - $padding-after : null, - $flow : map-get($susy-defaults, flow) -) { - $to : to($flow); - $from : from($flow); - - $output: ( - width: $width, - float: if($float == to, $to, null) or if($float == from, $from, null), - margin-#{$from}: $margin-before, - margin-#{$to}: $margin-after, - padding-#{$from}: $padding-before, - padding-#{$to}: $padding-after, - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/shared/_background.scss b/_sass/vendor/susy/susy/output/shared/_background.scss deleted file mode 100644 index c230f613..00000000 --- a/_sass/vendor/susy/susy/output/shared/_background.scss +++ /dev/null @@ -1,26 +0,0 @@ -// Grid Background API -// =================== -// - Sub-pixel rounding can lead to several pixels variation between browsers. - -// Grid Background Output -// ---------------------- -// - $image: background-image -// - $size: background-size -// - $clip: background-clip -// - [$flow]: ltr | rtl -@mixin background-grid-output ( - $image, - $size: null, - $clip: null, - $flow: map-get($susy-defaults, flow) -) { - $output: ( - background-image: $image, - background-size: $size, - background-origin: $clip, - background-clip: $clip, - background-position: from($flow) top, - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/shared/_container.scss b/_sass/vendor/susy/susy/output/shared/_container.scss deleted file mode 100644 index 7c7d4f17..00000000 --- a/_sass/vendor/susy/susy/output/shared/_container.scss +++ /dev/null @@ -1,21 +0,0 @@ -// Shared Container API -// ==================== - -// Container Output -// ---------------- -// - [$width] : -// - [$justify] : left | center | right -// - [$math] : fluid | static -@mixin container-output( - $width, - $justify: auto auto, - $property: max-width -) { - $output: ( - #{$property}: $width or 100%, - margin-left: nth($justify, 1), - margin-right: nth($justify, 2), - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/shared/_direction.scss b/_sass/vendor/susy/susy/output/shared/_direction.scss deleted file mode 100644 index abb9c36f..00000000 --- a/_sass/vendor/susy/susy/output/shared/_direction.scss +++ /dev/null @@ -1,42 +0,0 @@ -// Direction Helpers -// ================= - -// Susy Flow Defaults -// ------------------ -// - PRIVATE -@include susy-defaults(( - flow: ltr, -)); - -// Get Direction -// ------------- -// Return the 'from' or 'to' direction of a ltr or rtl flow. -// - [$flow] : ltr | rtl -// - [$key] : from | to -@function get-direction( - $flow: map-get($susy-defaults, flow), - $key: from -) { - $return: if($flow == rtl, (from: right, to: left), (from: left, to: right)); - @return map-get($return, $key); -} - -// To -// -- -// Return the 'to' direction of a flow -// - [$flow] : ltr | rtl -@function to( - $flow: map-get($susy-defaults, flow) -) { - @return get-direction($flow, to); -} - -// From -// ---- -// Return the 'from' direction of a flow -// - [$flow] : ltr | rtl -@function from( - $flow: map-get($susy-defaults, flow) -) { - @return get-direction($flow, from); -} diff --git a/_sass/vendor/susy/susy/output/shared/_inspect.scss b/_sass/vendor/susy/susy/output/shared/_inspect.scss deleted file mode 100644 index b0af9b6d..00000000 --- a/_sass/vendor/susy/susy/output/shared/_inspect.scss +++ /dev/null @@ -1,25 +0,0 @@ -// Debugging -// ========= - -// Susy Inspect -// ------------ -// Output arguments passed to a inspect. -// - $mixin : -// - $inspec : - -@mixin susy-inspect( - $mixin, - $inspect -) { - $show: false; - - @each $item in $inspect { - @if index($item, inspect) { - $show: true; - } - } - - @if $show or susy-get(debug inspect) { - -susy-#{$mixin}: inspect($inspect); - } -} diff --git a/_sass/vendor/susy/susy/output/shared/_margins.scss b/_sass/vendor/susy/susy/output/shared/_margins.scss deleted file mode 100644 index cd73e8cf..00000000 --- a/_sass/vendor/susy/susy/output/shared/_margins.scss +++ /dev/null @@ -1,23 +0,0 @@ -// Margins API -// =========== - -// Margin Output -// ------------- -// - $before : -// - $after : -// - [$flow] : ltr | rtl -@mixin margin-output( - $before, - $after, - $flow: map-get($susy-defaults, flow) -) { - $to: to($flow); - $from: from($flow); - - $output: ( - margin-#{$from}: $before, - margin-#{$to}: $after, - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/shared/_output.scss b/_sass/vendor/susy/susy/output/shared/_output.scss deleted file mode 100644 index 20fc2d61..00000000 --- a/_sass/vendor/susy/susy/output/shared/_output.scss +++ /dev/null @@ -1,14 +0,0 @@ -// Output -// ====== - -// Output -// ------ -// Output CSS with proper browser support. -// - $styles : -@mixin output( - $styles -) { - @each $prop, $val in $styles { - @include susy-support($prop, $val); - } -} diff --git a/_sass/vendor/susy/susy/output/shared/_padding.scss b/_sass/vendor/susy/susy/output/shared/_padding.scss deleted file mode 100644 index 5069d0cb..00000000 --- a/_sass/vendor/susy/susy/output/shared/_padding.scss +++ /dev/null @@ -1,23 +0,0 @@ -// Padding API -// =========== - -// Padding Output -// -------------- -// - $before : -// - $after : -// - [$flow] : ltr | rtl -@mixin padding-output( - $before, - $after, - $flow: map-get($susy-defaults, flow) -) { - $to: to($flow); - $from: from($flow); - - $output: ( - padding-#{$from}: $before, - padding-#{$to}: $after, - ); - - @include output($output); -} diff --git a/_sass/vendor/susy/susy/output/support/_background.scss b/_sass/vendor/susy/susy/output/support/_background.scss deleted file mode 100644 index b1415028..00000000 --- a/_sass/vendor/susy/susy/output/support/_background.scss +++ /dev/null @@ -1,58 +0,0 @@ -// Background Properties -// ===================== - -// Susy Background Image -// --------------------- -// Check for an existing support mixin, or provide a simple fallback. -// - $image: -@mixin susy-background-image( - $image -) { - @if susy-support(background-image, (mixin: background-image), $warn: false) { - @include background-image($image...); - } @else { - background-image: $image; - } -} - -// Susy Background Size -// --------------------- -// Check for an existing support mixin, or provide a simple fallback. -// - $image: -@mixin susy-background-size( - $size -) { - @if susy-support(background-options, (mixin: background-size)) { - @include background-size($size); - } @else { - background-size: $size; - } -} - -// Susy Background Origin -// ---------------------- -// Check for an existing support mixin, or provide a simple fallback. -// - $image: -@mixin susy-background-origin( - $origin -) { - @if susy-support(background-options, (mixin: background-origin)) { - @include background-origin($origin); - } @else { - background-origin: $origin; - } -} - -// Susy Background Clip -// -------------------- -// Check for an existing support mixin, or provide a simple fallback. -// - $image: -@mixin susy-background-clip( - $clip -) { - @if susy-support(background-options, (mixin: background-clip)) { - @include background-clip($clip); - } @else { - background-clip: $clip; - } -} diff --git a/_sass/vendor/susy/susy/output/support/_box-sizing.scss b/_sass/vendor/susy/susy/output/support/_box-sizing.scss deleted file mode 100644 index bf50bbc9..00000000 --- a/_sass/vendor/susy/susy/output/support/_box-sizing.scss +++ /dev/null @@ -1,19 +0,0 @@ -// Box Sizing -// ========== - -// Box Sizing -// ---------- -// Check for an existing support mixin, or provide a simple fallback. -// - $model: -@mixin susy-box-sizing( - $model: content-box -) { - @if $model { - @if susy-support(box-sizing, (mixin: box-sizing), $warn: false) { - @include box-sizing($model); - } @else { - $prefix: (moz, webkit, official); - @include susy-prefix(box-sizing, $model, $prefix); - } - } -} diff --git a/_sass/vendor/susy/susy/output/support/_clearfix.scss b/_sass/vendor/susy/susy/output/support/_clearfix.scss deleted file mode 100644 index 48c6e7b7..00000000 --- a/_sass/vendor/susy/susy/output/support/_clearfix.scss +++ /dev/null @@ -1,18 +0,0 @@ -// Susy Fallback Clearfix -// ====================== - - -// Clearfix -// -------- -// Check for an existing support mixin, or provide a simple fallback. -@mixin susy-clearfix { - @if susy-support(clearfix, (mixin: clearfix)) { - @include clearfix; - } @else { - &:after { - content: " "; - display: block; - clear: both; - } - } -} diff --git a/_sass/vendor/susy/susy/output/support/_prefix.scss b/_sass/vendor/susy/susy/output/support/_prefix.scss deleted file mode 100644 index f4e26ecc..00000000 --- a/_sass/vendor/susy/susy/output/support/_prefix.scss +++ /dev/null @@ -1,19 +0,0 @@ -// Susy Prefix -// =========== - -// Prefix -// ------ -// Output simple prefixed properties. -// - $prop : -// - $val : -// - [$prefix] : -@mixin susy-prefix( - $prop, - $val, - $prefix: official -) { - @each $fix in $prefix { - $fix: if($fix == official or not($fix), $prop, '-#{$fix}-#{$prop}'); - @include susy-rem($fix, $val); - } -} diff --git a/_sass/vendor/susy/susy/output/support/_rem.scss b/_sass/vendor/susy/susy/output/support/_rem.scss deleted file mode 100644 index 0a807f79..00000000 --- a/_sass/vendor/susy/susy/output/support/_rem.scss +++ /dev/null @@ -1,22 +0,0 @@ -// rem Support -// =========== - -// rem -// --- -// Check for an existing support mixin, or output directly. -// - $prop : -// - $val : -@mixin susy-rem( - $prop, - $val -) { - $_reqs: ( - variable: rhythm-unit rem-with-px-fallback, - mixin: rem, - ); - @if susy-support(rem, $_reqs, $warn: false) and $rhythm-unit == rem { - @include rem($prop, $val); - } @else { - #{$prop}: $val; - } -} diff --git a/_sass/vendor/susy/susy/output/support/_support.scss b/_sass/vendor/susy/susy/output/support/_support.scss deleted file mode 100644 index 96991135..00000000 --- a/_sass/vendor/susy/susy/output/support/_support.scss +++ /dev/null @@ -1,85 +0,0 @@ -// Browser Support -// =============== - -// Susy Support Defaults -// --------------------- -@include susy-defaults(( - use-custom: ( - clearfix: false, - background-image: true, - background-options: false, - breakpoint: true, - box-sizing: true, - rem: true, - ), -)); - - -// Susy Support [mixin] -// -------------------- -// Send property-value pairs to the proper support modules. -// - $prop : -// - $val : -@mixin susy-support( - $prop, - $val -) { - // Background Support - @if $prop == background-image { - @include susy-background-image($val); - } @else if $prop == background-size { - @include susy-background-size($val); - } @else if $prop == background-origin { - @include susy-background-origin($val); - } @else if $prop == background-clip { - @include susy-background-clip($val); - } - - // Box-Sizing Support - @else if $prop == box-sizing { - @include susy-box-sizing($val); - } - - // Rem Support - @else { - @include susy-rem($prop, $val); - } -} - - -// Susy Support [function] -// ----------------------- -// Check for support of a feature. -// - $feature : -// - e.g "rem" or "box-sizing" -// - $requirements : -// - e.g (variable: rem-with-px-fallback, mixin: rem) -// - $warn : -@function susy-support( - $feature, - $requirements: (), - $warn: true -) { - $_support: susy-get(use-custom $feature); - - @if $_support { - $_fail: false; - - @each $_type, $_req in $requirements { - @each $_i in $_req { - $_pass: call(unquote("#{$_type}-exists"), $_i); - - @if not($_pass) { - $_fail: true; - @if $warn { - @warn "You requested custom support of #{$feature}, but the #{$_i} #{$_type} is not available."; - } - } - } - } - - $_support: if($_fail, false, $_support); - } - - @return $_support; -} diff --git a/_sass/vendor/susy/susy/su/_grid.scss b/_sass/vendor/susy/susy/su/_grid.scss deleted file mode 100644 index 7fe2a02d..00000000 --- a/_sass/vendor/susy/susy/su/_grid.scss +++ /dev/null @@ -1,103 +0,0 @@ -// Column math -// =========== - - -// Is Symmetrical -// -------------- -// Returns true if a grid is symmetrical. -// - [$columns] : | -@function is-symmetrical( - $columns: susy-get(columns) -) { - $columns: valid-columns($columns); - @return if(type-of($columns) == number, $columns, null); -} - - -// Susy Count -// ---------- -// Find the number of columns in a given layout -// - [$columns] : | -@function susy-count( - $columns: susy-get(columns) -) { - $columns: valid-columns($columns); - @return is-symmetrical($columns) or length($columns); -} - - -// Susy Sum -// -------- -// Find the total sum of column-units in a layout -// - [$columns] : | -// - [$gutters] : -// - [$spread] : false/narrow | wide | wider -@function susy-sum( - $columns : susy-get(columns), - $gutters : susy-get(gutters), - $spread : false -) { - $columns: valid-columns($columns); - $gutters: valid-gutters($gutters); - - $spread: if($spread == wide, 0, if($spread == wider, 1, -1)); - $gutter-sum: (susy-count($columns) + $spread) * $gutters; - $column-sum: is-symmetrical($columns); - - @if not($column-sum) { - @each $column in $columns { - $column-sum: ($column-sum or 0) + $column; - } - } - - @return $column-sum + $gutter-sum; -} - - -// Susy Slice -// ---------- -// Return a subset of columns at a given location. -// - $span : -// - $location : -// - [$columns] : | -@function susy-slice( - $span, - $location, - $columns: susy-get(columns) -) { - $columns: valid-columns($columns); - $sub-columns: $span; - - @if not(is-symmetrical($columns)) { - $location: $location or 1; - $sub-columns: (); - @for $i from $location to ($location + $span) { - $sub-columns: append($sub-columns, nth($columns, $i)); - } - } - - @return $sub-columns; -} - - -// Susy -// ---- -// Find the sum of a column-span. -// - $span : -// - $location : -// - [$columns] : | -// - [$gutters] : -// - [$spread] : false/narrow | wide | wider -@function susy( - $span, - $location : false, - $columns : susy-get(columns), - $gutters : susy-get(gutters), - $spread : false -) { - $columns: valid-columns($columns); - $gutters: valid-gutters($gutters); - $span: susy-slice($span, $location, $columns); - - @return susy-sum($span, $gutters, $spread); -} diff --git a/_sass/vendor/susy/susy/su/_settings.scss b/_sass/vendor/susy/susy/su/_settings.scss deleted file mode 100644 index 8b439aaa..00000000 --- a/_sass/vendor/susy/susy/su/_settings.scss +++ /dev/null @@ -1,73 +0,0 @@ -// Settings -// ======== - -// Version -// ------- -$su-version: 1.1; - - -// Default Settings -// ---------------- -// PRIVATE: The basic settings -$susy-defaults: ( - columns: 4, - gutters: .25, -); - - -// User Settings -// ------------- -// - Define the $susy variable with a map of your own settings. -// - Set EITHER $column-width OR $container -// - Use $column-width for static layouts -$susy: () !default; - - -// Susy Defaults -// ------------- -// PRIVATE: Add defaults to Susy -@mixin susy-defaults( - $defaults -) { - $susy-defaults: map-merge($susy-defaults, $defaults) !global; -} - - -// Susy Set -// -------- -// Change one setting -// - $key : setting name -// - $value : setting value -@mixin susy-set( - $key-value... -) { - $susy: _susy-deep-set($susy, $key-value...) !global; -} - - -// Susy Get -// -------- -// Return one setting from a grid -// - $key : -// - $layout : -@function susy-get( - $key, - $layout: map-merge($susy-defaults, $susy) -) { - $layout: parse-grid($layout); - $_options: $layout $susy $susy-defaults; - $_break: false; - $_return: null; - - @each $opt in $_options { - @if type-of($opt) == map and not($_break) { - $_keyset: _susy-deep-has-key($opt, $key...); - @if $_keyset { - $_return: _susy-deep-get($opt, $key...); - $_break: true; - } - } - } - - @return $_return; -} diff --git a/_sass/vendor/susy/susy/su/_utilities.scss b/_sass/vendor/susy/susy/su/_utilities.scss deleted file mode 100644 index b737f212..00000000 --- a/_sass/vendor/susy/susy/su/_utilities.scss +++ /dev/null @@ -1,111 +0,0 @@ -// Map Functions -// ============= - - -// Truncate List -// ------------- -// - Return a list, truncated to a given length -@function _susy-truncate-list( - $list, - $length -) { - $_return: (); - - @for $i from 1 through length($list) { - $_return: if($i <= $length, append($_return, nth($list, $i)), $_return); - } - - @return $_return; -} - - -// Deep Get -// -------- -// - Return a value deep in nested maps -@function _susy-deep-get( - $map, - $keys... -) { - $_return: $map; - - @each $key in $keys { - @if type-of($_return) == map { - $_return: map-get($_return, $key); - } - } - - @return $_return; -} - - -// Deep Set -// -------- -// - Set a value deep in nested maps -@function _susy-deep-set( - $map, - $keys-value... -) { - $_value: nth($keys-value, -1); - $_keys: _susy-truncate-list($keys-value, length($keys-value) - 1); - $_length: length($_keys); - $_return: (); - - @for $i from 1 through $_length { - $_n: 0 - $i; - $_level: _susy-truncate-list($_keys, $_length + $_n); - $_level: _susy-deep-get($map, $_level...); - $_merge: nth($_keys, $_n); - $_merge: ($_merge: $_value); - $_return: if($_level, map-merge($_level, $_merge), $_merge); - $_value: $_return; - } - - @return $_return; -} - - -// Deep Merge -// ---------- -// Return 2 objects of any depth, merged -@function _susy-deep-merge( - $map1, - $map2 -) { - - @if type-of($map1) != map or type-of($map2) != map { - $map1: $map2; - } @else { - @each $key, $value in $map2 { - $_new: ($key: _susy_deep-merge(map-get($map1, $key), $value)); - $map1: map-merge($map1, $_new); - } - } - - @return $map1; -} - - -// Deep Has-Key -// ------------ -// - Return true if a deep key exists -@function _susy-deep-has-key( - $map, - $keys... -) { - $_return: null; - $_stop: false; - - @each $key in $keys { - @if not($_stop) { - $_return: map-has-key($map, $key); - } - - @if $_return { - $map: map-get($map, $key); - } @else { - $_stop: true; - } - } - - @return $_return; -} diff --git a/_sass/vendor/susy/susy/su/_validation.scss b/_sass/vendor/susy/susy/su/_validation.scss deleted file mode 100644 index 4c6ab8da..00000000 --- a/_sass/vendor/susy/susy/su/_validation.scss +++ /dev/null @@ -1,57 +0,0 @@ -// Math Validation -// =============== - - -// Valid Columns -// ------------- -// Check that a column setting is valid. -@function valid-columns( - $columns, - $silent: false -) { - $type: type-of($columns); - $return: null; - - @if $type == number and unitless($columns) { - $return: $columns; - } @else if $type == list { - $fail: null; - @each $col in $columns { - @if type-of($col) == number { - $fail: $fail or if(unitless($col), null, true); - } @else { - $fail: true; - } - } - $return: if($fail, $return, $columns); - } - - @if $return != $columns and not($silent) { - $return: null; - $warn: '$columns must be a unitless number or list of unitless numbers.'; - @warn $warn + ' Current value [#{$type}]: #{$columns}'; - } - - @return $return; -} - - -// Valid Gutters -// ------------- -// Check that a gutter setting is valid. -@function valid-gutters( - $gutters, - $silent: false -) { - $type: type-of($gutters); - $return: null; - - @if $type == number and unitless($gutters) { - $return: $gutters; - } @else if not($silent) { - $warn: '$gutters must be a unitless number.'; - @warn $warn + ' Current value [#{$type}]: #{$gutters}'; - } - - @return $return; -} diff --git a/_site/community/slack.md b/_site/community/slack.md new file mode 100644 index 00000000..22bbded7 --- /dev/null +++ b/_site/community/slack.md @@ -0,0 +1,46 @@ +--- +description: > + Need help with WireMock? + Want to share your experiences? + Interested in participating in the community or contributing? + We have a community Slack open to everyone! +--- + +# WireMock community Slack + +[![a](https://img.shields.io/badge/slack-Join%20us-brightgreen?style=flat&logo=slack)](https://slack.wiremock.org/) + +If you need help with WireMock, +interested in participating in the community, +or interested in contributing, please join us on the [WireMock Community Slack](https://slack.wiremock.org/). + +## How to join + +1. Go to [slack.wiremock.org](https://slack.wiremock.org/) +2. Register in the `wiremock-slack` workspace using this link +3. Open the Slack workspace using your favorite (or not so) client! +4. Nice 2 have: Say hello and tell us about your WireMock use-cases + on the `#introduce-yourself` channel + +Welcome aboard! + +## Key channels + +- `#help` - channel for any questions regarding WireMock usage, + including developing test automation with WireMock or using the standalone instance +- `#help-contributing` - the channel where you can ask any questions about contributing and get help from the community members +- `#announcements` - Channel where we announce new releases and key updates in the WireMock ecosystem and the community +- `#wiremock-cloud` - Anything about [WireMock Cloud](https://www.wiremock.io/product?utm_source=wiremock.org&utm_medium=referral&utm_campaign=community_slack), + including community support +- `#wiremock-${your tech}` - channel for discussing WireMock usage on specific technology stacks, for example `java`, `python`, `dotnet` or `golang` + +## Slack Archive + +We use the free version of Slack, so our history is limited to 3 months. +Nevertheless, you can access and search the conversation history +on [community.wiremock.io](https://community.wiremock.io/), +including searching for the issues in `#help`. + +## Other help channels + +- [WireMock on StackOverflow](https://stackoverflow.com/questions/tagged/wiremock) (`#wiremock` tag) diff --git a/_site/docs/README.md b/_site/docs/README.md new file mode 100644 index 00000000..6eeba017 --- /dev/null +++ b/_site/docs/README.md @@ -0,0 +1,264 @@ +--- +title: "WireMock User Documentation" +docs-wide: true +description: > + All of WireMock's features are accessible via its REST (JSON) interface and its Java API. + Additionally, stubs can be configured via JSON files. Read the full doc here. +--- + +WireMock is a popular open-source tool for API mock testing, +with over 5 million downloads per month. +It can help you to create stable test and +development environments, isolate you from flakey 3rd parties, and +simulate APIs that don't exist yet. + + + +## Getting Started + + + +## Distributions + +WireMock provides the following generic distributions that allow running it as a +[standalone server](./standalone.md) +in a container or within a Java Virtual Machine. + + + +## By use-case + +Below you can find links to the documentation for WireMock key use-cases. +You can find more documentation pages on the sidebar. + + + +## By protocol + +WireMock can serve all HTTP-based protocols and REST API. +Through built-in features and extensions, +it provides additional capabilities for widely used protocols. + + + +## By technology + +There are also solutions and guides for particular technologies and frameworks, +provided by the WireMock community and external contributors. + + diff --git a/_site/docs/advanced/deploy-to-servlet-container.md b/_site/docs/advanced/deploy-to-servlet-container.md new file mode 100644 index 00000000..abd4f5f4 --- /dev/null +++ b/_site/docs/advanced/deploy-to-servlet-container.md @@ -0,0 +1,32 @@ +--- +title: Deploying into a servlet container +meta_title: Deploying into a servlet container | WireMock +description: "package as WAR and deploy into a servlet +container" +--- + +WireMock can be packaged up as a WAR and deployed into a servlet +container, with the following caveats: + +- fault injection and browser proxying won't work. +- \_\_files won't be treated as a docroot as with standalone, +- the server cannot be remotely shut down. +- and the container must be configured to explode the WAR on deployment. + +!!! warinig + + This has only really been tested in Tomcat 6 and Jetty, so YMMV. + Running standalone is definitely the preferred option. + +The easiest way to create a WireMock WAR project is to clone the +[sample app](https://github.com/wiremock/wiremock/tree/master/sample-war). + +### Deploying under a sub-path of the context root + +If you want WireMock's servlet to have a non-root path, set the additional +init param `mappedUnder` with the sub-path `web.xml`, in +addition to configuring the servlet mapping appropriately). + +See [the custom mapped WAR +example](https://github.com/wiremock/wiremock/blob/master/sample-war/src/main/webappCustomMapping/WEB-INF/web.xml) +for details. diff --git a/_site/docs/advanced/java7.md b/_site/docs/advanced/java7.md new file mode 100644 index 00000000..3b5621eb --- /dev/null +++ b/_site/docs/advanced/java7.md @@ -0,0 +1,54 @@ +--- +description: > + WireMock versions that run on Java 1.7 +--- + +# Use older WireMock versions when Java 1.7 is required + +!!! WARNING: + + Recent WireMock versions do not run on Java 1.7. If you need to run on ava 1.7, use older + WireMock versions. Ability to run on Java 7 was deprecated in the 2.x linee, with version + 2.27.2 the latest release available. There will be noeither bugfixes nor security patches provided. + Make sure to update as soon as possible to Java 11 or above. + +The Java 7 distribution is aimed primarily at Android developers and enterprise Java teams that still use Java Runtime Environment (JRE) 1.7. +Some of its dependencies are not set to the latest versions. For example, Jetty 9.2.x is Jetty's last minor version to retain Java 7 compatibility. + +## Maven dependencies + +JUnit: + +```xml + + com.github.tomakehurst + wiremock + 2.27.2 + test + +``` + +Standalone JAR: + +```xml + + com.github.tomakehurst + wiremock-standalone + 2.27.2 + test + +``` + +## Gradle dependencies + +JUnit: + +```groovy +testImplementation "com.github.tomakehurst:wiremock:2.27.2" +``` + +Standalone JAR: + +```groovy +testImplementation "com.github.tomakehurst:wiremock-standalone:2.27.2" +``` diff --git a/images/favicon.svg b/_site/docs/assets/images/favicon.svg similarity index 100% rename from images/favicon.svg rename to _site/docs/assets/images/favicon.svg diff --git a/_docs/configuration.md b/_site/docs/configuration.md similarity index 70% rename from _docs/configuration.md rename to _site/docs/configuration.md index accf16a5..2d9dc37e 100644 --- a/_docs/configuration.md +++ b/_site/docs/configuration.md @@ -1,11 +1,11 @@ --- -layout: docs -title: "Java configuration" -meta_title: Configuring WireMock in Java | WireMock -description: Configuring WireMock progammatically in Java. +description: progammatic config in Java. --- -Both `WireMockServer` and the `WireMockRule` take a configuration builder as the parameter to their constructor e.g. +# Configuring WireMock in Java +// consider adding an introductory sentence here + +Both `WireMockServer` and the `WireMockRule` take a configuration builder as the parameter to their constructor like this example: ```java import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; @@ -16,7 +16,7 @@ WireMockServer wm = new WireMockServer(options().port(2345)); WireMockRule wm = new WireMockRule(options().port(2345)); ``` -Every option has a sensible default, so only options that you require an override for should be specified. +Every option has a sensible default, so only options for which you require an override should be specified. ## Network ports and binding @@ -91,12 +91,9 @@ WireMock can accept HTTPS connections from clients, require a client to present WireMock uses the trust store for three purposes: -1. As a server, when requiring client auth, WireMock will trust the client if it - presents a public certificate in this trust store -2. As a proxy, WireMock will use the private key & certificate in this key store - to authenticate its http client with target servers that require client auth -3. As a proxy, WireMock will trust a target server if it presents a public - certificate in this trust store +- As a server, when requiring client auth, WireMock will trust the client if it presents a public certificate in this trust store. +- As a proxy, WireMock will use the private key & certificate in this key store to authenticate its http client with target servers that require client auth. +- As a proxy, WireMock will trust a target server if it presents a public certificate in this trust store. ## Proxy settings @@ -134,7 +131,7 @@ WireMock uses the trust store for three purposes: ## File locations -WireMock, when started programmatically, will default to `src/test/resources` as a filesystem root if not configured otherwise. +If not configured otherwise, WireMock defaults to the filesystem root `src/test/resources` upon startup. ```java // Set the root of the filesystem WireMock will look under for files and mappings @@ -146,7 +143,7 @@ WireMock, when started programmatically, will default to `src/test/resources` as ## Request journal -The request journal records requests received by WireMock. It is required by the verification features, so these will throw errors if it is disabled. + Wiremock contains a request journal that records all requests it receives. The verification features require this, and will throw errors if it is disabled. ```java // Do not record received requests. Typically needed during load testing to avoid JVM heap exhaustion. @@ -175,7 +172,7 @@ Gzipping of responses can be disabled. ## Extensions -For details see [Extending WireMock](../extending-wiremock/). +For details see [Extending WireMock](./extending-wiremock.md). ```java // Add extensions @@ -184,9 +181,9 @@ For details see [Extending WireMock](../extending-wiremock/). ## Transfer encoding -By default WireMock will send all responses chunk encoded, meaning with a `Transfer-Encoding: chunked` header present and no `Content-Length` header. +By default WireMock sends all responses chunk encoded, which means it has a `Transfer-Encoding: chunked` header present and no `Content-Length` header. -This behaviour can be modified by setting a chunked encoding policy e.g. +You can modify the encoding policy: ```java .useChunkedTransferEncoding(Options.ChunkedEncodingPolicy.BODY_FILE) @@ -210,8 +207,7 @@ To enable automatic sending of CORS headers on stub responses, do the following: ## Limiting logged response body size -By default, response bodies will be recorded in the journal in their entirety. This can result in out of memory errors when very large bodies are served so WireMock -provides an option to limit the number of bytes of response bodies retained (truncating any that are larger). +By default, the journal records each entire response body. To prevent out-of-memory errors when working with large response bodies, you can set a limit, in bytes, to the response body size, with the result that WireMock truncates the larger ones upon saving. ```java .maxLoggedResponseSize(100000) // bytes @@ -219,16 +215,15 @@ provides an option to limit the number of bytes of response bodies retained (tru ## Preventing proxying to and recording from specific target addresses -As a security measure WireMock can be configured to only permit proxying (and therefore recording) to certain addresses. -This is achieved via a list of allowed address rules and a list of denied address rules, where the allowed list is evaluated first. +For security, you can set limits on prxying from WireMock, using using rules lists that specify allowed and denied addresses. WireMock evaluates the allowed list first. Each rule can be one of the following: * A single IP address -* An IP address range in the e.g. `10.1.1.1-10.2.2.2` -* A hostname wildcard e.g. `dev-*.example.com` +* An IP address range, as in `10.1.1.1-10.2.2.2` +* A hostname wildcard, as in `dev-*.example.com` -The ruleset is built and applied as follows: +The ruleset is built and applied as in the following example: ```java .limitProxyTargets(NetworkAddressRules.builder() @@ -241,28 +236,33 @@ The ruleset is built and applied as follows: ## Filename template -WireMock can set up specific filename template format based on stub information. -The main rule for set up specify stub metadata information in handlebar format. -For instance for endpoint `PUT /hosts/{id}` and format `{{{method}}}-{{{request.url}}}.json` -will be generated: `put-hosts-id.json` filename. Default template: `{{{method}}}-{{{path}}}-{{{id}}}.json`. +WireMock can set up specific filename template formats based on stub information. +The main rule for set up specify stub metadata information in handlebar format. +For instance for endpoint `PUT /hosts/{id}` and format +{% raw %} `{{{method}}}-{{{request.url}}}.json`{% endraw %} +will be generated: `put-hosts-id.json` filename. +Default template: {% raw %} `{{{method}}}-{{{path}}}-{{{id}}}.json` {% endraw %}. + +{% raw %} ```java .filenameTemplate("{{{request.url}}}-{{{request.url}}}.json") ``` -Note: starting from [3.0.0-beta-8](https://github.com/wiremock/wiremock/releases/tag/3.0.0-beta-8) +{% endraw %} +Note: starting from [3.0.0-beta-8](https://github.com/wiremock/wiremock/releases/tag/3.0.0-beta-8) ## Listening for raw traffic -If you would like to observe raw HTTP traffic to and from Jetty -for debugging purposes you can use a `WiremockNetworkTrafficListener`. +When debugging, you can observe raw HTTP traffic to and from Jetty + with a `WiremockNetworkTrafficListener`. + + !!! Warning "" + + Using WireMock's request listener extension points in some cases do not show some alterations that Jetty can make, in the response from Wiremock, before sending it to the client. For example, if you set it to append a --gzip postfix to the ETag response header for gzipped responses, it does not show. + -One scenario where it can be useful is where Jetty -alters the response from Wiremock before sending it to the client. -(An example of that is where Jetty appends a --gzip postfix to the ETag response header -if the response is gzipped.) -Using WireMock's request listener extension points in this case would not show those alterations. To output all raw traffic to console use `ConsoleNotifyingWiremockNetworkTrafficListener`, for example: @@ -270,6 +270,5 @@ To output all raw traffic to console use `ConsoleNotifyingWiremockNetworkTraffic .networkTrafficListener(new ConsoleNotifyingWiremockNetworkTrafficListener())); ``` -If you would like to collect the traffic -and for example add it to your acceptance test's output, +To collect raw traffic for other purposes, like adding to your acceptance test's output, you can use the `CollectingNetworkTrafficListener`. diff --git a/_site/docs/download-and-installation.md b/_site/docs/download-and-installation.md new file mode 100644 index 00000000..268a058e --- /dev/null +++ b/_site/docs/download-and-installation.md @@ -0,0 +1,90 @@ +--- +description: > + download and install WireMock. +--- + +# Download, install, and integrate with your app + +WireMock is available as a standalone service for: + +- Docker +- Java +- Java library +- NPM package +- SaaS + +## Download options + +WireMock ditributes Java packages in two flavours: + +- a standard JAR containing just WireMock. +- a standalone uber JAR containing WireMock plus all its dependencies. + +Most of the standalone JAR's dependencies are shaded--they are hidden in alternative packages. This allows WireMock to be used in projects with +conflicting versions of its dependencies. The standalone JAR is also runnable (see [Running as a Standalone Process](./running-standalone.md)). + +## Standalone Service + +Run the following in a terminal: + +=== "Docker" + + ```bash + docker run -it --rm -p 8080:8080 --name wiremock \ + wiremock/wiremock:{{ versions.wiremock_version }} + ``` + +## Declaring a dependency in your code + +=== "Maven" + + ```xml + + org.wiremock + wiremock-standalone + {{ versions.wiremock_version }} + test + + ``` + +=== "Gradle Groovy" + + ```groovy + testImplementation "org.wiremock:wiremock-standalone:{{ versions.wiremock_version }}" + ``` + +Learn more in the [Docker guide](./standalone/docker.md). + +### Direct download + +To run WireMock as a standalone process you can +download the standalone JAR from +here + +For next steps, take a look at: + +- the [Template library](https://library.wiremock.org). +- WireMock [tutorials](./getting-started.md). +- learn how to use [Request matching](./request-matching.md), +- learn how to use [Response templates](./response-templating.md). + +## Integrate WireMock into your app + +YOu have two options from which to choose: + +*Option 1*. Configure alternative endpoints. + +For example, if your app’s config file contains the following: + +`stripe.api.baseUrl=https://api.stripe.com` + +replace it in your dev/test environment’s config with: + +`stripe.api.baseUrl=https://:` + + +*Option 2*. Forward proxying. + +Set your HTTP client’s proxy host and port to the WireMock proxy/port and start wiremock with browser proxying enabled. + + diff --git a/_site/docs/extending-wiremock.md b/_site/docs/extending-wiremock.md new file mode 100644 index 00000000..ae0cea3b --- /dev/null +++ b/_site/docs/extending-wiremock.md @@ -0,0 +1,97 @@ +--- +description: > + creating and sharing WireMock extensions. +--- + +# Extending WireMock + +You can customise WireMock using a variety of extension points. You can create, package, and share reusable extensions. + +You have the option of registering extensions programmatically using the class name, class, or an instance. + +An interface defines each extension point, extendibg from `Extension`. Extension implementations load at startup time. + +At present, the following extension interfaces are available: + +- `RequestFilterV2`/`AdminRequestFilterV2`/`StubRequestFilterV2`: Intercept requests, modifying them or taking alternative actions based on their content. +- `ResponseDefinitionTransformerV2`: Modify the response definition used to generate a response. See [Transforming responses](./extensibility/transforming-responses.md). +- `ResponseTransformerV2`: Modify the response served to the client. See [Transforming responses](./extensibility/transforming-responses.md). +- `ServeEventListener`: Listen for events at various points in the request processing lifecycle. See [Listening for Serve Events](./extensibility/listening-for-serve-events.md). +- `AdminApiExtension`: Add admin API functions. See [Admin API Extensions](./extensibility/extending-the-admin-api.md). +- `RequestMatcherExtension`: Implement custom request matching logic. See [Custom matching](./extensibility/custom-matching.md). +- `GlobalSettingsListener`: Listen for changes to the settings object. See [Listening for Settings Changes](./extensibility/listening-for-settings-changes.md). +- `StubLifecycleListener`: Listen for changes to the stub mappings. See [Listening for Stub Changes](./extensibility/listening-for-stub-changes.md). +- `TemplateHelperProviderExtension`: Provide custom Handlebars helpers to the template engine. See [Adding Template Helpers](./extensibility/adding-template-helpers.md). +- `TemplateModelDataProviderExtension`: Provide additional data to the model passed to response templates. See [Adding Template Model Data](./extensibility/adding-template-model-data.md). +- `MappingsLoaderExtension`: Provide additional source to load the stub mappings. See [Adding Mappings Loader](./extensibility/adding-mappings-loader.md). + +The interfaces in this list ending with `V2` supercede deprecated equivalents with an older, more restrictive interface. Additionally `ServeEventListener` deprecates `PostServeAction`. + +## Registering Extensions + +You can directly register the extension programmatically using its class name, +class, or an instance: + +```java +new WireMockServer(wireMockConfig() + .extensions("com.mycorp.BodyContentTransformer", "com.mycorp.HeaderMangler")); + +new WireMockServer(wireMockConfig() + .extensions(BodyContentTransformer.class, HeaderMangler.class)); + +new WireMockServer(wireMockConfig() + .extensions(new BodyContentTransformer(), new HeaderMangler())); +``` + +See [Running as a Standalone Process](./standalone.md) for details on running with extensions from the command line. + +### Factories + +You can also register an extension factory, which allows an extension to be created with various core WireMock services passed to the constructor: + +```java +new WireMockServer(wireMockConfig() + .extensions(services -> + List.of( + new MiscInfoApi( + services.getAdmin(), + services.getOptions(), + services.getStores(), + services.getFiles(), + services.getExtensions() + )))); +``` + +Services currently available to extension factories are: + +- `Admin`: the main WireMock functional interface for stubbing, verification and configuration tasks. +- `Options`: the configuration object built at startup. +- `Stores`: the root interface for gaining access to the various stores of WireMock's state and creating/using custom stores. +- `FileSource`: the `__files` directory where larger response body files are often kept. +- `Extensions`: the service for creating and providing extension implementations. +- `TemplateEngine`: the Handlebars template engine. + +## Extension registration using service loading + +Iif they are placed on the classpath, extensions that are packaged with the relevant [Java service loader framework](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) metadata +will load automatically. + +For an example of such an extension, see [https://github.com/wiremock/wiremock/tree/master/test-extension](https://github.com/wiremock/wiremock/tree/master/test-extension). + +## Attaching sub-events during request processing + +You can make use of sub-events to report interesting/useful information during request processing. WireMock attaches the diff report generated when a request is not matched as a sub-event, and custom extension can exploit this approach to surface e.g. diagnostic and validation data in the serve event log, where it can be retrieved later via the API or exported to monitoring/observability tools via listeners. + + +Several types of extension act on WireMock's request processing: `RequestFilterV2` (and its stub/admin sub-interfaces), `ResponseDefinitionTransformer`, `ResponseTransformer` and `ServeEventListener`. + +The primary method in each of these takes the current `ServeEvent` as a parameter and sub-events can be attached to this: + +```java +serveEvent.appendSubEvent( + "JSON_PARSE_WARNING", + Map.of("message", "Single quotes are not permitted") +); +``` + +The second parameter to `appendSubEvent()` can be a Map or object containing any data required. diff --git a/_docs/extensibility/adding-mappings-loader.md b/_site/docs/extensibility/adding-mappings-loader.md similarity index 90% rename from _docs/extensibility/adding-mappings-loader.md rename to _site/docs/extensibility/adding-mappings-loader.md index df3339c6..5584391c 100644 --- a/_docs/extensibility/adding-mappings-loader.md +++ b/_site/docs/extensibility/adding-mappings-loader.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Mappings Loader Extensions -meta_title: Mappings Loader Extensions description: Adding additional source of loading mappings via extensions. --- +# Mappings Loader Extensions + Additional source to load the stub mappings can be configured by implementing `MappingsLoaderExtension`. ```java diff --git a/_docs/extensibility/adding-template-helpers.md b/_site/docs/extensibility/adding-template-helpers.md similarity index 90% rename from _docs/extensibility/adding-template-helpers.md rename to _site/docs/extensibility/adding-template-helpers.md index 1fa7ed78..6cabdec3 100644 --- a/_docs/extensibility/adding-template-helpers.md +++ b/_site/docs/extensibility/adding-template-helpers.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Adding Template Helpers -meta_title: Adding custom template helpers description: Adding custom Handlebars helpers to the template system via extensions --- +# Adding Custom Template Helpers + Extensions that implement the `TemplateHelperProviderExtension` interface provide additional Handlebars helpers to the templating system: ```java diff --git a/_docs/extensibility/adding-template-model-data.md b/_site/docs/extensibility/adding-template-model-data.md similarity index 89% rename from _docs/extensibility/adding-template-model-data.md rename to _site/docs/extensibility/adding-template-model-data.md index 7dc0f456..94ce8d8d 100644 --- a/_docs/extensibility/adding-template-model-data.md +++ b/_site/docs/extensibility/adding-template-model-data.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Adding Template Model Data -meta_title: Adding Template Model Data description: Adding extra elements to the template model during request processing --- +# Adding Template Model Data + Extensions that implement the `TemplateHelperProviderExtension` interface provide additional Handlebars helpers to the templating system: ```java diff --git a/_docs/extensibility/custom-matching.md b/_site/docs/extensibility/custom-matching.md similarity index 75% rename from _docs/extensibility/custom-matching.md rename to _site/docs/extensibility/custom-matching.md index 5099bde6..1d2f459d 100644 --- a/_docs/extensibility/custom-matching.md +++ b/_site/docs/extensibility/custom-matching.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Custom Matching -meta_title: Adding custom request matchers description: Adding custom request matchers via extensions --- +# Adding custom request matchers + If WireMock's standard set of request matching strategies isn't sufficient, you can register one or more request matcher classes containing your own logic. @@ -70,38 +69,30 @@ public class BodyLengthMatcher extends RequestMatcherExtension { Then define a stub with it: -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(requestMatching("body-too-long", Parameters.one("maxLength", 2048)) - .willReturn(aResponse().withStatus(422))); -``` +=== "Java" -{% endcodetab %} + ```java + stubFor(requestMatching("body-too-long", Parameters.one("maxLength", 2048)) + .willReturn(aResponse().withStatus(422))); + ``` -{% codetab JSON %} +=== "JSON" -```json -{ - "request": { - "customMatcher": { - "name": "body-too-long", - "parameters": { - "maxLength": 2048 + ```json + { + "request": { + "customMatcher": { + "name": "body-too-long", + "parameters": { + "maxLength": 2048 + } } + }, + "response": { + "status": 422 } - }, - "response": { - "status": 422 } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ### Combining standard and custom request matchers @@ -118,9 +109,7 @@ WireMock server. An exception will be thrown if attempting to use an inline cust Custom matchers defined as extensions can also be combined with standard matchers. -{% codetabs %} - -{% codetab Java %} +=== "Java" ```java stubFor(get(urlPathMatching("/the/.*/one")) @@ -128,28 +117,22 @@ stubFor(get(urlPathMatching("/the/.*/one")) .willReturn(ok())); ``` -{% endcodetab %} - -{% codetab JSON %} - -```json -{ - "request": { - "urlPathPattern": "/the/.*/one", - "method": "GET", - "customMatcher": { - "name": "path-contains-param", - "parameters": { - "path": "correct" +=== "JSON" + + ```json + { + "request": { + "urlPathPattern": "/the/.*/one", + "method": "GET", + "customMatcher": { + "name": "path-contains-param", + "parameters": { + "path": "correct" + } } + }, + "response": { + "status": 200 } - }, - "response": { - "status": 200 } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` diff --git a/_docs/extensibility/extending-the-admin-api.md b/_site/docs/extensibility/extending-the-admin-api.md similarity index 71% rename from _docs/extensibility/extending-the-admin-api.md rename to _site/docs/extensibility/extending-the-admin-api.md index adb50eab..ac6ceeab 100644 --- a/_docs/extensibility/extending-the-admin-api.md +++ b/_site/docs/extensibility/extending-the-admin-api.md @@ -1,8 +1,7 @@ --- -layout: docs -title: Admin API Extensions -meta_title: Admin API Extensions description: Adding additional admin API functions via extensions. --- +# Admin API Extensions + Additional API routes under WireMock's `/__admin` endpoint can be configured by implementing `AdminApiExtension`. \ No newline at end of file diff --git a/_docs/extensibility/filtering-requests.md b/_site/docs/extensibility/filtering-requests.md similarity index 96% rename from _docs/extensibility/filtering-requests.md rename to _site/docs/extensibility/filtering-requests.md index 3bda7a62..de2e66b1 100644 --- a/_docs/extensibility/filtering-requests.md +++ b/_site/docs/extensibility/filtering-requests.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Filtering and Modifying Requests -meta_title: Filtering and Modifying Requests description: Filtering and modifying requests via extensions --- +# Filtering and Modifying Requests + Requests to both stubs and the admin API can be intercepted and either modified or halted with an immediate response. This supports a number of use cases including: authentication, URL rewriting and request header injection. diff --git a/_docs/extensibility/listening-for-serve-events.md b/_site/docs/extensibility/listening-for-serve-events.md similarity index 96% rename from _docs/extensibility/listening-for-serve-events.md rename to _site/docs/extensibility/listening-for-serve-events.md index eacc08dc..4c49aafc 100644 --- a/_docs/extensibility/listening-for-serve-events.md +++ b/_site/docs/extensibility/listening-for-serve-events.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Listening for Serve Events -meta_title: Listening for Serve Events description: Creating and registering serve event listeners --- +# Listening for Serve Events + Serve event listeners are intended for use when you wish to take an action at a specific point in the request processing flow, without affecting processing in any way. For instance a serve event listener would be the most suitable extension point to use for exporting telemetry data to a monitoring/observability tool. The `ServeEventListener` interface (which deprecates `PostServeAction`) supports two different modes of operation - you can either override specific methods if the listener should only fire at a specific point in the request processing flow, or you can override a generic method then configure which lifecycle points it's fired at when binding the listener to specific stubs. Or it can simply be made to fire at all lifecycle points. diff --git a/_docs/extensibility/listening-for-settings-changes.md b/_site/docs/extensibility/listening-for-settings-changes.md similarity index 92% rename from _docs/extensibility/listening-for-settings-changes.md rename to _site/docs/extensibility/listening-for-settings-changes.md index 56cb99f1..7671c6c5 100644 --- a/_docs/extensibility/listening-for-settings-changes.md +++ b/_site/docs/extensibility/listening-for-settings-changes.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Listening for Settings Changes -meta_title: Listening for Settings Changes description: Listening for Settings Changes --- +# Listening for Settings Changes + You can listen for changes to the global settings object. This is most useful when combined with other extension points, allowing extensions to define and make use of extended settings values rather than rolling their own configuration strategy. diff --git a/_docs/extensibility/listening-for-stub-changes.md b/_site/docs/extensibility/listening-for-stub-changes.md similarity index 92% rename from _docs/extensibility/listening-for-stub-changes.md rename to _site/docs/extensibility/listening-for-stub-changes.md index 663deef4..9e3b0edc 100644 --- a/_docs/extensibility/listening-for-stub-changes.md +++ b/_site/docs/extensibility/listening-for-stub-changes.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Listening for Stub Changes -meta_title: Listening for Stub Changes description: Listening for Stub Changes --- +# Listening for Stub Changes + You can subscribe to changes in the state of WireMock's stubs via the `StubLifecycleListener` extension point. For instance, to respond after a new stub has been created you would do the following: diff --git a/_docs/extensibility/transforming-responses.md b/_site/docs/extensibility/transforming-responses.md similarity index 75% rename from _docs/extensibility/transforming-responses.md rename to _site/docs/extensibility/transforming-responses.md index cdf2f503..cc724afa 100644 --- a/_docs/extensibility/transforming-responses.md +++ b/_site/docs/extensibility/transforming-responses.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Transforming Responses -meta_title: Transforming response definitions and responses description: Transforming response definitions and responses via extensions --- +# Transforming response definitions and responses + Sometimes, returning wholly static responses to stub requests isn't practical e.g. when there are transaction IDs being passed between request/responses, dates that must be current. Via WireMock's extension @@ -64,42 +63,34 @@ intend to register them via an instance as described below. Parameters are supplied on a per stub mapping basis: -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(get(urlEqualTo("/transform")).willReturn( - aResponse() - .withTransformerParameter("newValue", 66) - .withTransformerParameter("inner", ImmutableMap.of("thing", "value")))); // ImmutableMap is from Guava, but any Map will do -``` - -{% endcodetab %} - -{% codetab JSON %} - -```json -{ - "request": { - "url": "/transform", - "method": "GET" - }, - "response": { - "status": 200, - "transformerParameters": { - "newValue": 66, - "inner": { - "thing": "value" +=== "Java" + + ```java + stubFor(get(urlEqualTo("/transform")).willReturn( + aResponse() + .withTransformerParameter("newValue", 66) + .withTransformerParameter("inner", ImmutableMap.of("thing", "value")))); // ImmutableMap is from Guava, but any Map will do + ``` + +=== "JSON" + + ```json + { + "request": { + "url": "/transform", + "method": "GET" + }, + "response": { + "status": 200, + "transformerParameters": { + "newValue": 66, + "inner": { + "thing": "value" + } } } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ### Non-global transformations @@ -116,37 +107,30 @@ public boolean applyGlobally() { Then you add the transformation to specific stubs via its name: -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(get(urlEqualTo("/local-transform")).willReturn(aResponse() - .withStatus(200) - .withBody("Original body") - .withTransformers("my-transformer", "other-transformer"))); -``` - -{% endcodetab %} - -{% codetab JSON %} - -```json -{ - "request": { - "method": "GET", - "url": "/local-transform" - }, - "response": { - "status": 200, - "body": "Original body", - "transformers": ["my-transformer", "other-transformer"] +=== "Java" + + ```java + stubFor(get(urlEqualTo("/local-transform")).willReturn(aResponse() + .withStatus(200) + .withBody("Original body") + .withTransformers("my-transformer", "other-transformer"))); + ``` + +=== "JSON" + + ```json + { + "request": { + "method": "GET", + "url": "/local-transform" + }, + "response": { + "status": 200, + "body": "Original body", + "transformers": ["my-transformer", "other-transformer"] + } } -} -``` -{% endcodetab %} - -{% endcodetabs %} + ``` The Java API also has a convenience method for adding transformers and parameters in one call: diff --git a/_site/docs/extensions/README.md b/_site/docs/extensions/README.md new file mode 100644 index 00000000..82802781 --- /dev/null +++ b/_site/docs/extensions/README.md @@ -0,0 +1,14 @@ +# WireMock Extensions + +WireMock can be customized via a variety of extension points. +The extensions allow implementing support for new protocols, +request filters, response templating expressions, +data storage and observability capabilities. + +## Available extensions + +See the list on the left panel. + +## Developing Extensions + +See [Extending WireMock](../extending-wiremock.md). diff --git a/_docs/faq.md b/_site/docs/faq.md similarity index 51% rename from _docs/faq.md rename to _site/docs/faq.md index c69e5a51..4c31d173 100644 --- a/_docs/faq.md +++ b/_site/docs/faq.md @@ -1,38 +1,36 @@ --- -layout: docs -title: Frequently Asked Questions -meta_title: "Frequently Asked Questions in WireMock" description: > Frequently asked questions and best practices regarding anything WireMock. --- -Here, you can find information about what API mocking and WireMock are, as well as recommendations and best practices for different challenges in various areas of WireMock. +# Frequently Asked Questions + +In this FAQ, you can find information about what API mocking and WireMock are, along with recommendations and best practices for different challenges in various areas of WireMock. ## API mocking and WireMock as a service ### What is WireMock? -WireMock is a free API mocking tool that can be run as a standalone server, or in a hosted version via the [WireMock Cloud](https://wiremock.io/) managed service. +WireMock is a free API mocking tool that you can run as a standalone server, or in a hosted version via the [WireMock Cloud](https://wiremock.io/) managed service. ### What is API mocking? -API mocking involves creating a simple simulation of an API, accepting the same types of request and returning identically structured responses as the real thing, -enabling fast and reliable development and testing. +API mocking involves enabling fast and reliable development and testing by creating a simple simulation of an API and using it to accept requests and return responses that are identically structured to those used in the real API. ### When do you need to mock APIs? -API mocking is typically used during development and testing as it allows you to build your app without worrying about 3rd party APIs or sandboxes breaking. -It can also be used to rapidly prototype APIs that don’t exist yet. +Because it allows you to focus on building your app without worrying about 3rd party APIs or sandboxes breaking, API mocking is typically used during development and testing. +Another important use is rapid prototyping of APIs that don’t yet exist. ### How do you create an API mock? -WireMock supports several approaches for creating mock APIs - in code, via its REST API, as JSON files and by recording HTTP traffic proxied to another destination. +WireMock supports several approaches for creating mock APIs--in code, via its REST API, as JSON files, and by recording HTTP traffic proxied to another destination. ### What makes WireMock unique? -WireMock has a rich [matching system](../request-matching/), allowing any part of an incoming request to be matched against complex and precise criteria. +WireMock has a rich [matching system](./request-matching.md), allowing any part of an incoming request to be matched against complex and precise criteria. Responses of any complexity can be dynamically generated via the Handlebars based templating system. -Finally, WireMock is easy to integrate into any workflow due to its numerous [extension points](../extending-wiremock/) and comprehensive APIs. +Finally, WireMock is easy to integrate into any workflow due to its numerous [extension points](./extending-wiremock.md) and comprehensive APIs. ### Is WireMock open source? @@ -45,13 +43,13 @@ WireMock is completely free under the Apache 2.0 license. ## Technical questions -### How to manage many mocks across different use cases and teams? +### How do I manage many mocks across different use cases and teams? -This question is valid especially when it is getting difficult to keep track of what test case(s) a particular mock was meant for. +This question tends to arise at the point when it gets difficult to keep track of the intended test case(s) for which specific mocks were built. #### Potential solutions -- Create your stubs (or most of them at least) in the test cases themselves, then [reset them](../stubbing/#reset) each time. -- Use the [`metadata` element](../stub-metadata/) in the stub data to tag stubs with info relating them to specific test cases. +- Create your stubs (or most of them at least) in the test cases themselves, then [reset them](./stubbing.md#reset) each time. +- Use the [`metadata` element](./stub-metadata.md) in the stub data to tag stubs with info relating them to specific test cases. #### Potential solutions for WireMock standalone - Use configuration-as-code, and store your definitions in a repository. You can have a hierarchical structure of Mappings and Files to specify teams. diff --git a/_docs/getting-started.md b/_site/docs/getting-started.md similarity index 68% rename from _docs/getting-started.md rename to _site/docs/getting-started.md index 76c09df5..778f26b9 100644 --- a/_docs/getting-started.md +++ b/_site/docs/getting-started.md @@ -1,29 +1,27 @@ --- -layout: docs -title: WireMock Tutorials -meta_title: Listing of WireMock Quick Starts and Tutorials -toc_rank: 10 -redirect_from: - - "/getting-started.html" - - "/docs/tutorials.html" -description: Provides links to WireMock tutorials and other entry materials +description: > + How to get started with WireMock + This page provides links to WireMock tutorials and other entry materials --- +# WireMock Tutorials + Getting Started with WireMock in your project? + Check out the guidelines below. ## Quick Starts At the moment, we provide the following quick starts for beginners: -- [API Mocking with Java and JUnit 4](../quickstart/java-junit) -- [Downloading and Installing WireMock](../download-and-installation) +- [API Mocking with Java and JUnit 4](./quickstart/java-junit.md) +- [Downloading and Installing WireMock](./download-and-installation.md) ## Featured tutorials -Here are some good tutorials from the [External Resources](/external-resources) you can use: +Here are some good tutorials from the [External Resources](../resources/external.md) you can use: - [WireMock Basics Workshop](https://github.com/basdijkstra/wiremock-workshop), by Bas Dijkstra - [Running your acceptance tests in Kubernetes using WireMock](https://blog.sebastian-daschner.com/entries/acceptance_tests_wiremock_kubernetes), by Sebastian Daschner @@ -34,3 +32,10 @@ Here are some good tutorials from the [External Resources](/external-resources) If you know about additional tutorials and extensions for WireMock, [let us know](https://github.com/wiremock/wiremock.org/issues/new?assignees=&labels=documentation&template=3_documentation+copy.yml&title=Add%20Tutorial%20to%20listing)! If you would like to write a new tutorial, see the [Contributor Guide](https://github.com/wiremock/community/tree/main/contributing#tutorials-and-guides). + + + +```plantuml +Alice -> Bob +``` + diff --git a/_docs/grpc.md b/_site/docs/grpc.md similarity index 56% rename from _docs/grpc.md rename to _site/docs/grpc.md index 7d264bc3..ae1adcf4 100644 --- a/_docs/grpc.md +++ b/_site/docs/grpc.md @@ -1,25 +1,29 @@ --- -layout: docs -title: Mocking gRPC services -meta_title: Mocking gRPC services -description: Mocking gRPC services with WireMock +description: > + WireMock extension for gRPC. og_image: solutions/grpc/wiremock_grpc_opengraph.png -header: - image: solutions/grpc/header.png -redirect_from: -- "/grpc.html" -- "/grpc/" +hero: solutions/grpc/header.png --- -WireMock 3.2.0+ supports mocking of gRPC services via the -[WireMock extension for gRPC](https://github.com/wiremock/wiremock-grpc-extension). +# Mocking gRPC services -The extension scans for descriptor files (generated from the service's `.proto` files) in the `grpc` subdirectory of WireMock's root. +The [WireMock extension for gRPC](https://github.com/wiremock/wiremock-grpc-extension), compatible with WireMock 3.2.0+, supports mocking of gRPC services. -Using these, it converts incoming messages to JSON before passing them to WireMock's core stubbing system which allows the existing JSON matchers to be used when matching requests. -It also converts JSON responses back into proto messages so that all of WireMock's response definition features including templating can be used. +To set up the extension for use, you: -WireMock and gRPC schema +- add the extension JAR dependency to your project. +- create a root directory for WireMock e.g. `src/test/resources/wiremock` with a subdirectory under it, named `grpc`. +- copy the descriptor files generated by `protoc` from your `.proto` files into the `grpc` subdirectory. + +For details, see [Setup](setup) below. + +At runtime, the extension: + +- scans for descriptor files (generated from the service's `.proto` files) in the `grpc` subdirectory of WireMock's root. +- using the descriptor file, it converts incoming messages to JSON before passing them to WireMock's core stubbing system, which allows the existing JSON matchers to be used when matching requests. +- converts JSON responses back into proto messages so that all of WireMock's response definition features including templating can be used. + +WireMock and gRPC schema The extension also adds a Java DSL that works with the Java classes generated by `protoc`, while also providing a more gRPC idiomatic way of defining stubs. @@ -29,25 +33,25 @@ The extension also adds a Java DSL that works with the Java classes generated by Add the extension JAR dependency to your project: -Gradle: +=== "Gradle" -```gradle -implementation 'org.wiremock:wiremock-grpc-extension:{{ site.grpc_extension_version }}' -``` + ```gradle + implementation 'org.wiremock:wiremock-grpc-extension:{{ versions.grpc_extension_version }}' + ``` -Maven: +=== "Maven" -```xml - - org.wiremock - wiremock-grpc-extension - {{ site.grpc_extension_version }} - -``` + ```xml + + org.wiremock + wiremock-grpc-extension + {{ versions.grpc_extension_version }} + + ``` -Create a root directory for WireMock e.g. `src/test/resources/wiremock` and create a subdirectory under this named `grpc`. +Create a root directory for WireMock, typically `src/test/resources/wiremock`, and create a subdirectory in it named `grpc`. -Put the descriptor files generated by `protoc` from your `.proto` files into the `grpc` directory. +Copy the descriptor files generated by `protoc` from your `.proto` files into the `grpc` subdirectory. Initialise WireMock server with the extension enabled and the root directory set to the path created in the previous steps: @@ -72,7 +76,7 @@ WireMockGrpcService mockGreetingService = ### Stubbing via JSON matching + responses -To specify request criteria and response data via JSON: +To specify request criteria and response data using JSON: ```java mockGreetingService.stubFor( @@ -81,8 +85,9 @@ mockGreetingService.stubFor( .willReturn(json("{ "greeting": "Hi Tom from JSON" }"))); ``` +Or, with a templated response: -Or with a templated response: +{% raw %} ```java mockGreetingService.stubFor( @@ -93,6 +98,8 @@ mockGreetingService.stubFor( "{ \"greeting\": \"Hello {{jsonPath request.body '$.name'}}\" }"))); ``` +{% endraw %} + ### Stubbing via Java message objects Matching and stubbing in the Java DSL can also be specified using the Java classes generated by `protoc`: @@ -126,10 +133,10 @@ For a more complete set of examples, see the [Java demo project](https://github. ### Setup -Download the standalone JAR at version 3.2.0 or above - and the gRPC extension JAR into your working directory. +Download the standalone JAR at version 3.2.0 or above + and the gRPC extension JAR into your working directory. -Create a WireMock data directory with a subdirectory for stub mappings and one for descriptor files: +Create a WireMock data directory with two subdirectories; one for stub mappings, and another for descriptor files: ```bash mkdir -p wiremock/mappings wiremock/grpc @@ -141,10 +148,10 @@ Compile your proto files into descriptors: protoc --descriptor_set_out wiremock/grpc/services.dsc ExampleServices.proto ``` -Run WireMock with both on the classpath: +Run WireMock, with both directories you just created on the classpath: ```bash -java -cp wiremock-standalone-{{ site.wiremock_version }}.jar:wiremock-grpc-extension-standalone-{{ site.grpc_extension_version }}.jar \ +java -cp wiremock-standalone-{{ versions.wiremock_version }}.jar:wiremock-grpc-extension-standalone-{{ versions.grpc_extension_version }}.jar \ wiremock.Run \ --root-dir wiremock-data ``` @@ -174,4 +181,4 @@ gRPC stubs are defined using WireMock's standard JSON format. Requests should al ## More Demos -For more see the [standalone demo project](https://github.com/wiremock/wiremock-grpc-demos/tree/main/standalone). \ No newline at end of file +For more see the [standalone demo project](https://github.com/wiremock/wiremock-grpc-demos/tree/main/standalone). diff --git a/_docs/https.md b/_site/docs/https.md similarity index 56% rename from _docs/https.md rename to _site/docs/https.md index 289c16c4..aaca291b 100644 --- a/_docs/https.md +++ b/_site/docs/https.md @@ -1,13 +1,11 @@ --- -layout: docs -title: Serving HTTPs -meta_title: Using WireMock with HTTPs using self-signed or custom certificates | WireMock -redirect_from: "/https.html" -description: WireMock can optionally accept requests over HTTPS. By default it will serve its own self-signed TLS certificate. +description: > + Optional HTTPS transport --- -WireMock can optionally accept requests over HTTPs. By default it will serve its own self-signed TLS certificate, but this can be -overridden if required by providing a keystore containing another certificate. +# Serving HTTPs + +As an option, WireMock can accept requests over HTTPs. By default, it serves its own self-signed TLS certificate, but you can override it as needed by providing a keystore containing another certificate. ## Handling HTTPS requests @@ -19,7 +17,7 @@ HTTPS port: public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().httpsPort(8443)); ``` -To use your own keystore you can specify its path and optionally its +To use your own keystore you can specify its path and, optionally, its password: ```java @@ -31,13 +29,13 @@ public WireMockRule wireMockRule = new WireMockRule(wireMockConfig() .keyManagerPassword("verysecret")); // The password used to access individual keys in the keystore. Defaults to "password" if omitted ``` -The keystore type defaults to JKS, but this can be changed if you're using another keystore format e.g. Bouncycastle's BKS with Android: +The keystore type defaults to JKS. To use a different keysotre format, specify it. For example, for Bouncycastle's BKS (with Android): ```java .keystoreType("BKS") ``` -To allow only HTTPS requests, disable HTTP by adding: +To allow for only HTTPS requests, disable HTTP by adding the following rule: ```java @Rule @@ -46,9 +44,10 @@ public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().httpsPort(8 ## Requiring client certificates -To make WireMock require clients to authenticate via a certificate you -need to supply a trust store containing the certs to trust and enable -client auth: +To make WireMock require clients to authenticate using a certificate, you must: + +- supply a trust store containing the certs to trust +- enable client auth: ```java @Rule @@ -59,14 +58,13 @@ public WireMockRule wireMockRule = new WireMockRule(wireMockConfig() .trustStorePassword("mostsecret")); // Defaults to "password" if omitted ``` -If you using WireMock as a proxy onto another system which requires client certificate authentication, you will also need to -specify a trust store containing the certificate(s). +If you using WireMock as a proxy onto another system that requires client certificate authentication, you must also specify a trust store containing the certificate(s). + + +!!! note -> **note** -> -> Jetty requires client certificates to contain Subject Alternative Names. -> See [this script](https://github.com/tomakehurst/wiremock/blob/master/scripts/create-client-cert.sh) for an example of how to build -> a truststore containing a valid certificate (you'll probably want to edit the client-cert.conf file before running this). + Jetty requires client certificates to contain Subject Alternative Names. + See [this script](https://github.com/tomakehurst/wiremock/blob/master/scripts/create-client-cert.sh) for an example of how to build a truststore containing a valid certificate (you'll probably want to edit the client-cert.conf file before running this). ## Common HTTPS issues @@ -76,4 +74,4 @@ HTTP port with a client that's expecting HTTPS (i.e. has `https://` in the URL). `org.apache.hc.core5.http.NoHttpResponseException: The target server failed to respond`: Could mean you've tried to connect to the HTTPS port with a client expecting HTTP. -`javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`: You are using WireMock's default (self-signed) TLS certificate or another certificate that isn't signed by a CA. In this case you need to specifically configure your HTTP client to trust the certificate being presented, or to trust all certificates. Here is an example of [how to do this with the Apache HTTP client](https://github.com/tomakehurst/wiremock/blob/{{ site.wiremock_version }}/src/main/java/com/github/tomakehurst/wiremock/http/HttpClientFactory.java). +`javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`: You are using WireMock's default (self-signed) TLS certificate or another certificate that isn't signed by a CA. In this case you need to specifically configure your HTTP client to trust the certificate being presented, or to trust all certificates. Here is an example of [how to do this with the Apache HTTP client](https://github.com/wiremock/wiremock/blob/{{ versions.wiremock_version }}/src/main/java/com/github/tomakehurst/wiremock/http/HttpClientFactory.java). diff --git a/_site/docs/java-usage.md b/_site/docs/java-usage.md new file mode 100644 index 00000000..56f67003 --- /dev/null +++ b/_site/docs/java-usage.md @@ -0,0 +1,84 @@ +--- +description: > + At runtime, programmatically create, start and stop the server for using WireMock from Java. +--- + +# Running WireMock from plain Java and other JVM Languages + +Programmatically create, start, and stop the server for using WireMock from Java, outside of JUnit. + + +## The Server + +If you want to use WireMock from Java (or any other JVM language) +outside of JUnit, you can programmatically create, start, and stop the +server: + +```java +WireMockServer wireMockServer = new WireMockServer(options().port(8089)); //No-args constructor will start on port 8080, no HTTPS +wireMockServer.start(); + +// Sometime later + +wireMockServer.stop(); +``` + +!!! info + + If you're neither using JUnit nor any of the WireMock rules, to suitably manage the + server lifecycle, you can construct and start the server directly. + +For more details of the `options()` builder accepted by the constructor see [Configuration](./configuration.md) for details. + +As an alternative to calling the client, you can call the stubbing/verifying DSL from the server object. +This works similarly to stubbing and verification using the [JUnit rule](./junit-extensions.md) + +### Managing ports + +To change the port number and/or you're running the server on +another host, you must tell the client: + +```java +WireMock.configureFor("wiremock.host", 8089); +``` + +When you deploy into a servlet container under a path other +than root, you need to set that too: + +```java +WireMock.configureFor("tomcat.host", 8080, "/wiremock"); +``` + +## The Client + +The `WireMock` class provides an over-the-wire client to a WireMock +server (the local one by default). + +### Configuring for static calls + +To configure the static client for an alternative host and port: + +```java +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +configureFor("wiremock.host", 8089); +stubFor(get(....)); +``` + +As above, when you deploy the server into a servlet container under a path +other than root, you'll need to set that too: + +```java +WireMock.configureFor("tomcat.host", 8080, "/wiremock"); +``` + +### Newing up + +If you need to talk to more than one server instance, new `WireMock` instances are useful. + +Create a new instance as follows: + +```java +WireMock wireMock = new WireMock("some.host", 9090, "/wm"); // As above, 3rd param is for non-root servlet deployments +wireMock.register(get(....)); // Equivalent to stubFor() +``` diff --git a/_site/docs/junit-extensions.md b/_site/docs/junit-extensions.md new file mode 100644 index 00000000..e08fb87e --- /dev/null +++ b/_site/docs/junit-extensions.md @@ -0,0 +1,103 @@ +--- +description: > + Manage one or more WireMock instances in your test cases with + WireMock's JUnit Rule +--- + +# Using WireMock in JUnit 4 and Vintage + +Manage one or more WireMock instances in your test cases with WireMock's JUnit Rule. + +The JUnit rule can handle the lifecycle for you, starting the server before +each test method and stopping it afterwards. + +!!! note + + Compatible with JUnit 4.x and JUnit 5 Vintage. + +## Basic usage + +Make WireMock available to your tests on its default port (8080), along with the WireMock rule: + +```java +@Rule +public WireMockRule wireMockRule = new WireMockRule(); +``` + +You can add an `Options` instance to the rule's constructor, to override +various settings. + +This example creates an `Options` implementation using the +`WireMockConfiguration.options()` builder: + +```java +@Rule +public WireMockRule wireMockRule = new WireMockRule(options().port(8888).httpsPort(8889)); +``` + +See [Configuration](./configuration.md) for additional details. + +## Unmatched requests + +The JUnit rule verifies that all requests received during the course of a test case are served by a configured stub, rather than the default 404. If any are not, the test fails and +throws a `VerificationException`. + +You can disable this behaviour by passing an extra constructor flag: + +```java +@Rule +public WireMockRule wireMockRule = new WireMockRule(options().port(8888), false); +``` + +## Other @Rule configurations + +With a bit more effort you can make the WireMock server continue to run +between test cases. This is easiest in JUnit 4.10: + +```java +@ClassRule +@Rule +public static WireMockClassRule wireMockRule = new WireMockClassRule(8089); +``` + +Unfortunately JUnit 4.11 and above prohibits `@Rule` on static members so a +slightly more verbose form is required, as in the following: + +```java +@ClassRule +public static WireMockClassRule wireMockRule = new WireMockClassRule(8089); + +@Rule +public WireMockClassRule instanceRule = wireMockRule; +``` + + +## Accessing the stubbing and verification DSL from the rule + +In addition to the static methods on the `WireMock` you can also +configure stubs etc. via the rule object directly. + +There are two advantages to this: +- it's a bit faster as it avoids sending +commands over HTTP. +- if you want to mock multiple services you can +declare a rule per service but not have to create a client object for +each. + +For example: + +```java +@Rule +public WireMockRule service1 = new WireMockRule(8081); + +@Rule +public WireMockRule service2 = new WireMockRule(8082); + +@Test +public void bothServicesDoStuff() { + service1.stubFor(get(urlEqualTo("/blah")).....); + service2.stubFor(post(urlEqualTo("/blap")).....); + + ... +} +``` diff --git a/_docs/junit-jupiter.md b/_site/docs/junit-jupiter.md similarity index 55% rename from _docs/junit-jupiter.md rename to _site/docs/junit-jupiter.md index 2645fb75..5214d5a5 100644 --- a/_docs/junit-jupiter.md +++ b/_site/docs/junit-jupiter.md @@ -1,20 +1,25 @@ --- -layout: docs -title: "JUnit 5+ Jupiter" -meta_title: Using WireMock's JUnit Jupiter extension | WireMock -description: WireMock includes a JUnit Jupiter extension which is used to manage the lifecycle and configuration of one or more WireMock instances in your test case. -redirect_from: - - "/docs/junit-5.html" +description: > + Use WireMock's JUnit Jupiter extension --- -The JUnit Jupiter extension simplifies running of one or more WireMock instances in a Jupiter test class. +# Using WireMock in JUnit 5 (Jupiter) -It supports two modes of operation - declarative (simple, limited configuration options) and programmatic (less simple, very configurable). -These are both explained in detail below. +Use WireMock's includes a JUnit Jupiter extension to: + +- simplify running of one or more WireMock instances from a Jupiter test class. +- manage the lifecycle and configuration of one or more WireMock instances in your test case. + +It supports two modes of operation: + +- declarative (simple, wiht limited configuration options). +- programmatic (less simple, and very configurable). + +These options are both explained in detail below. ## Basic usage - declarative -The extension can be applied to your test class declaratively by annotating it with `@WireMockTest`. This will run a single +Use `@WireMockTest`. to apply the extension to your test class declaratively by annotating it. This runs a single WireMock server, defaulting to a random port, HTTP only (no HTTPS). To get the running port number, base URL or a DSL instance you can declare a parameter of type `WireMockRuntimeInfo` @@ -43,14 +48,13 @@ public class DeclarativeWireMockTest { ### WireMock server lifecycle -In the above example a WireMock server will be started before the first test method in the test class and stopped after the -last test method has completed. +When the above example runs, the WireMock server starts up before the first test method in the test class, and stops after the last test method has completed. -Stub mappings and requests will be reset before each test method. +Stub mappings and requests are reset before each test method. ### Fixing the port number -If you need to run WireMock on a fixed port you can pass this via the `httpPort` parameter to the extension annotation: +To run WireMock on a fixed port, use the `httpPort` parameter to pass the extension annotation: ```java @WireMockTest(httpPort = 8080) @@ -61,7 +65,7 @@ public class FixedPortDeclarativeWireMockTest { ### Enabling HTTPS -You can also enable HTTPS via the `httpsEnabled` annotation parameter. By default a random port will be assigned: +You can also enable HTTPS using the `httpsEnabled` annotation parameter. By default a random port is assigned: ```java @WireMockTest(httpsEnabled = true) @@ -70,7 +74,7 @@ public class HttpsRandomPortDeclarativeWireMockTest { } ``` -But like with the HTTP port you can also fix the HTTPS port number via the `httpsPort` parameter: +As with the HTTP port, you can also fix the HTTPS port number using the `httpsPort` parameter: ```java @WireMockTest(httpsEnabled = true, httpsPort = 8443) @@ -118,16 +122,16 @@ public class ProgrammaticWireMockTest { ### Static vs. instance -In the above example, as with the declarative form, each WireMock server will be started before the first test method in the test class and stopped after the +In the above example, as with the declarative form, each WireMock server is started before the first test method in the test class and stopped after the last test method has completed, with a call to reset before each test method. -However, if the extension fields are declared at the instance scope (without the `static` modifier) each WireMock server will +However, if the extension fields are declared at the instance scope (without the `static` modifier) then each WireMock server will be created and started before each test method and stopped after the end of the test method. ### Configuring the static DSL -If you want to use the static DSL with one of the instances you have registered programmatically you can declare -this by calling `configureStaticDsl(true)` on the extension builder. The configuration will be automatically applied when the server is started: +If you want to use the static DSL with one of the instances you have registered programmatically, you can declare +this by calling `configureStaticDsl(true)` on the extension builder. The configuration is automatically applied when the server is started: ```java public class AutomaticStaticDslConfigTest { @@ -163,7 +167,7 @@ This behavior can be changed by calling `.failOnUnmatchedRequests(false)` on the ## Proxy mode The JUnit Jupiter extension can be configured to enable "proxy mode" which simplifies configuration and supports -[multi-domain mocking](../multi-domain-mocking/). +[multi-domain mocking](./multi-domain-mocking.md). ### Declarative @@ -172,98 +176,91 @@ HTTP client honours the JVM's proxy system properties, you can specify different ### Programmatic -Proxy mode can be enabled via the extension builder when using the programmatic form. +When using the programmatic form, enable proxy mode using the extension builder as in the following examples. -{% codetabs %} +=== "Declarative" -{% codetab Declarative %} + ```java + @WireMockTest(proxyMode = true) + public class JUnitJupiterExtensionJvmProxyDeclarativeTest { -```java -@WireMockTest(proxyMode = true) -public class JUnitJupiterExtensionJvmProxyDeclarativeTest { - - CloseableHttpClient client; - - @BeforeEach - void init() { - client = HttpClientBuilder.create() - .useSystemProperties() // This must be enabled for auto proxy config - .build(); - } - - @Test - void configures_jvm_proxy_and_enables_browser_proxying() throws Exception { - stubFor(get("/things") - .withHost(equalTo("one.my.domain")) - .willReturn(ok("1"))); - - stubFor(get("/things") - .withHost(equalTo("two.my.domain")) - .willReturn(ok("2"))); - - assertThat(getContent("http://one.my.domain/things"), is("1")); - assertThat(getContent("http://two.my.domain/things"), is("2")); - } - - private String getContent(String url) throws Exception { - try (CloseableHttpResponse response = client.execute(new HttpGet(url))) { - return EntityUtils.toString(response.getEntity()); - } - } -} -``` + CloseableHttpClient client; -{% endcodetab %} + @BeforeEach + void init() { + client = HttpClientBuilder.create() + .useSystemProperties() // This must be enabled for auto proxy config + .build(); + } -{% codetab Programmatic %} + @Test + void configures_jvm_proxy_and_enables_browser_proxying() throws Exception { + stubFor(get("/things") + .withHost(equalTo("one.my.domain")) + .willReturn(ok("1"))); -```java -public class JUnitJupiterProgrammaticProxyTest { + stubFor(get("/things") + .withHost(equalTo("two.my.domain")) + .willReturn(ok("2"))); - @RegisterExtension - static WireMockExtension wm = WireMockExtension.newInstance() - .proxyMode(true) - .build(); - - CloseableHttpClient client; - - @BeforeEach - void init() { - client = HttpClientBuilder.create() - .useSystemProperties() // This must be enabled for auto proxy config - .build(); - } - - @Test - void configures_jvm_proxy_and_enables_browser_proxying() throws Exception { - wm.stubFor(get("/things") - .withHost(equalTo("one.my.domain")) - .willReturn(ok("1"))); - - wm.stubFor(get("/things") - .withHost(equalTo("two.my.domain")) - .willReturn(ok("2"))); - - assertThat(getContent("http://one.my.domain/things"), is("1")); - assertThat(getContent("http://two.my.domain/things"), is("2")); - } - - private String getContent(String url) throws Exception { - try (CloseableHttpResponse response = client.execute(new HttpGet(url))) { - return EntityUtils.toString(response.getEntity()); - } - } -} -``` + assertThat(getContent("http://one.my.domain/things"), is("1")); + assertThat(getContent("http://two.my.domain/things"), is("2")); + } -{% endcodetab %} - -{% endcodetabs %} + private String getContent(String url) throws Exception { + try (CloseableHttpResponse response = client.execute(new HttpGet(url))) { + return EntityUtils.toString(response.getEntity()); + } + } + } + ``` + +=== "Programmatic" + + ```java + public class JUnitJupiterProgrammaticProxyTest { + + @RegisterExtension + static WireMockExtension wm = WireMockExtension.newInstance() + .proxyMode(true) + .build(); + + CloseableHttpClient client; + + @BeforeEach + void init() { + client = HttpClientBuilder.create() + .useSystemProperties() // This must be enabled for auto proxy config + .build(); + } + + @Test + void configures_jvm_proxy_and_enables_browser_proxying() throws Exception { + wm.stubFor(get("/things") + .withHost(equalTo("one.my.domain")) + .willReturn(ok("1"))); + + wm.stubFor(get("/things") + .withHost(equalTo("two.my.domain")) + .willReturn(ok("2"))); + + assertThat(getContent("http://one.my.domain/things"), is("1")); + assertThat(getContent("http://two.my.domain/things"), is("2")); + } + + private String getContent(String url) throws Exception { + try (CloseableHttpResponse response = client.execute(new HttpGet(url))) { + return EntityUtils.toString(response.getEntity()); + } + } + } + ``` ## Subclassing the extension -Like the JUnit 4.x rule, `WireMockExtension` can be subclassed in order to extend its behaviour by hooking into its lifecycle events. -This can also be a good approach for creating a domain-specific API mock, by adding methods to stub and verify specific calls. +To extend `WireMockExtension`, similar to what you can do in the JUnit 4.x rule, you can create subclasses by hooking into its lifecycle events. +This is also a good approach for creating a domain-specific API mock--by adding methods to stubs and verifying specific calls. + ```java public class MyMockApi extends WireMockExtension { @@ -294,8 +291,12 @@ public class MyMockApi extends WireMockExtension { } ``` -Note the constructor, which takes the extension's builder as its parameter. By making this public, you can pass an instance -of the builder in when constructing your extension as follows: +!!! note + + The constructor takes the extension's builder as its parameter. + +By making this public when constructing your extension, you can pass an instance +of the builder in, as follows: ```java @RegisterExtension @@ -306,5 +307,4 @@ of the builder in when constructing your extension as follows: .configureStaticDsl(true)); ``` -This will ensure that all parameters from the builder will be set as they would if you had constructed an instance of -`WireMockExtension` from it. +This ensures that all parameters from the builder will be set as they would if you had constructed an instance of `WireMockExtension` from it. diff --git a/_site/docs/mock-api-templates/README.md b/_site/docs/mock-api-templates/README.md new file mode 100644 index 00000000..94b1072a --- /dev/null +++ b/_site/docs/mock-api-templates/README.md @@ -0,0 +1,50 @@ +--- +description: > + API Templates library for WireMock and WireMock Cloud +--- + +# WireMock API templates library + +Using a existing template from the templates library, you can quickly get an API mock running on your local machine or in the cloud. + +Browse the [library.wiremock.org](https://library.wiremock.org) site to view an extensive set of mock API templates and examples +to use with both [WireMock](https://wiremock.org/) and [WireMock Cloud](https://wiremock.io). + + +[![Mock API Templates Library](https://library.wiremock.org/images/logo/template-library-wide.png)](https://library.wiremock.org/) + +## Use a template in you WireMock instance + +The library provides categories and search capabilities for you to use in locating approriate options. For each option that you choose: + +1. Click the _Download WireMock JSON_ button to download the JSON file. +2. Use the JSON file in your WireMock instance as indicated in [Using Templates](./usage.md). + +## Import templates into WireMock Cloud + + + +To quickly import a Mock API definition into your WireMock Cloud project, use the _Run in WireMock Cloud_ t + +## Editing and adding templates + +Template definitions can be found in another repository: +[wiremock/api-template-library](https://github.com/wiremock/api-template-library). + +If you would like to edit the existing template +or contribute a new mock API template, feel free to submit a pull request to +[wiremock/api-template-library](https://github.com/wiremock/api-template-library). +This is a public repository enables WireMock and WireMock Cloud users +to build their own Mock APIs based off a public template. + +You can add a template to the featured list by adding the `featured` tag in the metadata JSON. +If a template is somehow related to WireMock, please also use the `wiremock` tag. + +!!! note + + Please know that it can take some time to propagate changes to WireMock or WireMock Cloud. + +## References + +- [Templates Repository](https://github.com/wiremock/api-template-library) +- [WireMock Library Sources](https://github.com/wiremock/library.wiremock.org-sources) diff --git a/_docs/mock-api-templates/usage.md b/_site/docs/mock-api-templates/usage.md similarity index 63% rename from _docs/mock-api-templates/usage.md rename to _site/docs/mock-api-templates/usage.md index 1fc03706..cba3a35c 100644 --- a/_docs/mock-api-templates/usage.md +++ b/_site/docs/mock-api-templates/usage.md @@ -1,24 +1,22 @@ --- -layout: docs -title: Using Mock API Templates -meta_title: Using Mock API Templates -toc_rank: 66 -description: This guide explains how to run an API template after you've downloaded the JSON file from the library page +description: Run an API template after you've downloaded the JSON file from the library page. --- +# Using Mock API Templates + This guide explains how to run an API template after you've downloaded the JSON file from the library page. ## WireMock standalone JAR 1. Create a folder called `mappings` if one doesn't already exist in the directory containing the standalone JAR file. -2. Copy the downloaded JSON file into the `mappings` directory then e.g. -3. The JSON will be automatically loaded at startup, via the command line +2. Copy the downloaded JSON file into the `mappings` directory. +3. The JSON will be automatically loaded at startup, via the command line. ```bash -java -jar wiremock-jre8-standalone-{{ site.wiremock_version }}.jar +java -jar wiremock-jre8-standalone-{{ versions.wiremock_version }}.jar ``` -See [this page](../../standalone/java-jar) for general details on running WireMock standalone. +See [this page](./../standalone/java-jar.md) for general details on running WireMock standalone. ## In WireMock Docker @@ -31,15 +29,15 @@ docker run -it --rm \ -p 8080:8080 \ --name wiremock \ -v $PWD:/home/wiremock \ - wiremock/wiremock:{{ site.wiremock_version }} + wiremock/wiremock:{{ versions.wiremock_version }} ``` -See [this page](../../standalone/java-jar) for general details on running WireMock Docker. +See [this page](./../standalone/java-jar.md) for general details on running WireMock Docker. ## Plain Java If you're running WireMock embedded in a Java program or test suite -you can place the JSON file in a folder called `mappings` +you can place the JSON file in a folder called `mappings`, then set its parent as the WireMock server's root at startup. ```java @@ -49,7 +47,7 @@ WireMockServer wm = ); ``` -See [this](../../java-usage/) for general details on running WireMock in embedded Java. +See [this](./../java-usage.md) for general details on running WireMock in embedded Java. ## JUnit @@ -62,11 +60,11 @@ To do the same thing using the JUnit Jupiter extension: .build(); ``` -See [this](../../junit-jupiter/) for general details on running WireMock with JUnit 5+ Jupiter. +See [this](./../junit-jupiter.md) for general details on running WireMock with JUnit 5+ Jupiter. ## Pushing to a remotely running WireMock server -The mock API JSON can be pushed to a remotely running WireMock server via its [Admin API](../../standalone/administration). +The mock API JSON can be pushed to a remotely running WireMock server via its [Admin API](./../standalone/administration.md). For instance if the WireMock server is running on `wiremock.dev.mycompany.com` port 8080, you can POST the JSON file to it e.g. diff --git a/_docs/multi-domain-mocking.md b/_site/docs/multi-domain-mocking.md similarity index 74% rename from _docs/multi-domain-mocking.md rename to _site/docs/multi-domain-mocking.md index ecb8b420..6aca5877 100644 --- a/_docs/multi-domain-mocking.md +++ b/_site/docs/multi-domain-mocking.md @@ -1,33 +1,32 @@ --- -layout: docs -title: Multi-domain Mocking -meta_title: Multi-domain API Mocking with WireMock -toc_rank: 66 -description: A typical usage pattern is to run a WireMock instance per API you need to mock and configure your app to treat these instances as endpoints. +description: WireMock allows for several approaches to mocking APIs, including multi-domain mocking. --- -A typical usage pattern is to run a WireMock instance per API you need to mock and configure your app to treat these instances -as endpoints. +# Multi-domain API Mocking with WireMock -However, it's also possible to mock multiple APIs in a single instance via the use of the proxying and hostname matching features. -There are two advantages of this approach - lower overhead (memory, startup/shutdown time), and no need to modify each base URL in your app's -configuration. It can also avoid some of the headaches associated with binding to random ports. +While running a WireMock instance per API is typical, and requires that you mock and configure your app to treat the instances as endpoints, you can also mock multiple APIs in a single instance by the use of proxying and hostname matching features. -The key steps to enabling this configuration are: +There are advantages of this approach: -1. Enable browser (forward) proxying via `.enableBrowserProxying(true)` in the startup options. +- lower overhead (memory, startup/shutdown time). +- no need to modify each base URL in your app's configuration. +- avoid some of the headaches associated with binding to random ports. + +Key steps to enabling this configuration are: + +1. Enable browser (forward) proxying using `.enableBrowserProxying(true)` in the startup options. 2. Configure the JVM's proxy settings to point to the WireMock instance using `JvmProxyConfigurer`. The following sections detail how to achieve this in various deployment contexts. ## Configuring for JUnit Jupiter -The simplest way to enable this mode if you're using JUnit Jupiter it to toggle it on via the `WireMockExtension`. See the -[Junit Jupiter Proxy Mode](../junit-jupiter#proxy-mode) for details. +The simplest way to enable this mode if you're using JUnit Jupiter it to toggle it on using the `WireMockExtension`. See the +[Junit Jupiter Proxy Mode](./junit-jupiter.md#proxy-mode) for details. ## Configuring for JUnit 4.x -To use this mode with the JUnit 4.x rule we: +To use this mode with the JUnit 4.x rule: 1. Create the rule as usual with browser proxying enabled. 2. Ensure our HTTP client (the one used by our app to talk to the API we're mocking) honours the system properties relating to proxy servers. @@ -80,10 +79,10 @@ public class MultiDomainJUnit4Test { ## Configuring for other Java -To use this mode from Java code we: +To use this mode from Java code: 1. Create and start a `WireMockServer` instance with browser proxying enabled. -2. Ensure our HTTP client (the one used by our app to talk to the API we're mocking) honours the system properties relating to proxy servers +2. Ensure our HTTP client (the one used by our app to talk to the API we're mocking) honours the system properties relating to proxy servers. 3. Set the proxy properties using `JvmProxyConfigurer` before each bit of work and unset them afterwards. 4. Specify the host name we're targeting when creating stubs. diff --git a/_site/docs/overview.md b/_site/docs/overview.md new file mode 100644 index 00000000..8aeaee84 --- /dev/null +++ b/_site/docs/overview.md @@ -0,0 +1,64 @@ +--- +title: Overview +meta_title: WireMock Overview and Basics +toc_rank: 1 +description: Top-level overview of WireMock +--- + +**WireMock** is a popular open-source tool for API mock testing +with over 5 million downloads per month. +It can help you to: + +- create environments for testing and development that are stable while isolating yourself from third parties. + + —and— + +- simulate APIs that don't exist yet. + +Started in 2011 as a Java library by [Tom Akehurst](https://github.com/tomakehurst), +now WireMock spans across multiple programming languages and technology stacks. + +WireMock can run, in many languages, as: + +- a library. +- a client wrapper. +- a standalone server. + +There is a large community behind the project and its ecosystem. + +WireMock supports you in creating mock APIs: + +- in code, by making use of its REST API. +- as JSON objects. +- by recording HTTP traffic proxied to another destination. + +WireMock has a rich matching system, allowing you to match any part of an incoming request against complex and precise criteria. +In addition, you can dynamically generate responses of any complexity using its Handlebars-based templating system. +Finally, WireMock makes it easy to use its numerous extension points and its comprehensive APIs, for integrating into your workflow. + +## Key features + +- HTTP response stubbing, matchable on URL, header and body content patterns +- Request verification +- Runs in unit tests, as a standalone process or as a WAR app +- Record/playback of stubs +- Configurable response delays and Fault injection +- Per-request conditional proxying +- Browser proxying for request inspection and replacement +- Stateful behaviour simulation + +All the features are configurable using fluent Java API and JSON files, +or through JSON over HTTP for the standalone service. + +## Getting Started + +Check out WireMock Quick-starts and tutorials [here](./getting-started.md). + +## WireMock Ecosystem + +The WireMock ecosystem contains implementations and adapters for numerous languages and test frameworks. +It supports adapters and implementations for several technology stacks, including Python, .NET, Golang, and Rust. +For the JVM ecosystem, there are libraries for Spring Boot, Quarkus, Kotlin, Testcontainers, and others. +WireMock can also run on Android, and will soon provide official gRPC and GraphQL adapters. + +You can learn more about [WireMock Ecosystem here](https://github.com/wiremock/ecosystem). diff --git a/_docs/participate.md b/_site/docs/participate.md similarity index 70% rename from _docs/participate.md rename to _site/docs/participate.md index 6950c835..63fd770f 100644 --- a/_docs/participate.md +++ b/_site/docs/participate.md @@ -1,39 +1,35 @@ --- -layout: docs -title: Participate in WireMock -meta_title: How to participate in the WireMock Community -redirect_from: -- "/contributing.html" -- "/participate.html" description: > - Regardless of your expertise and time you could dedicate, there're opportunities to participate - in the project and its community! + opportunities to participate in the WireMock project and community! --- +# Participate in the WireMock community + WireMock exists and continues to thrive due to the efforts of over 150 contributors, and we continue to welcome contributions to its evolution. -Regardless of your expertise and time you could dedicate, there're opportunities to participate and help the project! + +You can avail yourself of opportunities to participate in the project regardless of your expertise and amount of time you can dedicate. ## Ways to contribute -You can help make WireMock a better tool and community in a number of ways: +You can choose from numerous opportunites to help make WireMock a better tool: -- Spread the word about WireMock, share your stories and contributions -- Help other WireMock users, e.g. by sharing your expertise or answering questions on community channels -- Write or improve documentation -- Raise an issue if you discover a bug -- Contribute new features, bug fixes or enhancements -- Improve WireMock user and developer experience +- Spread the word about WireMock, share your stories and contributions. +- Help other WireMock users, e.g. by sharing your expertise or answering questions on community channels. +- Write or improve documentation. +- Raise an issue if you discover a bug. +- Contribute new features, bug fixes or enhancements. +- Improve WireMock user and developer experience. - Create cool artwork! ## Quick Start We try to make contributing to WireMock easy for everyone, and we minimize the entry bar where possible. -Right now there are now contributor license agreements or anything else that would +Right now there are no contributor license agreements or anything else that would be an additional obstacle. -1. Join the [WireMock Slack](http://slack.wiremock.org/), +1. Join the [WireMock Slack](../community/slack.md), especially the `#help-contributing` channel that is dedicated to help the newcomers. 2. Check out the _Contributing Guide_ below. It describes all ways to contribute 3. Just do it! @@ -41,18 +37,17 @@ be an additional obstacle. ## Contributing Guide Our main resource is the [Contributor Guide](https://github.com/wiremock/community/tree/main/contributing). -As well as other community materials, +Along with other community materials, we keep it on GitHub in the [wiremock/community](https://github.com/wiremock/community) so everyone can easily access and edit the materials. Note that many repositories and areas have specialized contributor guidelines that could also help. ## Need help? -If you want to contribute in any way to WireMock itself or its ecosystem and got stuck, -do not hesitate to ask on the `#help-contributing` channel on the [WireMock Slack](http://slack.wiremock.org/). -The sole purpose of this channel is to resolve obstacles and route any questions -regarding the contributions. -From technical questions to permissions and blog post draft reviews, +If you want to contribute in any way to WireMock or its ecosystem and get stuck, +do not hesitate to ask on the `#help-contributing` channel on the [WireMock Slack](../community/slack.md). +The sole purpose of this channel is to resolve obstacles and route any questions that arise regarding the contributions. +From technical questions, to permissions, to blog post draft reviews, any query is welcome! Some activities like Advocacy and Documentation have their own channels on Slack, @@ -62,7 +57,7 @@ and you can use them as well. ### Do you accept money donations? -Short answer: no. But there are ways to support the project's evolution financially< +Short answer: **NO**, but there are ways to support the project's evolution financially. At the moment, we do NOT accept money donations. Time is the most precious resource for an open-source project, diff --git a/_site/docs/protocols/README.md b/_site/docs/protocols/README.md new file mode 100644 index 00000000..13039ee2 --- /dev/null +++ b/_site/docs/protocols/README.md @@ -0,0 +1,18 @@ +--- +description: WireMock supports not just REST API over HTTP, but many other protocols. +--- + +# Using protocols in WireMock + +## Supported Protocols + +WireMock supports the following protocols: + +- HTTP - Plain HTTP, REST API and other protocols that are compatible with it +- [HTTPs](../https.md) - Plain HTTPs, REST API and other protocols that are compatible with it +- [gRPC](../grpc.md) +- [GraphQL](../solutions/graphql.md) + +## Protocol Add-ons + +- [Webhooks and Callbacks](../webhooks-and-callbacks.md) diff --git a/_docs/proxying.md b/_site/docs/proxying.md similarity index 83% rename from _docs/proxying.md rename to _site/docs/proxying.md index 4bd01be1..22500a33 100644 --- a/_docs/proxying.md +++ b/_site/docs/proxying.md @@ -1,24 +1,20 @@ --- -layout: docs -title: Proxying -meta_title: Proxying and proxy stub mappings | WireMock -toc_rank: 65 -redirect_from: "/proxying.html" -description: Proxy responses are defined in exactly the same manner as stubs, meaning that the same request matching criteria can be used. +description: Working with WireMock proxies. --- +# Proxying and proxy stub mappings + WireMock has the ability to selectively proxy requests through to other hosts. This supports a proxy/intercept setup where requests are by default proxied to another (possibly real, live) service, but where specific stubs are configured these are returned in place of the remote service's response. Responses that the live service can't be forced to generate on demand can thus be injected for testing. Proxying also -supports [record and playback](../record-playback/). +supports [record and playback](./record-playback.md). # Proxy stub mappings -Proxy responses are defined in exactly the same manner as stubs, meaning -that the same request matching criteria can be used. +Define proxy responses in exactly the same manner as stubs&endash;meaning that the same request matching criteria can be used. The following code will proxy all GET requests made to `http://:/other/service/.*` to @@ -49,7 +45,7 @@ The JSON equivalent would be: The proxy/intercept pattern described above is achieved by adding a low priority proxy mapping with a broad URL match and any number of higher -priority stub mappings e.g. +priority stub mappings. For example: ```java // Low priority catch-all proxies to otherhost.com by default @@ -89,12 +85,12 @@ or } ``` -Requests using the above path will be forwarded +Requests using the above path are forwarded to `http://otherhost.com/approot/doc/123` # Additional headers -It is possible to configure the proxy to add headers before forwarding +You can configure the proxy to add headers before forwarding the request to the destination: ```java @@ -122,32 +118,32 @@ or } ``` -You can also add response headers via the same method as for non-proxy responses (see [Stubbing](../stubbing/)). +You can also add response headers via the same method as for non-proxy responses (see [Stubbing](./stubbing.md)). ## Standalone shortcut It is possible to start the standalone running with the catch-all stub -already configured: +already configured. -Then it's simply a case of adding your stub mapping `.json` files under `mappings` as usual (see [Stubbing](../stubbing/)). +Then it's simply a case of adding your stub mapping `.json` files under `mappings` as usual (see [Stubbing](./stubbing.md)). ## Running as a browser proxy -WireMock can be made to work as a forward (browser) proxy. +WireMock can also be made to work as a forward (browser) proxy. One benefit of this is that it supports a website-based variant of the proxy/intercept pattern described above, allowing you to modify specific AJAX requests or swap out CSS/Javascript files. -To configure your browser to proxy via WireMock, first start WireMock with browser proxying enabled: +To configure your browser to proxy using WireMock, first start WireMock with browser proxying enabled: ```bash -$ java -jar wiremock-standalone-{{ site.wiremock_version }}.jar --enable-browser-proxying --port 9999 +$ java -jar wiremock-standalone-{{ versions.wiremock_version }}.jar --enable-browser-proxying --port 9999 ``` Then open your browser's proxy settings and point them to the running server: -Firefox proxy screenshot +Firefox proxy screenshot -After that, you can configure stubs as described in [Running Standalone](../running-standalone#configuring-wiremock-using-the-java-client) and then browse to a website. Any resources fetched whose requests are matched by stubs you have configured will be overridden by the stub's response. +After that, you can configure stubs as described in [Running Standalone](./standalone/java-jar.md#configuring-wiremock-using-the-java-client) and then browse to a website. Any resources fetched whose requests are matched by stubs you have configured will be overridden by the stub's response. So for instance, say you're visiting a web page that fetches a user profile via an AJAX call to `/users/12345.json` and you wanted to test how it responded to a server unavailable response. You could create a stub like this and the response from the server would be swapped for a 503 response: @@ -160,7 +156,7 @@ stubFor(get(urlEqualTo("/users/12345.json")) Also, we can enable/disable pass through unmatched requests to the target indicated by the original requests by enabling/disabling proxyPassThrough flag. By default, flag is set to true. -This flag can be enabled/disabled at startup either by passing CLI option while running jar as described in [Running Standalone](../running-standalone#command-line-options) or by passing as options in Java client as shown below. +This flag can be enabled/disabled at startup either by passing CLI option while running jar as described in [Running Standalone](./standalone/java-jar.md#command-line-options) or by passing as options in Java client as shown below. ```java WireMockServer wireMockServer = new WireMockServer(options().proxyPassThrough(false)); @@ -168,7 +164,8 @@ WireMockServer wireMockServer = new WireMockServer(options().proxyPassThrough(fa We can also update this flag without WireMock restart either by using Admin API as described in [API section](../api/#tag/System/paths/~1__admin~1settings/post) if we are running as standalone or by updating the global settings in Java client. -Json payload to update via admin API +Json payload to update via admin API: + ```json { ... @@ -232,13 +229,13 @@ This would present a substantial security risk, so by default WireMock will veri You can trust specific hosts as follows: ```bash -$ java -jar wiremock-standalone-{{ site.wiremock_version }}.jar --enable-browser-proxying --trust-proxy-target localhost --trust-proxy-target dev.mycorp.com +$ java -jar wiremock-standalone-{{ versions.wiremock_version }}.jar --enable-browser-proxying --trust-proxy-target localhost --trust-proxy-target dev.mycorp.com ``` or if you're not interested in security you can trust all hosts: ```bash -$ java -jar wiremock-standalone-{{ site.wiremock_version }}.jar --enable-browser-proxying --trust-all-proxy-targets +$ java -jar wiremock-standalone-{{ versions.wiremock_version }}.jar --enable-browser-proxying --trust-all-proxy-targets ``` Additional trusted public certificates can also be added to the keystore @@ -282,8 +279,8 @@ curl --proxy-insecure -x https://localhost:44300 -k 'https://www.example.com/' #### Security concerns -Acting as a man in the middle for HTTPS traffic has to be done at your own risk. -Whilst best efforts have been taken to reduce your risk, you should be aware you are granting WireMock unencrypted access to all HTTPS traffic proxied via WireMock, +Acting as a "man in the middle" for HTTPS traffic introduces risk. +Whilst best efforts have been taken to reduce your risk, you should be aware you are granting WireMock unencrypted access to all HTTPS traffic proxied using WireMock, and that as part of its normal operation WireMock may store that traffic, in memory or on the file system, or print it to the console. If you choose to trust the root CA certificate WireMock is using, or you choose to bypass HTTPS verification for some or all target servers, you should understand the risk involved. @@ -291,7 +288,7 @@ you should understand the risk involved. ## Proxying via another proxy server If you're inside a network that only permits HTTP traffic out to the -internet via an opaque proxy you might wish to set up proxy mappings +internet with an opaque proxy you might wish to set up proxy mappings that route via this server. This can be configured programmatically by passing a configuration object to the constructor of `WireMockServer` or the JUnit rules like this: @@ -304,8 +301,7 @@ WireMockServer wireMockServer = new WireMockServer(options() ## Proxying to a target server that requires client certificate authentication -WireMock's proxy client will send a client certificate if the target -service requires it and a trust store containing the certificate is +If the target service requires it, WireMock's proxy client sends a client certificate, and a trust store containing the certificate is configured: ```java @@ -315,4 +311,4 @@ public WireMockRule wireMockRule = new WireMockRule(wireMockConfig() .trustStorePassword("mostsecret")); // Defaults to "password" if omitted ``` -See [Running as a Standalone Process](../running-standalone/) for command line equivalent. +See [Running as a Standalone Process](./standalone/java-jar.md) for command line equivalent. diff --git a/_docs/quickstart/java-junit.md b/_site/docs/quickstart/java-junit.md similarity index 54% rename from _docs/quickstart/java-junit.md rename to _site/docs/quickstart/java-junit.md index d9bc384a..51445177 100644 --- a/_docs/quickstart/java-junit.md +++ b/_site/docs/quickstart/java-junit.md @@ -1,76 +1,73 @@ --- -layout: docs -title: "Quick Start: API Mocking with Java and JUnit 4" -meta_title: "API Mocking QuickStart with Java and JUnit 4 | WireMock" -description: "Shows how to write your API Client first test with WireMock and JUnit" +description: + A simple test API Client with WireMock and JUnit 4 --- -In this guide we will write an API Unit test with WireMock and JUnit 4. +# Quick Start: A simple test client + +This topic demonstrates how to write a simple API Unit test with WireMock and JUnit 4, for an ongoing project. ## Prerequisites - Java 11 or 17 -- Maven or Gradle, recent versions +- Recent version of Maven or Gradle - A Java project, based on Maven and Gradle -- A Unit test file which we will use as a playground +- A Unit test file (example below) to use as a playground -## Add WireMock Dependency to your project +## Add WireMock Dependencies to your project -WireMock is distributed via Maven Central and can be included in your project using common build tools' dependency management. -To add the standard WireMock JAR as a project dependency, put the dependencies below section of your build file. +Maven Central ditributes WireMock, which can be included in your project using common build tools' dependency management. -In our test, we will also use AssertJ to verify the responses. -To send the requests, we will use the embedded HTTP client available in Java 11+. -If you want to add a Java 1.8 test, you will need to add an external HTTP Client implementation -like [Apache HttpClient](https://hc.apache.org/httpcomponents-client-5.2.x/#). +In this test use: -{% codetabs %} - -{% codetab Maven %} - -```xml - - org.wiremock - wiremock - {{ site.wiremock_version }} - test - - - org.assertj - assertj-core - 3.24.2 - test - -``` +- AssertJ to verify the responses. +- the embedded HTTP client available in Java 11+ to send the requests. -{% endcodetab %} +To add the standard WireMock JAR as a project dependency, you can use one of the following dependencies snippets in your build file: -{% codetab Gradle Groovy %} +=== "Maven" -```groovy -testImplementation "org.wiremock:wiremock:{{ site.wiremock_version }}" -testImplementation "org.assertj:assertj-core:3.24.2" -``` + ```xml + + org.wiremock + wiremock + {{ versions.wiremock_version }} + test + + + org.assertj + assertj-core + 3.24.2 + test + + ``` -{% endcodetab %} +=== "Gradle Groovy" -{% endcodetabs %} + ```groovy + testImplementation "org.wiremock:wiremock:{{ versions.wiremock_version }}" + testImplementation "org.assertj:assertj-core:3.24.2" + ``` -## Add the WireMock rule +To support using a Java 1.8 test, you must add an external HTTP Client implementation +like [Apache HttpClient](https://hc.apache.org/httpcomponents-client-5.2.x/#). -WireMock ships with some JUnit rules to manage the server's lifecycle -and setup/tear-down tasks. -To use WireMock's fluent API add the following import: +## Add the WireMock rule + +To use WireMock's fluent API, add the following import: ```java import static com.github.tomakehurst.wiremock.client.WireMock.*; ``` -To automatically start and stop WireMock per-test case, add -the following to your test class (or a superclass of it): +WireMock ships with some JUnit rules to manage the server's lifecycle +and setup/tear-down tasks. + +To automatically start and stop WireMock per test case, add +the following, either to your test class, or a superclass of it: ```java @Rule @@ -79,14 +76,14 @@ public WireMockRule wireMockRule = new WireMockRule(8089); // No-args constructo ## Write a test -Now you're ready to write a test case like this: +Now you're ready to write a test case like this example: ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -... +// ... @Test public void exampleTest() { @@ -116,32 +113,34 @@ public void exampleTest() { ## Extend the test -For a bit more control over the settings of the WireMock server created -by the rule you can pass a fluently built Options object to either rule's constructor. -Let's change the port numbers as an example. +For more control over the WireMock server settings that the rule creates, +you can pass a fluently built Options object to the rule's constructor. + +In the following example, we change the port numbers. ### Change the port numbers ```java import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -... +///... @Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8089).httpsPort(8443)); ``` -### Random port numbers +### Use random port numbers You can have WireMock (or more accurately the JVM) pick random, free HTTP and HTTPS ports. -It is a great idea if you want to run your tests concurrently. + +This works well when running your tests concurrently. ```java @Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort()); ``` -Then find out which ports to use from your tests as follows: +Then find out which ports to use from your tests, as follows: ```java int port = wireMockRule.port(); @@ -150,7 +149,7 @@ int httpsPort = wireMockRule.httpsPort(); ## Further reading -- For more details on verifying requests and stubbing responses, see [Stubbing](../../stubbing) and [Verifying](../../verifying/) -- For more information on the JUnit rules see [The JUnit 4 Rule](../../junit-4/). +- For more details on verifying requests and stubbing responses, see [Stubbing](./../stubbing.md) and [Verifying](./../verifying.md) +- For more information on the JUnit rules see [The JUnit 4 Rule](./../junit-extensions.md). - For many more examples of JUnit tests check out the [WireMock's own acceptance tests](https://github.com/wiremock/wiremock/tree/master/src/test/java/com/github/tomakehurst/wiremock) diff --git a/_docs/record-playback-legacy.md b/_site/docs/record-playback-legacy.md similarity index 50% rename from _docs/record-playback-legacy.md rename to _site/docs/record-playback-legacy.md index 1eb13421..7356d737 100644 --- a/_docs/record-playback-legacy.md +++ b/_site/docs/record-playback-legacy.md @@ -1,25 +1,21 @@ --- -layout: docs -title: Record and Playback (Legacy) -meta_title: Record and Playback (Legacy) | WireMock -toc_rank: 71 -description: Create stub mappings by recording them while you send requests. This can be used to quickly capture a collection of responses from a real service then use them offline in your tests. +description: > + Quickly capture stub mappings and response body content using WireMock's record and playback. --- -**WireMock has the ability to create stub mappings by recording them -while you send requests. This can be used to quickly capture a -collection of responses from a real service then use them offline in -your tests.** +# Record and Playback (Legacy) + +You can quickly capture a collection of stub mappings and response body content using WireMock's record and playback. ## Recording -Recording is done by starting the standalone runner like this: +To start recording, start the standalone runner as in the following: ```bash -$ java -jar wiremock-standalone-{{ site.wiremock_version }}.jar --proxy-all="http://search.twitter.com" --record-mappings --verbose +$ java -jar wiremock-standalone-{{ versions.wiremock_version }}.jar --proxy-all="http://search.twitter.com" --record-mappings --verbose ``` -Once it's started you send requests to it as if it was the remote +Once it's started, send requests to it as if it was the remote service: ```bash @@ -34,14 +30,13 @@ latter for the body content. ### Capturing request headers Optionally, you can record request headers so that your stub mappings -will match on those in addition to URL, method and body (if a POST or -PUT). This is done by adding an extra parameter to the command line e.g. +match on those in addition to URL, method and body (if a POST or +PUT). This is done by adding an extra parameter to the command line, like `--match-headers="Accept,Content-Type"` -> **note** -> -> The recorder will ignore any request matching one it has already -> captured. +!!! note + + The recorder ignores any request matching one it has already captured. ## Playback diff --git a/_site/docs/record-playback.md b/_site/docs/record-playback.md new file mode 100644 index 00000000..c3ca8c61 --- /dev/null +++ b/_site/docs/record-playback.md @@ -0,0 +1,384 @@ +--- +description: > + Create and record stub mappings +--- + +# Record and Playback an API to Create a Mock + +WireMock can create stub mappings from requests it has received. Combined with its proxying feature this allows you to "record" +stub mappings from interaction with existing APIs. + +The following two approaches available, and are described in detail below: + +- Recording. +- Snapshotting. + +The same results can be achieved with either approach, you can choose the best +fit with your workflow and preferences. However, if you're new to WireMock, recording is the simplest option for getting started. + +## Quick start + +To get started with WireMock's recorder, use the simple web UI provided: + +1. Start an instance of [WireMock running standalone](./standalone.md). +2. Visit the recorder UI page at [http://localhost:8080/\_\_admin/recorder](http://localhost:8080/__admin/recorder) +(assuming you started WireMock on the default port of 8080). + +![Recorder UI](../images/recorder-screenshot.png) + +3. Enter the target URL from which to record and click *Record*. You can use `http://examples.wiremockapi.cloud` to try it out. +4. Make a request through WireMock to the target API so that it can be recorded. If you're using the example URL, you can generate a request using curl: + +```bash +$ curl http://localhost:8080/recordables/123 +``` +5. Click *stop*. + +WireMock snads a message indicating the stub creation, and also stores a file (created during startup), named something like `recordables_123-40a93c4a-d378-4e07-8321-6158d5dbcb29.json`, for eahc new stub, in the `_admoin/mappings` directory. You can find the mapping at [http://localhost:8080/\_\_admin/mappings](http://localhost:8080/__admin/mappings). + +Requesting the same URL again (for firm proof, consider disabling your wifi first) will now serve the recorded result: + +``` +$ curl http://localhost:8080/recordables/123 + +{ + "message": "Congratulations on your first recording!" +} +``` + +!!! warning + + Stub mappings will only be created at the point that the recording is stopped. + +!!! note + + "Playback" doesn't require any explicit action. Recorded stubs will start being served immediately after recording is stopped. + +## Recording + +Recording can also be started and stopped via WireMock's JSON API and Java DSL. + +=== "Java" + + ```java + // Static DSL + WireMock.startRecording("http://examples.wiremockapi.cloud/"); + List recordedMappings = WireMock.stopRecording(); + + // Client instance + WireMock wireMockClient = new WireMock(8080); + wireMockClient.startStubRecording("http://examples.wiremockapi.cloud/"); + List recordedMappings = wireMockClient.stopStubRecording(); + + // Directly + WireMockServer wireMockServer = new WireMockServer(); + wireMockServer.start(); + wireMockServer.startRecording("http://examples.wiremockapi.cloud/"); + List recordedMappings = wireMockServer.stopRecording(); + ``` + +=== "API" + + ```json + POST /__admin/recordings/start + { + "targetBaseUrl": "http://examples.wiremockapi.cloud/" + } + ``` + + ``` + POST /__admin/recordings/stop + ``` + +## Snapshotting + +Snapshotting is effectively "recording after the fact". Rather than starting recording at a specific point, snapshotting allows you to convert requests already received by WireMock +into stub mappings. + +An implication of this order of events is that if you want to record an external API, you'll need to have configured proxying before you start generating traffic. +See [Proxying](./proxying.md) for details on proxy configuration, but in summary this can be achieved by creating a proxy mapping via the API or Java DSL: + +=== "Java" + + ```java + stubFor(proxyAllTo("http://examples.wiremockapi.cloud/").atPriority(1)); + ``` + +=== "API" + + ```json + POST /__admin/mappings + { + "priority": 1, + "request": { + "method": "ANY" + }, + "response": { + "proxyBaseUrl" : "http://examples.wiremockapi.cloud/" + } + } + ``` + +!!! note + + You can still take snapshots without a proxy stub configured. + You might want to do this e.g. if you want to capture requests made by your application under test that you can then modify by hand to provide the appropriate responses. + +Once you have made some requests through WireMock (which you can view under http://localhost:8080/\_\_admin/requests) you can trigger a snapshot to generate stub mappings: + +=== "Java" + + ```java + // Static DSL + List recordedMappings = WireMock.snapshotRecord(); + + // Client instance + WireMock wireMockClient = new WireMock(8080); + List recordedMappings = wireMockClient.takeSnapshotRecording(); + + // Directly + WireMockServer wireMockServer = new WireMockServer(); + wireMockServer.start(); + List recordedMappings = wireMockServer.snapshotRecord(); + ``` + +=== "API" + + ``` + POST /__admin/recordings/snapshot + {} + ``` + +## Customising your recordings + +The default recording behaviour can be tweaked in a number of ways by passing a "record spec" to the record or snapshot actions. + +In Java you use the DSL, and when using the API, send a POST to `_admin/recordings/start` + + +=== "Java" + + ```java + startRecording( + recordSpec() + .forTarget("http://examples.wiremockapi.cloud/") + .onlyRequestsMatching(getRequestedFor(urlPathMatching("/api/.*"))) + .captureHeader("Accept") + .captureHeader("Content-Type", true) + .extractBinaryBodiesOver(10240) + .extractTextBodiesOver(2048) + .makeStubsPersistent(false) + .ignoreRepeatRequests() + .transformers("modify-response-header") + .transformerParameters(Parameters.one("headerValue", "123")) + .matchRequestBodyWithEqualToJson(false, true) + ); + ``` + +=== "API" + + ```json + POST /__admin/recordings/start + { + "targetBaseUrl" : "http://examples.wiremockapi.cloud/", + "filters" : { + "urlPathPattern" : "/api/.*", + "method" : "GET", + "allowNonProxied": true + }, + "captureHeaders" : { + "Accept" : { }, + "Content-Type" : { + "caseInsensitive" : true + } + }, + "requestBodyPattern" : { + "matcher" : "equalToJson", + "ignoreArrayOrder" : false, + "ignoreExtraElements" : true + }, + "extractBodyCriteria" : { + "textSizeThreshold" : "2048", + "binarySizeThreshold" : "10240" + }, + "persist" : false, + "repeatsAsScenarios" : false, + "transformers" : [ "modify-response-header" ], + "transformerParameters" : { + "headerValue" : "123" + } + } + ``` + +The same specification can also be passed when snapshotting: + +=== "Java" + + ```java + snapshotRecord( + recordSpec() + .onlyRequestsMatching(getRequestedFor(urlPathMatching("/api/.*"))) + .onlyRequestIds(singletonList(UUID.fromString("40a93c4a-d378-4e07-8321-6158d5dbcb29"))) + .allowNonProxied(true) + .captureHeader("Accept") + .captureHeader("Content-Type", true) + .extractBinaryBodiesOver(10240) + .extractTextBodiesOver(2048) + .makeStubsPersistent(false) + .ignoreRepeatRequests() + .transformers("modify-response-header") + .transformerParameters(Parameters.one("headerValue", "123")) + .chooseBodyMatchTypeAutomatically() + ); + ``` + +=== "API" + + ```json + POST /__admin/recordings/snapshot + { + "filters" : { + "urlPathPattern" : "/api/.*", + "method" : "GET", + "ids" : [ "40a93c4a-d378-4e07-8321-6158d5dbcb29" ] + }, + "captureHeaders" : { + "Accept" : { }, + "Content-Type" : { + "caseInsensitive" : true + } + }, + "requestBodyPattern" : { + "matcher" : "equalToJson", + "ignoreArrayOrder" : false, + "ignoreExtraElements" : true + }, + "extractBodyCriteria" : { + "textSizeThreshold" : "2 kb", + "binarySizeThreshold" : "1 Mb" + }, + "outputFormat" : "FULL", + "persist" : false, + "repeatsAsScenarios" : false, + "transformers" : [ "modify-response-header" ], + "transformerParameters" : { + "headerValue" : "123" + } + } + ``` + +The following sections will detail each parameter in turn: + +### Filtering + +`filters` supports selection of requests to be recorded according to the same [request matcher](./request-matching.md) format used elsewhere in WireMock. + +Additionally, when snapshotting the `ids` parameter allows specific serve events to be selected by ID. + +The `allowNonProxied` attribute, when set to `true` will cause requests that did not get proxied to a target service to be recorded/snapshotted. This is useful if +you wish to "teach" WireMock your API by feeding it requests from your app that initially don't match a stub, then snapshotting to generate the correct stubs. + +### Capturing request headers + +You may want your recorded stub mappings to match on one or more specific request headers. +For instance if you're intending to record from an API that supports both XML and JSON responses via content negotiation, +then you will need to capture the value of the `Accept` header sent in each request. + +The `captureHeaders` attribute allows you to specify a map of header names to match parameter objects. Currently the only parameter +available is `caseInsensitive`, which defaults to false if absent. + +### Body files extraction size criteria + +By default, recorded response bodies will be included directly in the stub mapping response part, via the `body` attribute for text or `base64Body` for binary content. + +However, this can be overridden by setting the `textSizeThreshold` and `binarySizeThreshold` values under `extractBodyCriteria`. +The size values are of type string, and support friendly syntax for specifying the order of magnitude e.g. + +``` +"56 kb" +"10 Mb" +"18.2 GB" +"255" // bytes when no magnitude specified +``` + +In the Java DSL these values are specified as a `long` number of bytes: + +```java +recordSpec().extractBinaryBodiesOver(204800) +``` + +### Output format + +By default the stop recording and snapshot API calls will return the full JSON of all mappings captured. +If you only require the IDs of captured stubs you can specify: + +```json +{ + "outputFormat": "IDS" +} +``` + +### Persist stubs + +By default generated stubs will be set to persistent, meaning that they will be saved to the file system +(or other back-end if you've implemented your own `MappingsSource`) and will survive calls to reset mappings to default. + +Setting `persist` to `false` means that stubs will not be saved and will be deleted on the next reset. + +### Repeats as scenarios + +What happens when the recorder sees two identical requests that produce different results? + +There are two ways to handle this. Setting `repeatsAsScenarios` to `false` means that after the first request, subsequent identical ones will be ignored. + +However, when set to `true` (which is the default if omitted), multiple identical requests will be added to a [Scenario](./stateful-behaviour.md), meaning that when +playing back, a series of requests matching this stub will yield the same series of responses captured during recording. If more requests are made after the end of the series +is reached, the last response will continue to be returned. + +### Transforming generated stubs + +If you need even more control over how your recorded stubs are generated, you can write one or more custom transformers that will be applied to stubs as they are captured. + +A transformer is an implementations of `StubMappingTransformer` and needs to be registered when starting WireMock as described in [Extending WireMock](./extending-wiremock.md). + +Transformer implementations supply a name, and this is used to identify them in the `transformers` parameter e.g. + +```json +"transformers": ["transformer-one", "transformer-two"] +``` + +As with other types of WireMock extension, parameters can be supplied. The exact parameters required depend on the specifics of the transformer (or it may not require any). + +```json +"transformerParameters": { + "simpleParam1": "One", + "arrayParam2": [1, 2, 3], + ... +} +``` + +### Request body matching + +By default, the body match operator for a recorded stub is based on the `Content-Type` header of the request. For MIME types containing the string "json", the operator will be `equalToJson` with both the `ignoreArrayOrder` and `ignoreExtraElements` options set to `true`. For MIME types containing `xml`, it will use `equalToXml`. Otherwise, it will use `equalTo` with the `caseInsensitive` option set to `false`. + +This behavior can be customized via the `requestBodyPattern` parameter, which accepts a `matcher` (either `equalTo`, `equalToJson`, `equalToXml`, or `auto`) and any relevant matcher options (`ignoreArrayOrder`, `ignoreExtraElements`, or `caseInsensitive`). For example, here's how to preserve the default behavior, but set `ignoreArrayOrder` to `false` when `equalToJson` is used: + +```json +"requestBodyPattern" : { + "matcher": "auto", + "ignoreArrayOrder" : false + } +``` + +If you want to always match request bodies with `equalTo` case-insensitively, regardless of the MIME type, use: + +```json +"requestBodyPattern" : { + "matcher": "equalTo", + "caseInsensitive" : true + } +``` + +!!! note + + The `targetBaseUrl` parameter will be ignored when snapshotting and the `filters/ids` parameter will be ignored when recording. diff --git a/_site/docs/request-matching.md b/_site/docs/request-matching.md new file mode 100644 index 00000000..2b4363ff --- /dev/null +++ b/_site/docs/request-matching.md @@ -0,0 +1,1924 @@ +--- +description: Match requests to stubs and verify queries + using request attributes. +--- + +# Request matching + +WireMock enables flexible definition of a mock APIs by supporting rich matching and filtering of incoming requests. + +To understand how to set up request matching, you need to know how request matching works at runtime--for each incoming HTTP request, WireMock: + +- attempts a match against each stub in turn. +- checks the stub’s cruteria against the request. +- if all criteria for a stub match, matching stops and that stub’s response definition is used to build and return a response. + +You can set priority (1=highest, 10=lowest) to control the order in which the stub list is scanned. Within a single priority, most recently added stubs are scanned first. + +If no stub matches the request the default 404 response is returned with a report showing the difference between the closest stub and the request. + +You can make use of WireMock's in-built match operators, or set up [custom matching](./extending-wiremock.md#custom-request-matchers). + +Stub matching and verification queries can use the following request attributes: + +- URL +- HTTP Method +- Query parameters +- Form parameters +- Headers +- Basic authentication (a special case of header matching) +- Cookies +- Request body +- Multipart/form-data + +If you need more precise control, you can set up the stubs and configuration using the patterns given in the following examples. + +## Request with XML Body + +=== "Java code" + + ```java + stubFor(any(urlPathEqualTo("/everything")) + .withHeader("Accept", containing("xml")) + .withCookie("session", matching(".*12345.*")) + .withQueryParam("search_term", equalTo("WireMock")) + .withBasicAuth("jeff@example.com", "jeffteenjefftyjeff") + .withRequestBody(equalToXml("")) + .withRequestBody(matchingXPath("//search-results")) + .withMultipartRequestBody( + aMultipart() + .withName("info") + .withHeader("Content-Type", containing("charset")) + .withBody(equalToJson("{}")) + ) + .willReturn(aResponse())); + ``` + +=== "JSON configuration file" + + ```json + { + "request": { + "urlPath": "/everything", + "method": "ANY", + "headers": { + "Accept": { + "contains": "xml" + } + }, + "queryParameters": { + "search_term": { + "equalTo": "WireMock" + } + }, + "cookies": { + "session": { + "matches": ".*12345.*" + } + }, + "bodyPatterns": [ + { + "equalToXml": "" + }, + { + "matchesXPath": "//search-results" + } + ], + "multipartPatterns": [ + { + "matchingType": "ANY", + "headers": { + "Content-Disposition": { + "contains": "name=\"info\"" + }, + "Content-Type": { + "contains": "charset" + } + }, + "bodyPatterns": [ + { + "equalToJson": "{}" + } + ] + } + ], + "basicAuthCredentials": { + "username": "jeff@example.com", + "password": "jeffteenjefftyjeff" + } + }, + "response": { + "status": 200 + } + } + ``` + +## Request with Form Parameters + +=== "Java code" + + ```java + stubFor(post(urlPathEqualTo("/mock")) + .withFormParam("tool", equalTo("WireMock")) + ).willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPath": "/mock", + "method": "POST", + "formParameters": { + "tool": { + "equalTo": "WireMock" + } + } + }, + "response": { + "status": 200 + } + } + ``` + +The following sections contain examples of each type of matching strategy. + +## URL matching + +URLs can be matched either by equality or by regular expression. You also have a choice of whether to match just the path part of the URL or the path and query together. + +It is usually preferable to match on path only if you want to match multiple query parameters in an order invariant manner. + +### Equality matching on path and query + +=== "Java code" + + ```java + urlEqualTo("/your/url?and=query") + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/your/url?and=query" + ... + }, + ... + } + ``` + +### Regex matching on path and query + +=== "Java code" + + ```java + urlMatching("/your/([a-z]*)\\?and=query") + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPattern": "/your/([a-z]*)\\?and=query" + ... + }, + ... + } + ``` + +### Equality matching on the path only + +=== "Java code" + + ```java + urlPathEqualTo("/your/url") + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPath": "/your/url" + ... + }, + ... + } + ``` + +### Regex matching on the path only + +=== "Java code" + + ```java + urlPathMatching("/your/([a-z]*)") + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPathPattern": "/your/([a-z]*)" + ... + }, + ... + } + ``` + +### Path templates + +WireMock from 3.0.0 onwards supports matching on URL path templates conforming to the [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570) standard. + +When the path template URL match type is used this enables + +1. The ability to match path variables in the same way as query parameters, headers etc. +2. The ability to reference path variables by name in [response templates](./response-templating.md#the-request-model). + +To match any request URL that conforms to the path template, you can do the following. + +=== "Java code" + + ```java + stubFor( + get(urlPathTemplate("/contacts/{contactId}/addresses/{addressId}")) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPathTemplate": "/contacts/{contactId}/addresses/{addressId}" + "method" : "GET", + + }, + "response" : { + "status" : 200 + } + } + ``` + +To further constrain the match to specific values of the path variables you can add match clauses for some or all of the variables in the path expression. + +=== "Java code" + + ```java + stubFor( + get(urlPathTemplate("/contacts/{contactId}/addresses/{addressId}")) + .withPathParam("contactId", equalTo("12345")) + .withPathParam("addressId", equalTo("99876")) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request" : { + "urlPathTemplate" : "/v1/contacts/{contactId}/addresses/{addressId}", + "method" : "GET", + "pathParameters" : { + "contactId" : { + "equalTo" : "12345" + }, + "addressId" : { + "equalTo" : "99876" + } + } + }, + "response" : { + "status" : 200 + } + } + ``` + + +## Matching other attributes + +All request attributes other than the URL can be matched using the following set of operators. + +### Equality + +Deems a match if the entire attribute value equals the expected value. + +=== "Java code" + + ```java + .withHeader("Content-Type", equalTo("application/json")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "headers": { + "Content-Type": { + "equalTo": "application/json" + } + } + ... + }, + ... + } + ``` + +### Case-insensitive equality + +Deems a match if the entire attribute value equals the expected value, ignoring case. + +=== "Java code" + + ```java + .withHeader("Content-Type", equalToIgnoreCase("application/json")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "headers": { + "Content-Type": { + "equalTo": "application/json", + "caseInsensitive": true + } + } + ... + }, + ... + } + ``` + +### Binary Equality + +Deems a match if the entire binary attribute value equals the expected value. Unlike the above equalTo operator, this compares byte arrays (or their equivalent base64 representation). + +=== "Java code" + + ```java + // Specifying the expected value as a byte array + .withRequestBody(binaryEqualTo(new byte[] { 1, 2, 3 })) + + // Specifying the expected value as a base64 String + .withRequestBody(binaryEqualTo("AQID")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [{ + "binaryEqualTo" : "AQID" // Base 64 + }] + ... + }, + ... + } + ``` + +### Substring (contains) + +Deems a match if the a portion of the attribute value equals the expected value. + +=== "Java code" + + ```java + .withCookie("my_profile", containing("johnsmith@example.com")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "cookies" : { + "my_profile" : { + "contains" : "johnsmith@example.com" + } + } + ... + }, + ... + } + ``` + +### Negative substring (does not contain) + +Deems a match if the attribute value does not contain the expected value. + +=== "Java code" + + ```java + .withCookie("my_profile", notContaining("johnsmith@example.com")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "cookies" : { + "my_profile" : { + "doesNotContain" : "johnsmith@example.com" + } + } + ... + }, + ... + } + ``` + +### Regular expression + +Deems a match if the entire attribute value matched the expected regular expression. + +=== "Java code" + + ```java + .withQueryParam("search_term", matching("^(.*)wiremock([A-Za-z]+)$")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "queryParameters" : { + "search_term" : { + "matches" : "^(.*)wiremock([A-Za-z]+)$" + } + } + ... + }, + ... + } + ``` + +It is also possible to perform a negative match i.e. the match succeeds when the attribute value does not match the regex: + +=== "Java code" + + ```java + .withQueryParam("search_term", notMatching("^(.*)wiremock([A-Za-z]+)$")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "queryParameters" : { + "search_term" : { + "doesNotMatch" : "^(.*)wiremock([A-Za-z]+)$" + } + } + ... + }, + ... + } + ``` + +### JSON equality + +Deems a match if the attribute (most likely the request body in practice) is valid JSON and is a semantic match for the expected value. + +=== "Java code" + + ```java + .withRequestBody(equalToJson("{ \"total_results\": 4 }")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToJson" : { "total_results": 4 } + } ] + ... + }, + ... + } + ``` + +=== "JSON with string literal" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToJson" : "{ \"total_results\": 4 }" + } ] + ... + }, + ... + } + ``` + +#### Less strict matching + +By default different array orderings and additional object attributes will trigger a non-match. However, both of these conditions can be disabled individually. + +=== "Java code" + + ```java + .withRequestBody(equalToJson("{ \"total_results\": 4 }", true, true)) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToJson" : "{ \"total_results\": 4 }", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : true + } ] + ... + }, + ... + } + ``` + +#### Placeholders + +JSON equality matching is based on [JsonUnit](https://github.com/lukas-krecan/JsonUnit) and therefore supports placeholders. +This allows specific attributes to be treated as wildcards, rather than an exactly value being required for a match. + +For instance, the following: + + ```json + { "id": "${json-unit.any-string}" } + ``` + +would match a request with a JSON body of: + + ```json + { "id": "abc123" } + ``` + +It's also possible to use placeholders that constrain the expected value by type or regular expression. +See [the JsonUnit placeholders documentation](https://github.com/lukas-krecan/JsonUnit#typeplc) for the full syntax. + +### JSON Path + +Deems a match if the attribute value is valid JSON and matches the [JSON Path](http://goessner.net/articles/JsonPath/) expression supplied. A JSON body will be considered to match a path expression if the expression returns either a non-null single value (string, integer etc.), or a non-empty object or array. + +#### Presence matching + +Deems a match if the attribute value is present in the JSON. + +=== "Java code" + + ```java + .withRequestBody(matchingJsonPath("$.name")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesJsonPath" : "$.name" + } ] + ... + }, + ... + } + ``` + +=== "Request body example" + + ``` + // matching + { "name": "Wiremock" } + // not matching + { "price": 15 } + ``` + +#### Equality matching + +Deems a match if the attribute value equals the expected value. + +=== "Java code" + + ```java + .withRequestBody(matchingJsonPath("$.things[?(@.name == 'RequiredThing')]")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesJsonPath" : "$.things[?(@.name == 'RequiredThing')]" + } ] + ... + }, + ... + } + ``` + +=== "Request body example" + + ``` + // matching + { "things": { "name": "RequiredThing" } } + { "things": [ { "name": "RequiredThing" }, { "name": "Wiremock" } ] } + // not matching + { "price": 15 } + { "things": { "name": "Wiremock" } } + ``` + +#### Regex matching + +Deems a match if the attribute value matches the regex expected value. + +=== "Java code" + + ```java + .withRequestBody(matchingJsonPath("$.things[?(@.name =~ /Required.*/i)]")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesJsonPath" : "$.things[?(@.name =~ /Required.*/i)]" + } ] + ... + }, + ... + } + ``` + +=== "Request body example" + + ```json + // matching + { "things": { "name": "RequiredThing" } } + { "things": [ { "name": "Required" }, { "name": "Wiremock" } ] } + // not matching + { "price": 15 } + { "things": { "name": "Wiremock" } } + { "things": [ { "name": "Thing" }, { "name": "Wiremock" } ] } + ``` + +#### Size matching + +Deems a match if the attribute size matches the expected size. + +=== "Java code" + + ```java + .withRequestBody(matchingJsonPath("$[?(@.things.size() == 2)]")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.things.size() == 2)]" + } ] + ... + }, + ... + } + ``` + +Request body example: + + ```json + // matching + { "things": [ { "name": "RequiredThing" }, { "name": "Wiremock" } ] } + // not matching + { "things": [ { "name": "RequiredThing" } ] } + ``` + +#### Nested value matching + +The JSONPath matcher can be combined with another matcher, such that the value returned from the JSONPath query is evaluated against it: + +=== "Java code" + + ```java + .withRequestBody(matchingJsonPath("$..todoItem", containing("wash"))) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesJsonPath" : { + "expression": "$..todoItem", + "contains": "wash" + } + } ] + ... + }, + ... + } + ``` + +Since WireMock's matching operators all work on strings, the value selected by the JSONPath expression will be coerced to a string before the match is evaluated. This true even if the returned value +is an object or array. A benefit of this is that this allows a sub-document to be selected using JSONPath, then matched using the `equalToJson` operator. E.g. for the following request body: + +```json +{ + "outer": { + "inner": 42 + } +} +``` + +The following will match: + +=== "Java code" + + ```java + .withRequestBody(matchingJsonPath("$.outer", equalToJson("{ \n" + + " \"inner\": 42 \n" + + "}"))) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesJsonPath" : { + "expression": "$.outer", + "equalToJson": "{ \"inner\": 42 }" + } + } ] + ... + }, + ... + } + ``` + +### JSON schema + +Deems a match if the value conforms to the expected JSON schema. + +By default the [V202012](https://json-schema.org/draft/2020-12/schema) version of the JSON schema spec will be used, but this can be changed to one of `V4`, `V6`, `V7`, `V201909`, `V202012` via the `schemaVersion` parameter. + +=== "Java code" + + ```java + stubFor( + post(urlPathEqualTo("/schema-match")) + .withRequestBody(matchingJsonSchema("{\n" + + " \"type\": \"object\",\n" + + " \"required\": [\n" + + " \"name\"\n" + + " ],\n" + + " \"properties\": {\n" + + " \"name\": {\n" + + " \"type\": \"string\"\n" + + " },\n" + + " \"tag\": {\n" + + " \"type\": \"string\"\n" + + " }\n" + + " }\n" + + "}")) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request" : { + "urlPath" : "/schema-match", + "method" : "POST", + "bodyPatterns" : [ { + "matchesJsonSchema" : "{\n \"type\": \"object\",\n \"required\": [\n \"name\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"tag\": {\n \"type\": \"string\"\n }\n }\n}", + "schemaVersion" : "V202012" + } ] + }, + "response" : { + "status" : 200 + } + } + ``` + + +### XML equality + +Deems a match if the attribute value is valid XML and is semantically equal to the expected XML document. The underlying engine for determining XML equality is [XMLUnit](http://www.xmlunit.org/). + +=== "Java code" + + ```java + .withRequestBody(equalToXml("Hello")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToXml" : "Hello" + } ] + ... + }, + ... + } + ``` + +#### Use of placeholders + +The XMLUnit [placeholders](https://github.com/xmlunit/user-guide/wiki/Placeholders) feature is supported in WireMock. For example, when comparing the XML documents, you can ignore some text nodes. + +=== "Java code" + + ```java + .withRequestBody( + equalToXml("${xmlunit.ignore}Hello", true) + ) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToXml" : "${xmlunit.ignore}Hello", + "enablePlaceholders" : true + } ] + ... + }, + ... + } + ``` + +When the actual request body is `123456Hello`, it will be deemed a match. + +If the default placeholder delimiters `${` and `}` can not be used, you can specify custom delimiters (using regular expressions). For example + +=== "Java code" + + ```java + .withRequestBody( + equalToXml("[[xmlunit.ignore]]Hello", + true, + "\\[\\[", + "]]" + ) + ) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToXml" : "[[xmlunit.ignore]]Hello", + "enablePlaceholders" : true, + "placeholderOpeningDelimiterRegex" : "\\[\\[", + "placeholderClosingDelimiterRegex" : "]]" + } ] + ... + }, + ... + } + ``` + +#### Excluding specific types of comparison + +You can further tune how XML documents are compared for equality by disabling specific [XMLUnit comparison types](https://www.xmlunit.org/api/java/2.7.0/org/xmlunit/diff/ComparisonType.html). + +=== "Java code" + + ```java + import static org.xmlunit.diff.ComparisonType.*; + + ... + + .withRequestBody(equalToXml("Hello") + .exemptingComparisons(NAMESPACE_URI, ELEMENT_TAG_NAME) + ) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "equalToXml" : "Hello", + "exemptedComparisons": ["NAMESPACE_URI", "ELEMENT_TAG_NAME"] + } ] + ... + }, + ... + } + ``` + +The full list of comparison types used by default is as follows: + +`ELEMENT_TAG_NAME` +`SCHEMA_LOCATION` +`NO_NAMESPACE_SCHEMA_LOCATION` +`NODE_TYPE` +`NAMESPACE_URI` +`TEXT_VALUE` +`PROCESSING_INSTRUCTION_TARGET` +`PROCESSING_INSTRUCTION_DATA` +`ELEMENT_NUM_ATTRIBUTES` +`ATTR_VALUE` +`CHILD_NODELIST_LENGTH` +`CHILD_LOOKUP` +`ATTR_NAME_LOOKUP` + +### XPath + +Deems a match if the attribute value is valid XML and matches the XPath expression supplied. An XML document will be considered to match if any elements are returned by the XPath evaluation. WireMock delegates to Java's in-built XPath engine (via XMLUnit), therefore up to (at least) Java 8 it supports XPath version 1.0. + +=== "Java code" + + ```java + .withRequestBody(matchingXPath("/todo-list[count(todo-item) = 3]")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesXPath" : "/todo-list[count(todo-item) = 3]" + } ] + ... + }, + ... + } + ``` + +The above example will select elements based on their local name if used with a namespaced XML document. + +If you need to be able to select elements based on their namespace in addition to their name you can declare the prefix +to namespace URI mappings and use them in your XPath expression: + +=== "Java code" + + ```java + .withRequestBody(matchingXPath("/stuff:outer/more:inner[.=111]") + .withXPathNamespace("stuff", "http://stuff.example.com") + .withXPathNamespace("more", "http://more.example.com")) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesXPath" : "/stuff:outer/more:inner[.=111]", + "xPathNamespaces" : { + "stuff" : "http://stuff.example.com", + "more" : "http://more.example.com" + } + } ] + ... + }, + ... + } + ``` + +#### Nested value matching + +The XPath matcher described above can be combined with another matcher, such that the value returned from the XPath query is evaluated against it: + +=== "Java code" + + ```java + .withRequestBody(matchingXPath("//todo-item/text()", containing("wash"))) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesXPath" : { + "expression": "//todo-item/text()", + "contains": "wash" + } + } ] + ... + }, + ... + } + ``` + +If multiple nodes are returned from the XPath query, all will be evaluated and the returned match will be the one with the shortest distance. + +If the XPath expression returns an XML element rather than a value, this will be rendered as an XML string before it is passed to the value matcher. +This can be usefully combined with the `equalToXml` matcher e.g. + +=== "Java code" + + ```java + .withRequestBody(matchingXPath("//todo-item", equalToXml("Do the washing"))) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "bodyPatterns" : [ { + "matchesXPath" : { + "expression": "//todo-item", + "equalToXml": "Do the washing" + } + } ] + ... + }, + ... + } + ``` + +### Absence + +Deems a match if the attribute specified is absent from the request. + +=== "Java code" + + ```java + .withCookie("session", absent()) + .withQueryParam("search_term", absent()) + .withHeader("X-Absent", absent()) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "headers" : { + "X-Absent" : { + "absent" : true + } + }, + "queryParameters" : { + "search_term" : { + "absent" : true + } + }, + "cookies" : { + "session" : { + "absent" : true + } + } + ... + }, + ... + } + ``` + +## Multipart/form-data + +Deems a match if a multipart value is valid and matches any or all the multipart pattern matchers supplied. As a Multipart is a 'mini' HTTP request in itself all existing Header and Body content matchers can by applied to a Multipart pattern. +A Multipart pattern can be defined as matching `ANY` request multiparts or `ALL`. The default matching type is `ANY`. + +=== "Java code" + + ```java + stubFor(...) + ... + .withMultipartRequestBody( + aMultipart() + .withName("info") + .withHeader("Content-Type", containing("charset")) + .withMultipartBody(equalToJson("{}")) + ) + ``` + +=== "JSON configuration" + + ```json + { + "request": { + ... + "multipartPatterns" : [ { + "matchingType" : "ANY", + "headers" : { + "Content-Disposition" : { + "contains" : "name=\"info\"" + }, + "Content-Type" : { + "contains" : "charset" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{}" + } ] + } ], + ... + }, + ... + } + ``` + +## Basic Authentication + +Although matching on HTTP basic authentication could be supported via a +correctly encoded `Authorization` header, you can also do this more simply +via the API. + +=== "Java code" + + ```java + stubFor(get(urlEqualTo("/basic-auth")).withBasicAuth("user", "pass") + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "method": "GET", + "url": "/basic-auth", + "basicAuth": { + "username": "user", + "password": "pass" + } + }, + "response": { + "status": 200 + } + } + ``` + +## Dates and times + +Dates and times can be matched in several ways. Three comparison operators are available: `before`, `after` and +`equalToDateTime`, all of which have the same set of parameters. + +Additionally, the expected value can be either literal (fixed) or an offset from the current date. Both the expected and +actual dates can be truncated in various ways. + +### Literal date/times + +You can match an incoming date/time against a fixed value e.g. "match if the X-Munged-Date request header is after x": + +=== "Java code" + + ```java + stubFor(post("/dates") + .withHeader("X-Munged-Date", after("2021-05-01T00:00:00Z")) + .willReturn(ok())); + + // You can also use a ZonedDateTime or LocalDateTime object + stubFor(post("/dates") + .withHeader("X-Munged-Date", after(ZonedDateTime.parse("2021-05-01T00:00:00Z"))) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/dates", + "method": "POST", + "headers": { + "X-Munged-Date": { + "after": "2021-05-01T00:00:00Z" + } + } + }, + "response": { + "status": 200 + } + } + ``` + +### Offset + +You can also match in incoming value against the current date/time or an offset from it: + +=== "Java code" + + ```java + stubFor(post("/dates") + .withHeader("X-Munged-Date", beforeNow().expectedOffset(3, DateTimeUnit.DAYS)) + .withHeader("X-Finalised-Date", before("now +2 months")) // This form and beforeNow() are equivalent + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/dates", + "method": "POST", + "headers": { + "X-Munged-Date": { + "before": "now +3 days" + }, + "X-Finalised-Date": { + // This is equivalent to "now +2 months" + "before": "now", + "expectedOffset": 2, + "expectedOffsetUnit": "months" + } + } + } + } + ``` + +### Local vs. Zoned + +Both the expected and actual date/time values can either have timezone information or not. For instance a +date in ISO8601 format could be zoned: `2021-06-24T13:40:27+01:00` or `2021-06-24T12:40:27Z`, or local: `2021-06-24T12:40:27`. + +Likewise a date/time in RFC 1123 (HTTP standard) format is also zoned: `Tue, 01 Jun 2021 15:16:17 GMT`. + +Whether the expected and actual values are zoned or not affects whether they can be matched and how. Generally, the best +approach is to try to ensure you're using the same on both sides - if you're expected a zoned actual date, then use one +as the expected date also, plus the equivalent for local dates. + +If the expected date is zoned and the actual is local, the actual date will assume the system timezone before the +comparison is attempted. + +If the expected date is local and the actual is zoned, the timezone will be stripped from the actual value before the +comparison is attempted. + +### Date formats + +By default these matchers will attempt to parse date/times in ISO8601 format, plus the three standard formats defined by +HTTP RFCs 1123, 1036 and asctime (taken from C but also valid for specifying HTTP dates). + +It is also possible to specify your own format using +[Java's date format strings](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns). + +=== "Java code" + + ```java + stubFor(post("/dates") + .withHeader("X-Munged-Date", + equalToDateTime("2021-06-24T00:00:00").actualFormat("dd/MM/yyyy")) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/dates", + "method": "POST", + "headers": { + "X-Munged-Date": { + "equalToDateTime": "2021-06-24T00:00:00", + "actualFormat": "dd/MM/yyyy" + } + } + } + } + ``` + +### Truncation + +Both the expected and actual date/times can be truncated in various ways e.g. to the first hour of the day. When using +offset from now as the expected date with truncation, the truncation will be applied first followed by the offsetting. + +Truncation is useful if you want to create expressions like "before the end of this month" or "equal to the current hour". + +It can usefully be combined with offsetting so e.g. if the match required is "after the 15th of this month" we could do +as follows. + +=== "Java code" + + ```java + stubFor(post("/dates") + .withRequestBody(matchingJsonPath( + "$.completedDate", + after("now +15 days").truncateExpected(FIRST_DAY_OF_MONTH)) + ) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/dates", + "method": "POST", + "bodyPatterns": [ + { + "matchesJsonPath": { + "expression": "$.completedDate", + "after": "now +15 days", + "truncateExpected": "first day of month" + } + } + ] + } + } + ``` + +Truncating the actual value can be useful when checking for equality with literal date/times e.g. to say "is in March 2020": + +=== "Java code" + + ```java + stubFor(post("/dates") + .withRequestBody(matchingJsonPath( + "$.completedDate", + equalToDateTime("2020-03-01T00:00:00Z").truncateActual(FIRST_DAY_OF_MONTH)) + ) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/dates", + "method": "POST", + "bodyPatterns": [ + { + "matchesJsonPath": { + "expression": "$.completedDate", + "equalToDateTime": "2020-03-01T00:00:00Z", + "truncateActual": "first day of month" + } + } + ] + } + } + ``` + +
    +The full list of available truncations is: + +- `first minute of hour` +- `first hour of day` +- `first day of month` +- `first day of next month` +- `last day of month` +- `first day of year` +- `first day of next year` +- `last day of year` + +## Logical AND and OR + +You can combine two or more matchers in an AND expression. + +=== "Java code" + + ```java + // Both statements are equivalent + + stubFor(get(urlPathEqualTo("/and")) + .withHeader("X-Some-Value", and( + matching("[a-z]+"), + containing("magicvalue")) + ) + .willReturn(ok())); + + stubFor(get(urlPathEqualTo("/and")) + .withHeader("X-Some-Value", matching("[a-z]+").and(containing("magicvalue"))) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPath": "/and", + "method": "GET", + "headers": { + "X-Some-Value": { + "and": [ + { + "matches": "[a-z]+" + }, + { + "contains": "magicvalue" + } + ] + } + } + } + } + ``` + +Similarly you can also construct an OR expression. + +=== "Java code" + + ```java + // Both statements are equivalent + + stubFor(get(urlPathEqualTo("/or")) + .withQueryParam("search", or( + matching("[a-z]+"), + absent()) + ) + .willReturn(ok())); + + stubFor(get(urlPathEqualTo("/or")) + .withQueryParam("search", matching("[a-z]+").or(absent())) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "urlPath": "/or", + "method": "GET", + "queryParameters": { + "search": { + "or": [ + { + "matches": "[a-z]+" + }, + { + "absent": true + } + ] + } + } + } + } + ``` + +### Combining date matchers as JSONPath/XPath sub-matchers + +As an example of how various matchers can be combined, suppose we want to match if a field named `date` in a JSON request body +is a date/time between two points. + +We can do this by extracting the field using `matchesJsonPath` then matching the result +of this against the `before` and `after` matchers AND'd together. + +=== "Java code" + + ```java + stubFor(post("/date-range") + .withRequestBody(matchingJsonPath("$.date", + before("2022-01-01T00:00:00").and( + after("2020-01-01T00:00:00")))) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "request": { + "url": "/date-range", + "method": "POST", + "bodyPatterns": [ + { + "matchesJsonPath": { + "expression": "$.date", + "and": [ + { + "before": "2022-01-01T00:00:00" + }, + { + "after": "2020-01-01T00:00:00" + } + ] + } + } + ] + } + } + ``` + +=== "match the following JSON request body" + + ```json + { + "date": "2021-01-01T00:00:00" + } + ``` + +### Matching Header/Query parameter containing multiple values + +You can match multiple values of a query parameter or header with below provided matchers. + +Exactly matcher exactly matches multiple values or patterns and make sure that it does not contain any other value. + +=== "Java code exact match" + + ```java + // There must be 3 values of id exactly whose values are 1, 2, and 3 + stubFor(get(urlPathEqualTo("/things")) + .withQueryParam("id", havingExactly("1", "2", "3")) + .willReturn(ok())); + ``` + +=== "JSON configuration exact natch" + + ```json + { + "mapping": { + "request" : { + "urlPath" : "/things", + "method" : "GET", + "queryParameters" : { + "id" : { + "hasExactly" : [ + { + "equalTo": "1" + }, + { + "equalTo": "2" + }, + { + "equalTo": "3" + } + ] + } + } + }, + "response" : { + "status" : 200 + } + } + } + ``` + +=== "Java code including *notContaining*" + + ```java + // There must be 3 values of id exactly whose values conform to the match expressions + stubFor(get(urlPathEqualTo("/things")) + .withQueryParam("id", havingExactly( + equalTo("1"), + containing("2"), + notContaining("3") + )).willReturn(ok())); + ``` + +=== "JSON configuration with *notContaining*" + + ```json + { + "mapping": { + "request" : { + "urlPath" : "/things", + "method" : "GET", + "queryParameters" : { + "id" : { + "hasExactly" : [ + { + "equalTo": "1" + }, + { + "contains": "2" + }, + { + "doesNotContain": "3" + } + ] + } + } + }, + "response" : { + "status" : 200 + } + } + } + ``` + +Includes matcher matches multiple values or patterns specified and may contain other values as well. + +=== "Java code" + + ```java + // The values of id must include 1, 2, and 3. + stubFor(get(urlPathEqualTo("/things")) + .withQueryParam("id", including("1", "2", "3")) + .willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "mapping": { + "request" : { + "urlPath" : "/things", + "method" : "GET", + "queryParameters" : { + "id" : { + "includes" : [ + { + "equalTo": "1" + }, + { + "equalTo": "2" + }, + { + "equalTo": "3" + } + ] + } + } + }, + "response" : { + "status" : 200 + } + } + } + ``` + +=== "Java code including *notContaining*" + + ```java + //values of id must conform to the match expressions + stubFor(get(urlPathEqualTo("/things")) + .withQueryParam("id", including( + equalTo("1"), + containing("2"), + notContaining("3") + )).willReturn(ok())); + ``` + +=== "JSON configuration" + + ```json + { + "mapping": { + "request" : { + "urlPath" : "/things", + "method" : "GET", + "queryParameters" : { + "id" : { + "includes" : [ + { + "equalTo": "1" + }, + { + "contains": "2" + }, + { + "doesNotContain": "3" + } + ] + } + } + }, + "response" : { + "status" : 200 + } + } + } + ``` + +### Manage request template data with helpers + +Catgories of helpers for managing data while using results from response temaplates. + +#### Extract regular expression(s) + +To extract one or more values matching a regular expresson from a string use the `regexExtract` helper. + +Following are example Handlebar snippets. + +Extract a single value: + +{% raw %} +```handlebars +{{regexExtract request.body '[A-Z]+'}}" +``` +{% endraw %} + +To extract multiple parts into an object for later use, use regex groups. The last parameter, here listed as `parts`, is the variable name for use in labelling results: + +{% raw %} +```handlebars +{{regexExtract request.body '([a-z]+)-([A-Z]+)-([0-9]+)' 'parts'}} +{{parts.0}},{{parts.1}},{{parts.2}} +``` +{% endraw %} + +For cases in which there might be no match, you can specify a default value. + +{% raw %} +```handlebars +{{regexExtract 'abc' '[0-9]+' default='my default value'}} +``` +{% endraw %} + +!!! warning + + When the regex does not match and no default is specified, an error is thrown. + +!!! note + + Matching of regular expressions is case-insensitive. + If no permitted system key patterns are set, a single default of `wiremock.*` is used. + +#### Get data size + +The `size` helper returns the size of a string, list or map: + +{% raw %} +```handlebars +{{size 'abcde'}} +{{size request.query.things}} +``` +{% endraw %} + +#### Trim string whitespace + +Use the `trim` helper to remove whitespace from the start and end of the input: + +{% raw %} +```handlebars +{{trim request.headers.X-Padded-Header}} + +{{#trim}} + + Some stuff with whitespace + +{{/trim}} +``` +{% endraw %} + + +## Data types and comparisons using helpers + +#### Encode/decode in `base64` + +Tto base64 encode and decode values, use the `base64` helper: + +{% raw %} +```handlebars +{{base64 request.headers.X-Plain-Header}} +{{base64 request.headers.X-Encoded-Header decode=true}} + +{{#base64}} +Content to encode +{{/base64}} + +{{#base64 padding=false}} +Content to encode without padding +{{/base64}} + +{{#base64 decode=true}} +Q29udGVudCB0byBkZWNvZGUK +{{/base64}} +``` +{% endraw %} + + +#### `contains` helper + +The `contains` helper returns a boolean value indicating whether the string or array passed as the first parameter +contains the string passed in the second. + +It can be used as parameter to the `if` helper: + +{% raw %} +```handlebars +{{#if (contains 'abcde' 'abc')}}YES{{/if}} +{{#if (contains (array 'a' 'b' 'c') 'a')}}YES{{/if}} +``` +{% endraw %} + +Or as a block element on its own: + +{% raw %} +```handlebars +{{#contains 'abcde' 'abc'}}YES{{/contains}} +{{#contains (array 'a' 'b' 'c') 'a'}}YES{{/contains}} +``` +{% endraw %} + + +#### Boolean match + +The `matches` helper returns a boolean value indicating whether the string passed as the first parameter matches the regular expression passed in the second: + +Like the `contains` helper it can be used as parameter to the `if` helper: + +{% raw %} +```handlebars +{{#if (matches '123' '[0-9]+')}}YES{{/if}} +``` +{% endraw %} + +Or as a block element on its own: + +{% raw %} +```handlebars +{{#matches '123' '[0-9]+'}}YES{{/matches}} +``` +{% endraw %} + +#### Math helper + +The `math` (or maths, depending where you are) helper performs common arithmetic operations. It can accept integers, decimals +or strings as its operands and will always yield a number as its output rather than a string. + +Addition, subtraction, multiplication, division and remainder (mod) are supported: + +{% raw %} +```handlebars +{{math 1 '+' 2}} +{{math 4 '-' 2}} +{{math 2 '*' 3}} +{{math 8 '/' 2}} +{{math 10 '%' 3}} +``` +{% endraw %} + +#### Bounded integer array + +The `range` helper will produce an array of integers between the bounds specified: + +{% raw %} +```handlebars +{{range 3 8}} +{{range -2 2}} +``` +{% endraw %} + +This can be usefully combined with `randomInt` and `each` to output random length, repeating pieces of content e.g. + +{% raw %} +```handlebars +{{#each (range 0 (randomInt lower=1 upper=10)) as |index|}} +id: {{index}} +{{/each}} +``` +{% endraw %} + +#### Array literal + +The `array` helper will produce an array from the list of parameters specified. The values can be any valid type. +Providing no parameters will result in an empty array. + +{% raw %} +```handlebars +{{array 1 'two' true}} +{{array}} +``` +{% endraw %} + + diff --git a/_docs/response-templating.md b/_site/docs/response-templating.md similarity index 68% rename from _docs/response-templating.md rename to _site/docs/response-templating.md index a724cda7..5931fbee 100644 --- a/_docs/response-templating.md +++ b/_site/docs/response-templating.md @@ -1,167 +1,160 @@ --- -layout: docs -title: Response Templating -meta_title: Mock API Response Templating | WireMock -toc_rank: 71 -description: Response headers and bodies, as well as proxy URLs, can optionally be rendered using Handlebars templates. +description: > + Optional use of Handlebars templates for rendering response headers, bodies, and proxy URLs, --- -Response headers and bodies, as well as proxy URLs, can optionally be rendered using [Handlebars templates](http://handlebarsjs.com/). This enables attributes of the request -to be used in generating the response e.g. to pass the value of a request ID header as a response header or -render an identifier from part of the URL in the response body. +# Control mock API templated responses using Handlebars -## Enabling/disabling response templating +As an option, you can work with response headers, bodies, and proxy URLs using [Handlebars templates](http://handlebarsjs.com/). +This option supports: -Response templating is enabled by default in local mode when WireMock is started programmatically, meaning that it will only be applied to stubs that have the `response-template` transformer added to them (see [below](#applying-templating-in-local-mode) for details). +- passing the value of a request ID header as a response header. +- rendering an identifier from part of the URL into the response body. -Templating can be applied globally (without having to explicitly add `response-template`) via a startup option: +After applying Handlebars templates, you control the parameters that WireMock uses in generating mock responses with request attributes. + +## Enabling/disabling response template functionality + + +Starting WireMock programmatically, by default, starts response templating that is applied to the stubs that have the `response-template` transformer added to them (see [below](#applying-templating-in-local-mode) for details). + + +To apply response templating globally, without having to explicitly add `response-template`, use the `globalTemplating` startup option and set it to true: ```java WireMockServer wm = new WireMockServer(options().globalTemplating(true)); ``` -It can also be disabled completely via a startup option: +You can also disable templating completely by setting the `templatingEnabled` startup option to false: ```java WireMockServer wm = new WireMockServer(options().templatingEnabled(false)); ``` -See [the command line docs](../standalone/java-jar/#command-line-options) for the standalone equivalents of these parameters. +See [the command line docs](./standalone/java-jar.md#command-line-options) for the standalone equivalents of these parameters. ## Customising and extending the template engine -Custom Handlebars helpers can be registered via an extension point. See [Adding Template Helpers](../extensibility/adding-template-helpers/) for details. +You can register custom Handlebars helpers using an extension point. See [Adding Template Helpers](./extensibility/adding-template-helpers.md) for details. -Similarly custom model data providers can be registered as extensions. See [Adding Template Model Data](../extensibility/adding-template-model-data/) for details. +Similarly, you can register custom model data providers as extensions. See [Adding Template Model Data](./extensibility/adding-template-model-data.md) for details. ## Applying templating in local mode -When templating is enabled in local mode you must add it to each stub to which you require templating to be applied. -This is done by adding `response-template` to the set of transformers on the response. +When templating is enabled in local mode, you must add it to each stub to which you require templating to be applied, by adding `response-template` to the set of transformers on the response. -### Java +=== "Java" {% raw %} - -```java -wm.stubFor(get(urlPathEqualTo("/templated")) - .willReturn(aResponse() - .withBody("{{request.path.[0]}}") - .withTransformers("response-template"))); -``` - + ```java + wm.stubFor(get(urlPathEqualTo("/templated")) + .willReturn(aResponse() + .withBody("{{request.path.[0]}}") + .withTransformers("response-template"))); + ``` {% endraw %} +=== "JSON" {% raw %} - -### JSON - -```json -{ - "request": { - "urlPath": "/templated" - }, - "response": { - "body": "{{request.path.[0]}}", - "transformers": ["response-template"] + ```json + { + "request": { + "urlPath": "/templated" + }, + "response": { + "body": "{{request.path.[0]}}", + "transformers": ["response-template"] + } } -} -``` - + ``` {% endraw %} + ## Template caching -All templated fragments (headers, bodies and proxy URLs) are cached in their compiled form for performance, +To enhance performance, WireMock caches all templated fragments (headers, bodies and proxy URLs), in their compiled form, since compilation can be expensive for larger templates. -By default the capacity of this cache is not limited but a limit can be set via the startup options: +By default the capacity of this cache is not limited. As a startup option, you can set a limit: ```java WireMockServer wm = new WireMockServer(options().withMaxTemplateCacheEntries(10000)); ``` -See [the command line docs](../standalone/java-jar/#command-line-options) for the equivalent configuration setting when running standalone. +When running standalone, you can make equivalent settings in [the command line](./standalone/java-jar.md#command-line-options). ## Proxying -Templating also works when defining proxy URLs, e.g. +Templating also works when defining proxy URLs: -### Java +=== "Java" {% raw %} - -```java -wm.stubFor(get(urlPathEqualTo("/templated")) - .willReturn(aResponse() - .proxiedFrom("{{request.headers.X-WM-Proxy-Url}}") - .withTransformers("response-template"))); -``` - + ```java + wm.stubFor(get(urlPathEqualTo("/templated")) + .willReturn(aResponse() + .proxiedFrom("{{request.headers.X-WM-Proxy-Url}}") + .withTransformers("response-template"))); + ``` {% endraw %} -{% raw %} - -### JSON +=== "JSON" -```json -{ - "request": { - "urlPath": "/templated" - }, - "response": { - "proxyBaseUrl": "{{request.headers.X-WM-Proxy-Url}}", - "transformers": ["response-template"] +{% raw %} + ```json + { + "request": { + "urlPath": "/templated" + }, + "response": { + "proxyBaseUrl": "{{request.headers.X-WM-Proxy-Url}}", + "transformers": ["response-template"] + } } -} -``` - + ``` {% endraw %} ## Templated body file -The body file for a response can be selected dynamically by templating the file path: +To dynamically select a response, template the file path for the body file: -### Java +=== "Java" {% raw %} + ```java + wm.stubFor(get(urlPathMatching("/static/.*")) + .willReturn(ok() + .withBodyFile("files/{{request.pathSegments.[1]}}"))); -```java -wm.stubFor(get(urlPathMatching("/static/.*")) - .willReturn(ok() - .withBodyFile("files/{{request.pathSegments.[1]}}"))); - -``` - + ``` {% endraw %} -{% raw %} - -### JSON +=== "JSON" -```json -{ - "request": { - "urlPathPattern": "/static/.*", - "method": "GET" - }, - "response": { - "status": 200, - "bodyFileName": "files/{{request.pathSegments.[1]}}" +{% raw %} + ```json + { + "request": { + "urlPathPattern": "/static/.*", + "method": "GET" + }, + "response": { + "status": 200, + "bodyFileName": "files/{{request.pathSegments.[1]}}" + } } -} -``` - + ``` {% endraw %} + ## The request model -The model of the request is supplied to the header and body templates. The following request attributes are available: +The request data model controls both the header and body templates, making available the following request attributes: `request.url` - URL path and query @@ -203,8 +196,8 @@ this easy to work with by wrapping these in a "list or single" type that returns For instance, given a request URL like `/multi-query?things=1&things=2&things=3` I can extract the query data in the following ways: -{% raw %} +{% raw %} ```handlebars {{request.query.things}} // Will return 1 {{request.query.things.0}} // Will return 1 @@ -213,121 +206,122 @@ For instance, given a request URL like `/multi-query?things=1&things=2&things=3` {{request.query.things.[-1]}} // Will return 2 {{request.query.things.last}} // Will return 3 ``` - {% endraw %} -> **Note** -> -> When using the `eq` helper with one-or-many values, it is necessary to use the indexed form, even if only one value is present. -> The reason for this is that the non-indexed form returns the wrapper type and not a String, and will therefore fail any comparison -> with another String value. + +!!! note + + When using the `eq` helper with one-or-many values, you must use the indexed form, even if only one value is present. + The reason for this is that the non-indexed form returns the wrapper type and not a String, and will therefore fail any comparison + with another String value. ### Getting values with keys containing special characters -Certain characters have special meaning in Handlebars and therefore can't be used in key names when referencing values. +Some specific characters have special meaning in Handlebars and therefore can't be used in key names when referencing values. If you need to access keys containing these characters you can use the `lookup` helper, which permits you to pass the key name as a string literal and thus avoid the restriction. Probably the most common occurrence of this issue is with array-style query parameters, so for instance if your request -URLs you're matching are of the form `/stuff?ids[]=111&ids[]=222&ids[]=333` then you can access these values like: +URLs you're matching are of the form `/stuff?ids[]=111&ids[]=222&ids[]=333` then you can access these values as in the following: -{% raw %} +{% raw %} ```handlebars {{lookup request.query 'ids[].1'}} // Will return 222 ``` - {% endraw %} ## Using transformer parameters -Parameter values can be passed to the transformer as shown below (or dynamically added to the parameters map programmatically in custom transformers). +You can pass parameter values to the transformer as shown below (or dynamically added to the parameters map programmatically in custom transformers). -### Java +=== "Java" {% raw %} - -```java -wm.stubFor(get(urlPathEqualTo("/templated")) - .willReturn(aResponse() - .withBody("{{request.path.[0]}}") - .withTransformers("response-template") - .withTransformerParameter("MyCustomParameter", "Parameter Value"))); -``` - + ```java + wm.stubFor(get(urlPathEqualTo("/templated")) + .willReturn(aResponse() + .withBody("{{request.path.[0]}}") + .withTransformers("response-template") + .withTransformerParameter("MyCustomParameter", "Parameter Value"))); + ``` {% endraw %} -{% raw %} - -### JSON +=== "JSON" -```json -{ - "request": { - "urlPath": "/templated" - }, - "response": { - "body": "{{request.path.[0]}}", - "transformers": ["response-template"], - "transformerParameters": { - "MyCustomParameter": "Parameter Value" +{% raw %} + ```json + { + "request": { + "urlPath": "/templated" + }, + "response": { + "body": "{{request.path.[0]}}", + "transformers": ["response-template"], + "transformerParameters": { + "MyCustomParameter": "Parameter Value" + } } } -} -``` - + ``` {% endraw %} These parameters can be referenced in template body content using the `parameters.` prefix: {% raw %} - ```handlebars

    The MyCustomParameter value is {{parameters.MyCustomParameter}}

    ``` - {% endraw %} -## Handlebars helpers +### Handlebars helpers -All of the standard helpers (template functions) provided by the [Java Handlebars implementation by jknack](https://github.com/jknack/handlebars.java) -plus all of the [string helpers](https://github.com/jknack/handlebars.java/blob/master/handlebars/src/main/java/com/github/jknack/handlebars/helper/StringHelpers.java) -and the [conditional helpers](https://github.com/jknack/handlebars.java/blob/master/handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java) -are available e.g. +When building your customs WireMock response templates, you can use of all of the standard [Handlebars](https://handlebarsjs.com/guide/) helpers provided by the following open source resources: -{% raw %} +- [Java Handlebars implementation by jknack](https://github.com/jknack/handlebars.java) +- [string helpers](https://github.com/jknack/handlebars.java/blob/master/handlebars/src/main/java/com/github/jknack/handlebars/helper/StringHelpers.java) +- [conditional helpers](https://github.com/jknack/handlebars.java/blob/master/handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java) +are available. -```handlebars -{{capitalize request.query.search}} -``` +There are numerous use cases in which you might want to use test simple operations on strings. Changing capitalization provides simple examples of using conditional helpers: -{% endraw %} +=== "Sentence cap" -## Number and assignment helpers +{% raw %} + ```handlebars + {{capitalize request.query.search}} + (1) + ``` +{% endraw %} -Variable assignment and number helpers are available: +=== "Word cap" {% raw %} + ```handlebars + {{capitalizeAll request.query.search}} + (2) + ``` +{% endraw %} -```handlebars -{{#assign 'myCapitalisedQuery'}}{{capitalize request.query.search}}{{/assign}} - -{{isOdd 3}} -{{isOdd 3 'rightBox'}} +=== "Lowercase" -{{isEven 2}} -{{isEven 4 'leftBox'}} +{% raw %} + ```handlebars + {{lowercase request.query.search}} + (3) + ``` +{% endraw %} -{{stripes 3 'row-even' 'row-odd'}} -``` +1. Capitalizes the first letter in a string +2. Capitalizes the first letter of each word in a string. +3. Makes the entire string lowercase. -{% endraw %} ## XPath helpers -Additionally some helpers are available for working with JSON and XML. +Helpers are available for working with JSON and XML: -When the incoming request contains XML, the `xPath` helper can be used to extract values or sub documents via an XPath 1.0 expression. For instance, given the XML +For incoming requests that contain XML, use the `xPath` helper to extract values or sub documents using an XPath 1.0 expression. For exampke, given the XML: ```xml @@ -335,27 +329,23 @@ When the incoming request contains XML, the `xPath` helper can be used to extrac ``` -The following will render "Stuff" into the output: +The following renders "Stuff" into the output: {% raw %} - ```handlebars {{xPath request.body '/outer/inner/text()'}} ``` - {% endraw %} -And given the same XML the following will render `Stuff`: +And given the same XML, the following renders `Stuff`: {% raw %} - ```handlebars {{xPath request.body '/outer/inner'}} ``` - {% endraw %} -As a convenience the `soapXPath` helper also exists for extracting values from SOAP bodies e.g. for the SOAP document: +As a convenience, the `soapXPath` helper also exists for extracting values from SOAP bodies e.g. for the SOAP document: ```xml @@ -367,19 +357,17 @@ As a convenience the `soapXPath` helper also exists for extracting values from S ``` -The following will render "success" in the output: +The following renders "success" in the output: {% raw %} - ```handlebars {{soapXPath request.body '/a/test/text()'}} ``` - {% endraw %} ### Using the output of `xPath` in other helpers -Since version 2.27.0 the XPath helper returns collections of node objects rather than a single string, meaning that the result +Since version 2.27.0, the XPath helper returns collections of node objects rather than a single string, meaning that the result can be used in further helpers. The returned node objects have the following properties: @@ -395,16 +383,14 @@ Referring to the node itself will cause it to be printed. A common use case for returned node objects is to iterate over the collection with the `each` helper: {% raw %} - ```handlebars {{#each (xPath request.body '/things/item') as |node|}} name: {{node.name}}, text: {{node.text}}, ID attribute: {{node.attributes.id}} {{/each}} ``` - {% endraw %} -## JSONPath helper +### JSONPath helper It is similarly possible to extract JSON values or sub documents via JSONPath using the `jsonPath` helper. Given the JSON @@ -419,34 +405,28 @@ It is similarly possible to extract JSON values or sub documents via JSONPath us The following will render "Stuff" into the output: {% raw %} - ```handlebars {{jsonPath request.body '$.outer.inner'}} ``` - {% endraw %} And for the same JSON the following will render `{ "inner": "Stuff" }`: {% raw %} - ```handlebars {{jsonPath request.body '$.outer'}} ``` - {% endraw %} Default value can be specified if the path evaluates to null or undefined: {% raw %} - ```handlebars {{jsonPath request.body '$.size' default='M'}} ``` - {% endraw %} -## Parse JSON helper +### Parse JSON helper The `parseJson` helper will parse the input into a map-of-maps. It will assign the result to a variable if a name is specified, otherwise the result will be returned. @@ -454,7 +434,6 @@ otherwise the result will be returned. It can accept the JSON from a block: {% raw %} - ```handlebars {{#parseJson 'parsedObj'}} { @@ -465,36 +444,30 @@ It can accept the JSON from a block: {{!- Now we can access the object as usual --}} {{parsedObj.name}} ``` - {% endraw %} Or as a parameter: {% raw %} - ```handlebars {{parseJson request.body 'bodyJson'}} {{bodyJson.name}} ``` - {% endraw %} Without assigning to a variable: {% raw %} - ```handlebars {{lookup (parseJson request.body) 'name'}} ``` - {% endraw %} ## Date and time helpers -A helper is present to render the current date/time, with the ability to specify the format ([via Java's SimpleDateFormat](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)) and offset. +Helper to render the current date/time, with the ability to specify the format ([via Java's SimpleDateFormat](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)) and offset. {% raw %} - ```handlebars {{now}} {{now offset='3 days'}} @@ -502,35 +475,29 @@ A helper is present to render the current date/time, with the ability to specify {{now offset='1 years'}} {{now offset='10 years' format='yyyy-MM-dd'}} ``` - {% endraw %} Dates can be rendered in a specific timezone (the default is UTC): {% raw %} - ```handlebars {{now timezone='Australia/Sydney' format='yyyy-MM-dd HH:mm:ssZ'}} ``` - {% endraw %} Pass `epoch` as the format to render the date as UNIX epoch time (in milliseconds), or `unix` as the format to render the UNIX timestamp in seconds. {% raw %} - ```handlebars {{now offset='2 years' format='epoch'}} {{now offset='2 years' format='unix'}} ``` - {% endraw %} Dates can be parsed using the `parseDate` helper: {% raw %} - ```handlebars // Attempts parsing using ISO8601, RFC 1123, RFC 1036 and ASCTIME formats. // We wrap in the date helper in order to print the result as a string. @@ -542,29 +509,43 @@ Dates can be parsed using the `parseDate` helper: // Format can also be unix (epoch seconds) or epoch (epoch milliseconds) {{date (parseDate request.headers.MyDate format='unix')}} ``` - {% endraw %} Dates can be truncated to e.g. first day of month using the `truncateDate` helper: {% raw %} - ```handlebars // If the MyDate header is Tue, 15 Jun 2021 15:16:17 GMT // then the result of the following will be 2021-06-01T00:00:00Z {{date (truncateDate (parseDate request.headers.MyDate) 'first day of month')}} ``` - {% endraw %} -See the [full list of truncations here](../request-matching#all-truncations). +See the [full list of truncations here](./request-matching.md#all-truncations). -## Random value helper +## Number and assignment helpers -Random strings of various kinds can be generated: +Variable assignment and number helpers: {% raw %} +```handlebars +{{#assign 'myCapitalisedQuery'}}{{capitalize request.query.search}}{{/assign}} +{{isOdd 3}} +{{isOdd 3 'rightBox'}} + +{{isEven 2}} +{{isEven 4 'leftBox'}} + +{{stripes 3 'row-even' 'row-odd'}} +``` +{% endraw %} + +### Random value helpers + +Random strings of various kinds can be generated: + +{% raw %} ```handlebars {{randomValue length=33 type='ALPHANUMERIC'}} {{randomValue length=12 type='ALPHANUMERIC' uppercase=true}} @@ -575,32 +556,27 @@ Random strings of various kinds can be generated: {{randomValue type='UUID'}} {{randomValue length=32 type='HEXADECIMAL' uppercase=true}} ``` - {% endraw %} -## Pick random helper +### Pick random helper A value can be randomly selected from a literal list: {% raw %} - ```handlebars {{{pickRandom '1' '2' '3'}}} ``` - {% endraw %} Or from a list passed as a parameter: {% raw %} - ```handlebars {{{pickRandom (jsonPath request.body '$.names')}}} ``` - {% endraw %} -## Random number helpers +### Random number helpers These helpers produce random numbers of the desired type. By returning actual typed numbers rather than strings we can use them for further work e.g. by doing arithemetic with the `math` helper or randomising the bound in a `range`. @@ -608,42 +584,37 @@ we can use them for further work e.g. by doing arithemetic with the `math` helpe Random integers can be produced with lower and/or upper bounds, or neither: {% raw %} - ```handlebars {{randomInt}} {{randomInt lower=5 upper=9}} {{randomInt upper=54323}} {{randomInt lower=-24}} ``` - {% endraw %} Likewise decimals can be produced with or without bounds: {% raw %} - ```handlebars {{randomDecimal}} {{randomDecimal lower=-10.1 upper=-0.9}} {{randomDecimal upper=12.5}} {{randomDecimal lower=-24.01}} ``` - {% endraw %} -## Fake data helpers +### Random fake data helpers This helper produces random fake data of the desired types available in the [Data Faker library](https://github.com/datafaker-net/datafaker). Due to the size of this library, this helper has been provided via [`RandomExtension`](https://github.com/wiremock/wiremock-faker-extension). -{% raw %} +{% raw %} ```handlebars {{random 'Name.first_name'}} {{random 'Address.postcode_by_state.AL' }} ``` - {% endraw %} -## Math helper +### Math helper The `math` (or maths, depending where you are) helper performs common arithmetic operations. It can accept integers, decimals or strings as its operands and will always yield a number as its output rather than a string. @@ -651,7 +622,6 @@ or strings as its operands and will always yield a number as its output rather t Addition, subtraction, multiplication, division and remainder (mod) are supported: {% raw %} - ```handlebars {{math 1 '+' 2}} {{math 4 '-' 2}} @@ -659,32 +629,50 @@ Addition, subtraction, multiplication, division and remainder (mod) are supporte {{math 8 '/' 2}} {{math 10 '%' 3}} ``` - {% endraw %} -## Range helper +### Range helper The `range` helper will produce an array of integers between the bounds specified: {% raw %} - ```handlebars {{range 3 8}} {{range -2 2}} ``` - {% endraw %} This can be usefully combined with `randomInt` and `each` to output random length, repeating pieces of content e.g. {% raw %} - ```handlebars {{#each (range 0 (randomInt lower=1 upper=10)) as |index|}} id: {{index}} {{/each}} ``` +{% endraw %} + +### Base64 helper + +The `base64` helper can be used to base64 encode and decode values: +{% raw %} +```handlebars +{{base64 request.headers.X-Plain-Header}} +{{base64 request.headers.X-Encoded-Header decode=true}} + +{{#base64}} +Content to encode +{{/base64}} + +{{#base64 padding=false}} +Content to encode without padding +{{/base64}} + +{{#base64 decode=true}} +Q29udGVudCB0byBkZWNvZGUK +{{/base64}} +``` {% endraw %} ## Array literal helper @@ -693,12 +681,10 @@ The `array` helper will produce an array from the list of parameters specified. Providing no parameters will result in an empty array. {% raw %} - ```handlebars {{array 1 'two' true}} {{array}} ``` - {% endraw %} ## Contains helper @@ -709,23 +695,19 @@ contains the string passed in the second. It can be used as parameter to the `if` helper: {% raw %} - ```handlebars {{#if (contains 'abcde' 'abc')}}YES{{/if}} {{#if (contains (array 'a' 'b' 'c') 'a')}}YES{{/if}} ``` - {% endraw %} Or as a block element on its own: {% raw %} - ```handlebars {{#contains 'abcde' 'abc'}}YES{{/contains}} {{#contains (array 'a' 'b' 'c') 'a'}}YES{{/contains}} ``` - {% endraw %} ## Matches helper @@ -736,21 +718,17 @@ regular expression passed in the second: Like the `contains` helper it can be used as parameter to the `if` helper: {% raw %} - ```handlebars {{#if (matches '123' '[0-9]+')}}YES{{/if}} ``` - {% endraw %} Or as a block element on its own: {% raw %} - ```handlebars {{#matches '123' '[0-9]+'}}YES{{/matches}} ``` - {% endraw %} ## String trim helper @@ -758,7 +736,6 @@ Or as a block element on its own: Use the `trim` helper to remove whitespace from the start and end of the input: {% raw %} - ```handlebars {{trim request.headers.X-Padded-Header}} @@ -768,32 +745,6 @@ Use the `trim` helper to remove whitespace from the start and end of the input: {{/trim}} ``` - -{% endraw %} - -## Base64 helper - -The `base64` helper can be used to base64 encode and decode values: - -{% raw %} - -```handlebars -{{base64 request.headers.X-Plain-Header}} -{{base64 request.headers.X-Encoded-Header decode=true}} - -{{#base64}} -Content to encode -{{/base64}} - -{{#base64 padding=false}} -Content to encode without padding -{{/base64}} - -{{#base64 decode=true}} -Q29udGVudCB0byBkZWNvZGUK -{{/base64}} -``` - {% endraw %} ## URL encoding helper @@ -801,7 +752,6 @@ Q29udGVudCB0byBkZWNvZGUK The `urlEncode` helper can be used to URL encode and decode values: {% raw %} - ```handlebars {{urlEncode request.headers.X-Plain-Header}} {{urlEncode request.headers.X-Encoded-Header decode=true}} @@ -814,7 +764,6 @@ Content to encode Content%20to%20decode {{/urlEncode}} ``` - {% endraw %} ## Form helper @@ -824,22 +773,18 @@ The helper takes the input string and variable name as its required parameters, indicating that values should be URL decoded. The folowing example will parse the request body as a form, then output a single field `formField3`: {% raw %} - ```handlebars {{formData request.body 'form' urlDecode=true}}{{form.formField3}} ``` - {% endraw %} If the form submitted has multiple values for a given field, these can be accessed by index: {% raw %} - ```handlebars {{formData request.body 'form' urlDecode=true}}{{form.multiValueField.1}}, {{form.multiValueField.2}} {{formData request.body 'form' urlDecode=true}}{{form.multiValueField.first}}, {{form.multiValueField.last}} ``` - {% endraw %} ## Regular expression extract helper @@ -849,32 +794,26 @@ The `regexExtract` helper supports extraction of values matching a regular expre A single value can be extracted like this: {% raw %} - ```handlebars {{regexExtract request.body '[A-Z]+'}}" ``` - {% endraw %} Regex groups can be used to extract multiple parts into an object for later use (the last parameter is a variable name to which the object will be assigned): {% raw %} - ```handlebars {{regexExtract request.body '([a-z]+)-([A-Z]+)-([0-9]+)' 'parts'}} {{parts.0}},{{parts.1}},{{parts.2}} ``` - {% endraw %} Optionally, a default value can be specified for when there is no match. When the regex does not match and no default is specified, an error will be thrown instead. {% raw %} - ```handlebars {{regexExtract 'abc' '[0-9]+' default='my default value'}} ``` - {% endraw %} ## Size helper @@ -882,12 +821,10 @@ Optionally, a default value can be specified for when there is no match. When th The `size` helper returns the size of a string, list or map: {% raw %} - ```handlebars {{size 'abcde'}} {{size request.query.things}} ``` - {% endraw %} ## Hostname helper @@ -895,11 +832,9 @@ The `size` helper returns the size of a string, list or map: The local machine's hostname can be printed: {% raw %} - ```handlebars {{hostname}} ``` - {% endraw %} ## System property helper @@ -907,12 +842,10 @@ The local machine's hostname can be printed: Environment variables and system properties can be printed: {% raw %} - ```handlebars {{systemValue type='ENVIRONMENT' key='PATH'}} {{systemValue type='PROPERTY' key='os.path'}} ``` - {% endraw %} If you want to add permitted extensions to your rule, @@ -924,6 +857,7 @@ The `ResponseTemplateTransformer` accepts four arguments: 3. The `FileSource` which is a list of files that can be used for relative references in stub definitions 4. A list of `TemplateModelDataProviderExtension` objects which are additional metadata providers which will be injected into the model and consumed in the downstream resolution if needed +{% raw %} ```java @Rule public WireMockRule wm = new WireMockRule(options() @@ -938,7 +872,10 @@ public WireMockRule wm = new WireMockRule(options() ) ); ``` +{% endraw %} + +!!! note -The regular expressions are matched in a case-insensitive manner. -If no permitted system key patterns are set, a single default of `wiremock.*` will be used. + Matching of regular expressions is case-insensitive. + If no permitted system key patterns are set, a single default of `wiremock.*` is used. diff --git a/_site/docs/running-without-http-server.md b/_site/docs/running-without-http-server.md new file mode 100644 index 00000000..24c034b1 --- /dev/null +++ b/_site/docs/running-without-http-server.md @@ -0,0 +1,42 @@ +--- +description: Run WireMock inside Java without the inbuilt HTTP layer. +--- + +# Running WireMock without an HTTP Server + +You can run Wiremock inside another process, for example: + +- wrap it in a serverless function such as on AWS Lambda. +- use it as part of an application's integration tests. + +[Running as a Standalone Process](./standalone/java-jar.md) works well, however, it has the overhead of a full HTTP server and HTTP calls back and forth that in some cases may not be relevant. and adds a fair bit of overhead to each call, and the memory footprint of the application. + + +Since Wiremock v2.32.0, the `DirectCallHttpServer` provides the ability to run a Wiremock server without interacting with an HTTP layer. + +Following is an example construction and use (adapted from `DirectCallHttpServerIntegrationTest`): + +```java +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.http.Response; +import com.github.tomakehurst.wiremock.direct.DirectCallHttpServer; +import com.github.tomakehurst.wiremock.direct.DirectCallHttpServerFactory; + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +// .. + +DirectCallHttpServerFactory factory = new DirectCallHttpServerFactory(); +WireMockServer wm = new WireMockServer(wireMockConfig().httpServerFactory(factory)); +wm.start(); // no-op, not required + +DirectCallHttpServer server = factory.getHttpServer(); + +Request request = new Request() { + // fill in with the incoming request data +} + +Response response = server.stubRequest(request); +// then use the `response`'s data, and map it accordingly +``` + +Note that prior to Wiremock v2.32.0, you can use [the workaround as described by Jamie Tanna](https://www.jvt.me/posts/2021/04/29/wiremock-serverless/), which uses internal APIs. diff --git a/_docs/simulating-faults.md b/_site/docs/simulating-faults.md similarity index 64% rename from _docs/simulating-faults.md rename to _site/docs/simulating-faults.md index fd2af476..2a65d78a 100644 --- a/_docs/simulating-faults.md +++ b/_site/docs/simulating-faults.md @@ -1,45 +1,22 @@ --- -layout: docs -title: Simulating Faults -meta_title: Simulating faults in API behavior | WireMock -toc_rank: 80 -redirect_from: "/simulating-faults.html" -description: One of the main reasons it’s beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the real service to produce on demand. +description: > + use web service fakes when testing and inject faulty behaviour --- -**One of the main reasons it's beneficial to use web service fakes when -testing is to inject faulty behaviour that might be difficult to get the -real service to produce on demand. In addition to being able to send -back any HTTP response code indicating an error, WireMock is able to -generate a few other types of problem.** +# Simulating faults in API behavior -## Per-stub fixed delays +WireMock can generate problems for you to test, using web service fakes. You can inject +faulty behaviour that is difficult to to produce on demand from the +real service. -A stub response can have a fixed delay attached to it, such that the -response will not be returned until after the specified number of -milliseconds: +In addition to being able to send back any HTTP response code indicating an error, you can set up delays that are: -```java -stubFor(get(urlEqualTo("/delayed")).willReturn( - aResponse() - .withStatus(200) - .withFixedDelay(2000))); -``` +- fixed (in milliseconds). +- random. +- distributed uniformly or on lognormal. +- chunked. -Or - -```json -{ - "request": { - "method": "GET", - "url": "/delayed" - }, - "response": { - "status": 200, - "fixedDelayMilliseconds": 2000 - } -} -``` +You can also set up "corrupted" responses. ## Global fixed stub delays @@ -53,39 +30,72 @@ following form to `http://:/__admin/settings`: } ``` +## Per-stub fixed delays + +A stub response can have a fixed delay attached to it, such that the +response will not be returned until after the specified number of +milliseconds: + +=== "Java" + + ```java + stubFor(get(urlEqualTo("/delayed")).willReturn( + aResponse() + .withStatus(200) + .withFixedDelay(2000))); + ``` + +=== "JSON" + + ```json + { + "request": { + "method": "GET", + "url": "/delayed" + }, + "response": { + "status": 200, + "fixedDelayMilliseconds": 2000 + } + } + ``` + + ## Per-stub random delays In addition to fixed delays, a delay can be sampled from a random distribution. This allows simulation of more specific downstream latencies, such as a long tail. -Use `#withRandomDelay` on the stub to pass in the desired distribution: - -```java -stubFor(get(urlEqualTo("/random/delayed")).willReturn( - aResponse() - .withStatus(200) - .withLogNormalRandomDelay(90, 0.1))); -``` - -Or set it on the `delayDistribution` field via the JSON api: - -```json -{ - "request": { - "method": "GET", - "url": "/random/delayed" - }, - "response": { - "status": 200, - "delayDistribution": { - "type": "lognormal", - "median": 80, - "sigma": 0.4 +Use `#withRandomDelay` on the stub to pass in the desired distribution, or set it on the `delayDistribution` field via the JSON api: + +=== "Java" + + ```java + stubFor(get(urlEqualTo("/random/delayed")).willReturn( + aResponse() + .withStatus(200) + .withLogNormalRandomDelay(90, 0.1))); + ``` + +=== "JSON" + + ```json + { + "request": { + "method": "GET", + "url": "/random/delayed" + }, + "response": { + "status": 200, + "delayDistribution": { + "type": "lognormal", + "median": 80, + "sigma": 0.4 + } } } -} -``` + ``` ## Global random stub delays @@ -159,32 +169,36 @@ Use `#withChunkedDribbleDelay` on the stub to pass in the desired chunked respon - `numberOfChunks` - how many chunks you want your response body divided up into - `totalDuration` - the total duration you want the response to take in milliseconds -```java -stubFor(get("/chunked/delayed").willReturn( - aResponse() - .withStatus(200) - .withBody("Hello world!") - .withChunkedDribbleDelay(5, 1000))); -``` - Or set it on the `chunkedDribbleDelay` field via the JSON API: -```json -{ - "request": { - "method": "GET", - "url": "/chunked/delayed" - }, - "response": { - "status": 200, - "body": "Hello world!", - "chunkedDribbleDelay": { - "numberOfChunks": 5, - "totalDuration": 1000 +=== "Java" + + ```java + stubFor(get("/chunked/delayed").willReturn( + aResponse() + .withStatus(200) + .withBody("Hello world!") + .withChunkedDribbleDelay(5, 1000))); + ``` + +=== "JSON" + + ```json + { + "request": { + "method": "GET", + "url": "/chunked/delayed" + }, + "response": { + "status": 200, + "body": "Hello world!", + "chunkedDribbleDelay": { + "numberOfChunks": 5, + "totalDuration": 1000 + } } } -} -``` + ``` With the above settings the `Hello world!` response body will be broken into five chunks and returned one at a time with a 200ms gap between each. diff --git a/_site/docs/solutions/README.md b/_site/docs/solutions/README.md new file mode 100644 index 00000000..3bff898b --- /dev/null +++ b/_site/docs/solutions/README.md @@ -0,0 +1,5 @@ +# WireMock Solutions + +There are also solutions and guides for particular technologies and frameworks, provided by the WireMock community and external contributors. + +See the [documentation landing](../README.md) diff --git a/_docs/solutions/android.md b/_site/docs/solutions/android.md similarity index 65% rename from _docs/solutions/android.md rename to _site/docs/solutions/android.md index 580b287d..d163107f 100644 --- a/_docs/solutions/android.md +++ b/_site/docs/solutions/android.md @@ -4,7 +4,6 @@ title: Running on Android meta_title: Running WireMock on the Android platform | WireMock toc_rank: 115 description: With some effort it is now possible to run WireMock on Android. Please see Sam Edwards’ excellent blog post for instructions. -redirect_from: "/docs/android.html" logo: /images/logos/technology/android.svg --- @@ -24,8 +23,13 @@ References: +## Presentation by Michael Bailey + +Michael Bailey was the first person to publicly demonstrate the possibility of running WireMock on Android. Here's his presentation at Google's GTAC conference on the testing setup used by his team at Amex: +[https://www.youtube.com/watch?v=-xQCNf_5NNM](https://www.youtube.com/watch?v=-xQCNf_5NNM) + ## Useful pages -- [WireMock and Kotlin](../kotlin) - Android ecosystem embraces Kotlin as a development language, +- [WireMock and Kotlin](./kotlin.md) - Android ecosystem embraces Kotlin as a development language, and there are some additional tooling available -- [WireMock on Java and JVM](../jvm) - Some of JVM generic solutions are applicable to Android development too +- [WireMock on Java and JVM](./jvm.md) - Some of JVM generic solutions are applicable to Android development too diff --git a/_docs/solutions/c_cpp.md b/_site/docs/solutions/c_cpp.md similarity index 91% rename from _docs/solutions/c_cpp.md rename to _site/docs/solutions/c_cpp.md index 832036f9..fdab5033 100644 --- a/_docs/solutions/c_cpp.md +++ b/_site/docs/solutions/c_cpp.md @@ -9,11 +9,11 @@ og_image: solutions/testcontainers/testcontainers_c_opengraph.png ## Testcontainers for C/C++ module -Testcontainers C +Testcontainers C Recently we created an experimental WireMock module for [Testcontainers for C/C++](https://github.com/oleg-nenashev/testcontainers-c). -It allows provisioning the WireMock server as a standalone container within your tests, based on [WireMock Docker](/docker). +It allows provisioning the WireMock server as a standalone container within your tests, based on [WireMock Docker](../standalone/docker.md). It allows using WireMock with all popular C/C++ testing frameworks like Google Test, CTest, Doctest, QtTest or CppUnit. @@ -78,4 +78,4 @@ Sending HTTP requests printf("Server Response: HTTP-%d\n%s\n\n", response.r0, response.r1); return 0; } -``` \ No newline at end of file +``` diff --git a/_docs/solutions/dotnet.md b/_site/docs/solutions/dotnet.md similarity index 100% rename from _docs/solutions/dotnet.md rename to _site/docs/solutions/dotnet.md diff --git a/_docs/solutions/golang.md b/_site/docs/solutions/golang.md similarity index 93% rename from _docs/solutions/golang.md rename to _site/docs/solutions/golang.md index 5e2b8c5a..6ef66c37 100644 --- a/_docs/solutions/golang.md +++ b/_site/docs/solutions/golang.md @@ -4,9 +4,6 @@ title: "WireMock and Go" meta_title: "Golang Solutions | WireMock" description: "Additional solutions for WireMock when using Golang" logo: /images/logos/technology/golang.svg -redirect_from: -- "/go.html" -- "/go/" hide-disclaimer: true --- @@ -58,7 +55,7 @@ References: ## Go WireMock - WireMock REST API client -The Golang client library to stub API resources in WireMock using its [Administrative REST API](../../standalone/administration). +The Golang client library to stub API resources in WireMock using its [Administrative REST API](../standalone/administration.md). The project connects to the instance and allows setting up stubs and response templating, or using administrative API to extract observability data. References: @@ -89,5 +86,5 @@ func TestSome(t *testing.T) { ## Useful pages -- [WireMock and Docker](../docker) -- [WireMock and Kubernetes](../kubernetes) +- [WireMock and Docker](../standalone/docker.md) +- [WireMock and Kubernetes](./kubernetes.md) diff --git a/_docs/solutions/graphql.md b/_site/docs/solutions/graphql.md similarity index 96% rename from _docs/solutions/graphql.md rename to _site/docs/solutions/graphql.md index 24b0f91e..30aad877 100644 --- a/_docs/solutions/graphql.md +++ b/_site/docs/solutions/graphql.md @@ -5,9 +5,6 @@ meta_title: "GraphQL Solutions | WireMock" description: "Additional solutions for WireMock when using Golang" logo: /images/logos/technology/graphql.svg og_image: solutions/graphql/wiremock_graphql_opengraph.png -redirect_from: -- "/graphql.html" -- "/graphql/" hide-disclaimer: true --- diff --git a/_docs/solutions/groovy.md b/_site/docs/solutions/groovy.md similarity index 89% rename from _docs/solutions/groovy.md rename to _site/docs/solutions/groovy.md index 400f251c..b41f730c 100644 --- a/_docs/solutions/groovy.md +++ b/_site/docs/solutions/groovy.md @@ -45,4 +45,4 @@ def "test using groovy truth if you need at least one request and shows example ## Useful pages -- [WireMock on Java and JVM](../solutions/jvm) - Most of JVM generic solutions are applicable to Groovy development too +- [WireMock on Java and JVM](./jvm.md) - Most of JVM generic solutions are applicable to Groovy development too diff --git a/_docs/solutions/jvm.md b/_site/docs/solutions/jvm.md similarity index 56% rename from _docs/solutions/jvm.md rename to _site/docs/solutions/jvm.md index ff6c06d9..7ad90696 100644 --- a/_docs/solutions/jvm.md +++ b/_site/docs/solutions/jvm.md @@ -14,55 +14,54 @@ and there are plenty of solutions when developing applications powered by the Ja _WireMock_, also known as _WireMock Java_ is the flagman implementation of WireMock functionality and specifications, maintained on the WireMock GitHub organization. -It is included into many distributions (including [WireMock Docker](../docker)), test framework adapters and products. +It is included into many distributions (including [WireMock Docker](../standalone/docker.md)), test framework adapters and products. Most of the documentation on this website is about _WireMock Java_, unless specified explicitly. Usage: -- [Running WireMock as a Standalone server](../../running-standalone) -- [Using WireMock in plain Java without frameworks](../../java-usage) +- [Running WireMock as a Standalone server](../standalone.md) +- [Using WireMock in plain Java without frameworks](./../java-usage.md) References: - [WireMock Java on GitHub](https://github.com/wiremock/wiremock) -## Integrations with test frameworks +## WireMock Extensions + +_WireMock Java_ is [extensible](../extending-wiremock.md), +and there is a number of available extensions that can be included into WireMock +to extend its functionality, including but not limited to request filters, observability, storage, etc. + +See the list of WireMock Extensions [here](../extensions/README.md). + +## Integrations + +### Integrations with test frameworks WireMock has integrations with many popular Java test frameworks for unit and integration testing. -- [JUnit 5+ and Jupiter](../../junit-5) -- [JUnit 4 and Vintage](../../junit-4) -- [Testcontainers Java](https://github.com/wiremock/wiremock-testcontainers-java) +- [JUnit 5+ and Jupiter](../junit-jupiter.md) +- [JUnit 4 and Vintage](../junit-extensions.md) +- [Testcontainers for Java](./testcontainers.md) - [Spock](https://github.com/felipefzdz/spock-wiremock-extension) - maintained outside WireMock's organization on GitHub -## WireMock Extensions +### By JVM language -_WireMock Java_ is [extensible](../../extending-wiremock), -and there is a number of available extensions that can be included into WireMock -to extend its functionality, including but not limited to request filters, observability, storage, etc. +In addition to core Java, WireMock offers specialized integrations +(e.g. DSL Bindings or test framework libraries) +for the following languages: -A few popular extensions: +- [Kotlin](./kotlin.md) +- [Scala](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p) +- [Clojure](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p) +- [Groovy](./groovy.md) -- Response Template Transformer - - [Documentation](../../response-templating) - - This extension is a built-in part of the WireMock Java, but needs to be enabled explicitly -- Webhooks - - [Documentation](../../webhooks-and-callbacks/) -- JSON Body Transformer, Callback Simulator, Request time matcher - - [9cookies/wiremock-extensions](https://github.com/9cookies/wiremock-extensions) -Active -- CORS Protection Extension - - [RichieLoco/WiremockCorsExtension](https://github.com/RichieLoco/WiremockCorsExtension) +### By JVM Framework -## Solutions specific to JVM technologies +- [Spring Boot](./spring-boot.md) +- [Quarkus](./quarkus.md) -Here are references to particular JVM technologies and languages, -sorted by alphabet: +## Related topics -- [Android](../android) -- [Clojure](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p) -- [Groovy](../groovy) -- [Kotlin](../kotlin) -- [Scala](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p) -- [Spring Boot](../spring-boot) +- [WireMock on Android](./android.md) diff --git a/_docs/solutions/kotlin.md b/_site/docs/solutions/kotlin.md similarity index 99% rename from _docs/solutions/kotlin.md rename to _site/docs/solutions/kotlin.md index 322b90d8..a7933314 100644 --- a/_docs/solutions/kotlin.md +++ b/_site/docs/solutions/kotlin.md @@ -63,4 +63,3 @@ References: - [Documentation](https://kotest.io/docs/extensions/wiremock.html) - [GitHub repo: kotest/kotest-extensions-wiremock](https://github.com/kotest/kotest-extensions-wiremock) - diff --git a/_docs/solutions/kubernetes.md b/_site/docs/solutions/kubernetes.md similarity index 94% rename from _docs/solutions/kubernetes.md rename to _site/docs/solutions/kubernetes.md index 5e22728b..08f1956d 100644 --- a/_docs/solutions/kubernetes.md +++ b/_site/docs/solutions/kubernetes.md @@ -35,4 +35,4 @@ References: ## Useful pages -- [WireMock and Golang](../golang) - There's WireMock for Golang developers too! +- [WireMock and Golang](./golang.md) - There's WireMock for Golang developers too! diff --git a/_docs/solutions/nodejs.md b/_site/docs/solutions/nodejs.md similarity index 94% rename from _docs/solutions/nodejs.md rename to _site/docs/solutions/nodejs.md index 47f9f867..f18d481e 100644 --- a/_docs/solutions/nodejs.md +++ b/_site/docs/solutions/nodejs.md @@ -47,7 +47,7 @@ describe('Integration with WireMock', () => { ## WireMock REST Client The WireMock REST client is a lightweight module to interact with a running -WireMock server based on its [OpenAPI 3.0 spec](../../api) via REST API. +WireMock server based on its [OpenAPI 3.0 spec](../standalone/admin-api-reference.md) via REST API. Note that this library is maintained outside the WireMock organization on GitHub. - [GitHUb Repository](https://github.com/kwoding/wiremock-rest-client) diff --git a/_docs/solutions/python.md b/_site/docs/solutions/python.md similarity index 91% rename from _docs/solutions/python.md rename to _site/docs/solutions/python.md index 8f4f2f93..ea90813c 100644 --- a/_docs/solutions/python.md +++ b/_site/docs/solutions/python.md @@ -13,7 +13,7 @@ hide-disclaimer: true **Python WireMock** is a library that allows users to interact with a WireMock instance from within a Python project. Key features include: -- [Testcontainers Python](../testcontainers) module to easily start WireMock server for your tests +- [Testcontainers Python](./testcontainers.md) module to easily start WireMock server for your tests - REST API Client for a standalone WireMock Java server - Support for most of the major WireMock features (more on their way soon) diff --git a/_docs/solutions/quarkus.md b/_site/docs/solutions/quarkus.md similarity index 100% rename from _docs/solutions/quarkus.md rename to _site/docs/solutions/quarkus.md diff --git a/_docs/solutions/rust.md b/_site/docs/solutions/rust.md similarity index 97% rename from _docs/solutions/rust.md rename to _site/docs/solutions/rust.md index 150db781..1477fc41 100644 --- a/_docs/solutions/rust.md +++ b/_site/docs/solutions/rust.md @@ -79,7 +79,7 @@ References: ## Testcontainers module We are interested in providing a Testcontainers for Rust module that -would provide SDK for the official [WireMock Docker images](../../docker). +would provide SDK for the official [WireMock Docker images](../standalone/docker.md). This module is on our roadmap but have not been published yet, see [wiremock/ecosystem #8](https://github.com/wiremock/ecosystem/issues/8). Contributions are welcome! diff --git a/_docs/solutions/spring-boot.md b/_site/docs/solutions/spring-boot.md similarity index 92% rename from _docs/solutions/spring-boot.md rename to _site/docs/solutions/spring-boot.md index bb27b622..b166461e 100644 --- a/_docs/solutions/spring-boot.md +++ b/_site/docs/solutions/spring-boot.md @@ -4,8 +4,6 @@ title: "Using WireMock with Spring Boot" meta_title: Running WireMock with Spring Boot | WireMock toc_rank: 116 description: The team behind Spring Cloud Contract have created a library to support running WireMock using the “ambient” HTTP server -redirect_from: -- "/docs/spring-boot.html" logo: /images/logos/technology/spring.svg --- @@ -61,4 +59,4 @@ from Pivotal's blog shows how WireMock can be used to test Spring apps that use ## Useful pages -- [WireMock on Java and JVM](../solutions/jvm) - Most of JVM generic solutions are applicable to Spring Boot development too +- [WireMock on Java and JVM](./jvm.md) - Most of JVM generic solutions are applicable to Spring Boot development too diff --git a/_docs/solutions/testcontainers.md b/_site/docs/solutions/testcontainers.md similarity index 56% rename from _docs/solutions/testcontainers.md rename to _site/docs/solutions/testcontainers.md index c1d5f83b..6c474c17 100644 --- a/_docs/solutions/testcontainers.md +++ b/_site/docs/solutions/testcontainers.md @@ -5,11 +5,6 @@ meta_title: "Testcontainers Solutions | WireMock" description: "Additional solutions for WireMock when using Testcontainers" logo: /images/logos/technology/testcontainers.svg hide-disclaimer: true -redirect_from: -- "/docs/testcontainers.html" -- "/docs/testcontainers/" -- "/testcontainers.html" -- "/testcontainers/" --- The WireMock community provides modules for [Testcontainers](https://testcontainers.com/). @@ -20,7 +15,7 @@ All the modules are under active development. If there is no module implemented for your technology stack, a `GenericContainer` implementation from Testcontainers can be used. For features that are not implemented yet in Module APIs for your language, -it is possible to use the [Administrative REST API](../../standalone/administration). +it is possible to use the [Administrative REST API](../standalone/administration.md). Feedback and contributions are welcome! See WireMock on the [Testcontainers modules listing](https://testcontainers.com/modules/wiremock/). @@ -51,17 +46,17 @@ for all documentation and examples. Golang implementation is a multi-platform library that includes the Testcontainers module only. The module's full documentation and examples are available in its [GitHub Repository](https://github.com/wiremock/wiremock-testcontainers-go). -There is a separate library for the CLI, see the [Golang Solutions page](../golang). +There is a separate library for the CLI, see the [Golang Solutions page](./golang.md). ## Experimental modules **C/C++ and other native languages.** We created a WireMock module for [Testcontainers for C/C++](https://github.com/oleg-nenashev/testcontainers-c). -It allows provisioning the WireMock server as a standalone container within your tests, based on [WireMock Docker](/docker). +It allows provisioning the WireMock server as a standalone container within your tests, based on [WireMock Docker](../standalone/docker.md). It allows using WireMock with all popular C/C++ testing frameworks like Google Test, CTest, Doctest, QtTest or CppUnit. -Read More: [C/C++ Solutions Page](../c_cpp). +Read More: [C/C++ Solutions Page](./c_cpp.md). ## Other Languages @@ -76,105 +71,95 @@ Node.js, Rust, Haskell, Ruby, etc. Examples of using the Testcontainers Modules for different languages and Testcontainers modules: -{% codetabs %} - -{% codetab Java %} - -```java -import org.junit.jupiter.api.*; -import org.testcontainers.junit.jupiter.*; -import org.wiremock.integrations.testcontainers.testsupport.http.*; -import static org.assertj.core.api.Assertions.assertThat; - -@Testcontainers -class WireMockContainerJunit5Test { - - @Container - WireMockContainer wiremockServer = new WireMockContainer("2.35.0") - .withMapping("hello", WireMockContainerJunit5Test.class, "hello-world.json"); - - @Test - void helloWorld() throws Exception { - String url = wiremockServer.getUrl("/hello"); - HttpResponse response = new TestHttpClient().get(url); - assertThat(response.getBody()) - .as("Wrong response body") - .contains("Hello, world!"); +=== "Java" + + ```java + import org.junit.jupiter.api.*; + import org.testcontainers.junit.jupiter.*; + import org.wiremock.integrations.testcontainers.testsupport.http.*; + import static org.assertj.core.api.Assertions.assertThat; + + @Testcontainers + class WireMockContainerJunit5Test { + + @Container + WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + .withMapping("hello", WireMockContainerJunit5Test.class, "hello-world.json"); + + @Test + void helloWorld() throws Exception { + String url = wiremockServer.getUrl("/hello"); + HttpResponse response = new TestHttpClient().get(url); + assertThat(response.getBody()) + .as("Wrong response body") + .contains("Hello, world!"); + } } -} -``` - -{% endcodetab %} - -{% codetab Python %} - -```python -import pytest -from wiremock.testing.testcontainer import wiremock_container - -@pytest.fixture(scope="session") # (1) -def wm_server(): - with wiremock_container(secure=False) as wm: - Config.base_url = wm.get_url("__admin") # (2)= - Mappings.create_mapping( - Mapping( - request=MappingRequest(method=HttpMethods.GET, url="/hello"), - response=MappingResponse(status=200, body="hello"), - persistent=False, - ) - ) # (3) - yield wm - -def test_get_hello_world(wm_server): # (4) - resp1 = requests.get(wm_server.get_url("/hello"), verify=False) - assert resp1.status_code == 200 - assert resp1.content == b"hello" -``` - -{% endcodetab %} - -{% codetab Golang %} - -```golang -package testcontainers_wiremock_quickstart - -import ( - "context" - "testing" - - . "github.com/wiremock/wiremock-testcontainers-go" -) - -func TestWireMock(t *testing.T) { - ctx := context.Background() - mappingFileName := "hello-world.json" - - container, err := RunContainerAndStopOnCleanup(ctx, t, - WithMappingFile(mappingFileName), - ) - if err != nil { - t.Fatal(err) - } - - statusCode, out, err := SendHttpGet(container, "/hello", nil) - if err != nil { - t.Fatal(err, "Failed to get a response") - } - - // Verify the response - if statusCode != 200 { - t.Fatalf("expected HTTP-200 but got %d", statusCode) - } - - if string(out) != "Hello, world!" { - t.Fatalf("expected 'Hello, world!' but got %s", out) - } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` + +=== "Python" + + ```python + import pytest + from wiremock.testing.testcontainer import wiremock_container + + @pytest.fixture(scope="session") # (1) + def wm_server(): + with wiremock_container(secure=False) as wm: + Config.base_url = wm.get_url("__admin") # (2)= + Mappings.create_mapping( + Mapping( + request=MappingRequest(method=HttpMethods.GET, url="/hello"), + response=MappingResponse(status=200, body="hello"), + persistent=False, + ) + ) # (3) + yield wm + + def test_get_hello_world(wm_server): # (4) + resp1 = requests.get(wm_server.get_url("/hello"), verify=False) + assert resp1.status_code == 200 + assert resp1.content == b"hello" + ``` + +=== "Golang" + + ```golang + package testcontainers_wiremock_quickstart + + import ( + "context" + "testing" + + . "github.com/wiremock/wiremock-testcontainers-go" + ) + + func TestWireMock(t *testing.T) { + ctx := context.Background() + mappingFileName := "hello-world.json" + + container, err := RunContainerAndStopOnCleanup(ctx, t, + WithMappingFile(mappingFileName), + ) + if err != nil { + t.Fatal(err) + } + + statusCode, out, err := SendHttpGet(container, "/hello", nil) + if err != nil { + t.Fatal(err, "Failed to get a response") + } + + // Verify the response + if statusCode != 200 { + t.Fatalf("expected HTTP-200 but got %d", statusCode) + } + + if string(out) != "Hello, world!" { + t.Fatalf("expected 'Hello, world!' but got %s", out) + } + } + ``` ## Coming soon @@ -183,8 +168,6 @@ A lot more features can be implemented in the listed modules, and any contributions are welcome! If you are interested, join us on the [community Slack](http://slack.wiremock.org/). -## Learn More - ## References - Devoxx BE talk on API Integration testing with Testcontainers and WireMock, diff --git a/_site/docs/standalone.md b/_site/docs/standalone.md new file mode 100644 index 00000000..9d9414bc --- /dev/null +++ b/_site/docs/standalone.md @@ -0,0 +1,28 @@ +--- +description: + run as a standalone service. + We provide the JAR file and Docker image distributions for it. +--- + +# WireMock as a Standalone Service + +YOu can run WireMock as a standalone service, +configured using the Java API, JSON over HTTP, or JSON files. +We provide both a JAR file and Docker image distributions. + +## Running WireMock + +- [Running as a Docker Image](./standalone/docker.md) +- [Running as a JAR file](./standalone/java-jar.md) + +## Management + +When WireMock runs as a standalone service, it can be managed through its REST API. + +- [WireMock Administration](./standalone/administration.md) +- [Admin API Reference](./standalone/admin-api-reference.md) + +## API Clients + +There are several API clients that work with the standalone WireMock instance. +Check out the [Solution pages](./solutions/README.md) for more info and pointers. diff --git a/_site/docs/standalone/admin-api-reference.md b/_site/docs/standalone/admin-api-reference.md new file mode 100644 index 00000000..6c3ba16a --- /dev/null +++ b/_site/docs/standalone/admin-api-reference.md @@ -0,0 +1,15 @@ +--- +layout: splash +title: Admin API Reference +meta_title: WireMock Admin REST API Documentation | WireMock +toc_rank: 120 +description: The WireMock admin API is described in OpenAPI 3.0. +--- + +The WireMock admin API is described in [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md). + +The spec file plus an instance of Swagger UI can be accessed from a running WireMock instance under `/__admin/docs/`, e.g. `http://localhost:8080/__admin/docs/`. + +Below is the full API reference: + +!!swagger-http https://raw.githubusercontent.com/wiremock/wiremock/master/src/main/resources/swagger/wiremock-admin-api.json!! diff --git a/_docs/standalone/administration.md b/_site/docs/standalone/administration.md similarity index 79% rename from _docs/standalone/administration.md rename to _site/docs/standalone/administration.md index ff573545..3ae448a6 100644 --- a/_docs/standalone/administration.md +++ b/_site/docs/standalone/administration.md @@ -1,10 +1,9 @@ --- -layout: docs -title: Administration API -meta_title: Administration API in WireMock Standalone | WireMock description: Provides tips on managing standalone WireMock servers --- +# Administration API in WireMock Standalone + WireMock Standalone offers the REST API for administration, troubleshooting and analysis purposes. You can find the key use-cases and the full specification below. @@ -21,4 +20,4 @@ post a request with an empty body to `http://:/__admin/shutdown`. ## Full specification -The full specification is available [here](../admin-api-reference). +The full specification is available [here](./admin-api-reference.md). diff --git a/_docs/standalone/docker.md b/_site/docs/standalone/docker.md similarity index 74% rename from _docs/standalone/docker.md rename to _site/docs/standalone/docker.md index 2ebc00b4..29f47436 100644 --- a/_docs/standalone/docker.md +++ b/_site/docs/standalone/docker.md @@ -1,14 +1,11 @@ --- -layout: docs -title: Running in Docker -meta_title: Configuring and running WireMock in Docker | WireMock -description: The Docker image supports exactly the same set of command line arguments as the standalone version. These can be passed to the container by appending them to the end of the command. -redirect_from: - - "/docs/solutions/docker.html" - - "/docs/docker.html" - - "/docs/docker/" +description: > + The Docker image supports exactly the same set of command line arguments as the standalone version. + These can be passed to the container by appending them to the end of the command. --- +# Configuring and running WireMock in Docker + From version 2.31.0 WireMock has an [official Docker image](https://hub.docker.com/r/wiremock/wiremock). ## Getting started @@ -19,27 +16,27 @@ From version 2.31.0 WireMock has an [official Docker image](https://hub.docker.c docker run -it --rm \ -p 8080:8080 \ --name wiremock \ - wiremock/wiremock:{{ site.wiremock_version }} + wiremock/wiremock:{{ versions.wiremock_version }} ``` > Access [http://localhost:8080/\_\_admin/mappings](http://localhost:8080/__admin/mappings) to display the mappings (empty set) ### Start with command line arguments -The Docker image supports exactly the same set of command line arguments as the [standalone version](../java-jar#command-line-options). +The Docker image supports exactly the same set of command line arguments as the [standalone version](./java-jar.md#command-line-options). These can be passed to the container by appending them to the end of the command e.g.: ```sh docker run -it --rm \ -p 8443:8443 \ --name wiremock \ - wiremock/wiremock:{{ site.wiremock_version }} \ + wiremock/wiremock:{{ versions.wiremock_version }} \ --https-port 8443 --verbose ``` #### Passing command line arguments as environment variable -Starting from `3.2.0-2`, the Docker image supports passing command line arguments [standalone version](../java-jar#command-line-options) as the environment variable. +Starting from `3.2.0-2`, the Docker image supports passing command line arguments [standalone version](./java-jar.md#command-line-options) as the environment variable. Environment variable `WIREMOCK_OPTIONS` can be passed to container consisting of all command line arguments e.g.: ```sh @@ -47,7 +44,7 @@ docker run -it --rm \ -e WIREMOCK_OPTIONS='--https-port 8443 --verbose' \ -p 8443:8443 \ --name wiremock \ - wiremock/wiremock:{{ site.wiremock_version }} + wiremock/wiremock:{{ versions.wiremock_version }} ``` ### Mounting stub mapping files @@ -62,15 +59,15 @@ docker run -it --rm \ -p 8080:8080 \ --name wiremock \ -v $PWD:/home/wiremock \ - wiremock/wiremock:{{ site.wiremock_version }} + wiremock/wiremock:{{ versions.wiremock_version }} ``` ### Running with extensions -[WireMock extensions](../../extending-wiremock/) are packaged as JAR files. In order to use them they need to be made +[WireMock extensions](../extending-wiremock.md) are packaged as JAR files. In order to use them they need to be made available at runtime and WireMock must be configured to enable them. -For example, to use the [Webhooks extension](../../webhooks-and-callbacks/) we would first download [wiremock-webhooks-extension-{{ site.wiremock_version }}.jar](https://repo1.maven.org/maven2/org/wiremock/wiremock-webhooks-extension/{{ site.wiremock_version }}/wiremock-webhooks-extension-{{ site.wiremock_version }}.jar) +For example, to use the [Webhooks extension](../webhooks-and-callbacks.md) we would first download [wiremock-webhooks-extension-{{ versions.wiremock_version }}.jar](https://repo1.maven.org/maven2/org/wiremock/wiremock-webhooks-extension/{{ versions.wiremock_version }}/wiremock-webhooks-extension-{{ versions.wiremock_version }}.jar) into the `extensions` directory under our working directory. Then when starting Docker we would mount the extensions directory to `/var/wiremock/extensions` and enable the webhooks extension diff --git a/_docs/standalone/java-jar.md b/_site/docs/standalone/java-jar.md similarity index 86% rename from _docs/standalone/java-jar.md rename to _site/docs/standalone/java-jar.md index fd949cff..de2dece2 100644 --- a/_docs/standalone/java-jar.md +++ b/_site/docs/standalone/java-jar.md @@ -1,23 +1,16 @@ --- -layout: docs -title: Running as a Standalone Process -meta_title: Run an API Mock Server as a Standalone Process | WireMock -toc_rank: 41 -redirect_from: - - "/running-standalone.html" - - "/running-standalone/" - - "/docs/running-standalone.html" - - "/docs/running-standalone/" description: The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. --- +# Run the API Mock Server as a Standalone Process + The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. -Once you have [downloaded the standalone JAR](../../download) you can run it simply by doing this: +Once you have [downloaded the standalone JAR](./../download-and-installation.md) you can run it simply by doing this: ```bash -$ java -jar wiremock-standalone-{{ site.wiremock_version }}.jar +$ java -jar wiremock-standalone-{{ versions.wiremock_version }}.jar ``` ## Command line options @@ -52,8 +45,8 @@ sets the keystore password value. The key manager password can be set with the ( `--https-truststore`: Path to a keystore file containing client public certificates, proxy target public certificates & private keys to use when authenticate with a proxy target that require client authentication. Can be a path to a file or a resource on the classpath. See -[HTTPS configuration](../../configuration#https-configuration) -and [Running as a browser proxy](../../proxying#running-as-a-browser-proxy) for +[HTTPS configuration](./../configuration.md#https-configuration) +and [Running as a browser proxy](./../proxying.md#running-as-a-browser-proxy) for details. `--truststore-type`: The HTTPS trust store type. Usually JKS or PKCS12. @@ -62,7 +55,7 @@ details. to "password" if not specified. `--https-require-client-cert`: Force clients to authenticate with a -client certificate. See [HTTPS](../../https/) for details. +client certificate. See [HTTPS](./../https.md) for details. `--verbose`: Turn on verbose logging to stdout @@ -70,10 +63,10 @@ client certificate. See [HTTPS](../../https/) for details. `__files` reside. This defaults to the current directory. `--record-mappings`: Record incoming requests as stub mappings. See -[Record and Playback](../../record-playback/). +[Record and Playback](./../record-playback.md). `--match-headers`: When in record mode, capture request headers with the -keys specified. See [Record and Playback](../../record-playback/). +keys specified. See [Record and Playback](./../record-playback.md). `--proxy-all`: Proxy all requests through to another base URL e.g. `--proxy-all="http://api.someservice.com"` Typically used in conjunction @@ -95,7 +88,7 @@ internet access via an opaque proxy). e.g. e.g. `--proxy-via http://username:password@webproxy.mycorp.com:8080/`. `--enable-browser-proxying`: Run as a browser proxy. See -[Running as a browser proxy](../../proxying#running-as-a-browser-proxy). +[Running as a browser proxy](./../proxying.md#running-as-a-browser-proxy). `--ca-keystore`: A key store containing a root Certificate Authority private key and certificate that can be used to sign generated certificates when @@ -149,7 +142,7 @@ Recommended when using WireMock for performance testing with delays, as it allow Effective only with `asynchronousResponseEnabled=true`. Defaults to 10. `--extensions`: Extension class names e.g. -com.mycorp.HeaderTransformer,com.mycorp.BodyTransformer. See [Extending WireMock](../../extending-wiremock/). +com.mycorp.HeaderTransformer,com.mycorp.BodyTransformer. See [Extending WireMock](./../extending-wiremock.md). `--print-all-network-traffic`: Print all raw incoming and outgoing network traffic to console. @@ -174,15 +167,15 @@ The last of these will cause chunked encoding to be used only when a stub define `--logged-response-body-size-limit`: Set a limit in bytes beyond which response bodies in the log will be truncated. When enabled this helps avoid out of memory errors when serving large response bodies. -`--allow-proxy-targets`: Limit the permitted targets for proxying to and recording from the supplied addressess. This parameter takes a comma-separated list of single IP addresses, IP address ranges and hostname wildcards. See [this article](../../configuration#preventing-proxying-to-and-recording-from-specific-target-addresses) for details. +`--allow-proxy-targets`: Limit the permitted targets for proxying to and recording from the supplied addresses. This parameter takes a comma-separated list of single IP addresses, IP address ranges and hostname wildcards. See [this article](./../configuration.md#preventing-proxying-to-and-recording-from-specific-target-addresses) for details. -`--deny-proxy-targets`: Prevent proxying to and recording from the supplied addressess. This parameter takes a comma-separated list of single IP addresses, IP address ranges and hostname wildcards. Note: if both `--allow-proxy-targets` and this parameter are set, the allow list will be evaluated first. See [this article](../../configuration#preventing-proxying-to-and-recording-from-specific-target-addresses) for details. +`--deny-proxy-targets`: Prevent proxying to and recording from the supplied addresses. This parameter takes a comma-separated list of single IP addresses, IP address ranges and hostname wildcards. Note: if both `--allow-proxy-targets` and this parameter are set, the allow list will be evaluated first. See [this article](./../configuration.md#preventing-proxying-to-and-recording-from-specific-target-addresses) for details. `--proxy-timeout`: Set the timeout for requests to the proxy in milliseconds `--proxy-pass-through`: Flag used in browser-caching in order to enable or disable pass through unmatched requests to the target indicated by the original requests. By default, this flag is enabled and let the requests pass through. -`--filename-template`: Set filename template in handlebar format. For endpoint: `GET /pets/{id}` using the format: `{{{method}}}-{{{url}}}.json` output will be `get-pets-id.json`. Default format: `{{{method}}}-{{{path}}}-{{{id}}}.json` hence by default template filename will be: `get-pets-id-1.json`. +`--filename-template`: Set filename template in handlebar format. For endpoint: `GET /pets/{id}` using the format: {% raw %} `{{{method}}}-{{{url}}}.json` {% endraw %} output will be `get-pets-id.json`. Default format: {% raw %} `{{{method}}}-{{{path}}}-{{{id}}}.json` {% endraw %} hence by default template filename will be: `get-pets-id-1.json`. Note: introduced in [3.0.0-beta-8](https://github.com/wiremock/wiremock/releases/tag/3.0.0-beta-8). `--help`: Show command line help @@ -222,7 +215,7 @@ $ curl http://localhost:8080/get/this Here it is! ``` -The full stubbing API syntax is described in [Stubbing](../../stubbing/). +The full stubbing API syntax is described in [Stubbing](./../stubbing.md). ## JSON file configuration @@ -253,7 +246,7 @@ $ curl http://localhost:8080/api/mytest More content ``` -See [stubbing](../../stubbing/) and [verifying](../../verifying/) for more on the JSON API. +See [stubbing](./../stubbing.md) and [verifying](./../verifying.md) for more on the JSON API. ### Multi-stub JSON files diff --git a/_site/docs/stateful-behaviour.md b/_site/docs/stateful-behaviour.md new file mode 100644 index 00000000..b4666862 --- /dev/null +++ b/_site/docs/stateful-behaviour.md @@ -0,0 +1,181 @@ +--- +description: > + mocking states for Web services. +--- + +# Simulating Stateful Behavior for Testing + +WireMock supports simulations of stateful behaviors of Web services. You can make use of states that change during the time that +users interact with them. + +## Scenarios + +You manage mocking of stateful behavior using scenarios. A scenario is essentially a state machine whose states can be arbitrarily assigned. + +When working with scenarios: + +- the starting state is always `Scenario.STARTED`. +- stub mappings can be configured to match a scenario state, and run sequentially. +-- for example, stub A can be returned initially, then stub B once the next scenario state has been triggered. + +The following examples illustrate this concept, using a to-do list application that is a +rich client of some kind and sends requests to a REST service. This tests +that the UI can read the to-do list, add an item, and refresh itself, +showing the updated list: + +=== "Java" + + ```java + @Test + public void toDoListScenario() { + stubFor(get(urlEqualTo("/todo/items")).inScenario("To do list") + .whenScenarioStateIs(STARTED) + .willReturn(aResponse() + .withBody("" + + " Buy milk" + + ""))); + + stubFor(post(urlEqualTo("/todo/items")).inScenario("To do list") + .whenScenarioStateIs(STARTED) + .withRequestBody(containing("Cancel newspaper subscription")) + .willReturn(aResponse().withStatus(201)) + .willSetStateTo("Cancel newspaper item added")); + + stubFor(get(urlEqualTo("/todo/items")).inScenario("To do list") + .whenScenarioStateIs("Cancel newspaper item added") + .willReturn(aResponse() + .withBody("" + + " Buy milk" + + " Cancel newspaper subscription" + + ""))); + + WireMockResponse response = testClient.get("/todo/items"); + assertThat(response.content(), containsString("Buy milk")); + assertThat(response.content(), not(containsString("Cancel newspaper subscription"))); + + response = testClient.postWithBody("/todo/items", "Cancel newspaper subscription", "text/plain", "UTF-8"); + assertThat(response.statusCode(), is(201)); + + response = testClient.get("/todo/items"); + assertThat(response.content(), containsString("Buy milk")); + assertThat(response.content(), containsString("Cancel newspaper subscription")); + } + ``` + +=== "JSON" + + ```json + { + "mappings": [ + { + "scenarioName": "To do list", + "requiredScenarioState": "Started", + "request": { + "method": "GET", + "url": "/todo/items" + }, + "response": { + "status": 200, + "body": "Buy milk" + } + }, + { + "scenarioName": "To do list", + "requiredScenarioState": "Started", + "newScenarioState": "Cancel newspaper item added", + "request": { + "method": "POST", + "url": "/todo/items", + "bodyPatterns": [ + { "contains": "Cancel newspaper subscription" } + ] + }, + "response": { + "status": 201 + } + }, + { + "scenarioName": "To do list", + "requiredScenarioState": "Cancel newspaper item added", + "request": { + "method": "GET", + "url": "/todo/items" + }, + "response": { + "status": 200, + "body": "Buy milkCancel newspaper subscription" + } + } + ] + } + ``` + +## Getting scenario state + +The names, current state and possible states of all scenarios can be fetched. + +=== "Java" + + ```java + List allScenarios = getAllScenarios(); + ``` + +=== "JSON" + + ```json + GET /__admin/scenarios + { + "scenarios" : [ { + "id" : "my_scenario", + "name" : "my_scenario", + "state" : "Started", + "possibleStates" : [ "Started", "state_2", "state_3" ] + } ] + } + ``` + +## Resetting scenarios + +The state of all configured scenarios can be reset back to +`Scenario.START` either by calling + +Java: + +```java +WireMock.resetAllScenarios() +``` + +To do the equivalent via the HTTP API, send an empty `POST` request to `/__admin/scenarios/reset`. + + +## Resetting a single scenario + +You can reset the state of an individual scenario. + +Java: + +```java +WireMock.resetScenario("my_scenario"); +``` + +The do the equivalent via the HTTP API, send an empty `PUT` to `/__admin/scenarios/my_scenario/state`. + + +## Setting the state of an individual scenario + +You can also set the state of an individual scenario to a specific value: + +=== "Java" + + ```java + WireMock.setScenarioState("my_scenario", "state_2"); + ``` + +=== "HTTP" + + ```json + PUT /__admin/scenarios/my_scenario/state + { + "state": "state_2" + } + ``` diff --git a/_site/docs/stub-metadata.md b/_site/docs/stub-metadata.md new file mode 100644 index 00000000..b3a1e383 --- /dev/null +++ b/_site/docs/stub-metadata.md @@ -0,0 +1,103 @@ +--- +description: > + attach arbitrary metadata to stub mappings, + to use later in search, deletion, or retrieval. +--- + +# Associating and using metadata with API stubs + +You can attach arbitrary metadata to stub mappings, to be used later for any of the following: + +- search. +- deletion. +- retrieval. + +## Adding metadata to stubs + +Data under the `metadata` key is a JSON object, represented in Java by a `Map`, and can be added to a stub mapping on creation. + +=== "Java" + + ```java + stubFor(get("/with-metadata") + .withMetadata(metadata() + .attr("singleItem", 1234) + .list("listItem", 1, 2, 3, 4) + .attr("nestedObject", metadata() + .attr("innerItem", "Hello") + ) + )); + ``` + +=== "JSON" + + ```json + { + "request": { + "url": "/with-metadata" + }, + "response": { + "status": 200 + }, + + "metadata": { + "singleItem": 1234, + "listItem": [1, 2, 3, 4], + "nestedObject": { + "innerItem": "Hello" + } + } + } + ``` + +## Search for stubs by metadata + +To find stubs by matching against their metadata, use the same matching strategies as when you use [matching HTTP requests](./request-matching.md). +The most useful matcher for this is `matchesJsonPath`: + +=== "Java" + + ```java + List stubs = + findStubsByMetadata(matchingJsonPath("$.singleItem", containing("123"))); + ``` + +=== "JSON" + + ```json + POST /__admin/mappings/find-by-metadata + + { + "matchesJsonPath" : { + "expression" : "$.singleItem", + "contains" : "123" + } + } + ``` + +## Remove stubs by metadata + +Similarly, stubs with matching metadata can be removed: + +=== "Java" + + ```java + removeStubsByMetadata(matchingJsonPath("$.singleItem", containing("123"))); + ``` + +=== "JSON" + + POST /__admin/mappings/remove-by-metadata + + ```json + { + "matchesJsonPath" : { + "expression" : "$.singleItem", + "contains" : "123" + } + } + ``` + +## Remove request journal events by metadata + +See [Removing items from the journal](./verifying.md#by-criteria) diff --git a/_docs/stubbing.md b/_site/docs/stubbing.md similarity index 54% rename from _docs/stubbing.md rename to _site/docs/stubbing.md index eb72e0c3..28646341 100644 --- a/_docs/stubbing.md +++ b/_site/docs/stubbing.md @@ -1,14 +1,13 @@ --- -layout: docs -title: Stubbing -meta_title: Returning stubbed HTTP responses to specific requests | WireMock -toc_rank: 50 -redirect_from: "/stubbing.html" -description: A core feature of WireMock is the ability to return canned HTTP responses for requests matching criteria. These are described in detail in Request Matching. +description: > + A core feature of WireMock is the ability to return canned HTTP responses for requests that match criteria. + These are described in detail in Request Matching. --- -A core feature of WireMock [API mocking]({{ '/' | absolute_url }}) is the ability to return canned HTTP -responses for requests matching criteria. These are described in detail in [Request Matching](../request-matching/). +# Returning stubbed HTTP responses to specific requests + +A core feature of WireMock [API mocking](./overview.md) is the ability to return canned HTTP +responses for requests that match criteria. These are described in detail in [Request Matching](./request-matching.md). ## Basic stubbing @@ -25,73 +24,61 @@ when the relative URL exactly matches `/some/thing` (including query parameters) The body of the response will be "Hello world!" and a `Content-Type` header will be sent with a value of `text-plain`. -{% codetabs %} +=== "JSON" -{% codetab JSON %} + ```json + { + "request": { + "method": "GET", + "url": "/some/thing" + }, -```json -{ - "request": { - "method": "GET", - "url": "/some/thing" - }, - - "response": { - "status": 200, - "body": "Hello, world!", - "headers": { - "Content-Type": "text/plain" + "response": { + "status": 200, + "body": "Hello, world!", + "headers": { + "Content-Type": "text/plain" + } } - } -} -``` - -{% endcodetab %} - -{% codetab Java %} + } + ``` -```java -@Test -public void exactUrlOnly() { - stubFor(get(urlEqualTo("/some/thing")) - .willReturn(aResponse() - .withHeader("Content-Type", "text/plain") - .withBody("Hello world!"))); +=== "Java" - assertThat(testClient.get("/some/thing").statusCode(), is(200)); - assertThat(testClient.get("/some/thing/else").statusCode(), is(404)); -} -``` + ```java + @Test + public void exactUrlOnly() { + stubFor(get(urlEqualTo("/some/thing")) + .willReturn(aResponse() + .withHeader("Content-Type", "text/plain") + .withBody("Hello world!"))); -{% endcodetab %} + assertThat(testClient.get("/some/thing").statusCode(), is(200)); + assertThat(testClient.get("/some/thing/else").statusCode(), is(404)); + } + ``` -{% codetab Python %} +=== "Python" -```python -Mappings.create_mapping( - Mapping( - request=MappingRequest(method=HttpMethods.GET, url="/some/thing"), - response=MappingResponse(status=200, body="Hello, world!", headers=("Content-Type", "text/plain")), + ```python + Mappings.create_mapping( + Mapping( + request=MappingRequest(method=HttpMethods.GET, url="/some/thing"), + response=MappingResponse(status=200, body="Hello, world!", headers=("Content-Type", "text/plain")), + ) ) -) -``` + ``` -{% endcodetab %} +=== "Golang" -{% codetab Golang %} - -```go -wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo("/some/thing")). - WillReturnResponse( - wiremock.NewResponse(). - WithStatus(http.StatusOK). - WithBody("Hello, world!"). - WithHeader("Content-Type", "text/plain"))) -``` - -{% endcodetab %} - -{% endcodetabs %} + ```go + wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo("/some/thing")). + WillReturnResponse( + wiremock.NewResponse(). + WithStatus(http.StatusOK). + WithBody("Hello, world!"). + WithHeader("Content-Type", "text/plain"))) + ``` In Java, if you'd prefer to use slightly more BDDish language in your tests, you can replace `stubFor` with `givenThat`. @@ -141,44 +128,36 @@ you want the stub mapping to match on any request method. In addition to the status code, the status message can optionally also be set. -{% codetabs %} - -{% codetab Java %} +=== "Java" -```java -@Test -public void statusMessage() { - stubFor(get(urlEqualTo("/some/thing")) - .willReturn(aResponse() - .withStatus(200) - .withStatusMessage("Everything was just fine!") - .withHeader("Content-Type", "text/plain"))); - - assertThat(testClient.get("/some/thing").statusCode(), is(200)); - assertThat(testClient.get("/some/thing/else").statusCode(), is(404)); -} -``` - -{% endcodetab %} - -{% codetab JSON %} + ```java + @Test + public void statusMessage() { + stubFor(get(urlEqualTo("/some/thing")) + .willReturn(aResponse() + .withStatus(200) + .withStatusMessage("Everything was just fine!") + .withHeader("Content-Type", "text/plain"))); -```json -{ - "request": { - "method": "GET", - "url": "/some/thing" - }, - "response": { - "status": 200, - "statusMessage": "Everything was just fine!" + assertThat(testClient.get("/some/thing").statusCode(), is(200)); + assertThat(testClient.get("/some/thing/else").statusCode(), is(404)); } -} -``` + ``` -{% endcodetab %} +=== "JSON" -{% endcodetabs %} + ```json + { + "request": { + "method": "GET", + "url": "/some/thing" + }, + "response": { + "status": 200, + "statusMessage": "Everything was just fine!" + } + } + ``` ## Stub priority @@ -192,42 +171,34 @@ One example of this might be where you want to define a catch-all stub for any URL that doesn't match any more specific cases. Adding a priority to a stub mapping facilitates this: -{% codetabs %} - -{% codetab Java %} +=== "Java" -```java -//Catch-all case -stubFor(get(urlMatching("/api/.*")).atPriority(5) - .willReturn(aResponse().withStatus(401))); - -//Specific case -stubFor(get(urlEqualTo("/api/specific-resource")).atPriority(1) //1 is highest - .willReturn(aResponse() - .withStatus(200) - .withBody("Resource state"))); -``` + ```java + //Catch-all case + stubFor(get(urlMatching("/api/.*")).atPriority(5) + .willReturn(aResponse().withStatus(401))); -{% endcodetab %} + //Specific case + stubFor(get(urlEqualTo("/api/specific-resource")).atPriority(1) //1 is highest + .willReturn(aResponse() + .withStatus(200) + .withBody("Resource state"))); + ``` -{% codetab Json %} +=== "JSON" -```json -{ - "priority": 1, - "request": { - "method": "GET", - "url": "/api/specific-resource" - }, - "response": { - "status": 200 + ```json + { + "priority": 1, + "request": { + "method": "GET", + "url": "/api/specific-resource" + }, + "response": { + "status": 200 + } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` When unspecified, stubs default to a priority of `5`[^](https://github.com/wiremock/wiremock/blob/master/src/main/java/com/github/tomakehurst/wiremock/stubbing/StubMapping.java#L37) where `1` is the highest priority and Java `Integer.MAX_VALUE` (i.e., `2147483647`) is the minimum priority. @@ -235,80 +206,64 @@ When unspecified, stubs default to a priority of `5`[^](https://githu In addition to matching on request headers, it's also possible to send response headers. -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(get(urlEqualTo("/whatever")) - .willReturn(aResponse() - .withStatus(200) - .withHeader("Content-Type", "application/json") - .withHeader("Set-Cookie", "session_id=91837492837") - .withHeader("Set-Cookie", "split_test_group=B") // You can call withHeader more than once for the same header if multiple values are required - .withHeader("Cache-Control", "no-cache"))); -``` +=== "Java" -{% endcodetab %} - -{% codetab JSON %} - -```json -{ - "request": { - "method": "GET", - "url": "/whatever" - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "text/plain", - "Set-Cookie": ["session_id=91837492837", "split_test_group=B"], - "Cache-Control": "no-cache" + ```java + stubFor(get(urlEqualTo("/whatever")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withHeader("Set-Cookie", "session_id=91837492837") + .withHeader("Set-Cookie", "split_test_group=B") // You can call withHeader more than once for the same header if multiple values are required + .withHeader("Cache-Control", "no-cache"))); + ``` + +=== "JSON" + + ```json + { + "request": { + "method": "GET", + "url": "/whatever" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "text/plain", + "Set-Cookie": ["session_id=91837492837", "split_test_group=B"], + "Cache-Control": "no-cache" + } } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ## Specifying the response body The simplest way to specify a response body is as a string literal. -{% codetabs %} - -{% codetab Java %} +=== "Java" %}" -```java -stubFor(get(urlEqualTo("/body")) - .willReturn(aResponse() - .withBody("Literal text to put in the body"))); -``` - -{% endcodetab %} + ```java + stubFor(get(urlEqualTo("/body")) + .willReturn(aResponse() + .withBody("Literal text to put in the body"))); + ``` -{% codetab JSON %} +=== "JSON" -```json -{ - "request": { - "method": "GET", - "url": "/body" - }, - "response": { - "status": 200, - "body": "Literal text to put in the body" + ```json + { + "request": { + "method": "GET", + "url": "/body" + }, + "response": { + "status": 200, + "body": "Literal text to put in the body" + } } -} ``` -{% endcodetab %} - -{% endcodetabs %} - If you're specifying a JSON body via the JSON API, you can avoid having to escape it like this: ```json @@ -327,9 +282,7 @@ under the current directory in which the server was started. To make your stub use the file, simply call `bodyFile()` on the response builder with the file's path relative to `__files`: -{% codetabs %} - -{% codetab Java %} +=== "Java" ```java stubFor(get(urlEqualTo("/body-file")) @@ -337,26 +290,20 @@ stubFor(get(urlEqualTo("/body-file")) .withBodyFile("path/to/myfile.xml"))); ``` -{% endcodetab %} +=== "JSON" -{% codetab JSON %} - -```json -{ - "request": { - "method": "GET", - "url": "/body-file" - }, - "response": { - "status": 200, - "bodyFileName": "path/to/myfile.xml" + ```json + { + "request": { + "method": "GET", + "url": "/body-file" + }, + "response": { + "status": 200, + "bodyFileName": "path/to/myfile.xml" + } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` > **note** > @@ -374,36 +321,28 @@ overloaded `body()` in Java. JSON API accepts this as a base64 string (to avoid stupidly long JSON documents): -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(get(urlEqualTo("/binary-body")) - .willReturn(aResponse() - .withBody(new byte[] { 1, 2, 3, 4 }))); -``` +=== "Java" -{% endcodetab %} + ```java + stubFor(get(urlEqualTo("/binary-body")) + .willReturn(aResponse() + .withBody(new byte[] { 1, 2, 3, 4 }))); + ``` -{% codetab JSON %} +=== "JSON" -```json -{ - "request": { - "method": "GET", - "url": "/binary-body" - }, - "response": { - "status": 200, - "base64Body": "WUVTIElOREVFRCE=" + ```json + { + "request": { + "method": "GET", + "url": "/binary-body" + }, + "response": { + "status": 200, + "base64Body": "WUVTIElOREVFRCE=" + } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ## Default response for unmapped requests @@ -411,42 +350,34 @@ When a request cannot be mapped to a response, Wiremock returns an HTML response It is possible to customize the response by catching all URLs with a low priority. -{% codetabs %} - -{% codetab Java %} - -```java -stubFor(any(anyUrl()) - .atPriority(10) - .willReturn(aResponse() - .withStatus(404) - .withBody("{\"status\":\"Error\",\"message\":\"Endpoint not found\"}"))); -``` +=== "Java" -{% endcodetab %} + ```java + stubFor(any(anyUrl()) + .atPriority(10) + .willReturn(aResponse() + .withStatus(404) + .withBody("{\"status\":\"Error\",\"message\":\"Endpoint not found\"}"))); + ``` -{% codetab JSON %} +=== "JSON" -```json -{ - "priority": 10, - "request": { - "method": "ANY", - "urlPattern": ".*" - }, - "response": { - "status": 404, - "jsonBody": { "status": "Error", "message": "Endpoint not found" }, - "headers": { - "Content-Type": "application/json" + ```json + { + "priority": 10, + "request": { + "method": "ANY", + "urlPattern": ".*" + }, + "response": { + "status": 404, + "jsonBody": { "status": "Error", "message": "Endpoint not found" }, + "headers": { + "Content-Type": "application/json" + } } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ## Saving stubs @@ -464,45 +395,37 @@ In Java, Existing stub mappings can be modified, provided they have been assigne To do the equivalent via the JSON API, `PUT` the edited stub mapping to `/__admin/mappings/{id}` -{% codetabs %} - -{% codetab Java %} - -```java -wireMockServer.stubFor(get(urlEqualTo("/edit-this")) - .withId(id) - .willReturn(aResponse() - .withBody("Original"))); +=== "Java" -assertThat(testClient.get("/edit-this").content(), is("Original")); + ```java + wireMockServer.stubFor(get(urlEqualTo("/edit-this")) + .withId(id) + .willReturn(aResponse() + .withBody("Original"))); -wireMockServer.editStub(get(urlEqualTo("/edit-this")) - .withId(id) - .willReturn(aResponse() - .withBody("Modified"))); + assertThat(testClient.get("/edit-this").content(), is("Original")); -assertThat(testClient.get("/edit-this").content(), is("Modified")); -``` + wireMockServer.editStub(get(urlEqualTo("/edit-this")) + .withId(id) + .willReturn(aResponse() + .withBody("Modified"))); -{% endcodetab %} + assertThat(testClient.get("/edit-this").content(), is("Modified")); + ``` -{% codetab JSON %} +=== "JSON" -```json -{ - "request": { - "urlPath": "/edit-me", - "method": "ANY" - }, - "response": { - "status": 200 + ```json + { + "request": { + "urlPath": "/edit-me", + "method": "ANY" + }, + "response": { + "status": 200 + } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ## File serving @@ -534,16 +457,16 @@ where `id` is the UUID of the stub mapping, found in its `id` field. ## Reset The WireMock server can be reset at any time, removing all stub mappings -and deleting the request log. If you're using either of the JUnit rules -this will happen automatically at the start of every test case. However +and deleting the request log. If you're using either of the JUnit rules, +this will happen automatically at the start of every test case. However, you can do it yourself via a call to `WireMock.reset()` in Java or sending a `POST` request with an empty body to `http://:/__admin/reset`. To reset just the stub mappings leaving the request log intact send a `DELETE` to `http://:/__admin/mappings`. -If you've created some file based stub mappings to be loaded at startup -and you don't want these to disappear when you do a reset you can call +If you've created some file-based stub mappings to be loaded at startup +and you don't want these to disappear when you do a reset, you can call `WireMock.resetToDefault()` instead, or post an empty request to `http://:/__admin/mappings/reset`. @@ -569,57 +492,49 @@ In Java, Multiple stubs can be imported in one call. The equivalent can be carried out Via the JSON API, `POST` the to `/__admin/mappings/import`: -{% codetabs %} - -{% codetab Java %} - -```java -WireMock.importStubs(stubImport() - .stub(get("/one").willReturn(ok())) - .stub(post("/two").willReturn(ok("Body content"))) - .stub(put("/three").willReturn(ok())) - .ignoreExisting() - .deleteAllExistingStubsNotInImport()); -``` - -{% endcodetab %} - -{% codetab JSON %} - -```json -{ - "mappings": [ - { - "request": { - "method": "GET", - "url": "/one" - }, - "response": { - "status": 200 - } - }, - { - "id": "8c5db8b0-2db4-4ad7-a99f-38c9b00da3f7", - "request": { - "url": "/two" +=== "Java" + + ```java + WireMock.importStubs(stubImport() + .stub(get("/one").willReturn(ok())) + .stub(post("/two").willReturn(ok("Body content"))) + .stub(put("/three").willReturn(ok())) + .ignoreExisting() + .deleteAllExistingStubsNotInImport()); + ``` + +=== "JSON" + + ```json + { + "mappings": [ + { + "request": { + "method": "GET", + "url": "/one" + }, + "response": { + "status": 200 + } }, - "response": { - "status": 200, - "body": "Body content" + { + "id": "8c5db8b0-2db4-4ad7-a99f-38c9b00da3f7", + "request": { + "url": "/two" + }, + "response": { + "status": 200, + "body": "Body content" + } } - } - ], + ], - "importOptions": { - "duplicatePolicy": "IGNORE", - "deleteAllNotInImport": true + "importOptions": { + "duplicatePolicy": "IGNORE", + "deleteAllNotInImport": true + } } -} -``` - -{% endcodetab %} - -{% endcodetabs %} + ``` ### Existing stubs policy diff --git a/_docs/verifying.md b/_site/docs/verifying.md similarity index 94% rename from _docs/verifying.md rename to _site/docs/verifying.md index 4aee216b..56afc079 100644 --- a/_docs/verifying.md +++ b/_site/docs/verifying.md @@ -1,29 +1,29 @@ --- -layout: docs -title: Verifying -meta_title: Verifying whether specific HTTP requests were made | WireMock -toc_rank: 60 -redirect_from: "/verifying.html" -description: Verifying and querying requests relies on the request journal, which is an in-memory log of received requests. This can be disabled for load testing. +description: > + Verifying and querying requests relies on the request journal, + which is an in-memory log of received requests. + This can be disabled for load testing. --- +# Verifying whether specific HTTP requests were made + The WireMock server records all requests it receives in memory (at -least until it is [reset](../stubbing#reset)). This makes it possible to verify that +least until it is [reset](./stubbing.md#reset)). This makes it possible to verify that a request matching a specific pattern was received, and also to fetch the requests' details. Verifying and querying requests relies on the request journal, which is an in-memory log -of received requests. This can be disabled for load testing - see the [Configuration](../configuration/) section for details. +of received requests. This can be disabled for load testing - see the [Configuration](./configuration.md) section for details. -Like stubbing, verification also uses WireMock's [Request Matching](../request-matching/) system to filter and query requests. +Like stubbing, verification also uses WireMock's [Request Matching](./request-matching.md) system to filter and query requests. ## Verification failures, console output and IntelliJ When verifying via the Java API all failed verifications will result in a `VerificationException` being thrown. -![Verification exception]({{ '/images/verification-exception.png' | absolute_url }}) +![Verification exception](../images/verification-exception.png) The message text in the exception is formatted to enable IntelliJ's failure comparison view: -![Comparison failure]({{ '/images/idea-comparison-failure.png' | absolute_url }}) +![Comparison failure](../images/idea-comparison-failure.png) ## Verifying in Java @@ -37,7 +37,7 @@ verify(postRequestedFor(urlEqualTo("/verify/this")) The criteria part in the parameter to `postRequestedFor()` uses the same builder as for stubbing, so all of the same predicates are available. -See [Stubbing](../stubbing/) for more details. +See [Stubbing](./stubbing.md) for more details. To check for a precise number of requests matching the criteria, use this form: @@ -302,7 +302,7 @@ POST /__admin/requests/remove-by-metadata } ``` -For more info about stub metadata see [Stub Metadata](../stub-metadata/) +For more info about stub metadata see [Stub Metadata](./stub-metadata.md) ## Resetting the request journal diff --git a/_site/docs/webhooks-and-callbacks.md b/_site/docs/webhooks-and-callbacks.md new file mode 100644 index 00000000..f8ecc74f --- /dev/null +++ b/_site/docs/webhooks-and-callbacks.md @@ -0,0 +1,302 @@ +--- +description: Configuring WireMock to fire outbound HTTP requests when specific stubs are matched. +--- + +# Simulating Webhooks and Callbacks + +WireMock can make asynchronous outbound HTTP calls when an incoming request is matched to a specific stub. This pattern +is commonly referred to as webhooks or callbacks and is a common design in APIs that need to proactively notify their clients +of events or perform long-running processing asynchronously without blocking. + +## Enabling webhooks + +Prior to WireMock 3.1.0 webhooks were provided via an extension and needed to be explicitly enabled. See [the 2.x docs](https://wiremock.org/2.x/docs/webhooks-and-callbacks/) for details on how to do this. + +From version 3.1.0 the webhooks extension is part of WireMock's core and enabled by default. + +### Old vs. new extension point + +The revised version of webhooks in 3.1.0 makes use of the new `ServeEventListener` extension point. +This article shows how to use this newer extension point, however the legacy `PostServeAction` interface is still supported for backwards compatibility. + +## Creating a simple, single webhook + +You can trigger a single webhook request to a fixed URL, with fixed data like this: + +=== "Java" + + ```java + import static org.wiremock.webhooks.Webhooks.*; + ... + + wm.stubFor(post(urlPathEqualTo("/something-async")) + .willReturn(ok()) + .withServeEventListener("webhook", webhook() + .withMethod(POST) + .withUrl("http://my-target-host/callback") + .withHeader("Content-Type", "application/json") + .withBody("{ \"result\": \"SUCCESS\" }")) + ); + ``` + +=== "JSON" + + ```json + { + "request": { + "urlPath": "/something-async", + "method": "POST" + }, + "response": { + "status": 200 + }, + "serveEventListeners": [ + { + "name": "webhook", + "parameters": { + "method": "POST", + "url": "http://my-target-host/callback", + "headers": { + "Content-Type": "application/json" + }, + "body": "{ \"result\": \"SUCCESS\" }" + } + } + ] + } + ``` + +## Using data from the original request + +Webhooks use the same [templating system](./response-templating.md) as WireMock responses. This means that any of the +configuration fields can be provided with a template expression which will be resolved before firing the webhook. + +Similarly to response templates the original request data is available, although in this case it is named `originalRequest`. + +Supposing we wanted to pass a transaction ID from the original (triggering) request and insert it into the JSON request +body sent by the webhook call. + +For an original request body JSON like this: + +```json +{ + "transactionId": "12345" +} +``` + +We could construct a JSON request body in the webhook like this: + +=== "Java" + +{% raw %} + + ```java + wm.stubFor(post(urlPathEqualTo("/templating")) + .willReturn(ok()) + .withServeEventListener("webhook", webhook() + .withMethod(POST) + .withUrl("http://my-target-host/callback") + .withHeader("Content-Type", "application/json") + .withBody("{ \"message\": \"success\", \"transactionId\": \"{{jsonPath originalRequest.body '$.transactionId'}}\" }") + ); + ``` + +{% endraw %} + +=== "JSON" + +{% raw %} + + ```json + { + "request": { + "urlPath": "/templating", + "method": "POST" + }, + "response": { + "status": 200 + }, + "serveEventListeners": [ + { + "name": "webhook", + "parameters": { + "method": "POST", + "url": "http://my-target-host/callback", + "headers": { + "Content-Type": "application/json" + }, + "body": "{ \"message\": \"success\", \"transactionId\": \"{{jsonPath originalRequest.body '$.transactionId'}}\" }" + } + } + ] + } + ``` + +{% endraw %} + +!!! note + + Webhook templates currently do not support system or environment variables. + +## Implementing a callback using templating + +To implement the callback pattern, where the original request contains the target to be called on completion of a long-running task, +we can use templating on the URL and method. + +=== "Java" + +{% raw %} + ```java + wm.stubFor(post(urlPathEqualTo("/something-async")) + .willReturn(ok()) + .withServeEventListener("webhook", webhook() + .withMethod("{{jsonPath originalRequest.body '$.callbackMethod'}}") + .withUrl("{{jsonPath originalRequest.body '$.callbackUrl'}}")) + ); + ``` +{% endraw %} + +=== "JSON" + +{% raw %} + ```json + { + "request": { + "urlPath": "/something-async", + "method": "POST" + }, + "response": { + "status": 200 + }, + "serveEventListeners": [ + { + "name": "webhook", + "parameters": { + "method": "{{jsonPath originalRequest.body '$.callbackMethod'}}", + "url": "{{jsonPath originalRequest.body '$.callbackUrl'}}" + } + } + ] + } + ``` + +{% endraw %} + +## Adding delays + +A fixed or random delay can be added before the webhook call is made, using the same style of [delay parameters as stubs](./simulating-faults.md). + +### Fixed delays + +=== "Java" + +{% raw %} + + ```java + wm.stubFor(post(urlPathEqualTo("/delayed")) + .willReturn(ok()) + .withServeEventListener("webhook", webhook() + .withFixedDelay(1000) + .withMethod(RequestMethod.GET) + .withUrl("http://my-target-host/callback") + ) + ); + ``` +{% endraw %} + +=== "JSON" + +{% raw %} + + ```json + { + "request": { + "urlPath": "/delayed", + "method": "POST" + }, + "response": { + "status": 200 + }, + "serveEventListeners": [ + { + "name": "webhook", + "parameters": { + "method": "GET", + "url": "http://my-target-host/callback", + "delay": { + "type": "fixed", + "milliseconds": 1000 + } + } + } + ] + } + ``` +{% endraw %} + +### Random delays + +=== "Java" + +{% raw %} + + ```java + wm.stubFor(post(urlPathEqualTo("/delayed")) + .willReturn(ok()) + .withServeEventListener("webhook", webhook() + .withDelay(new UniformDistribution(500, 1000)) + .withMethod(RequestMethod.GET) + .withUrl("http://my-target-host/callback") + ) + ); + ``` +{% endraw %} + +=== "JSON" + +{% raw %} + ```json + { + "request": { + "urlPath": "/delayed", + "method": "POST" + }, + "response": { + "status": 200 + }, + "serveEventListeners": [ + { + "name": "webhook", + "parameters": { + "method": "GET", + "url": "http://my-target-host/callback", + "delay": { + "type": "uniform", + "lower": 500, + "upper": 1000 + } + } + } + ] + } + ``` +{% endraw %} + +## Extending webhooks + +Webhook behaviour can be further customised in code via an extension point. + +This works in a similar fashion to response transformation. The extension class implements the `WebhookTransformer` interface and is then loaded via +the extension mechanism (see [Extending WireMock](https://wiremock.org/docs/extending-wiremock/)). + +```java +public class MyWebhookTransformer implements WebhookTransformer { + + @Override + public WebhookDefinition transform( + ServeEvent serveEvent, + WebhookDefinition webhookDefinition) { + // build and return a new WebhookDefinition with some custom changes + } +} +``` diff --git a/images/WireMockShots.png b/_site/images/WireMockShots.png similarity index 100% rename from images/WireMockShots.png rename to _site/images/WireMockShots.png diff --git a/images/bio-photo.jpg b/_site/images/bio-photo.jpg similarity index 100% rename from images/bio-photo.jpg rename to _site/images/bio-photo.jpg diff --git a/images/blackGithubIcon.svg b/_site/images/blackGithubIcon.svg similarity index 100% rename from images/blackGithubIcon.svg rename to _site/images/blackGithubIcon.svg diff --git a/images/clients/em.jpg b/_site/images/clients/em.jpg similarity index 100% rename from images/clients/em.jpg rename to _site/images/clients/em.jpg diff --git a/images/clients/ft.jpg b/_site/images/clients/ft.jpg similarity index 100% rename from images/clients/ft.jpg rename to _site/images/clients/ft.jpg diff --git a/images/clients/intuit.jpg b/_site/images/clients/intuit.jpg similarity index 100% rename from images/clients/intuit.jpg rename to _site/images/clients/intuit.jpg diff --git a/images/clients/piksel.jpg b/_site/images/clients/piksel.jpg similarity index 100% rename from images/clients/piksel.jpg rename to _site/images/clients/piksel.jpg diff --git a/images/clients/pivotal.jpg b/_site/images/clients/pivotal.jpg similarity index 100% rename from images/clients/pivotal.jpg rename to _site/images/clients/pivotal.jpg diff --git a/images/clients/sky.jpg b/_site/images/clients/sky.jpg similarity index 100% rename from images/clients/sky.jpg rename to _site/images/clients/sky.jpg diff --git a/images/clients/softwire.jpg b/_site/images/clients/softwire.jpg similarity index 100% rename from images/clients/softwire.jpg rename to _site/images/clients/softwire.jpg diff --git a/images/clients/theguardian.jpg b/_site/images/clients/theguardian.jpg similarity index 100% rename from images/clients/theguardian.jpg rename to _site/images/clients/theguardian.jpg diff --git a/images/clients/yenlo.jpg b/_site/images/clients/yenlo.jpg similarity index 100% rename from images/clients/yenlo.jpg rename to _site/images/clients/yenlo.jpg diff --git a/images/closeMenuIcon.svg b/_site/images/closeMenuIcon.svg similarity index 100% rename from images/closeMenuIcon.svg rename to _site/images/closeMenuIcon.svg diff --git a/images/closeModalIcon.png b/_site/images/closeModalIcon.png similarity index 100% rename from images/closeModalIcon.png rename to _site/images/closeModalIcon.png diff --git a/images/codeTabsFootergithubIcon.svg b/_site/images/codeTabsFootergithubIcon.svg similarity index 100% rename from images/codeTabsFootergithubIcon.svg rename to _site/images/codeTabsFootergithubIcon.svg diff --git a/images/ctDownloadIcon.svg b/_site/images/ctDownloadIcon.svg similarity index 100% rename from images/ctDownloadIcon.svg rename to _site/images/ctDownloadIcon.svg diff --git a/images/ctGithubDownloadIcon.svg b/_site/images/ctGithubDownloadIcon.svg similarity index 100% rename from images/ctGithubDownloadIcon.svg rename to _site/images/ctGithubDownloadIcon.svg diff --git a/images/ctStarIcon.svg b/_site/images/ctStarIcon.svg similarity index 100% rename from images/ctStarIcon.svg rename to _site/images/ctStarIcon.svg diff --git a/images/ctUserIcon.svg b/_site/images/ctUserIcon.svg similarity index 100% rename from images/ctUserIcon.svg rename to _site/images/ctUserIcon.svg diff --git a/images/docker.png b/_site/images/docker.png similarity index 100% rename from images/docker.png rename to _site/images/docker.png diff --git a/images/elephantIcon.png b/_site/images/elephantIcon.png similarity index 100% rename from images/elephantIcon.png rename to _site/images/elephantIcon.png diff --git a/images/faultIcon.svg b/_site/images/faultIcon.svg similarity index 100% rename from images/faultIcon.svg rename to _site/images/faultIcon.svg diff --git a/_site/images/favicon.svg b/_site/images/favicon.svg new file mode 100644 index 00000000..071d4419 --- /dev/null +++ b/_site/images/favicon.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + diff --git a/images/firefox-proxy-screenshot.png b/_site/images/firefox-proxy-screenshot.png similarity index 100% rename from images/firefox-proxy-screenshot.png rename to _site/images/firefox-proxy-screenshot.png diff --git a/images/githubIcon.svg b/_site/images/githubIcon.svg similarity index 100% rename from images/githubIcon.svg rename to _site/images/githubIcon.svg diff --git a/images/groovy.png b/_site/images/groovy.png similarity index 100% rename from images/groovy.png rename to _site/images/groovy.png diff --git a/images/hamburgerMenuIcon.svg b/_site/images/hamburgerMenuIcon.svg similarity index 100% rename from images/hamburgerMenuIcon.svg rename to _site/images/hamburgerMenuIcon.svg diff --git a/images/home/cloud.png b/_site/images/home/cloud.png similarity index 100% rename from images/home/cloud.png rename to _site/images/home/cloud.png diff --git a/images/home/oss.png b/_site/images/home/oss.png similarity index 100% rename from images/home/oss.png rename to _site/images/home/oss.png diff --git a/images/httpIcon.svg b/_site/images/httpIcon.svg similarity index 100% rename from images/httpIcon.svg rename to _site/images/httpIcon.svg diff --git a/images/idea-comparison-failure.png b/_site/images/idea-comparison-failure.png similarity index 100% rename from images/idea-comparison-failure.png rename to _site/images/idea-comparison-failure.png diff --git a/images/idea-shots.png b/_site/images/idea-shots.png similarity index 100% rename from images/idea-shots.png rename to _site/images/idea-shots.png diff --git a/images/ivy.png b/_site/images/ivy.png similarity index 100% rename from images/ivy.png rename to _site/images/ivy.png diff --git a/images/java-wiremock-idea-shot.png b/_site/images/java-wiremock-idea-shot.png similarity index 100% rename from images/java-wiremock-idea-shot.png rename to _site/images/java-wiremock-idea-shot.png diff --git a/images/java-wiremock-sample-idea.png b/_site/images/java-wiremock-sample-idea.png similarity index 100% rename from images/java-wiremock-sample-idea.png rename to _site/images/java-wiremock-sample-idea.png diff --git a/images/java-wiremock-sample.jpg b/_site/images/java-wiremock-sample.jpg similarity index 100% rename from images/java-wiremock-sample.jpg rename to _site/images/java-wiremock-sample.jpg diff --git a/images/java.png b/_site/images/java.png similarity index 100% rename from images/java.png rename to _site/images/java.png diff --git a/images/json-wiremock-sample.jpg b/_site/images/json-wiremock-sample.jpg similarity index 100% rename from images/json-wiremock-sample.jpg rename to _site/images/json-wiremock-sample.jpg diff --git a/images/kotlin.png b/_site/images/kotlin.png similarity index 100% rename from images/kotlin.png rename to _site/images/kotlin.png diff --git a/images/leftHeaderHP.png b/_site/images/leftHeaderHP.png similarity index 100% rename from images/leftHeaderHP.png rename to _site/images/leftHeaderHP.png diff --git a/images/logos/EW-logo.png b/_site/images/logos/EW-logo.png similarity index 100% rename from images/logos/EW-logo.png rename to _site/images/logos/EW-logo.png diff --git a/images/logos/FT-Logo.jpg b/_site/images/logos/FT-Logo.jpg similarity index 100% rename from images/logos/FT-Logo.jpg rename to _site/images/logos/FT-Logo.jpg diff --git a/images/logos/Piksel_master.png b/_site/images/logos/Piksel_master.png similarity index 100% rename from images/logos/Piksel_master.png rename to _site/images/logos/Piksel_master.png diff --git a/images/logos/Pivotal_TealOnWhite.png b/_site/images/logos/Pivotal_TealOnWhite.png similarity index 100% rename from images/logos/Pivotal_TealOnWhite.png rename to _site/images/logos/Pivotal_TealOnWhite.png diff --git a/images/logos/Pivotal_WhiteOnTeal.png b/_site/images/logos/Pivotal_WhiteOnTeal.png similarity index 100% rename from images/logos/Pivotal_WhiteOnTeal.png rename to _site/images/logos/Pivotal_WhiteOnTeal.png diff --git a/images/logos/The_Guardian_logo.png b/_site/images/logos/The_Guardian_logo.png similarity index 100% rename from images/logos/The_Guardian_logo.png rename to _site/images/logos/The_Guardian_logo.png diff --git a/images/logos/Yenlo_logo_trans.png b/_site/images/logos/Yenlo_logo_trans.png similarity index 100% rename from images/logos/Yenlo_logo_trans.png rename to _site/images/logos/Yenlo_logo_trans.png diff --git a/images/logos/doc-sections/bug.svg b/_site/images/logos/doc-sections/bug.svg similarity index 100% rename from images/logos/doc-sections/bug.svg rename to _site/images/logos/doc-sections/bug.svg diff --git a/images/logos/doc-sections/checkcircle.svg b/_site/images/logos/doc-sections/checkcircle.svg similarity index 100% rename from images/logos/doc-sections/checkcircle.svg rename to _site/images/logos/doc-sections/checkcircle.svg diff --git a/images/logos/doc-sections/checklist.svg b/_site/images/logos/doc-sections/checklist.svg similarity index 100% rename from images/logos/doc-sections/checklist.svg rename to _site/images/logos/doc-sections/checklist.svg diff --git a/images/logos/doc-sections/cloud.svg b/_site/images/logos/doc-sections/cloud.svg similarity index 100% rename from images/logos/doc-sections/cloud.svg rename to _site/images/logos/doc-sections/cloud.svg diff --git a/images/logos/doc-sections/community.svg b/_site/images/logos/doc-sections/community.svg similarity index 100% rename from images/logos/doc-sections/community.svg rename to _site/images/logos/doc-sections/community.svg diff --git a/images/logos/doc-sections/connect.svg b/_site/images/logos/doc-sections/connect.svg similarity index 100% rename from images/logos/doc-sections/connect.svg rename to _site/images/logos/doc-sections/connect.svg diff --git a/images/logos/doc-sections/document.svg b/_site/images/logos/doc-sections/document.svg similarity index 100% rename from images/logos/doc-sections/document.svg rename to _site/images/logos/doc-sections/document.svg diff --git a/images/logos/doc-sections/documentBar.svg b/_site/images/logos/doc-sections/documentBar.svg similarity index 100% rename from images/logos/doc-sections/documentBar.svg rename to _site/images/logos/doc-sections/documentBar.svg diff --git a/images/logos/doc-sections/download.svg b/_site/images/logos/doc-sections/download.svg similarity index 100% rename from images/logos/doc-sections/download.svg rename to _site/images/logos/doc-sections/download.svg diff --git a/images/logos/doc-sections/edit.svg b/_site/images/logos/doc-sections/edit.svg similarity index 100% rename from images/logos/doc-sections/edit.svg rename to _site/images/logos/doc-sections/edit.svg diff --git a/images/logos/doc-sections/extensibility.svg b/_site/images/logos/doc-sections/extensibility.svg similarity index 100% rename from images/logos/doc-sections/extensibility.svg rename to _site/images/logos/doc-sections/extensibility.svg diff --git a/images/logos/doc-sections/help-mono.svg b/_site/images/logos/doc-sections/help-mono.svg similarity index 100% rename from images/logos/doc-sections/help-mono.svg rename to _site/images/logos/doc-sections/help-mono.svg diff --git a/images/logos/doc-sections/help.svg b/_site/images/logos/doc-sections/help.svg similarity index 100% rename from images/logos/doc-sections/help.svg rename to _site/images/logos/doc-sections/help.svg diff --git a/images/logos/doc-sections/helpsec.svg b/_site/images/logos/doc-sections/helpsec.svg similarity index 100% rename from images/logos/doc-sections/helpsec.svg rename to _site/images/logos/doc-sections/helpsec.svg diff --git a/images/logos/doc-sections/home.svg b/_site/images/logos/doc-sections/home.svg similarity index 100% rename from images/logos/doc-sections/home.svg rename to _site/images/logos/doc-sections/home.svg diff --git a/images/logos/doc-sections/link.svg b/_site/images/logos/doc-sections/link.svg similarity index 100% rename from images/logos/doc-sections/link.svg rename to _site/images/logos/doc-sections/link.svg diff --git a/images/logos/doc-sections/loudspeaker.svg b/_site/images/logos/doc-sections/loudspeaker.svg similarity index 100% rename from images/logos/doc-sections/loudspeaker.svg rename to _site/images/logos/doc-sections/loudspeaker.svg diff --git a/images/logos/doc-sections/plus.svg b/_site/images/logos/doc-sections/plus.svg similarity index 100% rename from images/logos/doc-sections/plus.svg rename to _site/images/logos/doc-sections/plus.svg diff --git a/images/logos/doc-sections/plusnew.svg b/_site/images/logos/doc-sections/plusnew.svg similarity index 100% rename from images/logos/doc-sections/plusnew.svg rename to _site/images/logos/doc-sections/plusnew.svg diff --git a/images/logos/doc-sections/quickstart.svg b/_site/images/logos/doc-sections/quickstart.svg similarity index 100% rename from images/logos/doc-sections/quickstart.svg rename to _site/images/logos/doc-sections/quickstart.svg diff --git a/images/logos/doc-sections/slack.svg b/_site/images/logos/doc-sections/slack.svg similarity index 100% rename from images/logos/doc-sections/slack.svg rename to _site/images/logos/doc-sections/slack.svg diff --git a/images/logos/doc-sections/summary.svg b/_site/images/logos/doc-sections/summary.svg similarity index 100% rename from images/logos/doc-sections/summary.svg rename to _site/images/logos/doc-sections/summary.svg diff --git a/images/logos/doc-sections/team.svg b/_site/images/logos/doc-sections/team.svg similarity index 100% rename from images/logos/doc-sections/team.svg rename to _site/images/logos/doc-sections/team.svg diff --git a/images/logos/doc-sections/template.svg b/_site/images/logos/doc-sections/template.svg similarity index 100% rename from images/logos/doc-sections/template.svg rename to _site/images/logos/doc-sections/template.svg diff --git a/images/logos/intuit_blue.gif b/_site/images/logos/intuit_blue.gif similarity index 100% rename from images/logos/intuit_blue.gif rename to _site/images/logos/intuit_blue.gif diff --git a/images/logos/sky-logo.png b/_site/images/logos/sky-logo.png similarity index 100% rename from images/logos/sky-logo.png rename to _site/images/logos/sky-logo.png diff --git a/images/logos/softwire-logo.jpg b/_site/images/logos/softwire-logo.jpg similarity index 100% rename from images/logos/softwire-logo.jpg rename to _site/images/logos/softwire-logo.jpg diff --git a/images/logos/technology/android.svg b/_site/images/logos/technology/android.svg similarity index 100% rename from images/logos/technology/android.svg rename to _site/images/logos/technology/android.svg diff --git a/images/logos/technology/c.png b/_site/images/logos/technology/c.png similarity index 100% rename from images/logos/technology/c.png rename to _site/images/logos/technology/c.png diff --git a/images/logos/technology/cpp.png b/_site/images/logos/technology/cpp.png similarity index 100% rename from images/logos/technology/cpp.png rename to _site/images/logos/technology/cpp.png diff --git a/images/logos/technology/docker.svg b/_site/images/logos/technology/docker.svg similarity index 100% rename from images/logos/technology/docker.svg rename to _site/images/logos/technology/docker.svg diff --git a/images/logos/technology/dotnet.svg b/_site/images/logos/technology/dotnet.svg similarity index 100% rename from images/logos/technology/dotnet.svg rename to _site/images/logos/technology/dotnet.svg diff --git a/images/logos/technology/golang.svg b/_site/images/logos/technology/golang.svg similarity index 100% rename from images/logos/technology/golang.svg rename to _site/images/logos/technology/golang.svg diff --git a/images/logos/technology/gradle.svg b/_site/images/logos/technology/gradle.svg similarity index 100% rename from images/logos/technology/gradle.svg rename to _site/images/logos/technology/gradle.svg diff --git a/images/logos/technology/graphql.svg b/_site/images/logos/technology/graphql.svg similarity index 100% rename from images/logos/technology/graphql.svg rename to _site/images/logos/technology/graphql.svg diff --git a/images/logos/technology/groovy.svg b/_site/images/logos/technology/groovy.svg similarity index 100% rename from images/logos/technology/groovy.svg rename to _site/images/logos/technology/groovy.svg diff --git a/images/logos/technology/grpc.png b/_site/images/logos/technology/grpc.png similarity index 100% rename from images/logos/technology/grpc.png rename to _site/images/logos/technology/grpc.png diff --git a/images/logos/technology/helm.svg b/_site/images/logos/technology/helm.svg similarity index 100% rename from images/logos/technology/helm.svg rename to _site/images/logos/technology/helm.svg diff --git a/images/logos/technology/http.svg b/_site/images/logos/technology/http.svg similarity index 100% rename from images/logos/technology/http.svg rename to _site/images/logos/technology/http.svg diff --git a/images/logos/technology/https.svg b/_site/images/logos/technology/https.svg similarity index 100% rename from images/logos/technology/https.svg rename to _site/images/logos/technology/https.svg diff --git a/images/logos/technology/jar.svg b/_site/images/logos/technology/jar.svg similarity index 100% rename from images/logos/technology/jar.svg rename to _site/images/logos/technology/jar.svg diff --git a/images/logos/technology/java.svg b/_site/images/logos/technology/java.svg similarity index 100% rename from images/logos/technology/java.svg rename to _site/images/logos/technology/java.svg diff --git a/images/logos/technology/kotlin.svg b/_site/images/logos/technology/kotlin.svg similarity index 100% rename from images/logos/technology/kotlin.svg rename to _site/images/logos/technology/kotlin.svg diff --git a/images/logos/technology/kubernetes.svg b/_site/images/logos/technology/kubernetes.svg similarity index 100% rename from images/logos/technology/kubernetes.svg rename to _site/images/logos/technology/kubernetes.svg diff --git a/images/logos/technology/maven.svg b/_site/images/logos/technology/maven.svg similarity index 100% rename from images/logos/technology/maven.svg rename to _site/images/logos/technology/maven.svg diff --git a/images/logos/technology/micronaut.svg b/_site/images/logos/technology/micronaut.svg similarity index 100% rename from images/logos/technology/micronaut.svg rename to _site/images/logos/technology/micronaut.svg diff --git a/images/logos/technology/nodejs.svg b/_site/images/logos/technology/nodejs.svg similarity index 100% rename from images/logos/technology/nodejs.svg rename to _site/images/logos/technology/nodejs.svg diff --git a/images/logos/technology/npm.svg b/_site/images/logos/technology/npm.svg similarity index 100% rename from images/logos/technology/npm.svg rename to _site/images/logos/technology/npm.svg diff --git a/images/logos/technology/openshift.svg b/_site/images/logos/technology/openshift.svg similarity index 100% rename from images/logos/technology/openshift.svg rename to _site/images/logos/technology/openshift.svg diff --git a/images/logos/technology/php.svg b/_site/images/logos/technology/php.svg similarity index 100% rename from images/logos/technology/php.svg rename to _site/images/logos/technology/php.svg diff --git a/images/logos/technology/prometheus.svg b/_site/images/logos/technology/prometheus.svg similarity index 100% rename from images/logos/technology/prometheus.svg rename to _site/images/logos/technology/prometheus.svg diff --git a/images/logos/technology/python.svg b/_site/images/logos/technology/python.svg similarity index 100% rename from images/logos/technology/python.svg rename to _site/images/logos/technology/python.svg diff --git a/images/logos/technology/quarkus.svg b/_site/images/logos/technology/quarkus.svg similarity index 100% rename from images/logos/technology/quarkus.svg rename to _site/images/logos/technology/quarkus.svg diff --git a/images/logos/technology/ruby.svg b/_site/images/logos/technology/ruby.svg similarity index 100% rename from images/logos/technology/ruby.svg rename to _site/images/logos/technology/ruby.svg diff --git a/images/logos/technology/rust.svg b/_site/images/logos/technology/rust.svg similarity index 100% rename from images/logos/technology/rust.svg rename to _site/images/logos/technology/rust.svg diff --git a/images/logos/technology/spring.svg b/_site/images/logos/technology/spring.svg similarity index 100% rename from images/logos/technology/spring.svg rename to _site/images/logos/technology/spring.svg diff --git a/images/logos/technology/testcontainers.svg b/_site/images/logos/technology/testcontainers.svg similarity index 100% rename from images/logos/technology/testcontainers.svg rename to _site/images/logos/technology/testcontainers.svg diff --git a/images/logos/technology/webhooks.svg b/_site/images/logos/technology/webhooks.svg similarity index 100% rename from images/logos/technology/webhooks.svg rename to _site/images/logos/technology/webhooks.svg diff --git a/images/logos/wiremock/logo_small.svg b/_site/images/logos/wiremock/logo_small.svg similarity index 100% rename from images/logos/wiremock/logo_small.svg rename to _site/images/logos/wiremock/logo_small.svg diff --git a/images/logos/wiremock/logo_square.svg b/_site/images/logos/wiremock/logo_square.svg similarity index 100% rename from images/logos/wiremock/logo_square.svg rename to _site/images/logos/wiremock/logo_square.svg diff --git a/images/logos/wiremock/logo_wide.svg b/_site/images/logos/wiremock/logo_wide.svg similarity index 100% rename from images/logos/wiremock/logo_wide.svg rename to _site/images/logos/wiremock/logo_wide.svg diff --git a/images/maven.png b/_site/images/maven.png similarity index 100% rename from images/maven.png rename to _site/images/maven.png diff --git a/images/mm-browser-mockups.png b/_site/images/mm-browser-mockups.png similarity index 100% rename from images/mm-browser-mockups.png rename to _site/images/mm-browser-mockups.png diff --git a/images/mm-layout-examples.png b/_site/images/mm-layout-examples.png similarity index 100% rename from images/mm-layout-examples.png rename to _site/images/mm-layout-examples.png diff --git a/images/mocklab/Mocklab_Logo_4x.png b/_site/images/mocklab/Mocklab_Logo_4x.png similarity index 100% rename from images/mocklab/Mocklab_Logo_4x.png rename to _site/images/mocklab/Mocklab_Logo_4x.png diff --git a/images/mocklab/Mocklab_Logo_4x_greyscale.png b/_site/images/mocklab/Mocklab_Logo_4x_greyscale.png similarity index 100% rename from images/mocklab/Mocklab_Logo_4x_greyscale.png rename to _site/images/mocklab/Mocklab_Logo_4x_greyscale.png diff --git a/images/mocklab/rest-example-stubs-screenshot.png b/_site/images/mocklab/rest-example-stubs-screenshot.png similarity index 100% rename from images/mocklab/rest-example-stubs-screenshot.png rename to _site/images/mocklab/rest-example-stubs-screenshot.png diff --git a/images/mocklab/stub-form-screenshot-5.png b/_site/images/mocklab/stub-form-screenshot-5.png similarity index 100% rename from images/mocklab/stub-form-screenshot-5.png rename to _site/images/mocklab/stub-form-screenshot-5.png diff --git a/images/mocklab_logo_4.png b/_site/images/mocklab_logo_4.png similarity index 100% rename from images/mocklab_logo_4.png rename to _site/images/mocklab_logo_4.png diff --git a/images/mocklab_logo_transparent.png b/_site/images/mocklab_logo_transparent.png similarity index 100% rename from images/mocklab_logo_transparent.png rename to _site/images/mocklab_logo_transparent.png diff --git a/_site/images/navigation/loudspeaker.svg b/_site/images/navigation/loudspeaker.svg new file mode 100644 index 00000000..80352dc3 --- /dev/null +++ b/_site/images/navigation/loudspeaker.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/images/openSourceRightIcon.svg b/_site/images/openSourceRightIcon.svg similarity index 100% rename from images/openSourceRightIcon.svg rename to _site/images/openSourceRightIcon.svg diff --git a/images/opengraphs/default.png b/_site/images/opengraphs/default.png similarity index 100% rename from images/opengraphs/default.png rename to _site/images/opengraphs/default.png diff --git a/images/paypalIcon.png b/_site/images/paypalIcon.png similarity index 100% rename from images/paypalIcon.png rename to _site/images/paypalIcon.png diff --git a/images/polygon-texture-2.jpg b/_site/images/polygon-texture-2.jpg old mode 100755 new mode 100644 similarity index 100% rename from images/polygon-texture-2.jpg rename to _site/images/polygon-texture-2.jpg diff --git a/images/recordIcon.svg b/_site/images/recordIcon.svg similarity index 100% rename from images/recordIcon.svg rename to _site/images/recordIcon.svg diff --git a/images/recorder-screenshot.png b/_site/images/recorder-screenshot.png similarity index 100% rename from images/recorder-screenshot.png rename to _site/images/recorder-screenshot.png diff --git a/images/requestIcon.svg b/_site/images/requestIcon.svg similarity index 100% rename from images/requestIcon.svg rename to _site/images/requestIcon.svg diff --git a/images/responseIcon.svg b/_site/images/responseIcon.svg similarity index 100% rename from images/responseIcon.svg rename to _site/images/responseIcon.svg diff --git a/images/rightHeaderHP.png b/_site/images/rightHeaderHP.png similarity index 100% rename from images/rightHeaderHP.png rename to _site/images/rightHeaderHP.png diff --git a/images/sbt.png b/_site/images/sbt.png similarity index 100% rename from images/sbt.png rename to _site/images/sbt.png diff --git a/images/screenshots/advanced-section-body-match.png b/_site/images/screenshots/advanced-section-body-match.png similarity index 100% rename from images/screenshots/advanced-section-body-match.png rename to _site/images/screenshots/advanced-section-body-match.png diff --git a/images/screenshots/base-url.png b/_site/images/screenshots/base-url.png similarity index 100% rename from images/screenshots/base-url.png rename to _site/images/screenshots/base-url.png diff --git a/images/screenshots/basic-new-stub.png b/_site/images/screenshots/basic-new-stub.png similarity index 100% rename from images/screenshots/basic-new-stub.png rename to _site/images/screenshots/basic-new-stub.png diff --git a/images/screenshots/basic-response.png b/_site/images/screenshots/basic-response.png similarity index 100% rename from images/screenshots/basic-response.png rename to _site/images/screenshots/basic-response.png diff --git a/images/screenshots/body-template-screenshot.png b/_site/images/screenshots/body-template-screenshot.png similarity index 100% rename from images/screenshots/body-template-screenshot.png rename to _site/images/screenshots/body-template-screenshot.png diff --git a/images/screenshots/chunked-dribble-delay.png b/_site/images/screenshots/chunked-dribble-delay.png similarity index 100% rename from images/screenshots/chunked-dribble-delay.png rename to _site/images/screenshots/chunked-dribble-delay.png diff --git a/images/screenshots/clone-stub-button.png b/_site/images/screenshots/clone-stub-button.png similarity index 100% rename from images/screenshots/clone-stub-button.png rename to _site/images/screenshots/clone-stub-button.png diff --git a/images/screenshots/default-equal-to-json.png b/_site/images/screenshots/default-equal-to-json.png similarity index 100% rename from images/screenshots/default-equal-to-json.png rename to _site/images/screenshots/default-equal-to-json.png diff --git a/images/screenshots/default-response-example-request.png b/_site/images/screenshots/default-response-example-request.png similarity index 100% rename from images/screenshots/default-response-example-request.png rename to _site/images/screenshots/default-response-example-request.png diff --git a/images/screenshots/default-response-example-response.png b/_site/images/screenshots/default-response-example-response.png similarity index 100% rename from images/screenshots/default-response-example-response.png rename to _site/images/screenshots/default-response-example-response.png diff --git a/images/screenshots/enable-response-templating-screenshot.png b/_site/images/screenshots/enable-response-templating-screenshot.png similarity index 100% rename from images/screenshots/enable-response-templating-screenshot.png rename to _site/images/screenshots/enable-response-templating-screenshot.png diff --git a/images/screenshots/enable-xml-placeholders.png b/_site/images/screenshots/enable-xml-placeholders.png similarity index 100% rename from images/screenshots/enable-xml-placeholders.png rename to _site/images/screenshots/enable-xml-placeholders.png diff --git a/images/screenshots/equal-to-json.png b/_site/images/screenshots/equal-to-json.png similarity index 100% rename from images/screenshots/equal-to-json.png rename to _site/images/screenshots/equal-to-json.png diff --git a/images/screenshots/equal-to-xml-with-placeholders.png b/_site/images/screenshots/equal-to-xml-with-placeholders.png similarity index 100% rename from images/screenshots/equal-to-xml-with-placeholders.png rename to _site/images/screenshots/equal-to-xml-with-placeholders.png diff --git a/images/screenshots/equal-to-xml.png b/_site/images/screenshots/equal-to-xml.png similarity index 100% rename from images/screenshots/equal-to-xml.png rename to _site/images/screenshots/equal-to-xml.png diff --git a/images/screenshots/export-button-on-toolbar.png b/_site/images/screenshots/export-button-on-toolbar.png similarity index 100% rename from images/screenshots/export-button-on-toolbar.png rename to _site/images/screenshots/export-button-on-toolbar.png diff --git a/images/screenshots/export-stubs.png b/_site/images/screenshots/export-stubs.png similarity index 100% rename from images/screenshots/export-stubs.png rename to _site/images/screenshots/export-stubs.png diff --git a/images/screenshots/fault-response.png b/_site/images/screenshots/fault-response.png similarity index 100% rename from images/screenshots/fault-response.png rename to _site/images/screenshots/fault-response.png diff --git a/images/screenshots/fixed-delay.png b/_site/images/screenshots/fixed-delay.png similarity index 100% rename from images/screenshots/fixed-delay.png rename to _site/images/screenshots/fixed-delay.png diff --git a/images/screenshots/header-template-screenshot.png b/_site/images/screenshots/header-template-screenshot.png similarity index 100% rename from images/screenshots/header-template-screenshot.png rename to _site/images/screenshots/header-template-screenshot.png diff --git a/images/screenshots/ignore-array-order.png b/_site/images/screenshots/ignore-array-order.png similarity index 100% rename from images/screenshots/ignore-array-order.png rename to _site/images/screenshots/ignore-array-order.png diff --git a/images/screenshots/ignore-extra-elements.png b/_site/images/screenshots/ignore-extra-elements.png similarity index 100% rename from images/screenshots/ignore-extra-elements.png rename to _site/images/screenshots/ignore-extra-elements.png diff --git a/images/screenshots/import-button-on-toolbar.png b/_site/images/screenshots/import-button-on-toolbar.png similarity index 100% rename from images/screenshots/import-button-on-toolbar.png rename to _site/images/screenshots/import-button-on-toolbar.png diff --git a/images/screenshots/import-file.png b/_site/images/screenshots/import-file.png similarity index 100% rename from images/screenshots/import-file.png rename to _site/images/screenshots/import-file.png diff --git a/images/screenshots/import-text.png b/_site/images/screenshots/import-text.png similarity index 100% rename from images/screenshots/import-text.png rename to _site/images/screenshots/import-text.png diff --git a/images/screenshots/json-placeholders.png b/_site/images/screenshots/json-placeholders.png similarity index 100% rename from images/screenshots/json-placeholders.png rename to _site/images/screenshots/json-placeholders.png diff --git a/images/screenshots/jsonpath-no-submatch.png b/_site/images/screenshots/jsonpath-no-submatch.png similarity index 100% rename from images/screenshots/jsonpath-no-submatch.png rename to _site/images/screenshots/jsonpath-no-submatch.png diff --git a/images/screenshots/jsonpath-with-submatch.png b/_site/images/screenshots/jsonpath-with-submatch.png similarity index 100% rename from images/screenshots/jsonpath-with-submatch.png rename to _site/images/screenshots/jsonpath-with-submatch.png diff --git a/images/screenshots/matches-json-path.png b/_site/images/screenshots/matches-json-path.png similarity index 100% rename from images/screenshots/matches-json-path.png rename to _site/images/screenshots/matches-json-path.png diff --git a/images/screenshots/mock-api-browser-screenshot.png b/_site/images/screenshots/mock-api-browser-screenshot.png similarity index 100% rename from images/screenshots/mock-api-browser-screenshot.png rename to _site/images/screenshots/mock-api-browser-screenshot.png diff --git a/images/screenshots/mock-rest-api/503-error-test-request.png b/_site/images/screenshots/mock-rest-api/503-error-test-request.png similarity index 100% rename from images/screenshots/mock-rest-api/503-error-test-request.png rename to _site/images/screenshots/mock-rest-api/503-error-test-request.png diff --git a/images/screenshots/mock-rest-api/503-response.png b/_site/images/screenshots/mock-rest-api/503-response.png similarity index 100% rename from images/screenshots/mock-rest-api/503-response.png rename to _site/images/screenshots/mock-rest-api/503-response.png diff --git a/images/screenshots/mock-rest-api/companies-list-1.png b/_site/images/screenshots/mock-rest-api/companies-list-1.png similarity index 100% rename from images/screenshots/mock-rest-api/companies-list-1.png rename to _site/images/screenshots/mock-rest-api/companies-list-1.png diff --git a/images/screenshots/mock-rest-api/companies-list-2.png b/_site/images/screenshots/mock-rest-api/companies-list-2.png similarity index 100% rename from images/screenshots/mock-rest-api/companies-list-2.png rename to _site/images/screenshots/mock-rest-api/companies-list-2.png diff --git a/images/screenshots/mock-rest-api/companies-scenario-1.png b/_site/images/screenshots/mock-rest-api/companies-scenario-1.png similarity index 100% rename from images/screenshots/mock-rest-api/companies-scenario-1.png rename to _site/images/screenshots/mock-rest-api/companies-scenario-1.png diff --git a/images/screenshots/mock-rest-api/companies-scenario-2.png b/_site/images/screenshots/mock-rest-api/companies-scenario-2.png similarity index 100% rename from images/screenshots/mock-rest-api/companies-scenario-2.png rename to _site/images/screenshots/mock-rest-api/companies-scenario-2.png diff --git a/images/screenshots/mock-rest-api/companies-scenario-state-change.png b/_site/images/screenshots/mock-rest-api/companies-scenario-state-change.png similarity index 100% rename from images/screenshots/mock-rest-api/companies-scenario-state-change.png rename to _site/images/screenshots/mock-rest-api/companies-scenario-state-change.png diff --git a/images/screenshots/mock-rest-api/contact-list-request.png b/_site/images/screenshots/mock-rest-api/contact-list-request.png similarity index 100% rename from images/screenshots/mock-rest-api/contact-list-request.png rename to _site/images/screenshots/mock-rest-api/contact-list-request.png diff --git a/images/screenshots/mock-rest-api/contact-list-response.png b/_site/images/screenshots/mock-rest-api/contact-list-response.png similarity index 100% rename from images/screenshots/mock-rest-api/contact-list-response.png rename to _site/images/screenshots/mock-rest-api/contact-list-response.png diff --git a/images/screenshots/mock-rest-api/contact-list-test-request.png b/_site/images/screenshots/mock-rest-api/contact-list-test-request.png similarity index 100% rename from images/screenshots/mock-rest-api/contact-list-test-request.png rename to _site/images/screenshots/mock-rest-api/contact-list-test-request.png diff --git a/images/screenshots/mock-rest-api/filtered-contacts-response.png b/_site/images/screenshots/mock-rest-api/filtered-contacts-response.png similarity index 100% rename from images/screenshots/mock-rest-api/filtered-contacts-response.png rename to _site/images/screenshots/mock-rest-api/filtered-contacts-response.png diff --git a/images/screenshots/mock-rest-api/matches-json-path.png b/_site/images/screenshots/mock-rest-api/matches-json-path.png similarity index 100% rename from images/screenshots/mock-rest-api/matches-json-path.png rename to _site/images/screenshots/mock-rest-api/matches-json-path.png diff --git a/images/screenshots/mock-rest-api/new-company-post.png b/_site/images/screenshots/mock-rest-api/new-company-post.png similarity index 100% rename from images/screenshots/mock-rest-api/new-company-post.png rename to _site/images/screenshots/mock-rest-api/new-company-post.png diff --git a/images/screenshots/mock-rest-api/new-contact-body-pattern.png b/_site/images/screenshots/mock-rest-api/new-contact-body-pattern.png similarity index 100% rename from images/screenshots/mock-rest-api/new-contact-body-pattern.png rename to _site/images/screenshots/mock-rest-api/new-contact-body-pattern.png diff --git a/images/screenshots/mock-rest-api/new-contact-post-stub.png b/_site/images/screenshots/mock-rest-api/new-contact-post-stub.png similarity index 100% rename from images/screenshots/mock-rest-api/new-contact-post-stub.png rename to _site/images/screenshots/mock-rest-api/new-contact-post-stub.png diff --git a/images/screenshots/mock-rest-api/new-contact-postman-mismatch.png b/_site/images/screenshots/mock-rest-api/new-contact-postman-mismatch.png similarity index 100% rename from images/screenshots/mock-rest-api/new-contact-postman-mismatch.png rename to _site/images/screenshots/mock-rest-api/new-contact-postman-mismatch.png diff --git a/images/screenshots/mock-rest-api/query-parameter-match.png b/_site/images/screenshots/mock-rest-api/query-parameter-match.png similarity index 100% rename from images/screenshots/mock-rest-api/query-parameter-match.png rename to _site/images/screenshots/mock-rest-api/query-parameter-match.png diff --git a/images/screenshots/mock-rest-api/raised-priority.png b/_site/images/screenshots/mock-rest-api/raised-priority.png similarity index 100% rename from images/screenshots/mock-rest-api/raised-priority.png rename to _site/images/screenshots/mock-rest-api/raised-priority.png diff --git a/images/screenshots/mock-rest-api/rest-api-template.png b/_site/images/screenshots/mock-rest-api/rest-api-template.png similarity index 100% rename from images/screenshots/mock-rest-api/rest-api-template.png rename to _site/images/screenshots/mock-rest-api/rest-api-template.png diff --git a/images/screenshots/mock-rest-api/single-contact-request.png b/_site/images/screenshots/mock-rest-api/single-contact-request.png similarity index 100% rename from images/screenshots/mock-rest-api/single-contact-request.png rename to _site/images/screenshots/mock-rest-api/single-contact-request.png diff --git a/images/screenshots/mock-rest-api/single-contact-response.png b/_site/images/screenshots/mock-rest-api/single-contact-response.png similarity index 100% rename from images/screenshots/mock-rest-api/single-contact-response.png rename to _site/images/screenshots/mock-rest-api/single-contact-response.png diff --git a/images/screenshots/mock-rest-api/templated-contact-request.png b/_site/images/screenshots/mock-rest-api/templated-contact-request.png similarity index 100% rename from images/screenshots/mock-rest-api/templated-contact-request.png rename to _site/images/screenshots/mock-rest-api/templated-contact-request.png diff --git a/images/screenshots/mock-rest-api/templated-contact-response.png b/_site/images/screenshots/mock-rest-api/templated-contact-response.png similarity index 100% rename from images/screenshots/mock-rest-api/templated-contact-response.png rename to _site/images/screenshots/mock-rest-api/templated-contact-response.png diff --git a/images/screenshots/mock-rest-api/templated-contact-test-request.png b/_site/images/screenshots/mock-rest-api/templated-contact-test-request.png similarity index 100% rename from images/screenshots/mock-rest-api/templated-contact-test-request.png rename to _site/images/screenshots/mock-rest-api/templated-contact-test-request.png diff --git a/images/screenshots/multiple-xpath-soap-match.png b/_site/images/screenshots/multiple-xpath-soap-match.png similarity index 100% rename from images/screenshots/multiple-xpath-soap-match.png rename to _site/images/screenshots/multiple-xpath-soap-match.png diff --git a/images/screenshots/new-body-pattern-button.png b/_site/images/screenshots/new-body-pattern-button.png similarity index 100% rename from images/screenshots/new-body-pattern-button.png rename to _site/images/screenshots/new-body-pattern-button.png diff --git a/images/screenshots/new-header-button.png b/_site/images/screenshots/new-header-button.png similarity index 100% rename from images/screenshots/new-header-button.png rename to _site/images/screenshots/new-header-button.png diff --git a/images/screenshots/new-mock-api-button.png b/_site/images/screenshots/new-mock-api-button.png similarity index 100% rename from images/screenshots/new-mock-api-button.png rename to _site/images/screenshots/new-mock-api-button.png diff --git a/images/screenshots/new-stub-button.png b/_site/images/screenshots/new-stub-button.png similarity index 100% rename from images/screenshots/new-stub-button.png rename to _site/images/screenshots/new-stub-button.png diff --git a/images/screenshots/new-to-do-item-field.png b/_site/images/screenshots/new-to-do-item-field.png similarity index 100% rename from images/screenshots/new-to-do-item-field.png rename to _site/images/screenshots/new-to-do-item-field.png diff --git a/images/screenshots/plain-proxy-response.png b/_site/images/screenshots/plain-proxy-response.png similarity index 100% rename from images/screenshots/plain-proxy-response.png rename to _site/images/screenshots/plain-proxy-response.png diff --git a/images/screenshots/postman-empty-api.png b/_site/images/screenshots/postman-empty-api.png similarity index 100% rename from images/screenshots/postman-empty-api.png rename to _site/images/screenshots/postman-empty-api.png diff --git a/images/screenshots/postman.png b/_site/images/screenshots/postman.png similarity index 100% rename from images/screenshots/postman.png rename to _site/images/screenshots/postman.png diff --git a/images/screenshots/proxy-all-by-default-stub.png b/_site/images/screenshots/proxy-all-by-default-stub.png similarity index 100% rename from images/screenshots/proxy-all-by-default-stub.png rename to _site/images/screenshots/proxy-all-by-default-stub.png diff --git a/images/screenshots/random-lognormal-delay.png b/_site/images/screenshots/random-lognormal-delay.png similarity index 100% rename from images/screenshots/random-lognormal-delay.png rename to _site/images/screenshots/random-lognormal-delay.png diff --git a/images/screenshots/random-uniform-delay.png b/_site/images/screenshots/random-uniform-delay.png similarity index 100% rename from images/screenshots/random-uniform-delay.png rename to _site/images/screenshots/random-uniform-delay.png diff --git a/images/screenshots/record-button-screenshot.png b/_site/images/screenshots/record-button-screenshot.png similarity index 100% rename from images/screenshots/record-button-screenshot.png rename to _site/images/screenshots/record-button-screenshot.png diff --git a/images/screenshots/record-dialog-screenshot-3.png b/_site/images/screenshots/record-dialog-screenshot-3.png similarity index 100% rename from images/screenshots/record-dialog-screenshot-3.png rename to _site/images/screenshots/record-dialog-screenshot-3.png diff --git a/images/screenshots/request-parameters.png b/_site/images/screenshots/request-parameters.png similarity index 100% rename from images/screenshots/request-parameters.png rename to _site/images/screenshots/request-parameters.png diff --git a/images/screenshots/response-headers.png b/_site/images/screenshots/response-headers.png similarity index 100% rename from images/screenshots/response-headers.png rename to _site/images/screenshots/response-headers.png diff --git a/images/screenshots/scenario-reset-button.png b/_site/images/screenshots/scenario-reset-button.png similarity index 100% rename from images/screenshots/scenario-reset-button.png rename to _site/images/screenshots/scenario-reset-button.png diff --git a/images/screenshots/scenario-single-item-stub-request.png b/_site/images/screenshots/scenario-single-item-stub-request.png similarity index 100% rename from images/screenshots/scenario-single-item-stub-request.png rename to _site/images/screenshots/scenario-single-item-stub-request.png diff --git a/images/screenshots/scenario-single-item-stub-response.png b/_site/images/screenshots/scenario-single-item-stub-response.png similarity index 100% rename from images/screenshots/scenario-single-item-stub-response.png rename to _site/images/screenshots/scenario-single-item-stub-response.png diff --git a/images/screenshots/scenarios-empty-list-stub-request.png b/_site/images/screenshots/scenarios-empty-list-stub-request.png similarity index 100% rename from images/screenshots/scenarios-empty-list-stub-request.png rename to _site/images/screenshots/scenarios-empty-list-stub-request.png diff --git a/images/screenshots/scenarios-empty-list-stub-response.png b/_site/images/screenshots/scenarios-empty-list-stub-response.png similarity index 100% rename from images/screenshots/scenarios-empty-list-stub-response.png rename to _site/images/screenshots/scenarios-empty-list-stub-response.png diff --git a/images/screenshots/scenarios-post-item-stub.png b/_site/images/screenshots/scenarios-post-item-stub.png similarity index 100% rename from images/screenshots/scenarios-post-item-stub.png rename to _site/images/screenshots/scenarios-post-item-stub.png diff --git a/images/screenshots/soap-action-header.png b/_site/images/screenshots/soap-action-header.png similarity index 100% rename from images/screenshots/soap-action-header.png rename to _site/images/screenshots/soap-action-header.png diff --git a/images/screenshots/soap-placeholders.png b/_site/images/screenshots/soap-placeholders.png similarity index 100% rename from images/screenshots/soap-placeholders.png rename to _site/images/screenshots/soap-placeholders.png diff --git a/images/screenshots/soap-request.png b/_site/images/screenshots/soap-request.png similarity index 100% rename from images/screenshots/soap-request.png rename to _site/images/screenshots/soap-request.png diff --git a/images/screenshots/soap-response.png b/_site/images/screenshots/soap-response.png similarity index 100% rename from images/screenshots/soap-response.png rename to _site/images/screenshots/soap-response.png diff --git a/images/screenshots/start-button-screenshot.png b/_site/images/screenshots/start-button-screenshot.png similarity index 100% rename from images/screenshots/start-button-screenshot.png rename to _site/images/screenshots/start-button-screenshot.png diff --git a/images/screenshots/stop-button-screenshot.png b/_site/images/screenshots/stop-button-screenshot.png similarity index 100% rename from images/screenshots/stop-button-screenshot.png rename to _site/images/screenshots/stop-button-screenshot.png diff --git a/images/screenshots/templated-proxy-response.png b/_site/images/screenshots/templated-proxy-response.png similarity index 100% rename from images/screenshots/templated-proxy-response.png rename to _site/images/screenshots/templated-proxy-response.png diff --git a/images/screenshots/to-do-bad-post-stub-request.png b/_site/images/screenshots/to-do-bad-post-stub-request.png similarity index 100% rename from images/screenshots/to-do-bad-post-stub-request.png rename to _site/images/screenshots/to-do-bad-post-stub-request.png diff --git a/images/screenshots/to-do-bad-post-stub-response.png b/_site/images/screenshots/to-do-bad-post-stub-response.png similarity index 100% rename from images/screenshots/to-do-bad-post-stub-response.png rename to _site/images/screenshots/to-do-bad-post-stub-response.png diff --git a/images/screenshots/to-do-error-page.png b/_site/images/screenshots/to-do-error-page.png similarity index 100% rename from images/screenshots/to-do-error-page.png rename to _site/images/screenshots/to-do-error-page.png diff --git a/images/screenshots/to-do-list-app.png b/_site/images/screenshots/to-do-list-app.png similarity index 100% rename from images/screenshots/to-do-list-app.png rename to _site/images/screenshots/to-do-list-app.png diff --git a/images/screenshots/to-do-list-success-message.png b/_site/images/screenshots/to-do-list-success-message.png similarity index 100% rename from images/screenshots/to-do-list-success-message.png rename to _site/images/screenshots/to-do-list-success-message.png diff --git a/images/screenshots/to-do-post-stub-request.png b/_site/images/screenshots/to-do-post-stub-request.png similarity index 100% rename from images/screenshots/to-do-post-stub-request.png rename to _site/images/screenshots/to-do-post-stub-request.png diff --git a/images/screenshots/to-do-post-stub-response.png b/_site/images/screenshots/to-do-post-stub-response.png similarity index 100% rename from images/screenshots/to-do-post-stub-response.png rename to _site/images/screenshots/to-do-post-stub-response.png diff --git a/images/screenshots/to-do-post-stub.png b/_site/images/screenshots/to-do-post-stub.png similarity index 100% rename from images/screenshots/to-do-post-stub.png rename to _site/images/screenshots/to-do-post-stub.png diff --git a/images/screenshots/to-do-request-log.png b/_site/images/screenshots/to-do-request-log.png similarity index 100% rename from images/screenshots/to-do-request-log.png rename to _site/images/screenshots/to-do-request-log.png diff --git a/images/screenshots/to-do-stub-old.png b/_site/images/screenshots/to-do-stub-old.png similarity index 100% rename from images/screenshots/to-do-stub-old.png rename to _site/images/screenshots/to-do-stub-old.png diff --git a/images/screenshots/to-do-stub-request.png b/_site/images/screenshots/to-do-stub-request.png similarity index 100% rename from images/screenshots/to-do-stub-request.png rename to _site/images/screenshots/to-do-stub-request.png diff --git a/images/screenshots/to-do-stub-response.png b/_site/images/screenshots/to-do-stub-response.png similarity index 100% rename from images/screenshots/to-do-stub-response.png rename to _site/images/screenshots/to-do-stub-response.png diff --git a/images/screenshots/to-do-stub.png b/_site/images/screenshots/to-do-stub.png similarity index 100% rename from images/screenshots/to-do-stub.png rename to _site/images/screenshots/to-do-stub.png diff --git a/images/screenshots/url-match-type.png b/_site/images/screenshots/url-match-type.png similarity index 100% rename from images/screenshots/url-match-type.png rename to _site/images/screenshots/url-match-type.png diff --git a/images/screenshots/url-path-and-query.png b/_site/images/screenshots/url-path-and-query.png similarity index 100% rename from images/screenshots/url-path-and-query.png rename to _site/images/screenshots/url-path-and-query.png diff --git a/images/screenshots/url-path-matching.png b/_site/images/screenshots/url-path-matching.png similarity index 100% rename from images/screenshots/url-path-matching.png rename to _site/images/screenshots/url-path-matching.png diff --git a/images/screenshots/wiremock-folder-drop.png b/_site/images/screenshots/wiremock-folder-drop.png similarity index 100% rename from images/screenshots/wiremock-folder-drop.png rename to _site/images/screenshots/wiremock-folder-drop.png diff --git a/images/screenshots/xpath-body-match.png b/_site/images/screenshots/xpath-body-match.png similarity index 100% rename from images/screenshots/xpath-body-match.png rename to _site/images/screenshots/xpath-body-match.png diff --git a/images/screenshots/xpath-soap-match.png b/_site/images/screenshots/xpath-soap-match.png similarity index 100% rename from images/screenshots/xpath-soap-match.png rename to _site/images/screenshots/xpath-soap-match.png diff --git a/images/separatorLine.png b/_site/images/separatorLine.png similarity index 100% rename from images/separatorLine.png rename to _site/images/separatorLine.png diff --git a/images/shortLogo.png b/_site/images/shortLogo.png similarity index 100% rename from images/shortLogo.png rename to _site/images/shortLogo.png diff --git a/images/signupModalRobot.png b/_site/images/signupModalRobot.png similarity index 100% rename from images/signupModalRobot.png rename to _site/images/signupModalRobot.png diff --git a/images/slack-logo-medium.png b/_site/images/slack-logo-medium.png similarity index 100% rename from images/slack-logo-medium.png rename to _site/images/slack-logo-medium.png diff --git a/images/slackIcon.svg b/_site/images/slackIcon.svg similarity index 100% rename from images/slackIcon.svg rename to _site/images/slackIcon.svg diff --git a/images/small-json-idea-shot.png b/_site/images/small-json-idea-shot.png similarity index 100% rename from images/small-json-idea-shot.png rename to _site/images/small-json-idea-shot.png diff --git a/images/solutions/graphql/wiremock_graphql_opengraph.png b/_site/images/solutions/graphql/wiremock_graphql_opengraph.png similarity index 100% rename from images/solutions/graphql/wiremock_graphql_opengraph.png rename to _site/images/solutions/graphql/wiremock_graphql_opengraph.png diff --git a/images/solutions/grpc/header.png b/_site/images/solutions/grpc/header.png similarity index 100% rename from images/solutions/grpc/header.png rename to _site/images/solutions/grpc/header.png diff --git a/images/solutions/grpc/intro_schema.png b/_site/images/solutions/grpc/intro_schema.png similarity index 100% rename from images/solutions/grpc/intro_schema.png rename to _site/images/solutions/grpc/intro_schema.png diff --git a/images/solutions/grpc/wiremock-grpc-opengraph.png b/_site/images/solutions/grpc/wiremock-grpc-opengraph.png similarity index 100% rename from images/solutions/grpc/wiremock-grpc-opengraph.png rename to _site/images/solutions/grpc/wiremock-grpc-opengraph.png diff --git a/images/solutions/testcontainers/testcontainers_c_logo_square.png b/_site/images/solutions/testcontainers/testcontainers_c_logo_square.png similarity index 100% rename from images/solutions/testcontainers/testcontainers_c_logo_square.png rename to _site/images/solutions/testcontainers/testcontainers_c_logo_square.png diff --git a/images/solutions/testcontainers/testcontainers_c_logo_wide.png b/_site/images/solutions/testcontainers/testcontainers_c_logo_wide.png similarity index 100% rename from images/solutions/testcontainers/testcontainers_c_logo_wide.png rename to _site/images/solutions/testcontainers/testcontainers_c_logo_wide.png diff --git a/images/solutions/testcontainers/testcontainers_c_opengraph.png b/_site/images/solutions/testcontainers/testcontainers_c_opengraph.png similarity index 100% rename from images/solutions/testcontainers/testcontainers_c_opengraph.png rename to _site/images/solutions/testcontainers/testcontainers_c_opengraph.png diff --git a/images/studio/console-splash.png b/_site/images/studio/console-splash.png similarity index 100% rename from images/studio/console-splash.png rename to _site/images/studio/console-splash.png diff --git a/images/studio/hero-screenshot.png b/_site/images/studio/hero-screenshot.png similarity index 100% rename from images/studio/hero-screenshot.png rename to _site/images/studio/hero-screenshot.png diff --git a/images/wiremockStudioDashboard.png b/_site/images/studio/wiremockStudioDashboard.png similarity index 100% rename from images/wiremockStudioDashboard.png rename to _site/images/studio/wiremockStudioDashboard.png diff --git a/images/studioRightIcon.svg b/_site/images/studioRightIcon.svg similarity index 100% rename from images/studioRightIcon.svg rename to _site/images/studioRightIcon.svg diff --git a/assets/svg/bullet.svg b/_site/images/svg/bullet.svg similarity index 100% rename from assets/svg/bullet.svg rename to _site/images/svg/bullet.svg diff --git a/assets/svg/cloud-logo.svg b/_site/images/svg/cloud-logo.svg similarity index 100% rename from assets/svg/cloud-logo.svg rename to _site/images/svg/cloud-logo.svg diff --git a/assets/svg/cloud.svg b/_site/images/svg/cloud.svg similarity index 100% rename from assets/svg/cloud.svg rename to _site/images/svg/cloud.svg diff --git a/assets/svg/faq.svg b/_site/images/svg/faq.svg similarity index 100% rename from assets/svg/faq.svg rename to _site/images/svg/faq.svg diff --git a/assets/svg/source.svg b/_site/images/svg/source.svg similarity index 100% rename from assets/svg/source.svg rename to _site/images/svg/source.svg diff --git a/images/twitterIcon.svg b/_site/images/twitterIcon.svg similarity index 100% rename from images/twitterIcon.svg rename to _site/images/twitterIcon.svg diff --git a/images/ui-bg_glass_20_555555_1x400.png b/_site/images/ui-bg_glass_20_555555_1x400.png similarity index 100% rename from images/ui-bg_glass_20_555555_1x400.png rename to _site/images/ui-bg_glass_20_555555_1x400.png diff --git a/images/ui-bg_glass_40_7E8AA2_1x400.png b/_site/images/ui-bg_glass_40_7E8AA2_1x400.png similarity index 100% rename from images/ui-bg_glass_40_7E8AA2_1x400.png rename to _site/images/ui-bg_glass_40_7E8AA2_1x400.png diff --git a/images/ui-bg_glass_40_ffc73d_1x400.png b/_site/images/ui-bg_glass_40_ffc73d_1x400.png similarity index 100% rename from images/ui-bg_glass_40_ffc73d_1x400.png rename to _site/images/ui-bg_glass_40_ffc73d_1x400.png diff --git a/images/ui-bg_gloss-wave_25_333333_500x100.png b/_site/images/ui-bg_gloss-wave_25_333333_500x100.png similarity index 100% rename from images/ui-bg_gloss-wave_25_333333_500x100.png rename to _site/images/ui-bg_gloss-wave_25_333333_500x100.png diff --git a/images/ui-bg_highlight-soft_80_eeeeee_1x100.png b/_site/images/ui-bg_highlight-soft_80_eeeeee_1x100.png similarity index 100% rename from images/ui-bg_highlight-soft_80_eeeeee_1x100.png rename to _site/images/ui-bg_highlight-soft_80_eeeeee_1x100.png diff --git a/images/ui-bg_inset-soft_25_000000_1x100.png b/_site/images/ui-bg_inset-soft_25_000000_1x100.png similarity index 100% rename from images/ui-bg_inset-soft_25_000000_1x100.png rename to _site/images/ui-bg_inset-soft_25_000000_1x100.png diff --git a/images/ui-bg_inset-soft_30_FF9800_1x100.png b/_site/images/ui-bg_inset-soft_30_FF9800_1x100.png similarity index 100% rename from images/ui-bg_inset-soft_30_FF9800_1x100.png rename to _site/images/ui-bg_inset-soft_30_FF9800_1x100.png diff --git a/images/ui-icons_222222_256x240.png b/_site/images/ui-icons_222222_256x240.png similarity index 100% rename from images/ui-icons_222222_256x240.png rename to _site/images/ui-icons_222222_256x240.png diff --git a/images/ui-icons_4b8e0b_256x240.png b/_site/images/ui-icons_4b8e0b_256x240.png similarity index 100% rename from images/ui-icons_4b8e0b_256x240.png rename to _site/images/ui-icons_4b8e0b_256x240.png diff --git a/images/ui-icons_a83300_256x240.png b/_site/images/ui-icons_a83300_256x240.png similarity index 100% rename from images/ui-icons_a83300_256x240.png rename to _site/images/ui-icons_a83300_256x240.png diff --git a/images/ui-icons_cccccc_256x240.png b/_site/images/ui-icons_cccccc_256x240.png similarity index 100% rename from images/ui-icons_cccccc_256x240.png rename to _site/images/ui-icons_cccccc_256x240.png diff --git a/images/ui-icons_ffffff_256x240.png b/_site/images/ui-icons_ffffff_256x240.png similarity index 100% rename from images/ui-icons_ffffff_256x240.png rename to _site/images/ui-icons_ffffff_256x240.png diff --git a/images/unitTestIcon.svg b/_site/images/unitTestIcon.svg similarity index 100% rename from images/unitTestIcon.svg rename to _site/images/unitTestIcon.svg diff --git a/images/verification-exception.png b/_site/images/verification-exception.png similarity index 100% rename from images/verification-exception.png rename to _site/images/verification-exception.png diff --git a/images/wireMockLogo.png b/_site/images/wireMockLogo.png similarity index 100% rename from images/wireMockLogo.png rename to _site/images/wireMockLogo.png diff --git a/images/wiremock-cloud/hero-dash.png b/_site/images/wiremock-cloud/hero-dash.png similarity index 100% rename from images/wiremock-cloud/hero-dash.png rename to _site/images/wiremock-cloud/hero-dash.png diff --git a/images/wiremock-cloud/hero-screenshot.png b/_site/images/wiremock-cloud/hero-screenshot.png similarity index 100% rename from images/wiremock-cloud/hero-screenshot.png rename to _site/images/wiremock-cloud/hero-screenshot.png diff --git a/images/wiremock-cloud/wiremock_cloud_favicon.svg b/_site/images/wiremock-cloud/wiremock_cloud_favicon.svg similarity index 100% rename from images/wiremock-cloud/wiremock_cloud_favicon.svg rename to _site/images/wiremock-cloud/wiremock_cloud_favicon.svg diff --git a/images/wiremock-cloud/wiremock_cloud_logo.png b/_site/images/wiremock-cloud/wiremock_cloud_logo.png similarity index 100% rename from images/wiremock-cloud/wiremock_cloud_logo.png rename to _site/images/wiremock-cloud/wiremock_cloud_logo.png diff --git a/images/wiremock-cloud/wiremock_cloud_logo.svg b/_site/images/wiremock-cloud/wiremock_cloud_logo.svg similarity index 100% rename from images/wiremock-cloud/wiremock_cloud_logo.svg rename to _site/images/wiremock-cloud/wiremock_cloud_logo.svg diff --git a/images/wiremock-idea-shots.png b/_site/images/wiremock-idea-shots.png similarity index 100% rename from images/wiremock-idea-shots.png rename to _site/images/wiremock-idea-shots.png diff --git a/images/wiremockBIG.png b/_site/images/wiremockBIG.png similarity index 100% rename from images/wiremockBIG.png rename to _site/images/wiremockBIG.png diff --git a/images/wiremockBYUP9.png b/_site/images/wiremockBYUP9.png similarity index 100% rename from images/wiremockBYUP9.png rename to _site/images/wiremockBYUP9.png diff --git a/images/wiremockBigModal.png b/_site/images/wiremockBigModal.png similarity index 100% rename from images/wiremockBigModal.png rename to _site/images/wiremockBigModal.png diff --git a/images/wiremockDashboard.png b/_site/images/wiremockDashboard.png similarity index 100% rename from images/wiremockDashboard.png rename to _site/images/wiremockDashboard.png diff --git a/images/wiremockRobot.png b/_site/images/wiremockRobot.png similarity index 100% rename from images/wiremockRobot.png rename to _site/images/wiremockRobot.png diff --git a/images/wiremockRobotBG.png b/_site/images/wiremockRobotBG.png similarity index 100% rename from images/wiremockRobotBG.png rename to _site/images/wiremockRobotBG.png diff --git a/images/wiremockStudioLeft.png b/_site/images/wiremockStudioLeft.png similarity index 100% rename from images/wiremockStudioLeft.png rename to _site/images/wiremockStudioLeft.png diff --git a/images/wiremockStudioRight.png b/_site/images/wiremockStudioRight.png similarity index 100% rename from images/wiremockStudioRight.png rename to _site/images/wiremockStudioRight.png diff --git a/images/wiremockTypeExample.svg b/_site/images/wiremockTypeExample.svg similarity index 100% rename from images/wiremockTypeExample.svg rename to _site/images/wiremockTypeExample.svg diff --git a/images/wm-concept-01.svg b/_site/images/wm-concept-01.svg similarity index 98% rename from images/wm-concept-01.svg rename to _site/images/wm-concept-01.svg index f9fd5100..c686885f 100644 --- a/images/wm-concept-01.svg +++ b/_site/images/wm-concept-01.svg @@ -1,58 +1,58 @@ - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/_site/index.md similarity index 61% rename from index.html rename to _site/index.md index 84a0a719..450068b0 100644 --- a/index.html +++ b/_site/index.md @@ -1,22 +1,7 @@ --- -layout: default -title: WireMock - flexible, open source API mocking -description: WireMock is a tool for building mock APIs. API mocking enables you build stable, predictable development environments when the APIs you depend on are unreliable or don't exist. -header_signup_link: "https://www.wiremock.io/product?utm_source=wiremock.org&utm_medium=referral&utm_campaign=masthead" +template: static.html --- - -

    Mock the APIs You Depend On

    @@ -25,7 +10,7 @@

    Mock the APIs You Depend On

    source @@ -44,7 +29,7 @@

    cloud @@ -121,11 +106,11 @@

    - Documentation Slack Community @@ -133,45 +118,33 @@

    -   Join us for Hacktoberfest 2023! -

    -

    Learn WireMock and contribute to open source

    -

    - - - -

    +   + What's NEW? WireMock API Template Library

    - This October we participate in Hacktoberfest - a global open source - hack fest. We invite you to join us, regardless of your profile and - technology stack. + Test against popular 3rd-party services in a few clicks!

    - Adopt WireMock in your projects, contribute new features and fixes, - improve docs, create new demos and artwork, etc. + + +

    - Learn More... + Browse our library of mock API templates and examples, find the API that you need, + and mock it in seconds - on your local machine or in the cloud. + Learn More...

    -
    - z +
    wiremock cloud screenshot
    @@ -179,7 +152,7 @@

    Key Features

    Wiremock Features
    @@ -233,7 +206,7 @@

    Key Features

    wiremock dynamic response
    @@ -242,7 +215,7 @@

    Key Features

    wiremock unit tests
    @@ -253,7 +226,7 @@

    Key Features

    wiremock fault and latency
    @@ -262,7 +235,7 @@

    Key Features

    wiremock record playback
    @@ -271,7 +244,7 @@

    Key Features

    wiremock java, python, http
    @@ -289,8 +262,17 @@

    Downloads

    integrations for modern languages and technology stacks.

    - {% include downloads.html show_standalone="true" %} -
    +
    Maven
    Gradle
    Kotlin
    SBT
    Java
    Docker
    • Maven
    • Gradle Groovy
    • Gradle Kotlin
    • Scala SBT
    • Standalone
    • Docker

    Add the following to your project's pom.xml dependencies:

    <dependency>
    +  <groupId>org.wiremock</groupId>
    +  <artifactId>wiremock</artifactId>
    +  <version>3.3.1</version>
    +  <scope>test</scope>
    +</dependency>

    Then follow the next steps for JUnit 5+ or plain Java.

    Add the following to your project's build.gradle:

    testImplementation "org.wiremock:wiremock:3.3.1"

    Then follow the next steps for JUnit 5+ or plain Java.

    Add the following to your project's build.gradle.kts:

    testImplementation("org.wiremock:wiremock:3.3.1")

    Then follow the next steps for JUnit 5+ or plain Java.

    Add the following to your project’s build.sbt:

    libraryDependencies +=
    +  "org.wiremock" % "wiremock" % "3.3.1" % Test

    Download the latest standalone JAR then run the following in a terminal:

    java -jar wiremock-standalone-3.3.1.jar

    Learn more in the running standalone guide.

    Run the following in a terminal:

    docker run -it --rm \
    +  -p 8080:8080 \
    +  --name wiremock \
    +  wiremock/wiremock:3.3.1

    Learn more in the Docker guide.

    +
    @@ -353,4 +335,4 @@

    Frequently Asked Questions

    -
    +
    \ No newline at end of file diff --git a/assets/js/jekyll-code-tabs.js b/_site/js/code-tabs.js similarity index 100% rename from assets/js/jekyll-code-tabs.js rename to _site/js/code-tabs.js diff --git a/assets/js/codeTab.js b/_site/js/codeTab.js similarity index 100% rename from assets/js/codeTab.js rename to _site/js/codeTab.js diff --git a/assets/js/faq.js b/_site/js/faq.js similarity index 100% rename from assets/js/faq.js rename to _site/js/faq.js diff --git a/assets/js/vendor/jquery/jquery-1.12.1.min.js b/_site/js/jquery/jquery-1.12.1.min.js similarity index 100% rename from assets/js/vendor/jquery/jquery-1.12.1.min.js rename to _site/js/jquery/jquery-1.12.1.min.js diff --git a/assets/js/mobile-navbar.js b/_site/js/mobile-navbar.js similarity index 100% rename from assets/js/mobile-navbar.js rename to _site/js/mobile-navbar.js diff --git a/_site/resources/README.md b/_site/resources/README.md new file mode 100644 index 00000000..230868e0 --- /dev/null +++ b/_site/resources/README.md @@ -0,0 +1,4 @@ +# Community Resources + +* [Community Slack](../community/slack.md) +* [External Resource](external.md) - Code, articles and videos related to WireMock from around the web. diff --git a/support/commercial.md b/_site/resources/commercial-support.md similarity index 90% rename from support/commercial.md rename to _site/resources/commercial-support.md index eb5710a4..fb669d27 100644 --- a/support/commercial.md +++ b/_site/resources/commercial-support.md @@ -1,14 +1,14 @@ --- -layout: single -title: Commercial Support -meta_title: How to get WireMock commercial support with SLA -description: Enterprise and commercial support and consulting options +description: How to get WireMock enterprise and commercial support with SLA, training and consulting options +template: standalone.html --- +# Commercial Support for WireMock + WireMock is an open source project. In accordance with the [Apache License 2.0](https://github.com/wiremock/wiremock/blob/master/LICENSE.txt), in general there is no support or guarantees provided for it. -You can get some assistance through WireMock community channels, +You can get some [community assistance](community-support.md) through the WireMock community channels, and contribute to helping other users too. At the same time, there are vendors that provide commercial support for WireMock. @@ -33,9 +33,10 @@ You can find more info about WireMock Cloud support plans [here](https://www.wir WireMocha is a plugin for IntelliJ based IDEs, and has tools for WireMock specific static code analysis (in the Java and JSON DSLs), code generation, stubbing, and many others to overall simplify the work with WireMock. Two prominent code generation features, beside a handful of smaller ones, can help you: + - generate a scenario's Java and JSON stub implementations by simply modeling its states and transitions in a dedicated tool window, - generate and preview the Java version of JSON stub mappings on-the-fly during editing JSON mapping files. It can speed -up migration from JSON to Java implementation. + up migration from JSON to Java implementation. JSON schemas are also associated to JSON mapping files, and are joined with various language injections. They provide additional syntax highlighting (e.g. Handlebars, XPath, ...) and validation, as well as code completion that can greatly speed up the implementation and maintenance of JSON mapping files. diff --git a/support/index.md b/_site/resources/community-support.md similarity index 81% rename from support/index.md rename to _site/resources/community-support.md index a60c6900..475093a5 100644 --- a/support/index.md +++ b/_site/resources/community-support.md @@ -1,12 +1,9 @@ --- -layout: support -title: Support -meta_title: How to get WireMock support -description: Community Assistance, Enterprise and commercial support and consulting options -redirect_from: - - "/docs/support.html" +description: How to get community assistance if you are a WireMock user --- +# WireMock Community Support + WireMock is an open source project. In accordance with the [Apache License 2.0](https://github.com/wiremock/wiremock/blob/master/LICENSE.txt), in general there is no support or guarantees provided for it. @@ -14,7 +11,7 @@ At the same time, you can get some assistance through WireMock community channel and contribute to helping other users too. There are also vendors that provide commercial support for WireMock. -## WireMock Community +## Community Support If you’re looking for help or advice, you can find a community of users and contributors on the WireMock community Slack channels. @@ -29,4 +26,4 @@ Every community member is welcome to participate, help to triage and answer the ## Commercial support, trainings and consulting -See [this page](./commercial). +See [this page](commercial-support.md). diff --git a/_site/resources/external.md b/_site/resources/external.md new file mode 100644 index 00000000..169787b7 --- /dev/null +++ b/_site/resources/external.md @@ -0,0 +1,131 @@ +# External Resources + +Code, articles and videos related to WireMock from around the web. + +## Integrations + +WireMocha is a WireMock plugin for IntelliJ: +[Plugin Page](https://plugins.jetbrains.com/plugin/18860-wiremocha) + +Spring Contract Verifier (previously called Accurest) is a consumer driven contracts tool that generates WireMock stub mappings as examples for client testing. + +[http://cloud.spring.io/spring-cloud-contract/](http://cloud.spring.io/spring-cloud-contract/) + + +A Spring REST Docs integration for WireMock that generates WireMock stub mappings from your test cases: + +[https://github.com/epages-de/restdocs-wiremock](https://github.com/epages-de/restdocs-wiremock) + + +WireMock Maven Plugin: + +[https://github.com/automatictester/wiremock-maven-plugin](https://github.com/automatictester/wiremock-maven-plugin) + + +Maciej Walkowiak has built a library providing zero-config, fully declarative Spring Boot integration with WireMock in JUnit 5 tests: + +[https://github.com/maciejwalkowiak/wiremock-spring-boot](https://github.com/maciejwalkowiak/wiremock-spring-boot) + + +`@GenerateWireMockStub` for Spring REST controllers, built by Lukasz Gryzbon, makes the creation of WireMock stubs for tests safe and effortless: + +[https://github.com/lsd-consulting/spring-wiremock-stub-generator](https://github.com/lsd-consulting/spring-wiremock-stub-generator) + + +Felipe Fernández has built a Spock extension to enhance automation around record and replay functionality: + +[https://github.com/felipefzdz/spock-wiremock-extension](https://github.com/felipefzdz/spock-wiremock-extension) + + +Automate configuration of stubs, given JAX-RS annotated resources, with this extension: + +[https://github.com/tomasbjerre/wiremock-jaxrs](https://github.com/tomasbjerre/wiremock-jaxrs) + + +## WireMock Extensions + +Listing of WireMock Extensions is now available on the documentation site +[here](../docs/extensions/README.md). + +## Other languages + +Most of the language integrations are linked from the [Documentation Root](../docs/README.md). +Below there are some technologies that are yet to be added. + +PHP client by Rowan Hill: + +[https://github.com/rowanhill/wiremock-php](https://github.com/rowanhill/wiremock-php) + + +Ruby wrapper by Jeffres S. Morgan: + +[https://rubygems.org/gems/service_mock](https://rubygems.org/gems/service_mock) + + +Groovy binding by Tom Jankes: + +[https://github.com/tomjankes/wiremock-groovy](https://github.com/tomjankes/wiremock-groovy) + + +Dusan Dević at Yenlo wrote a useful guide to testing error conditions in the WSO2 ESB using Wiremock: + +[https://www.yenlo.com/blog/wso2torial-error-handling-in-wso2-esb-with-wiremock](https://www.yenlo.com/blog/wso2torial-error-handling-in-wso2-esb-with-wiremock) + + +Phill Barber has written a couple of interesting posts about practical testing scenarios with WireMock: + +[http://phillbarber.blogspot.co.uk/2015/05/how-to-write-end-to-end-tests-for-nginx.html](http://phillbarber.blogspot.co.uk/2015/05/how-to-write-end-to-end-tests-for-nginx.html) + +[http://phillbarber.blogspot.co.uk/2015/02/how-to-test-for-connection-leaks.html](http://phillbarber.blogspot.co.uk/2015/02/how-to-test-for-connection-leaks.html) + + +Bas Dijkstra kindly open sourced the content for the workshop he ran on WireMock and REST Assured: + +[http://www.ontestautomation.com/open-sourcing-my-workshop-on-wiremock/](http://www.ontestautomation.com/open-sourcing-my-workshop-on-wiremock/) + + +`@GenerateWireMockStub` for Spring REST controllers, built by Lukasz Gryzbon, makes the creation of WireMock stubs for tests safe and effortless: + +[https://dzone.com/articles/wiremock-the-ridiculously-easy-way](https://dzone.com/articles/wiremock-the-ridiculously-easy-way) + + +WireMock workshop: + +[https://github.com/basdijkstra/wiremock-workshop](https://github.com/basdijkstra/wiremock-workshop) + +## Videos + +Fluent and thorough live-coding demonstration of WireMock delivered by Sam Edwards at DevFest DC: + +[https://youtu.be/x3MvZ8DFrpE](https://youtu.be/x3MvZ8DFrpE) + + +Sebastian Daschner presents a step-by-step guide to running your acceptance tests in Kubernetes using WireMock: + +[https://blog.sebastian-daschner.com/entries/acceptance_tests_wiremock_kubernetes](https://blog.sebastian-daschner.com/entries/acceptance_tests_wiremock_kubernetes) + + +Interesting and detailed presentation by Lotte Johansen on testing microservices with WireMock at Norway's top online marketplace: + +[https://www.youtube.com/watch?v=cmJfMnGK-r0](https://www.youtube.com/watch?v=cmJfMnGK-r0) + + +Chris Batey did an excellent talk at Skillsmatter in London about building fault tolerant microservices. He showed some practical failure testing strategies using WireMock and Saboteur he'd used for real while working at Sky: + +[https://skillsmatter.com/skillscasts/5810-building-fault-tolerant-microservices](https://skillsmatter.com/skillscasts/5810-building-fault-tolerant-microservices) + + +Daniel Bryant's excellent QCon presentation “The Seven Deadly Sins of Microservices” covers the full gamut of microservice anti-patterns seen in the wild, with some sound advice on how to fix them. WireMock and Saboteur get an honourable mention in the testing discussion: + +[https://www.infoq.com/presentations/7-sins-microservices](https://www.infoq.com/presentations/7-sins-microservices) + + +The folks at Intuit have built a very impressive and ambitious testing +setup, using WireMock to isolate individual services. Here's a talk they did at AWS:Reinvent: + +[https://www.youtube.com/watch?list=PLhr1KZpdzuke5pqzTvI2ZxwP8-NwLACuU&v=sUsh3EnzKKk](https://www.youtube.com/watch?list=PLhr1KZpdzuke5pqzTvI2ZxwP8-NwLACuU&v=sUsh3EnzKKk) + + +Tom and Rob Elliot gave a join talk at Skillsmatter about patterns for readable and scalable tests with WireMock, and an approach for unit testing a CDN: + +[https://skillsmatter.com/skillscasts/6853-scalable-management-of-test-data-making-tests-readable](https://skillsmatter.com/skillscasts/6853-scalable-management-of-test-data-making-tests-readable) diff --git a/_studio_docs/index.md b/_studio_docs/index.md deleted file mode 100644 index eb82f557..00000000 --- a/_studio_docs/index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -layout: docs -title: WireMock Studio Documentation - Home -permalink: /studio/docs/ -description: Welcome to the WireMock Studio documentation ---- - -WireMock Studio has now been discontinued. Please check out [WireMock Cloud](https://wiremock.io) instead. diff --git a/about/index.md b/about/index.md deleted file mode 100644 index 9f4ce289..00000000 --- a/about/index.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -layout: default -author_profile: true -title: About -meta_title: Contributors | WireMock ---- - -# About WireMock - -WireMock was originally created by [Tom Akehurst](http://tomakehurst.com) in 2011. Since then a whole host of people have been kind enough to contribute code, documentation and community support. - -Many thanks to all of the following folks: - -Adrian Ng
    -[Akshay Deodhar](https://github.com/planetakshay)
    -[Aman King](https://github.com/amanking)
    -[Andrés Di Falco](https://github.com/adifalco)
    -[Ashley Taylor](https://github.com/ashley-taylor)
    -[Belema Gancarz](https://github.com/Belema)
    -[Chris Batey](https://github.com/chbatey)
    -[Christian Amann](https://github.com/camann9)
    -[Christian Trimble](https://github.com/ctrimble)
    -[Claudius Böttcher](https://github.com/clboettcher)
    -[David Smith](https://github.com/shmish111)
    -[Diego de Oliveira](https://github.com/diegooliveira)
    -[Dipanjan Laha](https://github.com/dlaha21)
    -[Dominic Tootell](https://github.com/tootedom)
    -[Emma Burrows](https://github.com/emma-burrows)
    -[Eric Driggs](https://github.com/edriggs)
    -[Florian Lasinger](https://github.com/)
    -[Gus Power](https://github.com/guspower)
    -[James Ravn](https://github.com/jsravn)
    -[Jamie Furnaghan](https://github.com/reines)
    -[Jay Goldberg](https://github.com/carthoris)
    -[Julian Vergel de Dios](https://github.com/jvergeldedios)
    -[Kai Hofstetter](https://github.com/KaiHofstetter)
    -[Kamil Szymański](https://github.com/kamilszymanski)
    -[Kjetil Valstadsve](https://github.com/kjetilv)
    -[Matt Nathan](https://github.com/mattnathan)
    -[Mike Castleman](https://github.com/mlc)
    -[Mike Rogers](https://github.com/mike-rogers)
    -[Moritz Kammerer](https://github.com/)
    -[Neil Green](https://github.com/neilg)
    -[Nils Christian Haugen](https://github.com/nchaugen)
    -[Oleg Kalnichevski](https://github.com/ok2c)
    -[Oliver Schönherr](https://github.com/oschoen)
    -[Paul Clarkin](https://github.com/paulclarkin)
    -Paul Smith
    -[Quenio dos Santos](https://github.com/quenio)
    -R. Michael Rogers
    -[Rainer Friesen](https://github.com/rainerfriesen)
    -[Rob Elliot](https://github.com/Mahoney)
    -[Rowan Hill](https://github.com/rowanhill)
    -[Sam Edwards](https://github.com/handstandsam)
    -[Sam Pengilly](https://github.com/sampengilly)
    -[Sebastian Mancke](https://github.com/smancke)
    -[Seth Bresnett](https://github.com/SethBresnettSoftwire)
    -[Thomas LÉVEIL](https://github.com/thomasleveil)
    -[Tim Perry](https://github.com/pimterry)
    -[Todd Ricker](https://github.com/tricker)
    -[Tomasz Wroniak](https://github.com/twroniak)
    -[Zoran Regvart](https://github.com/zregvart)
    diff --git a/assets/css/main.scss b/assets/css/main.scss deleted file mode 100644 index 0af1c9c1..00000000 --- a/assets/css/main.scss +++ /dev/null @@ -1,54 +0,0 @@ ---- -# For SCSS discoverability -search: false ---- - -/* - * Minimal Mistakes Jekyll Theme - * - * - Michael Rose - * - mademistakes.com - * - https://twitter.com/mmistakes - * -*/ - -@import "vendor/breakpoint/breakpoint"; // media query mixins -@import "variables"; -@import "mixins"; -@import "vendor/susy/susy"; -@import "vendor/jquery-ui"; - -@import "reset"; -@import "base"; - -@import "utilities"; -@import "animations"; -@import "tables"; -@import "buttons"; -@import "notices"; -@import "masthead"; -@import "navigation"; -@import "footer"; -@import "syntax"; -@import "notify"; - -@import "forms"; - -@import "homepage"; -@import "page"; -@import "archive"; -@import "sidebar"; -@import "studio"; -@import "splash"; -@import "support"; - -@import "sidebar-docs"; - -@import "vendor/font-awesome/font-awesome"; -@import "vendor/magnific-popup/magnific-popup"; -@import "print"; -@import "faq"; - -@import "code"; - -@import "mocklab-popup"; diff --git a/assets/css/support.css b/assets/css/support.css deleted file mode 100644 index 4c0259ca..00000000 --- a/assets/css/support.css +++ /dev/null @@ -1,3 +0,0 @@ -.support{width:950px;height:100vh;margin-left:auto;margin-right:auto;padding:0 0 50px 0}@media (max-width: 990px){.support{width:90%}}.support h1,.support h2,.support h3,.support h4{font-family:"Ubuntu";font-style:normal;font-weight:bold;color:#18253d;border:none !important}.support h1{font-size:2.8rem;margin-top:0px;margin-bottom:0px}.support h2{margin-top:30px;margin-bottom:0px;font-size:2rem;padding-bottom:10px}.support h2 :first-child{padding-top:0px !important;margin-top:0px !important}.support p{font-family:"Ubuntu";font-style:normal;font-weight:normal;font-size:18px;color:#18253d;margin-top:0px !important;margin-bottom:0} - -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN1cHBvcnQuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFNBQVMsV0FBVyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQywwQkFBMEIsU0FBUyxTQUFTLENBQUMsQ0FBQyxnREFBZ0Qsb0JBQW9CLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLHNCQUFzQixDQUFDLFlBQVksZ0JBQWdCLENBQUMsY0FBYyxDQUFDLGlCQUFpQixDQUFDLFlBQVksZUFBZSxDQUFDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsMEJBQTBCLENBQUMseUJBQXlCLENBQUMsV0FBVyxvQkFBb0IsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLHlCQUF5QixDQUFDLGVBQWUiLCJmaWxlIjoic3VwcG9ydC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuc3VwcG9ydHt3aWR0aDo5NTBweDtoZWlnaHQ6MTAwdmg7bWFyZ2luLWxlZnQ6YXV0bzttYXJnaW4tcmlnaHQ6YXV0bztwYWRkaW5nOjAgMCA1MHB4IDB9QG1lZGlhIChtYXgtd2lkdGg6IDk5MHB4KXsuc3VwcG9ydHt3aWR0aDo5MCV9fS5zdXBwb3J0IGgxLC5zdXBwb3J0IGgyLC5zdXBwb3J0IGgzLC5zdXBwb3J0IGg0e2ZvbnQtZmFtaWx5OlwiVWJ1bnR1XCI7Zm9udC1zdHlsZTpub3JtYWw7Zm9udC13ZWlnaHQ6Ym9sZDtjb2xvcjojMTgyNTNkO2JvcmRlcjpub25lICFpbXBvcnRhbnR9LnN1cHBvcnQgaDF7Zm9udC1zaXplOjIuOHJlbTttYXJnaW4tdG9wOjBweDttYXJnaW4tYm90dG9tOjBweH0uc3VwcG9ydCBoMnttYXJnaW4tdG9wOjMwcHg7bWFyZ2luLWJvdHRvbTowcHg7Zm9udC1zaXplOjJyZW07cGFkZGluZy1ib3R0b206MTBweH0uc3VwcG9ydCBoMiA6Zmlyc3QtY2hpbGR7cGFkZGluZy10b3A6MHB4ICFpbXBvcnRhbnQ7bWFyZ2luLXRvcDowcHggIWltcG9ydGFudH0uc3VwcG9ydCBwe2ZvbnQtZmFtaWx5OlwiVWJ1bnR1XCI7Zm9udC1zdHlsZTpub3JtYWw7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtc2l6ZToxOHB4O2NvbG9yOiMxODI1M2Q7bWFyZ2luLXRvcDowcHggIWltcG9ydGFudDttYXJnaW4tYm90dG9tOjB9XG4iXX0= */ \ No newline at end of file diff --git a/assets/fonts/DMSans-Medium.ttf b/assets/fonts/DMSans-Medium.ttf deleted file mode 100644 index c29713e5..00000000 Binary files a/assets/fonts/DMSans-Medium.ttf and /dev/null differ diff --git a/assets/fonts/DMSans-Regular.ttf b/assets/fonts/DMSans-Regular.ttf deleted file mode 100644 index 28ff3c87..00000000 Binary files a/assets/fonts/DMSans-Regular.ttf and /dev/null differ diff --git a/assets/fonts/FontAwesome.otf b/assets/fonts/FontAwesome.otf deleted file mode 100644 index 59853bcd..00000000 Binary files a/assets/fonts/FontAwesome.otf and /dev/null differ diff --git a/assets/fonts/SF_Pro.ttf b/assets/fonts/SF_Pro.ttf deleted file mode 100644 index b63615e9..00000000 Binary files a/assets/fonts/SF_Pro.ttf and /dev/null differ diff --git a/assets/fonts/fontawesome-webfont.eot b/assets/fonts/fontawesome-webfont.eot deleted file mode 100644 index 96f92f9b..00000000 Binary files a/assets/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/assets/fonts/fontawesome-webfont.svg b/assets/fonts/fontawesome-webfont.svg deleted file mode 100644 index 5a5f0ecd..00000000 --- a/assets/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,685 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/fonts/fontawesome-webfont.ttf b/assets/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 86784df9..00000000 Binary files a/assets/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/assets/fonts/fontawesome-webfont.woff b/assets/fonts/fontawesome-webfont.woff deleted file mode 100644 index c7faa19c..00000000 Binary files a/assets/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/assets/fonts/fontawesome-webfont.woff2 b/assets/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index cab8571d..00000000 Binary files a/assets/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/assets/js/_main.js b/assets/js/_main.js deleted file mode 100644 index 08ac4d90..00000000 --- a/assets/js/_main.js +++ /dev/null @@ -1,81 +0,0 @@ -/* ========================================================================== - jQuery plugin settings and other scripts - ========================================================================== */ - -$(document).ready(function () { - // FitVids init - $("#main").fitVids(); - - // init sticky sidebar - $(".sticky").Stickyfill(); - - var stickySideBar = function () { - var windowWidth = $(window).width(); - if (windowWidth > 1024) { - // fix - Stickyfill.rebuild(); - Stickyfill.init(); - } else { - // unfix - Stickyfill.stop(); - } - }; - - stickySideBar(); - - $(window).resize(function () { - stickySideBar(); - }); - - // Follow menu drop down - - $(".author__urls-wrapper button").on("click", function () { - $(".author__urls").fadeToggle("fast", function () {}); - $(".author__urls-wrapper button").toggleClass("open"); - }); - - // init smooth scroll - $("a").smoothScroll({ offset: -20 }); - - // add lightbox class to all image links - $( - "a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif']" - ).addClass("image-popup"); - - // Magnific-Popup options - $(".image-popup").magnificPopup({ - disableOn: function () { - if ($(window).width() < 500) { - return false; - } - return true; - }, - type: "image", - tLoading: "Loading image #%curr%...", - gallery: { - enabled: true, - navigateByImgClick: true, - preload: [0, 1], // Will preload 0 - before current, and 1 after the current image - }, - image: { - tError: 'Image #%curr% could not be loaded.', - }, - removalDelay: 500, // Delay in milliseconds before popup is removed - // Class that is added to body when popup is open. - // make it unique to apply your CSS animations just to this exact popup - mainClass: "mfp-zoom-in", - callbacks: { - beforeOpen: function () { - // just a hack that adds mfp-anim class to markup - this.st.image.markup = this.st.image.markup.replace( - "mfp-figure", - "mfp-figure mfp-with-anim" - ); - }, - }, - closeOnContentClick: true, - midClick: true, // allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source. - }); - - $(".code-sample-tabs").tabs(); -}); diff --git a/assets/js/homeHeaderCard.js b/assets/js/homeHeaderCard.js deleted file mode 100644 index 2a3b6f38..00000000 --- a/assets/js/homeHeaderCard.js +++ /dev/null @@ -1,21 +0,0 @@ -const openSourceCard = document.querySelector("#openSourceCard"); -const leftHeaderHP = document.querySelector(".home-header-leftHeaderHP"); - -const wiremockCloudCard = document.querySelector("#wiremockCloudCard"); -const rightHeaderHP = document.querySelector(".home-header-rightHeaderHP"); - -openSourceCard.addEventListener("mouseover", () => { - leftHeaderHP.classList.add("headerHoverCardOpenStuio"); - leftHeaderHP.classList.add("headerHoverCard"); -}); -openSourceCard.addEventListener("mouseout", () => { - leftHeaderHP.classList.remove("headerHoverCard"); -}); - -wiremockCloudCard.addEventListener("mouseover", () => { - rightHeaderHP.classList.add("headerHoverCardStudio"); - rightHeaderHP.classList.add("headerHoverCard"); -}); -wiremockCloudCard.addEventListener("mouseout", () => { - rightHeaderHP.classList.remove("headerHoverCard"); -}); diff --git a/assets/js/jquery.min.js b/assets/js/jquery.min.js deleted file mode 100644 index 4024b662..00000000 --- a/assets/js/jquery.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; -}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("'+ - '
    ', - - srcAction: 'iframe_src', - - // we don't care and support only one default type of URL by default - patterns: { - youtube: { - index: 'youtube.com', - id: 'v=', - src: '//www.youtube.com/embed/%id%?autoplay=1' - }, - vimeo: { - index: 'vimeo.com/', - id: '/', - src: '//player.vimeo.com/video/%id%?autoplay=1' - }, - gmaps: { - index: '//maps.google.', - src: '%id%&output=embed' - } - } - }, - - proto: { - initIframe: function() { - mfp.types.push(IFRAME_NS); - - _mfpOn('BeforeChange', function(e, prevType, newType) { - if(prevType !== newType) { - if(prevType === IFRAME_NS) { - _fixIframeBugs(); // iframe if removed - } else if(newType === IFRAME_NS) { - _fixIframeBugs(true); // iframe is showing - } - }// else { - // iframe source is switched, don't do anything - //} - }); - - _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { - _fixIframeBugs(); - }); - }, - - getIframe: function(item, template) { - var embedSrc = item.src; - var iframeSt = mfp.st.iframe; - - $.each(iframeSt.patterns, function() { - if(embedSrc.indexOf( this.index ) > -1) { - if(this.id) { - if(typeof this.id === 'string') { - embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); - } else { - embedSrc = this.id.call( this, embedSrc ); - } - } - embedSrc = this.src.replace('%id%', embedSrc ); - return false; // break; - } - }); - - var dataObj = {}; - if(iframeSt.srcAction) { - dataObj[iframeSt.srcAction] = embedSrc; - } - mfp._parseMarkup(template, dataObj, item); - - mfp.updateStatus('ready'); - - return template; - } - } -}); - - - -/*>>iframe*/ - -/*>>gallery*/ -/** - * Get looped index depending on number of slides - */ -var _getLoopedId = function(index) { - var numSlides = mfp.items.length; - if(index > numSlides - 1) { - return index - numSlides; - } else if(index < 0) { - return numSlides + index; - } - return index; - }, - _replaceCurrTotal = function(text, curr, total) { - return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); - }; - -$.magnificPopup.registerModule('gallery', { - - options: { - enabled: false, - arrowMarkup: '', - preload: [0,2], - navigateByImgClick: true, - arrows: true, - - tPrev: 'Previous (Left arrow key)', - tNext: 'Next (Right arrow key)', - tCounter: '%curr% of %total%' - }, - - proto: { - initGallery: function() { - - var gSt = mfp.st.gallery, - ns = '.mfp-gallery', - supportsFastClick = Boolean($.fn.mfpFastClick); - - mfp.direction = true; // true - next, false - prev - - if(!gSt || !gSt.enabled ) return false; - - _wrapClasses += ' mfp-gallery'; - - _mfpOn(OPEN_EVENT+ns, function() { - - if(gSt.navigateByImgClick) { - mfp.wrap.on('click'+ns, '.mfp-img', function() { - if(mfp.items.length > 1) { - mfp.next(); - return false; - } - }); - } - - _document.on('keydown'+ns, function(e) { - if (e.keyCode === 37) { - mfp.prev(); - } else if (e.keyCode === 39) { - mfp.next(); - } - }); - }); - - _mfpOn('UpdateStatus'+ns, function(e, data) { - if(data.text) { - data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); - } - }); - - _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { - var l = mfp.items.length; - values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; - }); - - _mfpOn('BuildControls' + ns, function() { - if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { - var markup = gSt.arrowMarkup, - arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS), - arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS); - - var eName = supportsFastClick ? 'mfpFastClick' : 'click'; - arrowLeft[eName](function() { - mfp.prev(); - }); - arrowRight[eName](function() { - mfp.next(); - }); - - // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) - if(mfp.isIE7) { - _getEl('b', arrowLeft[0], false, true); - _getEl('a', arrowLeft[0], false, true); - _getEl('b', arrowRight[0], false, true); - _getEl('a', arrowRight[0], false, true); - } - - mfp.container.append(arrowLeft.add(arrowRight)); - } - }); - - _mfpOn(CHANGE_EVENT+ns, function() { - if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); - - mfp._preloadTimeout = setTimeout(function() { - mfp.preloadNearbyImages(); - mfp._preloadTimeout = null; - }, 16); - }); - - - _mfpOn(CLOSE_EVENT+ns, function() { - _document.off(ns); - mfp.wrap.off('click'+ns); - - if(mfp.arrowLeft && supportsFastClick) { - mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); - } - mfp.arrowRight = mfp.arrowLeft = null; - }); - - }, - next: function() { - mfp.direction = true; - mfp.index = _getLoopedId(mfp.index + 1); - mfp.updateItemHTML(); - }, - prev: function() { - mfp.direction = false; - mfp.index = _getLoopedId(mfp.index - 1); - mfp.updateItemHTML(); - }, - goTo: function(newIndex) { - mfp.direction = (newIndex >= mfp.index); - mfp.index = newIndex; - mfp.updateItemHTML(); - }, - preloadNearbyImages: function() { - var p = mfp.st.gallery.preload, - preloadBefore = Math.min(p[0], mfp.items.length), - preloadAfter = Math.min(p[1], mfp.items.length), - i; - - for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { - mfp._preloadItem(mfp.index+i); - } - for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { - mfp._preloadItem(mfp.index-i); - } - }, - _preloadItem: function(index) { - index = _getLoopedId(index); - - if(mfp.items[index].preloaded) { - return; - } - - var item = mfp.items[index]; - if(!item.parsed) { - item = mfp.parseEl( index ); - } - - _mfpTrigger('LazyLoad', item); - - if(item.type === 'image') { - item.img = $('').on('load.mfploader', function() { - item.hasSize = true; - }).on('error.mfploader', function() { - item.hasSize = true; - item.loadError = true; - _mfpTrigger('LazyLoadError', item); - }).attr('src', item.src); - } - - - item.preloaded = true; - } - } -}); - -/* -Touch Support that might be implemented some day - -addSwipeGesture: function() { - var startX, - moved, - multipleTouches; - - return; - - var namespace = '.mfp', - addEventNames = function(pref, down, move, up, cancel) { - mfp._tStart = pref + down + namespace; - mfp._tMove = pref + move + namespace; - mfp._tEnd = pref + up + namespace; - mfp._tCancel = pref + cancel + namespace; - }; - - if(window.navigator.msPointerEnabled) { - addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); - } else if('ontouchstart' in window) { - addEventNames('touch', 'start', 'move', 'end', 'cancel'); - } else { - return; - } - _window.on(mfp._tStart, function(e) { - var oE = e.originalEvent; - multipleTouches = moved = false; - startX = oE.pageX || oE.changedTouches[0].pageX; - }).on(mfp._tMove, function(e) { - if(e.originalEvent.touches.length > 1) { - multipleTouches = e.originalEvent.touches.length; - } else { - //e.preventDefault(); - moved = true; - } - }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { - if(moved && !multipleTouches) { - var oE = e.originalEvent, - diff = startX - (oE.pageX || oE.changedTouches[0].pageX); - - if(diff > 20) { - mfp.next(); - } else if(diff < -20) { - mfp.prev(); - } - } - }); -}, -*/ - - -/*>>gallery*/ - -/*>>retina*/ - -var RETINA_NS = 'retina'; - -$.magnificPopup.registerModule(RETINA_NS, { - options: { - replaceSrc: function(item) { - return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); - }, - ratio: 1 // Function or number. Set to 1 to disable. - }, - proto: { - initRetina: function() { - if(window.devicePixelRatio > 1) { - - var st = mfp.st.retina, - ratio = st.ratio; - - ratio = !isNaN(ratio) ? ratio : ratio(); - - if(ratio > 1) { - _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { - item.img.css({ - 'max-width': item.img[0].naturalWidth / ratio, - 'width': '100%' - }); - }); - _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { - item.src = st.replaceSrc(item, ratio); - }); - } - } - - } - } -}); - -/*>>retina*/ - -/*>>fastclick*/ -/** - * FastClick event implementation. (removes 300ms delay on touch devices) - * Based on https://developers.google.com/mobile/articles/fast_buttons - * - * You may use it outside the Magnific Popup by calling just: - * - * $('.your-el').mfpFastClick(function() { - * console.log('Clicked!'); - * }); - * - * To unbind: - * $('.your-el').destroyMfpFastClick(); - * - * - * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. - * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick - * - */ - -(function() { - var ghostClickDelay = 1000, - supportsTouch = 'ontouchstart' in window, - unbindTouchMove = function() { - _window.off('touchmove'+ns+' touchend'+ns); - }, - eName = 'mfpFastClick', - ns = '.'+eName; - - - // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way - $.fn.mfpFastClick = function(callback) { - - return $(this).each(function() { - - var elem = $(this), - lock; - - if( supportsTouch ) { - - var timeout, - startX, - startY, - pointerMoved, - point, - numPointers; - - elem.on('touchstart' + ns, function(e) { - pointerMoved = false; - numPointers = 1; - - point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; - startX = point.clientX; - startY = point.clientY; - - _window.on('touchmove'+ns, function(e) { - point = e.originalEvent ? e.originalEvent.touches : e.touches; - numPointers = point.length; - point = point[0]; - if (Math.abs(point.clientX - startX) > 10 || - Math.abs(point.clientY - startY) > 10) { - pointerMoved = true; - unbindTouchMove(); - } - }).on('touchend'+ns, function(e) { - unbindTouchMove(); - if(pointerMoved || numPointers > 1) { - return; - } - lock = true; - e.preventDefault(); - clearTimeout(timeout); - timeout = setTimeout(function() { - lock = false; - }, ghostClickDelay); - callback(); - }); - }); - - } - - elem.on('click' + ns, function() { - if(!lock) { - callback(); - } - }); - }); - }; - - $.fn.destroyMfpFastClick = function() { - $(this).off('touchstart' + ns + ' click' + ns); - if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); - }; -})(); - -/*>>fastclick*/ - _checkInstance(); })(window.jQuery || window.Zepto); diff --git a/assets/js/plugins/jquery.smooth-scroll.min.js b/assets/js/plugins/jquery.smooth-scroll.min.js deleted file mode 100644 index 3576b049..00000000 --- a/assets/js/plugins/jquery.smooth-scroll.min.js +++ /dev/null @@ -1,8 +0,0 @@ -/*! - * jQuery Smooth Scroll - v1.7.2 - 2016-01-23 - * https://github.com/kswedberg/jquery-smooth-scroll - * Copyright (c) 2016 Karl Swedberg - * Licensed MIT - */ - -!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof module&&module.exports?require("jquery"):jQuery)}(function(a){var b="1.7.2",c={},d={exclude:[],excludeWithin:[],offset:0,direction:"top",delegateSelector:null,scrollElement:null,scrollTarget:null,beforeScroll:function(){},afterScroll:function(){},easing:"swing",speed:400,autoCoefficient:2,preventDefault:!0},e=function(b){var c=[],d=!1,e=b.dir&&"left"===b.dir?"scrollLeft":"scrollTop";return this.each(function(){var b=a(this);if(this!==document&&this!==window)return!document.scrollingElement||this!==document.documentElement&&this!==document.body?void(b[e]()>0?c.push(this):(b[e](1),d=b[e]()>0,d&&c.push(this),b[e](0))):(c.push(document.scrollingElement),!1)}),c.length||this.each(function(){this===document.documentElement&&"smooth"===a(this).css("scrollBehavior")&&(c=[this]),c.length||"BODY"!==this.nodeName||(c=[this])}),"first"===b.el&&c.length>1&&(c=[c[0]]),c};a.fn.extend({scrollable:function(a){var b=e.call(this,{dir:a});return this.pushStack(b)},firstScrollable:function(a){var b=e.call(this,{el:"first",dir:a});return this.pushStack(b)},smoothScroll:function(b,c){if(b=b||{},"options"===b)return c?this.each(function(){var b=a(this),d=a.extend(b.data("ssOpts")||{},c);a(this).data("ssOpts",d)}):this.first().data("ssOpts");var d=a.extend({},a.fn.smoothScroll.defaults,b),e=function(b){var c=function(a){return a.replace(/(:|\.|\/)/g,"\\$1")},e=this,f=a(this),g=a.extend({},d,f.data("ssOpts")||{}),h=d.exclude,i=g.excludeWithin,j=0,k=0,l=!0,m={},n=a.smoothScroll.filterPath(location.pathname),o=a.smoothScroll.filterPath(e.pathname),p=location.hostname===e.hostname||!e.hostname,q=g.scrollTarget||o===n,r=c(e.hash);if(r&&!a(r).length&&(l=!1),g.scrollTarget||p&&q&&r){for(;l&&j=0;a--)j(H[a])}function j(a){if(a.inited){var b=F.top<=a.limit.start?0:F.top>=a.limit.end?2:1;a.mode!=b&&p(a,b)}}function k(){for(var a=H.length-1;a>=0;a--)if(H[a].inited){var b=Math.abs(t(H[a].clone)-H[a].docOffsetTop),c=Math.abs(H[a].parent.node.offsetHeight-H[a].parent.height);if(b>=2||c>=2)return!1}return!0}function l(a){isNaN(parseFloat(a.computed.top))||a.isCell||"none"==a.computed.display||(a.inited=!0,a.clone||q(a),"absolute"!=a.parent.computed.position&&"relative"!=a.parent.computed.position&&(a.parent.node.style.position="relative"),j(a),a.parent.height=a.parent.node.offsetHeight,a.docOffsetTop=t(a.clone))}function m(a){var b=!0;a.clone&&r(a),d(a.node.style,a.css);for(var c=H.length-1;c>=0;c--)if(H[c].node!==a.node&&H[c].parent.node===a.parent.node){b=!1;break}b&&(a.parent.node.style.position=a.parent.css.position),a.mode=-1}function n(){for(var a=H.length-1;a>=0;a--)l(H[a])}function o(){for(var a=H.length-1;a>=0;a--)m(H[a])}function p(a,b){var c=a.node.style;switch(b){case 0:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top=a.offset.top+"px",c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 1:c.position="fixed",c.left=a.box.left+"px",c.right=a.box.right+"px",c.top=a.css.top,c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 2:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top="auto",c.bottom=0,c.width="auto",c.marginLeft=0,c.marginRight=0}a.mode=b}function q(a){a.clone=document.createElement("div");var b=a.node.nextSibling||a.node,c=a.clone.style;c.height=a.height+"px",c.width=a.width+"px",c.marginTop=a.computed.marginTop,c.marginBottom=a.computed.marginBottom,c.marginLeft=a.computed.marginLeft,c.marginRight=a.computed.marginRight,c.padding=c.border=c.borderSpacing=0,c.fontSize="1em",c.position="static",c.cssFloat=a.computed.cssFloat,a.node.parentNode.insertBefore(a.clone,b)}function r(a){a.clone.parentNode.removeChild(a.clone),a.clone=void 0}function s(a){var b=getComputedStyle(a),c=a.parentNode,d=getComputedStyle(c),f=a.style.position;a.style.position="relative";var g={top:b.top,marginTop:b.marginTop,marginBottom:b.marginBottom,marginLeft:b.marginLeft,marginRight:b.marginRight,cssFloat:b.cssFloat,display:b.display},h={top:e(b.top),marginBottom:e(b.marginBottom),paddingLeft:e(b.paddingLeft),paddingRight:e(b.paddingRight),borderLeftWidth:e(b.borderLeftWidth),borderRightWidth:e(b.borderRightWidth)};a.style.position=f;var i={position:a.style.position,top:a.style.top,bottom:a.style.bottom,left:a.style.left,right:a.style.right,width:a.style.width,marginTop:a.style.marginTop,marginLeft:a.style.marginLeft,marginRight:a.style.marginRight},j=u(a),k=u(c),l={node:c,css:{position:c.style.position},computed:{position:d.position},numeric:{borderLeftWidth:e(d.borderLeftWidth),borderRightWidth:e(d.borderRightWidth),borderTopWidth:e(d.borderTopWidth),borderBottomWidth:e(d.borderBottomWidth)}},m={node:a,box:{left:j.win.left,right:J.clientWidth-j.win.right},offset:{top:j.win.top-k.win.top-l.numeric.borderTopWidth,left:j.win.left-k.win.left-l.numeric.borderLeftWidth,right:-j.win.right+k.win.right-l.numeric.borderRightWidth},css:i,isCell:"table-cell"==b.display,computed:g,numeric:h,width:j.win.right-j.win.left,height:j.win.bottom-j.win.top,mode:-1,inited:!1,parent:l,limit:{start:j.doc.top-h.top,end:k.doc.top+c.offsetHeight-l.numeric.borderBottomWidth-a.offsetHeight-h.top-h.marginBottom}};return m}function t(a){for(var b=0;a;)b+=a.offsetTop,a=a.offsetParent;return b}function u(a){var c=a.getBoundingClientRect();return{doc:{top:c.top+b.pageYOffset,left:c.left+b.pageXOffset},win:c}}function v(){G=setInterval(function(){!k()&&z()},500)}function w(){clearInterval(G)}function x(){I&&(document[L]?w():v())}function y(){I||(f(),n(),b.addEventListener("scroll",g),b.addEventListener("wheel",h),b.addEventListener("resize",z),b.addEventListener("orientationchange",z),a.addEventListener(M,x),v(),I=!0)}function z(){if(I){o();for(var a=H.length-1;a>=0;a--)H[a]=s(H[a].node);n()}}function A(){b.removeEventListener("scroll",g),b.removeEventListener("wheel",h),b.removeEventListener("resize",z),b.removeEventListener("orientationchange",z),a.removeEventListener(M,x),w(),I=!1}function B(){A(),o()}function C(){for(B();H.length;)H.pop()}function D(a){for(var b=H.length-1;b>=0;b--)if(H[b].node===a)return;var c=s(a);H.push(c),I?l(c):y()}function E(a){for(var b=H.length-1;b>=0;b--)H[b].node===a&&(m(H[b]),H.splice(b,1))}var F,G,H=[],I=!1,J=a.documentElement,K=function(){},L="hidden",M="visibilitychange";void 0!==a.webkitHidden&&(L="webkitHidden",M="webkitvisibilitychange"),b.getComputedStyle||c();for(var N=["","-webkit-","-moz-","-ms-"],O=document.createElement("div"),P=N.length-1;P>=0;P--){try{O.style.position=N[P]+"sticky"}catch(Q){}""!=O.style.position&&c()}f(),b.Stickyfill={stickies:H,add:D,remove:E,init:y,rebuild:z,pause:A,stop:B,kill:C}}(document,window),window.jQuery&&!function($){$.fn.Stickyfill=function(){return this.each(function(){Stickyfill.add(this)}),this}}(window.jQuery); \ No newline at end of file diff --git a/assets/js/redoc.standalone.js b/assets/js/redoc.standalone.js deleted file mode 100644 index 7fa12786..00000000 --- a/assets/js/redoc.standalone.js +++ /dev/null @@ -1,122 +0,0 @@ -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null"),function(){try{return require("esprima")}catch(e){}}()):"function"==typeof define&&define.amd?define(["null","esprima"],t):"object"==typeof exports?exports.Redoc=t(require("null"),function(){try{return require("esprima")}catch(e){}}()):e.Redoc=t(e.null,e.esprima)}(this,(function(e,t){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=153)}([function(e,t,n){"use strict";e.exports=n(216)},function(e,t,n){"use strict";n.r(t),n.d(t,"__extends",(function(){return o})),n.d(t,"__assign",(function(){return i})),n.d(t,"__rest",(function(){return a})),n.d(t,"__decorate",(function(){return s})),n.d(t,"__param",(function(){return l})),n.d(t,"__metadata",(function(){return c})),n.d(t,"__awaiter",(function(){return u})),n.d(t,"__generator",(function(){return p})),n.d(t,"__exportStar",(function(){return f})),n.d(t,"__values",(function(){return d})),n.d(t,"__read",(function(){return h})),n.d(t,"__spread",(function(){return m})),n.d(t,"__spreadArrays",(function(){return g})),n.d(t,"__await",(function(){return y})),n.d(t,"__asyncGenerator",(function(){return v})),n.d(t,"__asyncDelegator",(function(){return b})),n.d(t,"__asyncValues",(function(){return w})),n.d(t,"__makeTemplateObject",(function(){return x})),n.d(t,"__importStar",(function(){return k})),n.d(t,"__importDefault",(function(){return _})); -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ -var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function o(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var i=function(){return(i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}function l(e,t){return function(n,r){t(n,r,e)}}function c(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function u(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{l(r.next(e))}catch(e){i(e)}}function s(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){e.done?o(e.value):new n((function(t){t(e.value)})).then(a,s)}l((r=r.apply(e,t||[])).next())}))}function p(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}}function h(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a}function m(){for(var e=[],t=0;t1||s(e,t)}))})}function s(e,t){try{(n=o[e](t)).value instanceof y?Promise.resolve(n.value.v).then(l,c):u(i[0][2],n)}catch(e){u(i[0][3],e)}var n}function l(e){s("next",e)}function c(e){s("throw",e)}function u(e,t){e(t),i.shift(),i.length&&s(i[0][0],i[0][1])}}function b(e){var t,n;return t={},r("next"),r("throw",(function(e){throw e})),r("return"),t[Symbol.iterator]=function(){return this},t;function r(r,o){t[r]=e[r]?function(t){return(n=!n)?{value:y(e[r](t)),done:"return"===r}:o?o(t):t}:o}}function w(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=d(e),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,o){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,o,(t=e[n](t)).done,t.value)}))}}}function x(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}function k(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function _(e){return e&&e.__esModule?e:{default:e}}},function(e,t,n){"use strict";(function(e,r){n.d(t,"a",(function(){return an})),n.d(t,"b",(function(){return Ue})),n.d(t,"c",(function(){return ue})),n.d(t,"d",(function(){return tt})),n.d(t,"e",(function(){return se})),n.d(t,"f",(function(){return lt})),n.d(t,"g",(function(){return M})),n.d(t,"h",(function(){return ut})),n.d(t,"i",(function(){return Mt})),n.d(t,"j",(function(){return zt})),n.d(t,"k",(function(){return Kt})),n.d(t,"l",(function(){return re})),n.d(t,"m",(function(){return ht})),n.d(t,"n",(function(){return Ke})),n.d(t,"o",(function(){return mt})),n.d(t,"p",(function(){return Ee})); -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ -var o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function i(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a}function l(){for(var e=[],t=0;t2&&oe("box");var n=X(t);return new de(e,K(n),n.name,!0,n.equals)},shallowBox:function(e,t){return arguments.length>2&&oe("shallowBox"),re.box(e,{name:t,deep:!1})},array:function(e,t){arguments.length>2&&oe("array");var n=X(t);return new At(e,K(n),n.name)},shallowArray:function(e,t){return arguments.length>2&&oe("shallowArray"),re.array(e,{name:t,deep:!1})},map:function(e,t){arguments.length>2&&oe("map");var n=X(t);return new Ft(e,K(n),n.name)},shallowMap:function(e,t){return arguments.length>2&&oe("shallowMap"),re.map(e,{name:t,deep:!1})},set:function(e,t){arguments.length>2&&oe("set");var n=X(t);return new $t(e,K(n),n.name)},object:function(e,t,n){"string"==typeof arguments[1]&&oe("object");var r=X(n);return ct({},e,t,r)},shallowObject:function(e,t){return"string"==typeof arguments[1]&&oe("shallowObject"),re.object(e,{},{name:t,deep:!1})},ref:ee,shallow:Z,deep:J,struct:te},re=function(e,t,n){if("string"==typeof arguments[1])return J.apply(null,arguments);if(dt(e))return e;var r=w(e)?re.object(e,t,n):Array.isArray(e)?re.array(e,t):E(e)?re.map(e,t):O(e)?re.set(e,t):e;if(r!==e)return r;m(!1)};function oe(e){m("Expected one or two arguments to observable."+e+". Did you accidentally try to use observable."+e+" as decorator?")}Object.keys(ne).forEach((function(e){return re[e]=ne[e]}));var ie=q(!1,(function(e,t,n,r,o){var i=n.get,s=n.set,l=o[0]||{};!function(e,t,n){var r=Ht(e);n.name=r.name+"."+t,n.context=e,r.values[t]=new he(n),Object.defineProperty(e,t,function(e){return Qt[e]||(Qt[e]={configurable:Ie.computedConfigurable,enumerable:!1,get:function(){return Gt(this).read(this,e)},set:function(t){Gt(this).write(this,e,t)}})}(t))}(e,t,a({get:i,set:s},l))})),ae=ie({equals:F.structural}),se=function(e,t,n){if("string"==typeof t)return ie.apply(null,arguments);if(null!==e&&"object"==typeof e&&1===arguments.length)return ie.apply(null,arguments);var r="object"==typeof t?t:{};return r.get=e,r.set="function"==typeof t?t:r.set,r.name=r.name||e.name||"",new he(r)};function le(e,t){var n=function(){return ce(e,t,this,arguments)};return n.isMobxAction=!0,n}function ce(e,t,n,r){var o=function(e,t,n){var r=Ve()&&!!e,o=0;if(r){o=Date.now();var i=n&&n.length||0,a=new Array(i);if(i>0)for(var s=0;s0;Ie.computationDepth>0&&t&&m(!1),Ie.allowStateChanges||!t&&"strict"!==Ie.enforceActions||m(!1)}function ke(e,t,n){Te(e),e.newObserving=new Array(e.observing.length+100),e.unboundDepsCount=0,e.runId=++Ie.runId;var r,o=Ie.trackingDerivation;if(Ie.trackingDerivation=e,!0===Ie.disableErrorBoundaries)r=t.call(n);else try{r=t.call(n)}catch(e){r=new ve(e)}return Ie.trackingDerivation=o,function(e){for(var t=e.observing,n=e.observing=e.newObserving,r=me.UP_TO_DATE,o=0,i=e.unboundDepsCount,a=0;ar&&(r=s.dependenciesState)}n.length=o,e.newObserving=null,i=t.length;for(;i--;){0===(s=t[i]).diffValue&&Re(s,e),s.diffValue=0}for(;o--;){var s;1===(s=n[o]).diffValue&&(s.diffValue=0,Pe(s,e))}r!==me.UP_TO_DATE&&(e.dependenciesState=r,e.onBecomeStale())}(e),r}function _e(e){var t=e.observing;e.observing=[];for(var n=t.length;n--;)Re(t[n],e);e.dependenciesState=me.NOT_TRACKING}function Ee(e){var t=Oe(),n=e();return Se(t),n}function Oe(){var e=Ie.trackingDerivation;return Ie.trackingDerivation=null,e}function Se(e){Ie.trackingDerivation=e}function Te(e){if(e.dependenciesState!==me.UP_TO_DATE){e.dependenciesState=me.UP_TO_DATE;for(var t=e.observing,n=t.length;n--;)t[n].lowestObserverState=me.UP_TO_DATE}}var je=function(){this.version=5,this.UNCHANGED={},this.trackingDerivation=null,this.computationDepth=0,this.runId=0,this.mobxGuid=0,this.inBatch=0,this.pendingUnobservations=[],this.pendingReactions=[],this.isRunningReactions=!1,this.allowStateChanges=!0,this.enforceActions=!1,this.spyListeners=[],this.globalReactionErrorHandlers=[],this.computedRequiresReaction=!1,this.computedConfigurable=!1,this.disableErrorBoundaries=!1,this.suppressReactionErrors=!1,this.currentActionId=0,this.nextActionId=1},Ce=!0,Ae=!1,Ie=function(){var e=d();return e.__mobxInstanceCount>0&&!e.__mobxGlobals&&(Ce=!1),e.__mobxGlobals&&e.__mobxGlobals.version!==(new je).version&&(Ce=!1),Ce?e.__mobxGlobals?(e.__mobxInstanceCount+=1,e.__mobxGlobals.UNCHANGED||(e.__mobxGlobals.UNCHANGED={}),e.__mobxGlobals):(e.__mobxInstanceCount=1,e.__mobxGlobals=new je):(setTimeout((function(){Ae||m("There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`")}),1),new je)}();function Pe(e,t){var n=e.observers.length;n&&(e.observersIndexes[t.__mapid]=n),e.observers[n]=t,e.lowestObserverState>t.dependenciesState&&(e.lowestObserverState=t.dependenciesState)}function Re(e,t){if(1===e.observers.length)e.observers.length=0,Ne(e);else{var n=e.observers,r=e.observersIndexes,o=n.pop();if(o!==t){var i=r[t.__mapid]||0;i?r[o.__mapid]=i:delete r[o.__mapid],n[i]=o}delete r[t.__mapid]}}function Ne(e){!1===e.isPendingUnobservation&&(e.isPendingUnobservation=!0,Ie.pendingUnobservations.push(e))}function Le(){Ie.inBatch++}function Me(){if(0==--Ie.inBatch){$e();for(var e=Ie.pendingUnobservations,t=0;t0&&Ne(e),!1)}function Fe(e,t){if(console.log("[mobx.trace] '"+e.name+"' is invalidated due to a change in: '"+t.name+"'"),e.isTracing===ge.BREAK){var n=[];!function e(t,n,r){if(n.length>=1e3)return void n.push("(and many more)");n.push(""+new Array(r).join("\t")+t.name);t.dependencies&&t.dependencies.forEach((function(t){return e(t,n,r+1)}))}(ut(e),n,1),new Function("debugger;\n/*\nTracing '"+e.name+"'\n\nYou are entering this break point because derivation '"+e.name+"' is being traced and '"+t.name+"' is now forcing it to update.\nJust follow the stacktrace you should now see in the devtools to see precisely what piece of your code is causing this update\nThe stackframe you are looking for is at least ~6-8 stack-frames up.\n\n"+(e instanceof he?e.derivation.toString().replace(/[*]\//g,"/"):"")+"\n\nThe dependencies for this derivation are:\n\n"+n.join("\n")+"\n*/\n ")()}}var Ue=function(){function e(e,t,n){void 0===e&&(e="Reaction@"+h()),this.name=e,this.onInvalidate=t,this.errorHandler=n,this.observing=[],this.newObserving=[],this.dependenciesState=me.NOT_TRACKING,this.diffValue=0,this.runId=0,this.unboundDepsCount=0,this.__mapid="#"+h(),this.isDisposed=!1,this._isScheduled=!1,this._isTrackPending=!1,this._isRunning=!1,this.isTracing=ge.NONE}return e.prototype.onBecomeStale=function(){this.schedule()},e.prototype.schedule=function(){this._isScheduled||(this._isScheduled=!0,Ie.pendingReactions.push(this),$e())},e.prototype.isScheduled=function(){return this._isScheduled},e.prototype.runReaction=function(){if(!this.isDisposed){if(Le(),this._isScheduled=!1,we(this)){this._isTrackPending=!0;try{this.onInvalidate(),this._isTrackPending&&Ve()&&Ye({name:this.name,type:"scheduled-reaction"})}catch(e){this.reportExceptionInDerivation(e)}}Me()}},e.prototype.track=function(e){Le();var t,n=Ve();n&&(t=Date.now(),Qe({name:this.name,type:"reaction"})),this._isRunning=!0;var r=ke(this,e,void 0);this._isRunning=!1,this._isTrackPending=!1,this.isDisposed&&_e(this),be(r)&&this.reportExceptionInDerivation(r.cause),n&&Xe({time:Date.now()-t}),Me()},e.prototype.reportExceptionInDerivation=function(e){var t=this;if(this.errorHandler)this.errorHandler(e,this);else{if(Ie.disableErrorBoundaries)throw e;var n="[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '"+this+"'";Ie.suppressReactionErrors?console.warn("[mobx] (error in reaction '"+this.name+"' suppressed, fix error of causing action below)"):console.error(n,e),Ve()&&Ye({type:"error",name:this.name,message:n,error:""+e}),Ie.globalReactionErrorHandlers.forEach((function(n){return n(e,t)}))}},e.prototype.dispose=function(){this.isDisposed||(this.isDisposed=!0,this._isRunning||(Le(),_e(this),Me()))},e.prototype.getDisposer=function(){var e=this.dispose.bind(this);return e.$mobx=this,e},e.prototype.toString=function(){return"Reaction["+this.name+"]"},e.prototype.trace=function(e){void 0===e&&(e=!1),function(){for(var e=[],t=0;t0||Ie.isRunningReactions||Be(qe)}function qe(){Ie.isRunningReactions=!0;for(var e=Ie.pendingReactions,t=0;e.length>0;){++t===ze&&(console.error("Reaction doesn't converge to a stable state after "+ze+" iterations. Probably there is a cycle in the reactive function: "+e[0]),e.splice(0));for(var n=e.splice(0),r=0,o=n.length;r",e):2===arguments.length&&"function"==typeof t?le(e,t):1===arguments.length&&"string"==typeof e?Ze(e):!0!==r?Ze(t).apply(null,arguments):void(e[t]=le(e.name||t,n.value))};function nt(e,t,n){x(e,t,le(t,n.bind(e)))}function rt(e,t){void 0===t&&(t=p);var n,r=t&&t.name||e.name||"Autorun@"+h();if(!t.scheduler&&!t.delay)n=new Ue(r,(function(){this.track(a)}),t.onError);else{var o=it(t),i=!1;n=new Ue(r,(function(){i||(i=!0,o((function(){i=!1,n.isDisposed||n.track(a)})))}),t.onError)}function a(){e(n)}return n.schedule(),n.getDisposer()}tt.bound=function(e,t,n,r){return!0===r?(nt(e,t,n.value),null):n?{configurable:!0,enumerable:!1,get:function(){return nt(this,t,n.value||n.initializer.call(this)),this[t]},set:Je}:{enumerable:!1,configurable:!0,set:function(e){nt(this,t,e)},get:function(){}}};var ot=function(e){return e()};function it(e){return e.scheduler?e.scheduler:e.delay?function(t){return setTimeout(t,e.delay)}:ot}function at(e,t,n){return st("onBecomeUnobserved",e,t,n)}function st(e,t,n,r){var o="function"==typeof r?Jt(t,n):Jt(t),i="function"==typeof r?r:n,a=o[e];return"function"!=typeof a?m(!1):(o[e]=function(){a.call(this),i.call(this)},function(){o[e]=a})}function lt(e){var t=e.enforceActions,n=e.computedRequiresReaction,r=e.computedConfigurable,o=e.disableErrorBoundaries,i=e.arrayBuffer,a=e.reactionScheduler;if(!0===e.isolateGlobalState&&((Ie.pendingReactions.length||Ie.inBatch||Ie.isRunningReactions)&&m("isolateGlobalState should be called before MobX is running any reactions"),Ae=!0,Ce&&(0==--d().__mobxInstanceCount&&(d().__mobxGlobals=void 0),Ie=new je)),void 0!==t){var s=void 0;switch(t){case!0:case"observed":s=!0;break;case!1:case"never":s=!1;break;case"strict":case"always":s="strict";break;default:m("Invalid value for 'enforceActions': '"+t+"', expected 'never', 'always' or 'observed'")}Ie.enforceActions=s,Ie.allowStateChanges=!0!==s&&"strict"!==s}void 0!==n&&(Ie.computedRequiresReaction=!!n),void 0!==r&&(Ie.computedConfigurable=!!r),void 0!==o&&(!0===o&&console.warn("WARNING: Debug feature only. MobX will NOT recover from errors if this is on."),Ie.disableErrorBoundaries=!!o),"number"==typeof i&&Nt(i),a&&He(a)}function ct(e,t,n,r){var o=(r=X(r)).defaultDecorator||(!1===r.deep?ee:J);$(e),Ht(e,r.name,o.enhancer),Le();try{for(var i in t){var a=Object.getOwnPropertyDescriptor(t,i);0;var s=(n&&i in n?n[i]:a.get?ie:o)(e,i,a,!0);s&&Object.defineProperty(e,i,s)}}finally{Me()}return e}function ut(e,t){return pt(Jt(e,t))}function pt(e){var t,n,r={name:e.name};return e.observing&&e.observing.length>0&&(r.dependencies=(t=e.observing,n=[],t.forEach((function(e){-1===n.indexOf(e)&&n.push(e)})),n).map(pt)),r}function ft(e,t){if(null==e)return!1;if(void 0!==t){if(Kt(e)){var n=e.$mobx;return n.values&&!!n.values[t]}return!1}return Kt(e)||!!e.$mobx||L(e)||We(e)||ye(e)}function dt(e){return 1!==arguments.length&&m(!1),ft(e)}function ht(e,t,n,r){return"function"==typeof n?function(e,t,n,r){return Zt(e,t).observe(n,r)}(e,t,n,r):function(e,t,n){return Zt(e).observe(t,n)}(e,t,n)}function mt(e,t){void 0===t&&(t=void 0),Le();try{return e.apply(t)}finally{Me()}}function gt(e){return void 0!==e.interceptors&&e.interceptors.length>0}function yt(e,t){var n=e.interceptors||(e.interceptors=[]);return n.push(t),y((function(){var e=n.indexOf(t);-1!==e&&n.splice(e,1)}))}function vt(e,t){var n=Oe();try{var r=e.interceptors;if(r)for(var o=0,i=r.length;o0}function wt(e,t){var n=e.changeListeners||(e.changeListeners=[]);return n.push(t),y((function(){var e=n.indexOf(t);-1!==e&&n.splice(e,1)}))}function xt(e,t){var n=Oe(),r=e.changeListeners;if(r){for(var o=0,i=(r=r.slice()).length;o0?e.map(this.dehancer):e},e.prototype.intercept=function(e){return yt(this,e)},e.prototype.observe=function(e,t){return void 0===t&&(t=!1),t&&e({object:this.array,type:"splice",index:0,added:this.values.slice(),addedCount:this.values.length,removed:[],removedCount:0}),wt(this,e)},e.prototype.getArrayLength=function(){return this.atom.reportObserved(),this.values.length},e.prototype.setArrayLength=function(e){if("number"!=typeof e||e<0)throw new Error("[mobx.array] Out of range: "+e);var t=this.values.length;if(e!==t)if(e>t){for(var n=new Array(e-t),r=0;r0&&e+t+1>Tt&&Nt(e+t+1)},e.prototype.spliceWithArray=function(e,t,n){var r=this;xe(this.atom);var o=this.values.length;if(void 0===e?e=0:e>o?e=o:e<0&&(e=Math.max(0,o+e)),t=1===arguments.length?o-e:null==t?0:Math.max(0,Math.min(t,o-e)),void 0===n&&(n=u),gt(this)){var i=vt(this,{object:this.array,type:"splice",index:e,removedCount:t,added:n});if(!i)return u;t=i.removedCount,n=i.added}var a=(n=0===n.length?n:n.map((function(e){return r.enhancer(e,void 0)}))).length-t;this.updateArrayLength(o,a);var s=this.spliceItemsIntoValues(e,t,n);return 0===t&&0===n.length||this.notifyArraySplice(e,n,s),this.dehanceValues(s)},e.prototype.spliceItemsIntoValues=function(e,t,n){var r;if(n.length<1e4)return(r=this.values).splice.apply(r,l([e,t],n));var o=this.values.slice(e,e+t);return this.values=this.values.slice(0,e).concat(n,this.values.slice(e+t)),o},e.prototype.notifyArrayChildUpdate=function(e,t,n){var r=!this.owned&&Ve(),o=bt(this),i=o||r?{object:this.array,type:"update",index:e,newValue:t,oldValue:n}:null;r&&Qe(a({},i,{name:this.atom.name})),this.atom.reportChanged(),o&&xt(this,i),r&&Xe()},e.prototype.notifyArraySplice=function(e,t,n){var r=!this.owned&&Ve(),o=bt(this),i=o||r?{object:this.array,type:"splice",index:e,removed:n,added:t,removedCount:n.length,addedCount:t.length}:null;r&&Qe(a({},i,{name:this.atom.name})),this.atom.reportChanged(),o&&xt(this,i),r&&Xe()},e}(),At=function(e){function t(t,n,r,o){void 0===r&&(r="ObservableArray@"+h()),void 0===o&&(o=!1);var i=e.call(this)||this,a=new Ct(r,n,i,o);if(k(i,"$mobx",a),t&&t.length){var s=pe(!0);i.spliceWithArray(0,0,t),fe(s)}return St&&Object.defineProperty(a.array,"0",It),i}return i(t,e),t.prototype.intercept=function(e){return this.$mobx.intercept(e)},t.prototype.observe=function(e,t){return void 0===t&&(t=!1),this.$mobx.observe(e,t)},t.prototype.clear=function(){return this.splice(0)},t.prototype.concat=function(){for(var e=[],t=0;t-1&&(this.splice(t,1),!0)},t.prototype.move=function(e,t){function n(e){if(e<0)throw new Error("[mobx.array] Index out of bounds: "+e+" is negative");var t=this.$mobx.values.length;if(e>=t)throw new Error("[mobx.array] Index out of bounds: "+e+" is not smaller than "+t)}if(n.call(this,e),n.call(this,t),e!==t){var r,o=this.$mobx.values;r=e",'"',"`"," ","\r","\n","\t"]),u=["'"].concat(c),p=["%","/","?",";","#"].concat(u),f=["/","?","#"],d=/^[+a-z0-9A-Z_-]{0,63}$/,h=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,m={javascript:!0,"javascript:":!0},g={javascript:!0,"javascript:":!0},y={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},v=n(225);function b(e,t,n){if(e&&o.isObject(e)&&e instanceof i)return e;var r=new i;return r.parse(e,t,n),r}i.prototype.parse=function(e,t,n){if(!o.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var i=e.indexOf("?"),s=-1!==i&&i127?R+="x":R+=P[N];if(!R.match(d)){var M=A.slice(0,T),D=A.slice(T+1),F=P.match(h);F&&(M.push(F[1]),D.unshift(F[2])),D.length&&(b="/"+D.join(".")+b),this.hostname=M.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),C||(this.hostname=r.toASCII(this.hostname));var U=this.port?":"+this.port:"",z=this.hostname||"";this.host=z+U,this.href+=this.host,C&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==b[0]&&(b="/"+b))}if(!m[k])for(T=0,I=u.length;T0)&&n.host.split("@"))&&(n.auth=C.shift(),n.host=n.hostname=C.shift());return n.search=e.search,n.query=e.query,o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!_.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var O=_.slice(-1)[0],S=(n.host||e.host||_.length>1)&&("."===O||".."===O)||""===O,T=0,j=_.length;j>=0;j--)"."===(O=_[j])?_.splice(j,1):".."===O?(_.splice(j,1),T++):T&&(_.splice(j,1),T--);if(!x&&!k)for(;T--;T)_.unshift("..");!x||""===_[0]||_[0]&&"/"===_[0].charAt(0)||_.unshift(""),S&&"/"!==_.join("/").substr(-1)&&_.push("");var C,A=""===_[0]||_[0]&&"/"===_[0].charAt(0);E&&(n.hostname=n.host=A?"":_.length?_.shift():"",(C=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=C.shift(),n.host=n.hostname=C.shift()));return(x=x||n.host&&_.length)&&!A&&_.unshift(""),_.length?n.pathname=_.join("/"):(n.pathname=null,n.path=null),o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},i.prototype.parseHost=function(){var e=this.host,t=s.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){var r=n(25),o=n(13),i=n(121),a=n(15).f;e.exports=function(e){var t=r.Symbol||(r.Symbol={});o(t,e)||a(t,e,{value:i.f(e)})}},function(e,t,n){"use strict";(function(e){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -var r=n(229),o=n(230),i=n(123);function a(){return l.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function h(e,t){if(l.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return B(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return $(e).length;default:if(r)return B(e).length;t=(""+t).toLowerCase(),r=!0}}function m(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return A(this,t,n);case"utf8":case"utf-8":return S(this,t,n);case"ascii":return j(this,t,n);case"latin1":case"binary":return C(this,t,n);case"base64":return O(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return I(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=l.from(t,r)),l.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,l.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,l=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,l/=2,n/=2}function c(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var u=-1;for(i=n;is&&(n=s-l),i=n;i>=0;i--){for(var p=!0,f=0;fo&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function O(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function S(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+p<=n)switch(p){case 1:c<128&&(u=c);break;case 2:128==(192&(i=e[o+1]))&&(l=(31&c)<<6|63&i)>127&&(u=l);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(l=(15&c)<<12|(63&i)<<6|63&a)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(l=(15&c)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&l<1114112&&(u=l)}null===u?(u=65533,p=1):u>65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u),o+=p}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},l.prototype.compare=function(e,t,n,r,o){if(!l.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),c=this.slice(r,o),u=e.slice(t,n),p=0;po)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return w(this,e,t,n);case"ascii":return x(this,e,t,n);case"latin1":case"binary":return k(this,e,t,n);case"base64":return _(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return E(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},l.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function j(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function R(e,t,n,r,o,i){if(!l.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function N(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function L(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function M(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(e,t,n,r,i){return i||M(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function F(e,t,n,r,i){return i||M(e,0,n,8),o.write(e,t,n,r,52,8),n+8}l.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},l.prototype.readUInt8=function(e,t){return t||P(e,1,this.length),this[e]},l.prototype.readUInt16LE=function(e,t){return t||P(e,2,this.length),this[e]|this[e+1]<<8},l.prototype.readUInt16BE=function(e,t){return t||P(e,2,this.length),this[e]<<8|this[e+1]},l.prototype.readUInt32LE=function(e,t){return t||P(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},l.prototype.readUInt32BE=function(e,t){return t||P(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},l.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},l.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},l.prototype.readInt8=function(e,t){return t||P(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},l.prototype.readInt16LE=function(e,t){t||P(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},l.prototype.readInt16BE=function(e,t){t||P(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},l.prototype.readInt32LE=function(e,t){return t||P(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},l.prototype.readInt32BE=function(e,t){return t||P(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},l.prototype.readFloatLE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!0,23,4)},l.prototype.readFloatBE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!1,23,4)},l.prototype.readDoubleLE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!0,52,8)},l.prototype.readDoubleBE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!1,52,8)},l.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||R(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},l.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,1,255,0),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},l.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},l.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},l.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):L(this,e,t,!0),t+4},l.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},l.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);R(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},l.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);R(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},l.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,1,127,-128),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},l.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},l.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},l.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,2147483647,-2147483648),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):L(this,e,t,!0),t+4},l.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},l.prototype.writeFloatLE=function(e,t,n){return D(this,e,t,!0,n)},l.prototype.writeFloatBE=function(e,t,n){return D(this,e,t,!1,n)},l.prototype.writeDoubleLE=function(e,t,n){return F(this,e,t,!0,n)},l.prototype.writeDoubleBE=function(e,t,n){return F(this,e,t,!1,n)},l.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!l.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function $(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(6))},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var l,c=[],u=!1,p=-1;function f(){u&&l&&(u=!1,l.length?c=l.concat(c):p=-1,c.length&&d())}function d(){if(!u){var e=s(f);u=!0;for(var t=c.length;t;){for(l=c,c=[];++p1)for(var n=1;n=0?e.substr(t).toLowerCase():""},t.getHash=function(e){var t=e.indexOf("#");return t>=0?e.substr(t):"#"},t.stripHash=function(e){var t=e.indexOf("#");return t>=0&&(e=e.substr(0,t)),e},t.isHttp=function(e){var t=s.getProtocol(e);return"http"===t||"https"===t||void 0===t&&r.browser},t.isFileSystemPath=function(e){if(r.browser)return!1;var t=s.getProtocol(e);return void 0===t||"file"===t},t.fromFileSystemPath=function(e){o&&(e=e.replace(/\\/g,"/")),e=encodeURI(e);for(var t=0;t0&&(p=e.exports.formatter.apply(null,s)),n&&n.message&&(p+=(p?" \n":"")+n.message);var f=new t(p);return l(f,n),c(f),u(f,r),f}}function l(e,t){!function(e,t){!function(e){if(!m)return!1;var t=Object.getOwnPropertyDescriptor(e,"stack");if(!t)return!1;return"function"==typeof t.get}(e)?e.stack=t?d(e.stack,t.stack):h(e.stack):t?function(e,t){var n=Object.getOwnPropertyDescriptor(e,"stack");Object.defineProperty(e,"stack",{get:function(){return d(n.get.apply(e),t.stack)},enumerable:!1,configurable:!0})}(e,t):(n=e,r=Object.getOwnPropertyDescriptor(n,"stack"),Object.defineProperty(n,"stack",{get:function(){return h(r.get.apply(n))},enumerable:!1,configurable:!0}));var n,r}(e,t),u(e,t)}function c(e){e.toJSON=p,e.inspect=f}function u(e,t){if(t&&"object"==typeof t)for(var n=Object.keys(t),r=0;r=0))try{e[o]=t[o]}catch(e){}}}function p(){var e={},t=Object.keys(this);t=t.concat(a);for(var n=0;n=0)return t.splice(n,1),t.join("\n")}return e}}e.exports=s(Error),e.exports.error=s(Error),e.exports.eval=s(EvalError),e.exports.range=s(RangeError),e.exports.reference=s(ReferenceError),e.exports.syntax=s(SyntaxError),e.exports.type=s(TypeError),e.exports.uri=s(URIError),e.exports.formatter=r;var m=!(!Object.getOwnPropertyDescriptor||!Object.defineProperty||"undefined"!=typeof navigator&&/Android/.test(navigator.userAgent))},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}}(),e.exports=n(217)},function(e,t){e.exports=!1},function(e,t,n){var r,o,i,a=n(156),s=n(3),l=n(7),c=n(20),u=n(13),p=n(53),f=n(39),d=s.WeakMap;if(a){var h=new d,m=h.get,g=h.has,y=h.set;r=function(e,t){return y.call(h,e,t),t},o=function(e){return m.call(h,e)||{}},i=function(e){return g.call(h,e)}}else{var v=p("state");f[v]=!0,r=function(e,t){return c(e,v,t),t},o=function(e){return u(e,v)?e[v]:{}},i=function(e){return u(e,v)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!l(t)||(n=o(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},function(e,t,n){var r=n(71),o=n(40);e.exports=function(e){return r(o(e))}},function(e,t,n){var r=n(68),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){"use strict";var r=n(46),o=n(58),i=n(5);function a(e,t,n){var r=[];return e.include.forEach((function(e){n=a(e,t,n)})),e[t].forEach((function(e){n.forEach((function(t,n){t.tag===e.tag&&t.kind===e.kind&&r.push(n)})),n.push(e)})),n.filter((function(e,t){return-1===r.indexOf(t)}))}function s(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach((function(e){if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")})),this.compiledImplicit=a(this,"implicit",[]),this.compiledExplicit=a(this,"explicit",[]),this.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{}};function r(e){n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;ee.length)return;if(!(x instanceof o)){if(m&&b!=t.length-1){if(f.lastIndex=w,!(T=f.exec(e)))break;for(var k=T.index+(h?T[1].length:0),_=T.index+T[0].length,E=b,O=w,S=t.length;E=(O+=t[E].length)&&(++b,w=O);if(t[b]instanceof o)continue;j=E-b,x=e.slice(w,O),T.index-=w}else{f.lastIndex=0;var T=f.exec(x),j=1}if(T){h&&(g=T[1]?T[1].length:0);_=(k=T.index+g)+(T=T[0].slice(g)).length;var C=x.slice(0,k),A=x.slice(_),I=[b,j];C&&(++b,w+=C.length,I.push(C));var P=new o(c,d?r.tokenize(T,d):T,y,T,m);if(I.push(P),A&&I.push(A),Array.prototype.splice.apply(t,I),1!=j&&r.matchGrammar(e,t,n,b,w,!0,c),s)break}else if(s)break}}}}},tokenize:function(e,t){var n=[e],o=t.rest;if(o){for(var i in o)t[i]=o[i];delete t.rest}return r.matchGrammar(e,n,t,0,0,!1),n},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var o,i=0;o=n[i++];)o(t)}},Token:o};function o(e,t,n,r,o){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!o}if(e.Prism=r,o.stringify=function(e,t){if("string"==typeof e)return e;if(Array.isArray(e))return e.map((function(e){return o.stringify(e,t)})).join("");var n={type:e.type,content:o.stringify(e.content,t),tag:"span",classes:["token",e.type],attributes:{},language:t};if(e.alias){var i=Array.isArray(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(n.classes,i)}r.hooks.run("wrap",n);var a=Object.keys(n.attributes).map((function(e){return e+'="'+(n.attributes[e]||"").replace(/"/g,""")+'"'})).join(" ");return"<"+n.tag+' class="'+n.classes.join(" ")+'"'+(a?" "+a:"")+">"+n.content+""},!e.document)return e.addEventListener?(r.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),o=n.language,i=n.code,a=n.immediateClose;e.postMessage(r.highlight(i,r.languages[o],o)),a&&e.close()}),!1),r):r;var i=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return i&&(r.filename=i.src,r.manual||i.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(r.highlightAll):window.setTimeout(r.highlightAll,16):document.addEventListener("DOMContentLoaded",r.highlightAll))),r}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=n),void 0!==t&&(t.Prism=n),n.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},n.languages.markup.tag.inside["attr-value"].inside.entity=n.languages.markup.entity,n.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(n.languages.markup.tag,"addInlined",{value:function(e,t){var r={};r["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:n.languages[t]},r.cdata=/^$/i;var o={"included-cdata":{pattern://i,inside:r}};o["language-"+t]={pattern:/[\s\S]+/,inside:n.languages[t]};var i={};i[e]={pattern:RegExp(/(<__[\s\S]*?>)(?:\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g,e),"i"),lookbehind:!0,greedy:!0,inside:o},n.languages.insertBefore("markup","cdata",i)}}),n.languages.xml=n.languages.extend("markup",{}),n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/@[\w-]+/}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},n.tag))}(n),n.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},n.languages.javascript=n.languages.extend("clike",{"class-name":[n.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),n.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,n.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:n.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:n.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:n.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:n.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),n.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:n.languages.javascript}},string:/[\s\S]+/}}}),n.languages.markup&&n.languages.markup.tag.addInlined("script","javascript"),n.languages.js=n.languages.javascript,"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(e){e=e||document;var t={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.slice.call(e.querySelectorAll("pre[data-src]")).forEach((function(e){if(!e.hasAttribute("data-src-loaded")){for(var r,o=e.getAttribute("data-src"),i=e,a=/\blang(?:uage)?-([\w-]+)\b/i;i&&!a.test(i.className);)i=i.parentNode;if(i&&(r=(e.className.match(a)||[,""])[1]),!r){var s=(o.match(/\.(\w+)$/)||[,""])[1];r=t[s]||s}var l=document.createElement("code");l.className="language-"+r,e.textContent="",l.textContent="Loading…",e.appendChild(l);var c=new XMLHttpRequest;c.open("GET",o,!0),c.onreadystatechange=function(){4==c.readyState&&(c.status<400&&c.responseText?(l.textContent=c.responseText,n.highlightElement(l),e.setAttribute("data-src-loaded","")):c.status>=400?l.textContent="✖ Error "+c.status+" while fetching file: "+c.statusText:l.textContent="✖ Error: File does not exist or is empty")},c.send(null)}})),n.plugins.toolbar&&n.plugins.toolbar.registerButton("download-file",(function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-src")&&t.hasAttribute("data-download-link")){var n=t.getAttribute("data-src"),r=document.createElement("a");return r.textContent=t.getAttribute("data-download-link-label")||"Download",r.setAttribute("download",""),r.href=n,r}}))},document.addEventListener("DOMContentLoaded",(function(){self.Prism.fileHighlight()})))}).call(this,n(6))},function(e,t,n){var r=n(3),o=n(66),i=n(30),a=r["__core-js_shared__"]||o("__core-js_shared__",{});(e.exports=function(e,t){return a[e]||(a[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.2.1",mode:i?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t){e.exports={}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){var r=n(25),o=n(3),i=function(e){return"function"==typeof e?e:void 0};e.exports=function(e,t){return arguments.length<2?i(r[e])||i(o[e]):r[e]&&r[e][t]||o[e]&&o[e][t]}},function(e,t,n){var r=n(40);e.exports=function(e){return Object(r(e))}},function(e,t){e.exports={}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},function(e,t,n){var r=n(44);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){"use strict";function r(e){return null==e}e.exports.isNothing=r,e.exports.isObject=function(e){return"object"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:r(e)?[]:[e]},e.exports.repeat=function(e,t){var n,r="";for(n=0;n=0;r--){var o=e[r];"."===o?e.splice(r,1):".."===o?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}function r(e,t){if(e.filter)return e.filter(t);for(var n=[],r=0;r=-1&&!o;i--){var a=i>=0?arguments[i]:e.cwd();if("string"!=typeof a)throw new TypeError("Arguments to path.resolve must be strings");a&&(t=a+"/"+t,o="/"===a.charAt(0))}return(o?"/":"")+(t=n(r(t.split("/"),(function(e){return!!e})),!o).join("/"))||"."},t.normalize=function(e){var i=t.isAbsolute(e),a="/"===o(e,-1);return(e=n(r(e.split("/"),(function(e){return!!e})),!i).join("/"))||i||(e="."),e&&a&&(e+="/"),(i?"/":"")+e},t.isAbsolute=function(e){return"/"===e.charAt(0)},t.join=function(){var e=Array.prototype.slice.call(arguments,0);return t.normalize(r(e,(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))},t.relative=function(e,n){function r(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=t.resolve(e).substr(1),n=t.resolve(n).substr(1);for(var o=r(e.split("/")),i=r(n.split("/")),a=Math.min(o.length,i.length),s=a,l=0;l=1;--i)if(47===(t=e.charCodeAt(i))){if(!o){r=i;break}}else o=!1;return-1===r?n?"/":".":n&&1===r?"/":e.slice(0,r)},t.basename=function(e,t){var n=function(e){"string"!=typeof e&&(e+="");var t,n=0,r=-1,o=!0;for(t=e.length-1;t>=0;--t)if(47===e.charCodeAt(t)){if(!o){n=t+1;break}}else-1===r&&(o=!1,r=t+1);return-1===r?"":e.slice(n,r)}(e);return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},t.extname=function(e){"string"!=typeof e&&(e+="");for(var t=-1,n=0,r=-1,o=!0,i=0,a=e.length-1;a>=0;--a){var s=e.charCodeAt(a);if(47!==s)-1===r&&(o=!1,r=a+1),46===s?-1===t?t=a:1!==i&&(i=1):-1!==t&&(i=-1);else if(!o){n=a+1;break}}return-1===t||-1===r||0===i||1===i&&t===r-1&&t===n+1?"":e.slice(t,r)};var o="b"==="ab".substr(-1)?function(e,t,n){return e.substr(t,n)}:function(e,t,n){return t<0&&(t=e.length+t),e.substr(t,n)}}).call(this,n(12))},function(e,t,n){var r,o,i;o=[t],void 0===(i="function"==typeof(r=function(e){"use strict";e.__esModule=!0;var t={},n=Object.prototype.hasOwnProperty,r=function(e){var r=arguments.length<=1||void 0===arguments[1]?t:arguments[1],o=r.cache||{};return function(){for(var t=arguments.length,i=Array(t),a=0;a2?r:e).apply(void 0,o)}}e.memoize=a,e.debounce=s,e.bind=l,e.default={memoize:a,debounce:s,bind:l}})?r.apply(t,o):r)||(e.exports=i)},function(e,t,n){(function(t){!function(t){"use strict";var n={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:/^ {0,3}(`{3,}|~{3,})([^`~\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:g,table:g,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,text:/^[^\n]+/};function r(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||k.defaults,this.rules=n.normal,this.options.pedantic?this.rules=n.pedantic:this.options.gfm&&(this.rules=n.gfm)}n._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,n._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,n.def=f(n.def).replace("label",n._label).replace("title",n._title).getRegex(),n.bullet=/(?:[*+-]|\d{1,9}\.)/,n.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,n.item=f(n.item,"gm").replace(/bull/g,n.bullet).getRegex(),n.list=f(n.list).replace(/bull/g,n.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+n.def.source+")").getRegex(),n._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",n._comment=//,n.html=f(n.html,"i").replace("comment",n._comment).replace("tag",n._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),n.paragraph=f(n._paragraph).replace("hr",n.hr).replace("heading"," {0,3}#{1,6} +").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}|~{3,})[^`\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",n._tag).getRegex(),n.blockquote=f(n.blockquote).replace("paragraph",n.paragraph).getRegex(),n.normal=y({},n),n.gfm=y({},n.normal,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),n.pedantic=y({},n.normal,{html:f("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",n._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,fences:g,paragraph:f(n.normal._paragraph).replace("hr",n.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",n.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()}),r.rules=n,r.lex=function(e,t){return new r(t).lex(e)},r.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},r.prototype.token=function(e,t){var r,o,i,a,s,l,c,p,f,d,h,m,g,y,w,x;for(e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e)){var k=this.tokens[this.tokens.length-1];e=e.substring(i[0].length),k&&"paragraph"===k.type?k.text+="\n"+i[0].trimRight():(i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",codeBlockStyle:"indented",text:this.options.pedantic?i:b(i,"\n")}))}else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2]?i[2].trim():i[2],text:i[3]||""});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if((i=this.rules.nptable.exec(e))&&(l={type:"table",header:v(i[1].replace(/^ *| *\| *$/g,"")),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3]?i[3].replace(/\n$/,"").split("\n"):[]}).header.length===l.align.length){for(e=e.substring(i[0].length),h=0;h ?/gm,""),this.token(i,t),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),c={type:"list_start",ordered:y=(a=i[2]).length>1,start:y?+a:"",loose:!1},this.tokens.push(c),p=[],r=!1,g=(i=i[0].match(this.rules.item)).length,h=0;h1?1===s.length:s.length>1||this.options.smartLists&&s!==a)&&(e=i.slice(h+1).join("\n")+e,h=g-1)),o=r||/\n\n(?!\s*$)/.test(l),h!==g-1&&(r="\n"===l.charAt(l.length-1),o||(o=r)),o&&(c.loose=!0),x=void 0,(w=/^\[[ xX]\] /.test(l))&&(x=" "!==l[1],l=l.replace(/^\[[ xX]\] +/,"")),f={type:"list_item_start",task:w,checked:x,loose:o},p.push(f),this.tokens.push(f),this.token(l,!1),this.tokens.push({type:"list_item_end"});if(c.loose)for(g=p.length,h=0;h?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:g,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:g,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~",o.em=f(o.em).replace(/punctuation/g,o._punctuation).getRegex(),o._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,o._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,o._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,o.autolink=f(o.autolink).replace("scheme",o._scheme).replace("email",o._email).getRegex(),o._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,o.tag=f(o.tag).replace("comment",n._comment).replace("attribute",o._attribute).getRegex(),o._label=/(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,o._href=/<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/,o._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,o.link=f(o.link).replace("label",o._label).replace("href",o._href).replace("title",o._title).getRegex(),o.reflink=f(o.reflink).replace("label",o._label).getRegex(),o.normal=y({},o),o.pedantic=y({},o.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:f(/^!?\[(label)\]\((.*?)\)/).replace("label",o._label).getRegex(),reflink:f(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",o._label).getRegex()}),o.gfm=y({},o.normal,{escape:f(o.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(a[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(a[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(a[0])&&(this.inRawBlock=!1),e=e.substring(a[0].length),l+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):u(a[0]):a[0];else if(a=this.rules.link.exec(e)){var c=w(a[2],"()");if(c>-1){var p=4+a[1].length+c;a[2]=a[2].substring(0,c),a[0]=a[0].substring(0,p).trim(),a[3]=""}e=e.substring(a[0].length),this.inLink=!0,r=a[2],this.options.pedantic?(t=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(r))?(r=t[1],o=t[3]):o="":o=a[3]?a[3].slice(1,-1):"",r=r.trim().replace(/^<([\s\S]*)>$/,"$1"),l+=this.outputLink(a,{href:i.escapes(r),title:i.escapes(o)}),this.inLink=!1}else if((a=this.rules.reflink.exec(e))||(a=this.rules.nolink.exec(e))){if(e=e.substring(a[0].length),t=(a[2]||a[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){l+=a[0].charAt(0),e=a[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(a,t),this.inLink=!1}else if(a=this.rules.strong.exec(e))e=e.substring(a[0].length),l+=this.renderer.strong(this.output(a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.em.exec(e))e=e.substring(a[0].length),l+=this.renderer.em(this.output(a[6]||a[5]||a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.code.exec(e))e=e.substring(a[0].length),l+=this.renderer.codespan(u(a[2].trim(),!0));else if(a=this.rules.br.exec(e))e=e.substring(a[0].length),l+=this.renderer.br();else if(a=this.rules.del.exec(e))e=e.substring(a[0].length),l+=this.renderer.del(this.output(a[1]));else if(a=this.rules.autolink.exec(e))e=e.substring(a[0].length),r="@"===a[2]?"mailto:"+(n=u(this.mangle(a[1]))):n=u(a[1]),l+=this.renderer.link(r,null,n);else if(this.inLink||!(a=this.rules.url.exec(e))){if(a=this.rules.text.exec(e))e=e.substring(a[0].length),this.inRawBlock?l+=this.renderer.text(this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):u(a[0]):a[0]):l+=this.renderer.text(u(this.smartypants(a[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{if("@"===a[2])r="mailto:"+(n=u(a[0]));else{do{s=a[0],a[0]=this.rules._backpedal.exec(a[0])[0]}while(s!==a[0]);n=u(a[0]),r="www."===a[1]?"http://"+n:n}e=e.substring(a[0].length),l+=this.renderer.link(r,null,n)}return l},i.escapes=function(e){return e?e.replace(i.rules._escapes,"$1"):e},i.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},i.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},i.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,o=0;o.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},a.prototype.code=function(e,t,n){var r=(t||"").match(/\S*/)[0];if(this.options.highlight){var o=this.options.highlight(e,r);null!=o&&o!==e&&(n=!0,e=o)}return r?'
    '+(n?e:u(e,!0))+"
    \n":"
    "+(n?e:u(e,!0))+"
    "},a.prototype.blockquote=function(e){return"
    \n"+e+"
    \n"},a.prototype.html=function(e){return e},a.prototype.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},a.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"},a.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},a.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},a.prototype.checkbox=function(e){return" "},a.prototype.paragraph=function(e){return"

    "+e+"

    \n"},a.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},a.prototype.tablerow=function(e){return"\n"+e+"\n"},a.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},a.prototype.strong=function(e){return""+e+""},a.prototype.em=function(e){return""+e+""},a.prototype.codespan=function(e){return""+e+""},a.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},a.prototype.del=function(e){return""+e+""},a.prototype.link=function(e,t,n){if(null===(e=d(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"},a.prototype.image=function(e,t,n){if(null===(e=d(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},a.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},l.parse=function(e,t){return new l(t).parse(e)},l.prototype.parse=function(e){this.inline=new i(e.links,this.options),this.inlineText=new i(e.links,y({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},l.prototype.next=function(){return this.token=this.tokens.pop(),this.token},l.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},l.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},l.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,p(this.inlineText.output(this.token.text)),this.slugger);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,o="",i="";for(n="",e=0;e?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t)){var n=t;do{this.seen[n]++,t=n+"-"+this.seen[n]}while(this.seen.hasOwnProperty(t))}return this.seen[t]=0,t},u.escapeTest=/[&<>"']/,u.escapeReplace=/[&<>"']/g,u.replacements={"&":"&","<":"<",">":">",'"':""","'":"'"},u.escapeTestNoEncode=/[<>"']|&(?!#?\w+;)/,u.escapeReplaceNoEncode=/[<>"']|&(?!#?\w+;)/g;var h={},m=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function g(){}function y(e){for(var t,n,r=1;r=0&&"\\"===n[o];)r=!r;return r?"|":" |"})).split(/ \|/),r=0;if(n.length>t)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}g.exec=g,k.options=k.setOptions=function(e){return y(k.defaults,e),k},k.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new a,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,xhtml:!1}},k.defaults=k.getDefaults(),k.Parser=l,k.parser=l.parse,k.Renderer=a,k.TextRenderer=s,k.Lexer=r,k.lexer=r.lex,k.InlineLexer=i,k.inlineLexer=i.output,k.Slugger=c,k.parse=k,e.exports=k}(this||"undefined"!=typeof window&&window)}).call(this,n(6))},function(e,t,n){var r=n(7);e.exports=function(e,t){if(!r(e))return e;var n,o;if(t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;if("function"==typeof(n=e.valueOf)&&!r(o=n.call(e)))return o;if(!t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e,t,n){var r=n(37),o=n(54),i=r("keys");e.exports=function(e){return i[e]||(i[e]=o(e))}},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++n+r).toString(36)}},function(e,t,n){var r=n(18),o=n(70),i=n(38),a=n(32),s=n(52),l=n(13),c=n(94),u=Object.getOwnPropertyDescriptor;t.f=r?u:function(e,t){if(e=a(e),t=s(t,!0),c)try{return u(e,t)}catch(e){}if(l(e,t))return i(!o.f.call(e,t),e[t])}},function(e,t,n){var r=n(19),o=n(164),i=n(73),a=n(39),s=n(103),l=n(67),c=n(53)("IE_PROTO"),u=function(){},p=function(){var e,t=l("iframe"),n=i.length;for(t.style.display="none",s.appendChild(t),t.src=String("javascript:"),(e=t.contentWindow.document).open(),e.write("