├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug.md │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── build.yml │ ├── deploy.yml │ ├── dev_deploy.yml │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Vagrantfile ├── config.rb ├── deploy.sh ├── font-selection.json ├── lib ├── monokai_sublime_slate.rb ├── multilang.rb ├── nesting_unique_head.rb ├── toc_data.rb └── unique_head.rb ├── slate.sh └── source ├── fonts ├── slate.eot ├── slate.svg ├── slate.ttf ├── slate.woff └── slate.woff2 ├── images ├── logo.png └── navbar.png ├── includes └── _errors.md ├── index.html.md ├── javascripts ├── all.js ├── all_nosearch.js ├── app │ ├── _copy.js │ ├── _lang.js │ ├── _search.js │ └── _toc.js └── lib │ ├── _energize.js │ ├── _imagesloaded.min.js │ ├── _jquery.highlight.js │ ├── _jquery.js │ └── _lunr.js ├── layouts └── layout.erb └── stylesheets ├── _icon-font.scss ├── _normalize.scss ├── _rtl.scss ├── _variables.scss ├── print.css.scss └── screen.css.scss /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .github/ 3 | build/ 4 | .editorconfig 5 | .gitattributes 6 | .gitignore 7 | CHANGELOG.md 8 | CODE_OF_CONDUCT.md 9 | deploy.sh 10 | font-selection.json 11 | README.md 12 | Vagrantfile -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # Top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | trim_trailing_whitespace = true 13 | 14 | [*.rb] 15 | charset = utf-8 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | source/javascripts/lib/* linguist-vendored 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a Bug 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Bug Description** 11 | A clear and concise description of what the bug is and how to reproduce it. 12 | 13 | **Screenshots** 14 | If applicable, add screenshots to help explain your problem. 15 | 16 | **Browser (please complete the following information):** 17 | - OS: [e.g. iOS] 18 | - Browser [e.g. chrome, safari] 19 | - Version [e.g. 22] 20 | 21 | **Last upstream Slate commit (run `git log --author="\(Robert Lord\)\|\(Matthew Peveler\)\|\(Mike Ralphson\)" | head -n 1`):** 22 | Put the commit hash here 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Questions, Ideas, Discussions 4 | url: https://github.com/slatedocs/slate/discussions 5 | about: Ask and answer questions, and propose new features. 6 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | target-branch: dev 9 | versioning-strategy: increase-if-necessary 10 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ '*' ] 6 | pull_request: 7 | branches: [ '*' ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | ruby-version: [2.6, 2.7, '3.0', 3.1, 3.2] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up Ruby 20 | uses: ruby/setup-ruby@v1 21 | with: 22 | ruby-version: ${{ matrix.ruby-version }} 23 | 24 | - uses: actions/cache@v3 25 | with: 26 | path: vendor/bundle 27 | key: gems-${{ runner.os }}-${{ matrix.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} 28 | restore-keys: | 29 | gems-${{ runner.os }}-${{ matrix.ruby-version }}- 30 | gems-${{ runner.os }}- 31 | 32 | - run: bundle config set deployment 'true' 33 | - name: bundle install 34 | run: | 35 | bundle config path vendor/bundle 36 | bundle install --jobs 4 --retry 3 37 | 38 | - run: bundle exec middleman build 39 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: [ 'main' ] 6 | 7 | jobs: 8 | deploy: 9 | permissions: 10 | contents: write 11 | 12 | runs-on: ubuntu-latest 13 | env: 14 | ruby-version: 2.6 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Set up Ruby 19 | uses: ruby/setup-ruby@v1 20 | with: 21 | ruby-version: ${{ env.ruby-version }} 22 | 23 | - uses: actions/cache@v3 24 | with: 25 | path: vendor/bundle 26 | key: gems-${{ runner.os }}-${{ env.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} 27 | restore-keys: | 28 | gems-${{ runner.os }}-${{ env.ruby-version }}- 29 | gems-${{ runner.os }}- 30 | 31 | - run: bundle config set deployment 'true' 32 | - name: bundle install 33 | run: | 34 | bundle config path vendor/bundle 35 | bundle install --jobs 4 --retry 3 36 | 37 | - run: bundle exec middleman build 38 | 39 | - name: Deploy 40 | uses: peaceiris/actions-gh-pages@v3 41 | with: 42 | github_token: ${{ secrets.GITHUB_TOKEN }} 43 | publish_dir: ./build 44 | keep_files: true 45 | -------------------------------------------------------------------------------- /.github/workflows/dev_deploy.yml: -------------------------------------------------------------------------------- 1 | name: Dev Deploy 2 | 3 | on: 4 | push: 5 | branches: [ 'dev' ] 6 | 7 | jobs: 8 | push_to_registry: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Check out the repo 13 | uses: actions/checkout@v3 14 | 15 | - name: Set up QEMU 16 | uses: docker/setup-qemu-action@v1 17 | with: 18 | platforms: all 19 | 20 | - name: Docker meta 21 | id: meta 22 | uses: docker/metadata-action@v3 23 | with: 24 | images: | 25 | slatedocs/slate 26 | tags: | 27 | type=ref,event=branch 28 | 29 | - name: Set up Docker Buildx 30 | id: buildx 31 | uses: docker/setup-buildx-action@v1 32 | 33 | - name: Login to DockerHub 34 | uses: docker/login-action@v1 35 | with: 36 | username: ${{ secrets.DOCKER_USERNAME }} 37 | password: ${{ secrets.DOCKER_ACCESS_KEY }} 38 | 39 | - name: Push to Docker Hub 40 | uses: docker/build-push-action@v2 41 | with: 42 | builder: ${{ steps.buildx.outputs.name }} 43 | context: . 44 | file: ./Dockerfile 45 | platforms: linux/amd64,linux/arm64,linux/ppc64le 46 | push: true 47 | tags: ${{ steps.meta.outputs.tags }} 48 | labels: ${{ steps.meta.outputs.labels }} 49 | 50 | deploy_gh: 51 | permissions: 52 | contents: write 53 | 54 | runs-on: ubuntu-latest 55 | env: 56 | ruby-version: 2.6 57 | 58 | steps: 59 | - uses: actions/checkout@v3 60 | - name: Set up Ruby 61 | uses: ruby/setup-ruby@v1 62 | with: 63 | ruby-version: ${{ env.ruby-version }} 64 | 65 | - uses: actions/cache@v3 66 | with: 67 | path: vendor/bundle 68 | key: gems-${{ runner.os }}-${{ env.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} 69 | restore-keys: | 70 | gems-${{ runner.os }}-${{ env.ruby-version }}- 71 | gems-${{ runner.os }}- 72 | - run: bundle config set deployment 'true' 73 | - name: bundle install 74 | run: | 75 | bundle config path vendor/bundle 76 | bundle install --jobs 4 --retry 3 77 | - run: bundle exec middleman build 78 | 79 | - name: Deploy 80 | uses: peaceiris/actions-gh-pages@v3.7.0-8 81 | with: 82 | github_token: ${{ secrets.GITHUB_TOKEN }} 83 | destination_dir: dev 84 | publish_dir: ./build 85 | keep_files: true 86 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Docker image 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | push_to_registry: 9 | name: Push Docker image to Docker Hub 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Check out the repo 13 | uses: actions/checkout@v3 14 | 15 | - name: Set up QEMU 16 | uses: docker/setup-qemu-action@v1 17 | with: 18 | platforms: all 19 | 20 | - name: Docker meta 21 | id: meta 22 | uses: docker/metadata-action@v3 23 | with: 24 | images: slatedocs/slate 25 | tags: | 26 | type=ref,event=tag 27 | 28 | - name: Set up Docker Buildx 29 | id: buildx 30 | uses: docker/setup-buildx-action@v1 31 | 32 | - name: Login to DockerHub 33 | uses: docker/login-action@v1 34 | with: 35 | username: ${{ secrets.DOCKER_USERNAME }} 36 | password: ${{ secrets.DOCKER_ACCESS_KEY }} 37 | 38 | - name: Push to Docker Hub 39 | uses: docker/build-push-action@v2 40 | with: 41 | builder: ${{ steps.buildx.outputs.name }} 42 | context: . 43 | file: ./Dockerfile 44 | platforms: linux/amd64,linux/arm64,linux/ppc64le 45 | push: true 46 | tags: ${{ steps.meta.outputs.tags }} 47 | labels: ${{ steps.meta.outputs.labels }} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | *.DS_STORE 15 | build/ 16 | .cache 17 | .vagrant 18 | .sass-cache 19 | 20 | # YARD artifacts 21 | .yardoc 22 | _yardoc 23 | doc/ 24 | .idea/ 25 | 26 | # Vagrant artifacts 27 | ubuntu-*-console.log 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 2.13.1 4 | 5 | *January 31, 2023* 6 | 7 | * Fix Vagrantfile gem install for ruby >= 2.6 (thanks @Cyb0rk) 8 | * Disable file watcher in run_build() for sake of qemu on arm64 (thanks @anapsix) 9 | * Expand deprecated git.io links to full url in docs (thanks @judge2020) 10 | * Add margin to paragraph following code-block on phones (thanks @tlhunter) 11 | * Bump nokogiri from 1.13.4 to 1.13.9 12 | * Bump rouge from 3.28.0 to 3.30.0 13 | * Bump redcarpet from 3.5.1 to 3.6.0 14 | * Bump middleman from 4.4.2 to 4.4.3 15 | * Bump middleman-syntax from 3.2.0 to 3.3.0 16 | * Bump webrick from 1.7.0 to 1.8.1 17 | 18 | ## Version 2.13.0 19 | 20 | *April 22, 2022* 21 | 22 | * __Drop support for ruby 2.5__ 23 | * Bump rouge from 3.26.1 to 3.28.0 24 | * Formally support ruby 3.1 25 | * Bump nokogiri from 1.12.5 to 1.13.4 26 | * Build docker images for multiple architectures (e.g. `aarch64`) 27 | * Remove `VOLUME` declaration from Dockerfile (thanks @aemengo) 28 | 29 | The security vulnerabilities reported against recent versions of nokogiri should not affect slate users with a regular setup. 30 | 31 | ## Version 2.12.0 32 | 33 | *November 04, 2021* 34 | 35 | * Bump nokogiri from 1.12.3 to 1.12.5 36 | * Bump ffi from 1.15.0 to 1.15.4 37 | * Bump rouge from 3.26.0 to 3.26.1 38 | * Bump middleman from 4.4.0 to 4.4.2 39 | * Remove unnecessary files from docker images 40 | 41 | ## Version 2.11.0 42 | 43 | *August 12, 2021* 44 | 45 | * __[Security]__ Bump addressable transitive dependency from 2.7.0 to 2.8.0 46 | * Support specifying custom meta tags in YAML front-matter 47 | * Bump nokogiri from 1.11.3 to 1.12.3 (minimum supported version is 1.11.4) 48 | * Bump middleman-autoprefixer from 2.10.1 to 3.0.0 49 | * Bump jquery from 3.5.1 to 3.6.0 50 | * Bump middleman from [`d180ca3`](https://github.com/middleman/middleman/commit/d180ca337202873f2601310c74ba2b6b4cf063ec) to 4.4.0 51 | 52 | ## Version 2.10.0 53 | 54 | *April 13, 2021* 55 | 56 | * Add support for Ruby 3.0 (thanks @shaun-scale) 57 | * Add requirement for Git on installing dependencies 58 | * Bump nokogiri from 1.11.2 to 1.11.3 59 | * Bump middleman from 4.3.11 to [`d180ca3`](https://github.com/middleman/middleman/commit/d180ca337202873f2601310c74ba2b6b4cf063ec) 60 | 61 | ## Version 2.9.2 62 | 63 | *March 30, 2021* 64 | 65 | * __[Security]__ Bump kramdown from 2.3.0 to 2.3.1 66 | * Bump nokogiri from 1.11.1 to 1.11.2 67 | 68 | ## Version 2.9.1 69 | 70 | *February 27, 2021* 71 | 72 | * Fix Slate language tabs not working if localStorage is disabled 73 | 74 | ## Version 2.9.0 75 | 76 | *January 19, 2021* 77 | 78 | * __Drop support for Ruby 2.3 and 2.4__ 79 | * __[Security]__ Bump nokogiri from 1.10.10 to 1.11.1 80 | * __[Security]__ Bump redcarpet from 3.5.0 to 3.5.1 81 | * Specify slate is not supported on Ruby 3.x 82 | * Bump rouge from 3.24.0 to 3.26.0 83 | 84 | ## Version 2.8.0 85 | 86 | *October 27, 2020* 87 | 88 | * Remove last trailing newline when using the copy code button 89 | * Rework docker image and make available at slatedocs/slate 90 | * Improve Dockerfile layout to improve caching (thanks @micvbang) 91 | * Bump rouge from 3.20 to 3.24 92 | * Bump nokogiri from 1.10.9 to 1.10.10 93 | * Bump middleman from 4.3.8 to 4.3.11 94 | * Bump lunr.js from 2.3.8 to 2.3.9 95 | 96 | ## Version 2.7.1 97 | 98 | *August 13, 2020* 99 | 100 | * __[security]__ Bumped middleman from 4.3.7 to 4.3.8 101 | 102 | _Note_: Slate uses redcarpet, not kramdown, for rendering markdown to HTML, and so was unaffected by the security vulnerability in middleman. 103 | If you have changed slate to use kramdown, and with GFM, you may need to install the `kramdown-parser-gfm` gem. 104 | 105 | ## Version 2.7.0 106 | 107 | *June 21, 2020* 108 | 109 | * __[security]__ Bumped rack in Gemfile.lock from 2.2.2 to 2.2.3 110 | * Bumped bundled jQuery from 3.2.1 to 3.5.1 111 | * Bumped bundled lunr from 0.5.7 to 2.3.8 112 | * Bumped imagesloaded from 3.1.8 to 4.1.4 113 | * Bumped rouge from 3.17.0 to 3.20.0 114 | * Bumped redcarpet from 3.4.0 to 3.5.0 115 | * Fix color of highlighted code being unreadable when printing page 116 | * Add clipboard icon for "Copy to Clipboard" functionality to code boxes (see note below) 117 | * Fix handling of ToC selectors that contain punctutation (thanks @gruis) 118 | * Fix language bar truncating languages that overflow screen width 119 | * Strip HTML tags from ToC title before displaying it in title bar in JS (backup to stripping done in Ruby code) (thanks @atic) 120 | 121 | To enable the new clipboard icon, you need to add `code_clipboard: true` to the frontmatter of source/index.html.md. 122 | See [this line](https://github.com/slatedocs/slate/blame/main/source/index.html.md#L19) for an example of usage. 123 | 124 | ## Version 2.6.1 125 | 126 | *May 30, 2020* 127 | 128 | * __[security]__ update child dependency activesupport in Gemfile.lock to 5.4.2.3 129 | * Update Middleman in Gemfile.lock to 4.3.7 130 | * Replace Travis-CI with GitHub actions for continuous integration 131 | * Replace Spectrum with GitHub discussions 132 | 133 | ## Version 2.6.0 134 | 135 | *May 18, 2020* 136 | 137 | __Note__: 2.5.0 was "pulled" due to a breaking bug discovered after release. It is recommended to skip it, and move straight to 2.6.0. 138 | 139 | * Fix large whitespace gap in middle column for sections with codeblocks 140 | * Fix highlighted code elements having a different background than rest of code block 141 | * Change JSON keys to have a different font color than their values 142 | * Disable asset hashing for woff and woff2 elements due to middleman bug breaking woff2 asset hashing in general 143 | * Move Dockerfile to Debian from Alpine 144 | * Converted repo to a [GitHub template](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-template-repository) 145 | * Update sassc to 2.3.0 in Gemfile.lock 146 | 147 | ## Version 2.5.0 148 | 149 | *May 8, 2020* 150 | 151 | * __[security]__ update nokogiri to ~> 1.10.8 152 | * Update links in example docs to https://github.com/slatedocs/slate from https://github.com/lord/slate 153 | * Update LICENSE to include full Apache 2.0 text 154 | * Test slate against Ruby 2.5 and 2.6 on Travis-CI 155 | * Update Vagrantfile to use Ubuntu 18.04 (thanks @bradthurber) 156 | * Parse arguments and flags for deploy.sh on script start, instead of potentially after building source files 157 | * Install nodejs inside Vagrantfile (thanks @fernandoaguilar) 158 | * Add Dockerfile for running slate (thanks @redhatxl) 159 | * update middleman-syntax and rouge to ~>3.2 160 | * update middleman to 4.3.6 161 | 162 | ## Version 2.4.0 163 | 164 | *October 19, 2019* 165 | 166 | - Move repository from lord/slate to slatedocs/slate 167 | - Fix documentation to point at new repo link, thanks to [Arun](https://github.com/slash-arun), [Gustavo Gawryszewski](https://github.com/gawry), and [Daniel Korbit](https://github.com/danielkorbit) 168 | - Update `nokogiri` to 1.10.4 169 | - Update `ffi` in `Gemfile.lock` to fix security warnings, thanks to [Grey Baker](https://github.com/greysteil) and [jakemack](https://github.com/jakemack) 170 | - Update `rack` to 2.0.7 in `Gemfile.lock` to fix security warnings, thanks to [Grey Baker](https://github.com/greysteil) and [jakemack](https://github.com/jakemack) 171 | - Update middleman to `4.3` and relax constraints on middleman related gems, thanks to [jakemack](https://github.com/jakemack) 172 | - Add sass gem, thanks to [jakemack](https://github.com/jakemack) 173 | - Activate `asset_cache` in middleman to improve cacheability of static files, thanks to [Sam Gilman](https://github.com/thenengah) 174 | - Update to using bundler 2 for `Gemfile.lock`, thanks to [jakemack](https://github.com/jakemack) 175 | 176 | ## Version 2.3.1 177 | 178 | *July 5, 2018* 179 | 180 | - Update `sprockets` in `Gemfile.lock` to fix security warnings 181 | 182 | ## Version 2.3 183 | 184 | *July 5, 2018* 185 | 186 | - Allows strikethrough in markdown by default. 187 | - Upgrades jQuery to 3.2.1, thanks to [Tomi Takussaari](https://github.com/TomiTakussaari) 188 | - Fixes invalid HTML in `layout.erb`, thanks to [Eric Scouten](https://github.com/scouten) for pointing out 189 | - Hopefully fixes Vagrant memory issues, thanks to [Petter Blomberg](https://github.com/p-blomberg) for the suggestion 190 | - Cleans HTML in headers before setting `document.title`, thanks to [Dan Levy](https://github.com/justsml) 191 | - Allows trailing whitespace in markdown files, thanks to [Samuel Cousin](https://github.com/kuzyn) 192 | - Fixes pushState/replaceState problems with scrolling not changing the document hash, thanks to [Andrey Fedorov](https://github.com/anfedorov) 193 | - Removes some outdated examples, thanks [@al-tr](https://github.com/al-tr), [Jerome Dahdah](https://github.com/jdahdah), and [Ricardo Castro](https://github.com/mccricardo) 194 | - Fixes `nav-padding` bug, thanks [Jerome Dahdah](https://github.com/jdahdah) 195 | - Code style fixes thanks to [Sebastian Zaremba](https://github.com/vassyz) 196 | - Nokogiri version bump thanks to [Grey Baker](https://github.com/greysteil) 197 | - Fix to default `index.md` text thanks to [Nick Busey](https://github.com/NickBusey) 198 | 199 | Thanks to everyone who contributed to this release! 200 | 201 | ## Version 2.2 202 | 203 | *January 19, 2018* 204 | 205 | - Fixes bugs with some non-roman languages not generating unique headers 206 | - Adds editorconfig, thanks to [Jay Thomas](https://github.com/jaythomas) 207 | - Adds optional `NestingUniqueHeadCounter`, thanks to [Vladimir Morozov](https://github.com/greenhost87) 208 | - Small fixes to typos and language, thx [Emir Ribić](https://github.com/ribice), [Gregor Martynus](https://github.com/gr2m), and [Martius](https://github.com/martiuslim)! 209 | - Adds links to Spectrum chat for questions in README and ISSUE_TEMPLATE 210 | 211 | ## Version 2.1 212 | 213 | *October 30, 2017* 214 | 215 | - Right-to-left text stylesheet option, thanks to [Mohammad Hossein Rabiee](https://github.com/mhrabiee) 216 | - Fix for HTML5 history state bug, thanks to [Zach Toolson](https://github.com/ztoolson) 217 | - Small styling changes, typo fixes, small bug fixes from [Marian Friedmann](https://github.com/rnarian), [Ben Wilhelm](https://github.com/benwilhelm), [Fouad Matin](https://github.com/fouad), [Nicolas Bonduel](https://github.com/NicolasBonduel), [Christian Oliff](https://github.com/coliff) 218 | 219 | Thanks to everyone who submitted PRs for this version! 220 | 221 | ## Version 2.0 222 | 223 | *July 17, 2017* 224 | 225 | - All-new statically generated table of contents 226 | - Should be much faster loading and scrolling for large pages 227 | - Smaller Javascript file sizes 228 | - Avoids the problem with the last link in the ToC not ever highlighting if the section was shorter than the page 229 | - Fixes control-click not opening in a new page 230 | - Automatically updates the HTML title as you scroll 231 | - Updated design 232 | - New default colors! 233 | - New spacings and sizes! 234 | - System-default typefaces, just like GitHub 235 | - Added search input delay on large corpuses to reduce lag 236 | - We even bumped the major version cause hey, why not? 237 | - Various small bug fixes 238 | 239 | Thanks to everyone who helped debug or wrote code for this version! It was a serious community effort, and I couldn't have done it alone. 240 | 241 | ## Version 1.5 242 | 243 | *February 23, 2017* 244 | 245 | - Add [multiple tabs per programming language](https://github.com/lord/slate/wiki/Multiple-language-tabs-per-programming-language) feature 246 | - Upgrade Middleman to add Ruby 1.4.0 compatibility 247 | - Switch default code highlighting color scheme to better highlight JSON 248 | - Various small typo and bug fixes 249 | 250 | ## Version 1.4 251 | 252 | *November 24, 2016* 253 | 254 | - Upgrade Middleman and Rouge gems, should hopefully solve a number of bugs 255 | - Update some links in README 256 | - Fix broken Vagrant startup script 257 | - Fix some problems with deploy.sh help message 258 | - Fix bug with language tabs not hiding properly if no error 259 | - Add `!default` to SASS variables 260 | - Fix bug with logo margin 261 | - Bump tested Ruby versions in .travis.yml 262 | 263 | ## Version 1.3.3 264 | 265 | *June 11, 2016* 266 | 267 | Documentation and example changes. 268 | 269 | ## Version 1.3.2 270 | 271 | *February 3, 2016* 272 | 273 | A small bugfix for slightly incorrect background colors on code samples in some cases. 274 | 275 | ## Version 1.3.1 276 | 277 | *January 31, 2016* 278 | 279 | A small bugfix for incorrect whitespace in code blocks. 280 | 281 | ## Version 1.3 282 | 283 | *January 27, 2016* 284 | 285 | We've upgraded Middleman and a number of other dependencies, which should fix quite a few bugs. 286 | 287 | Instead of `rake build` and `rake deploy`, you should now run `bundle exec middleman build --clean` to build your server, and `./deploy.sh` to deploy it to Github Pages. 288 | 289 | ## Version 1.2 290 | 291 | *June 20, 2015* 292 | 293 | **Fixes:** 294 | 295 | - Remove crash on invalid languages 296 | - Update Tocify to scroll to the highlighted header in the Table of Contents 297 | - Fix variable leak and update search algorithms 298 | - Update Python examples to be valid Python 299 | - Update gems 300 | - More misc. bugfixes of Javascript errors 301 | - Add Dockerfile 302 | - Remove unused gems 303 | - Optimize images, fonts, and generated asset files 304 | - Add chinese font support 305 | - Remove RedCarpet header ID patch 306 | - Update language tabs to not disturb existing query strings 307 | 308 | ## Version 1.1 309 | 310 | *July 27, 2014* 311 | 312 | **Fixes:** 313 | 314 | - Finally, a fix for the redcarpet upgrade bug 315 | 316 | ## Version 1.0 317 | 318 | *July 2, 2014* 319 | 320 | [View Issues](https://github.com/tripit/slate/issues?milestone=1&state=closed) 321 | 322 | **Features:** 323 | 324 | - Responsive designs for phones and tablets 325 | - Started tagging versions 326 | 327 | **Fixes:** 328 | 329 | - Fixed 'unrecognized expression' error 330 | - Fixed #undefined hash bug 331 | - Fixed bug where the current language tab would be unselected 332 | - Fixed bug where tocify wouldn't highlight the current section while searching 333 | - Fixed bug where ids of header tags would have special characters that caused problems 334 | - Updated layout so that pages with disabled search wouldn't load search.js 335 | - Cleaned up Javascript 336 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@lord.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.6-slim 2 | 3 | WORKDIR /srv/slate 4 | 5 | EXPOSE 4567 6 | 7 | COPY Gemfile . 8 | COPY Gemfile.lock . 9 | 10 | RUN apt-get update \ 11 | && apt-get install -y --no-install-recommends \ 12 | build-essential \ 13 | git \ 14 | nodejs \ 15 | && gem install bundler \ 16 | && bundle install \ 17 | && apt-get remove -y build-essential git \ 18 | && apt-get autoremove -y \ 19 | && rm -rf /var/lib/apt/lists/* 20 | 21 | COPY . /srv/slate 22 | 23 | RUN chmod +x /srv/slate/slate.sh 24 | 25 | ENTRYPOINT ["/srv/slate/slate.sh"] 26 | CMD ["build"] 27 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | ruby '>= 2.6' 2 | source 'https://rubygems.org' 3 | 4 | # Middleman 5 | gem 'middleman', '~> 4.4' 6 | gem 'middleman-syntax', '~> 3.2' 7 | gem 'middleman-autoprefixer', '~> 3.0' 8 | gem 'middleman-sprockets', '~> 4.1' 9 | gem 'rouge', '~> 3.21' 10 | gem 'redcarpet', '~> 3.6.0' 11 | gem 'nokogiri', '~> 1.13.3' 12 | gem 'sass' 13 | gem 'webrick' 14 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (6.1.6.1) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (>= 1.6, < 2) 7 | minitest (>= 5.1) 8 | tzinfo (~> 2.0) 9 | zeitwerk (~> 2.3) 10 | addressable (2.8.1) 11 | public_suffix (>= 2.0.2, < 6.0) 12 | autoprefixer-rails (10.2.5.0) 13 | execjs (< 2.8.0) 14 | backports (3.23.0) 15 | coffee-script (2.4.1) 16 | coffee-script-source 17 | execjs 18 | coffee-script-source (1.12.2) 19 | concurrent-ruby (1.2.0) 20 | contracts (0.16.1) 21 | dotenv (2.8.1) 22 | erubis (2.7.0) 23 | execjs (2.7.0) 24 | fast_blank (1.0.1) 25 | fastimage (2.2.6) 26 | ffi (1.15.5) 27 | haml (5.2.2) 28 | temple (>= 0.8.0) 29 | tilt 30 | hamster (3.0.0) 31 | concurrent-ruby (~> 1.0) 32 | hashie (3.6.0) 33 | i18n (1.6.0) 34 | concurrent-ruby (~> 1.0) 35 | kramdown (2.4.0) 36 | rexml 37 | listen (3.8.0) 38 | rb-fsevent (~> 0.10, >= 0.10.3) 39 | rb-inotify (~> 0.9, >= 0.9.10) 40 | memoist (0.16.2) 41 | middleman (4.4.3) 42 | coffee-script (~> 2.2) 43 | haml (>= 4.0.5, < 6.0) 44 | kramdown (>= 2.3.0) 45 | middleman-cli (= 4.4.3) 46 | middleman-core (= 4.4.3) 47 | middleman-autoprefixer (3.0.0) 48 | autoprefixer-rails (~> 10.0) 49 | middleman-core (>= 4.0.0) 50 | middleman-cli (4.4.3) 51 | thor (>= 0.17.0, < 2.0) 52 | middleman-core (4.4.3) 53 | activesupport (>= 6.1, < 7.1) 54 | addressable (~> 2.4) 55 | backports (~> 3.6) 56 | bundler (~> 2.0) 57 | contracts (~> 0.13) 58 | dotenv 59 | erubis 60 | execjs (~> 2.0) 61 | fast_blank 62 | fastimage (~> 2.0) 63 | hamster (~> 3.0) 64 | hashie (~> 3.4) 65 | i18n (~> 1.6.0) 66 | listen (~> 3.0) 67 | memoist (~> 0.14) 68 | padrino-helpers (~> 0.15.0) 69 | parallel 70 | rack (>= 1.4.5, < 3) 71 | sassc (~> 2.0) 72 | servolux 73 | tilt (~> 2.0.9) 74 | toml 75 | uglifier (~> 3.0) 76 | webrick 77 | middleman-sprockets (4.1.1) 78 | middleman-core (~> 4.0) 79 | sprockets (>= 3.0) 80 | middleman-syntax (3.3.0) 81 | middleman-core (>= 3.2) 82 | rouge (~> 3.2) 83 | mini_portile2 (2.8.0) 84 | minitest (5.17.0) 85 | nokogiri (1.13.9) 86 | mini_portile2 (~> 2.8.0) 87 | racc (~> 1.4) 88 | padrino-helpers (0.15.2) 89 | i18n (>= 0.6.7, < 2) 90 | padrino-support (= 0.15.2) 91 | tilt (>= 1.4.1, < 3) 92 | padrino-support (0.15.2) 93 | parallel (1.22.1) 94 | parslet (2.0.0) 95 | public_suffix (5.0.1) 96 | racc (1.6.0) 97 | rack (2.2.6.2) 98 | rb-fsevent (0.11.2) 99 | rb-inotify (0.10.1) 100 | ffi (~> 1.0) 101 | redcarpet (3.6.0) 102 | rexml (3.2.5) 103 | rouge (3.30.0) 104 | sass (3.7.4) 105 | sass-listen (~> 4.0.0) 106 | sass-listen (4.0.0) 107 | rb-fsevent (~> 0.9, >= 0.9.4) 108 | rb-inotify (~> 0.9, >= 0.9.7) 109 | sassc (2.4.0) 110 | ffi (~> 1.9) 111 | servolux (0.13.0) 112 | sprockets (3.7.2) 113 | concurrent-ruby (~> 1.0) 114 | rack (> 1, < 3) 115 | temple (0.10.0) 116 | thor (1.2.1) 117 | tilt (2.0.11) 118 | toml (0.3.0) 119 | parslet (>= 1.8.0, < 3.0.0) 120 | tzinfo (2.0.6) 121 | concurrent-ruby (~> 1.0) 122 | uglifier (3.2.0) 123 | execjs (>= 0.3.0, < 3) 124 | webrick (1.8.1) 125 | zeitwerk (2.6.0) 126 | 127 | PLATFORMS 128 | ruby 129 | 130 | DEPENDENCIES 131 | middleman (~> 4.4) 132 | middleman-autoprefixer (~> 3.0) 133 | middleman-sprockets (~> 4.1) 134 | middleman-syntax (~> 3.2) 135 | nokogiri (~> 1.13.3) 136 | redcarpet (~> 3.6.0) 137 | rouge (~> 3.21) 138 | sass 139 | webrick 140 | 141 | RUBY VERSION 142 | ruby 2.7.2p137 143 | 144 | BUNDLED WITH 145 | 2.2.22 146 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Slate: API Documentation Generator 3 |
4 | Build Status 5 | Docker Version 6 |

7 | 8 |

Slate helps you create beautiful, intelligent, responsive API documentation.

9 | 10 |

Screenshot of Example Documentation created with Slate

11 | 12 |

The example above was created with Slate. Check it out at slatedocs.github.io/slate.

13 | 14 | Features 15 | ------------ 16 | 17 | * **Clean, intuitive design** — With Slate, the description of your API is on the left side of your documentation, and all the code examples are on the right side. Inspired by [Stripe's](https://stripe.com/docs/api) and [PayPal's](https://developer.paypal.com/webapps/developer/docs/api/) API docs. Slate is responsive, so it looks great on tablets, phones, and even in print. 18 | 19 | * **Everything on a single page** — Gone are the days when your users had to search through a million pages to find what they wanted. Slate puts the entire documentation on a single page. We haven't sacrificed linkability, though. As you scroll, your browser's hash will update to the nearest header, so linking to a particular point in the documentation is still natural and easy. 20 | 21 | * **Slate is just Markdown** — When you write docs with Slate, you're just writing Markdown, which makes it simple to edit and understand. Everything is written in Markdown — even the code samples are just Markdown code blocks. 22 | 23 | * **Write code samples in multiple languages** — If your API has bindings in multiple programming languages, you can easily put in tabs to switch between them. In your document, you'll distinguish different languages by specifying the language name at the top of each code block, just like with GitHub Flavored Markdown. 24 | 25 | * **Out-of-the-box syntax highlighting** for [over 100 languages](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers), no configuration required. 26 | 27 | * **Automatic, smoothly scrolling table of contents** on the far left of the page. As you scroll, it displays your current position in the document. It's fast, too. We're using Slate at TripIt to build documentation for our new API, where our table of contents has over 180 entries. We've made sure that the performance remains excellent, even for larger documents. 28 | 29 | * **Let your users update your documentation for you** — By default, your Slate-generated documentation is hosted in a public GitHub repository. Not only does this mean you get free hosting for your docs with GitHub Pages, but it also makes it simple for other developers to make pull requests to your docs if they find typos or other problems. Of course, if you don't want to use GitHub, you're also welcome to host your docs elsewhere. 30 | 31 | * **RTL Support** Full right-to-left layout for RTL languages such as Arabic, Persian (Farsi), Hebrew etc. 32 | 33 | Getting started with Slate is super easy! Simply press the green "use this template" button above and follow the instructions below. Or, if you'd like to check out what Slate is capable of, take a look at the [sample docs](https://slatedocs.github.io/slate/). 34 | 35 | Getting Started with Slate 36 | ------------------------------ 37 | 38 | To get started with Slate, please check out the [Getting Started](https://github.com/slatedocs/slate/wiki#getting-started) 39 | section in our [wiki](https://github.com/slatedocs/slate/wiki). 40 | 41 | We support running Slate in three different ways: 42 | * [Natively](https://github.com/slatedocs/slate/wiki/Using-Slate-Natively) 43 | * [Using Vagrant](https://github.com/slatedocs/slate/wiki/Using-Slate-in-Vagrant) 44 | * [Using Docker](https://github.com/slatedocs/slate/wiki/Using-Slate-in-Docker) 45 | 46 | Companies Using Slate 47 | --------------------------------- 48 | 49 | * [NASA](https://api.nasa.gov) 50 | * [Sony](http://developers.cimediacloud.com) 51 | * [Best Buy](https://bestbuyapis.github.io/api-documentation/) 52 | * [Travis-CI](https://docs.travis-ci.com/api/) 53 | * [Greenhouse](https://developers.greenhouse.io/harvest.html) 54 | * [WooCommerce](http://woocommerce.github.io/woocommerce-rest-api-docs/) 55 | * [Dwolla](https://docs.dwolla.com/) 56 | * [Clearbit](https://clearbit.com/docs) 57 | * [Coinbase](https://developers.coinbase.com/api) 58 | * [Parrot Drones](http://developer.parrot.com/docs/bebop/) 59 | * [CoinAPI](https://docs.coinapi.io/) 60 | 61 | You can view more in [the list on the wiki](https://github.com/slatedocs/slate/wiki/Slate-in-the-Wild). 62 | 63 | Questions? Need Help? Found a bug? 64 | -------------------- 65 | 66 | If you've got questions about setup, deploying, special feature implementation in your fork, or just want to chat with the developer, please feel free to [start a thread in our Discussions tab](https://github.com/slatedocs/slate/discussions)! 67 | 68 | Found a bug with upstream Slate? Go ahead and [submit an issue](https://github.com/slatedocs/slate/issues). And, of course, feel free to submit pull requests with bug fixes or changes to the `dev` branch. 69 | 70 | Contributors 71 | -------------------- 72 | 73 | Slate was built by [Robert Lord](https://lord.io) while at [TripIt](https://www.tripit.com/). The project is now maintained by [Matthew Peveler](https://github.com/MasterOdin) and [Mike Ralphson](https://github.com/MikeRalphson). 74 | 75 | Thanks to the following people who have submitted major pull requests: 76 | 77 | - [@chrissrogers](https://github.com/chrissrogers) 78 | - [@bootstraponline](https://github.com/bootstraponline) 79 | - [@realityking](https://github.com/realityking) 80 | - [@cvkef](https://github.com/cvkef) 81 | 82 | Also, thanks to [Sauce Labs](http://saucelabs.com) for sponsoring the development of the responsive styles. 83 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | config.vm.box = "ubuntu/focal64" 3 | config.vm.network :forwarded_port, guest: 4567, host: 4567 4 | config.vm.provider "virtualbox" do |vb| 5 | vb.memory = "2048" 6 | end 7 | 8 | config.vm.provision "bootstrap", 9 | type: "shell", 10 | inline: <<-SHELL 11 | # add nodejs v12 repository 12 | curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - 13 | 14 | sudo apt-get update 15 | sudo apt-get install -yq ruby ruby-dev 16 | sudo apt-get install -yq pkg-config build-essential nodejs git libxml2-dev libxslt-dev 17 | sudo apt-get autoremove -yq 18 | gem install --no-document bundler 19 | SHELL 20 | 21 | # add the local user git config to the vm 22 | config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig" 23 | 24 | config.vm.provision "install", 25 | type: "shell", 26 | privileged: false, 27 | inline: <<-SHELL 28 | echo "==============================================" 29 | echo "Installing app dependencies" 30 | cd /vagrant 31 | sudo gem install bundler -v "$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1)" 32 | bundle config build.nokogiri --use-system-libraries 33 | bundle install 34 | SHELL 35 | 36 | config.vm.provision "run", 37 | type: "shell", 38 | privileged: false, 39 | run: "always", 40 | inline: <<-SHELL 41 | echo "==============================================" 42 | echo "Starting up middleman at http://localhost:4567" 43 | echo "If it does not come up, check the ~/middleman.log file for any error messages" 44 | cd /vagrant 45 | bundle exec middleman server --watcher-force-polling --watcher-latency=1 &> ~/middleman.log & 46 | SHELL 47 | end 48 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Unique header generation 2 | require './lib/unique_head.rb' 3 | 4 | # Markdown 5 | set :markdown_engine, :redcarpet 6 | set :markdown, 7 | fenced_code_blocks: true, 8 | smartypants: true, 9 | disable_indented_code_blocks: true, 10 | prettify: true, 11 | strikethrough: true, 12 | tables: true, 13 | with_toc_data: true, 14 | no_intra_emphasis: true, 15 | renderer: UniqueHeadCounter 16 | 17 | # Assets 18 | set :css_dir, 'stylesheets' 19 | set :js_dir, 'javascripts' 20 | set :images_dir, 'images' 21 | set :fonts_dir, 'fonts' 22 | 23 | # Activate the syntax highlighter 24 | activate :syntax 25 | ready do 26 | require './lib/monokai_sublime_slate.rb' 27 | require './lib/multilang.rb' 28 | end 29 | 30 | activate :sprockets 31 | 32 | activate :autoprefixer do |config| 33 | config.browsers = ['last 2 version', 'Firefox ESR'] 34 | config.cascade = false 35 | config.inline = true 36 | end 37 | 38 | # Github pages require relative links 39 | activate :relative_assets 40 | set :relative_links, true 41 | 42 | # Build Configuration 43 | configure :build do 44 | # We do want to hash woff and woff2 as there's a bug where woff2 will use 45 | # woff asset hash which breaks things. Trying to use a combination of ignore and 46 | # rewrite_ignore does not work as it conflicts weirdly with relative_assets. Disabling 47 | # the .woff2 extension only does not work as .woff will still activate it so have to 48 | # have both. See https://github.com/slatedocs/slate/issues/1171 for more details. 49 | activate :asset_hash, :exts => app.config[:asset_extensions] - %w[.woff .woff2] 50 | # If you're having trouble with Middleman hanging, commenting 51 | # out the following two lines has been known to help 52 | activate :minify_css 53 | activate :minify_javascript 54 | # activate :gzip 55 | end 56 | 57 | # Deploy Configuration 58 | # If you want Middleman to listen on a different port, you can set that below 59 | set :port, 4567 60 | 61 | helpers do 62 | require './lib/toc_data.rb' 63 | end 64 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit #abort if any command fails 3 | me=$(basename "$0") 4 | 5 | help_message="\ 6 | Usage: $me [-c FILE] [] 7 | Deploy generated files to a git branch. 8 | 9 | Options: 10 | 11 | -h, --help Show this help information. 12 | -v, --verbose Increase verbosity. Useful for debugging. 13 | -e, --allow-empty Allow deployment of an empty directory. 14 | -m, --message MESSAGE Specify the message used when committing on the 15 | deploy branch. 16 | -n, --no-hash Don't append the source commit's hash to the deploy 17 | commit's message. 18 | --source-only Only build but not push 19 | --push-only Only push but not build 20 | " 21 | 22 | 23 | run_build() { 24 | bundle exec middleman build --clean 25 | } 26 | 27 | parse_args() { 28 | # Set args from a local environment file. 29 | if [ -e ".env" ]; then 30 | source .env 31 | fi 32 | 33 | # Parse arg flags 34 | # If something is exposed as an environment variable, set/overwrite it 35 | # here. Otherwise, set/overwrite the internal variable instead. 36 | while : ; do 37 | if [[ $1 = "-h" || $1 = "--help" ]]; then 38 | echo "$help_message" 39 | exit 0 40 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then 41 | verbose=true 42 | shift 43 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then 44 | allow_empty=true 45 | shift 46 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then 47 | commit_message=$2 48 | shift 2 49 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then 50 | GIT_DEPLOY_APPEND_HASH=false 51 | shift 52 | elif [[ $1 = "--source-only" ]]; then 53 | source_only=true 54 | shift 55 | elif [[ $1 = "--push-only" ]]; then 56 | push_only=true 57 | shift 58 | else 59 | break 60 | fi 61 | done 62 | 63 | if [ ${source_only} ] && [ ${push_only} ]; then 64 | >&2 echo "You can only specify one of --source-only or --push-only" 65 | exit 1 66 | fi 67 | 68 | # Set internal option vars from the environment and arg flags. All internal 69 | # vars should be declared here, with sane defaults if applicable. 70 | 71 | # Source directory & target branch. 72 | deploy_directory=build 73 | deploy_branch=gh-pages 74 | 75 | #if no user identity is already set in the current git environment, use this: 76 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh} 77 | default_email=${GIT_DEPLOY_EMAIL:-} 78 | 79 | #repository to deploy to. must be readable and writable. 80 | repo=origin 81 | 82 | #append commit hash to the end of message by default 83 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true} 84 | } 85 | 86 | main() { 87 | enable_expanded_output 88 | 89 | if ! git diff --exit-code --quiet --cached; then 90 | echo Aborting due to uncommitted changes in the index >&2 91 | return 1 92 | fi 93 | 94 | commit_title=`git log -n 1 --format="%s" HEAD` 95 | commit_hash=` git log -n 1 --format="%H" HEAD` 96 | 97 | #default commit message uses last title if a custom one is not supplied 98 | if [[ -z $commit_message ]]; then 99 | commit_message="publish: $commit_title" 100 | fi 101 | 102 | #append hash to commit message unless no hash flag was found 103 | if [ $append_hash = true ]; then 104 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash" 105 | fi 106 | 107 | previous_branch=`git rev-parse --abbrev-ref HEAD` 108 | 109 | if [ ! -d "$deploy_directory" ]; then 110 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2 111 | return 1 112 | fi 113 | 114 | # must use short form of flag in ls for compatibility with macOS and BSD 115 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then 116 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2 117 | return 1 118 | fi 119 | 120 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then 121 | # deploy_branch exists in $repo; make sure we have the latest version 122 | 123 | disable_expanded_output 124 | git fetch --force $repo $deploy_branch:$deploy_branch 125 | enable_expanded_output 126 | fi 127 | 128 | # check if deploy_branch exists locally 129 | if git show-ref --verify --quiet "refs/heads/$deploy_branch" 130 | then incremental_deploy 131 | else initial_deploy 132 | fi 133 | 134 | restore_head 135 | } 136 | 137 | initial_deploy() { 138 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch 139 | git --work-tree "$deploy_directory" add --all 140 | commit+push 141 | } 142 | 143 | incremental_deploy() { 144 | #make deploy_branch the current branch 145 | git symbolic-ref HEAD refs/heads/$deploy_branch 146 | #put the previously committed contents of deploy_branch into the index 147 | git --work-tree "$deploy_directory" reset --mixed --quiet 148 | git --work-tree "$deploy_directory" add --all 149 | 150 | set +o errexit 151 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$? 152 | set -o errexit 153 | case $diff in 154 | 0) echo No changes to files in $deploy_directory. Skipping commit.;; 155 | 1) commit+push;; 156 | *) 157 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to main, use: git symbolic-ref HEAD refs/heads/main && git reset --mixed >&2 158 | return $diff 159 | ;; 160 | esac 161 | } 162 | 163 | commit+push() { 164 | set_user_id 165 | git --work-tree "$deploy_directory" commit -m "$commit_message" 166 | 167 | disable_expanded_output 168 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token 169 | git push --quiet $repo $deploy_branch 170 | enable_expanded_output 171 | } 172 | 173 | #echo expanded commands as they are executed (for debugging) 174 | enable_expanded_output() { 175 | if [ $verbose ]; then 176 | set -o xtrace 177 | set +o verbose 178 | fi 179 | } 180 | 181 | #this is used to avoid outputting the repo URL, which may contain a secret token 182 | disable_expanded_output() { 183 | if [ $verbose ]; then 184 | set +o xtrace 185 | set -o verbose 186 | fi 187 | } 188 | 189 | set_user_id() { 190 | if [[ -z `git config user.name` ]]; then 191 | git config user.name "$default_username" 192 | fi 193 | if [[ -z `git config user.email` ]]; then 194 | git config user.email "$default_email" 195 | fi 196 | } 197 | 198 | restore_head() { 199 | if [[ $previous_branch = "HEAD" ]]; then 200 | #we weren't on any branch before, so just set HEAD back to the commit it was on 201 | git update-ref --no-deref HEAD $commit_hash $deploy_branch 202 | else 203 | git symbolic-ref HEAD refs/heads/$previous_branch 204 | fi 205 | 206 | git reset --mixed 207 | } 208 | 209 | filter() { 210 | sed -e "s|$repo|\$repo|g" 211 | } 212 | 213 | sanitize() { 214 | "$@" 2> >(filter 1>&2) | filter 215 | } 216 | 217 | parse_args "$@" 218 | 219 | if [[ ${source_only} ]]; then 220 | run_build 221 | elif [[ ${push_only} ]]; then 222 | main "$@" 223 | else 224 | run_build 225 | main "$@" 226 | fi 227 | -------------------------------------------------------------------------------- /font-selection.json: -------------------------------------------------------------------------------- 1 | { 2 | "IcoMoonType": "selection", 3 | "icons": [ 4 | { 5 | "icon": { 6 | "paths": [ 7 | "M438.857 73.143q119.429 0 220.286 58.857t159.714 159.714 58.857 220.286-58.857 220.286-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857zM512 785.714v-108.571q0-8-5.143-13.429t-12.571-5.429h-109.714q-7.429 0-13.143 5.714t-5.714 13.143v108.571q0 7.429 5.714 13.143t13.143 5.714h109.714q7.429 0 12.571-5.429t5.143-13.429zM510.857 589.143l10.286-354.857q0-6.857-5.714-10.286-5.714-4.571-13.714-4.571h-125.714q-8 0-13.714 4.571-5.714 3.429-5.714 10.286l9.714 354.857q0 5.714 5.714 10t13.714 4.286h105.714q8 0 13.429-4.286t6-10z" 8 | ], 9 | "attrs": [], 10 | "isMulticolor": false, 11 | "tags": [ 12 | "exclamation-circle" 13 | ], 14 | "defaultCode": 61546, 15 | "grid": 14 16 | }, 17 | "attrs": [], 18 | "properties": { 19 | "id": 100, 20 | "order": 4, 21 | "prevSize": 28, 22 | "code": 58880, 23 | "name": "exclamation-sign", 24 | "ligatures": "" 25 | }, 26 | "setIdx": 0, 27 | "iconIdx": 0 28 | }, 29 | { 30 | "icon": { 31 | "paths": [ 32 | "M585.143 786.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-54.857v-292.571q0-8-5.143-13.143t-13.143-5.143h-182.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h54.857v182.857h-54.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h256q8 0 13.143-5.143t5.143-13.143zM512 274.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-109.714q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h109.714q8 0 13.143-5.143t5.143-13.143zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z" 33 | ], 34 | "attrs": [], 35 | "isMulticolor": false, 36 | "tags": [ 37 | "info-circle" 38 | ], 39 | "defaultCode": 61530, 40 | "grid": 14 41 | }, 42 | "attrs": [], 43 | "properties": { 44 | "id": 85, 45 | "order": 3, 46 | "name": "info-sign", 47 | "prevSize": 28, 48 | "code": 58882 49 | }, 50 | "setIdx": 0, 51 | "iconIdx": 2 52 | }, 53 | { 54 | "icon": { 55 | "paths": [ 56 | "M733.714 419.429q0-16-10.286-26.286l-52-51.429q-10.857-10.857-25.714-10.857t-25.714 10.857l-233.143 232.571-129.143-129.143q-10.857-10.857-25.714-10.857t-25.714 10.857l-52 51.429q-10.286 10.286-10.286 26.286 0 15.429 10.286 25.714l206.857 206.857q10.857 10.857 25.714 10.857 15.429 0 26.286-10.857l310.286-310.286q10.286-10.286 10.286-25.714zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z" 57 | ], 58 | "attrs": [], 59 | "isMulticolor": false, 60 | "tags": [ 61 | "check-circle" 62 | ], 63 | "defaultCode": 61528, 64 | "grid": 14 65 | }, 66 | "attrs": [], 67 | "properties": { 68 | "id": 83, 69 | "order": 9, 70 | "prevSize": 28, 71 | "code": 58886, 72 | "name": "ok-sign" 73 | }, 74 | "setIdx": 0, 75 | "iconIdx": 6 76 | }, 77 | { 78 | "icon": { 79 | "paths": [ 80 | "M658.286 475.429q0-105.714-75.143-180.857t-180.857-75.143-180.857 75.143-75.143 180.857 75.143 180.857 180.857 75.143 180.857-75.143 75.143-180.857zM950.857 950.857q0 29.714-21.714 51.429t-51.429 21.714q-30.857 0-51.429-21.714l-196-195.429q-102.286 70.857-228 70.857-81.714 0-156.286-31.714t-128.571-85.714-85.714-128.571-31.714-156.286 31.714-156.286 85.714-128.571 128.571-85.714 156.286-31.714 156.286 31.714 128.571 85.714 85.714 128.571 31.714 156.286q0 125.714-70.857 228l196 196q21.143 21.143 21.143 51.429z" 81 | ], 82 | "width": 951, 83 | "attrs": [], 84 | "isMulticolor": false, 85 | "tags": [ 86 | "search" 87 | ], 88 | "defaultCode": 61442, 89 | "grid": 14 90 | }, 91 | "attrs": [], 92 | "properties": { 93 | "id": 2, 94 | "order": 1, 95 | "prevSize": 28, 96 | "code": 58887, 97 | "name": "icon-search" 98 | }, 99 | "setIdx": 0, 100 | "iconIdx": 7 101 | } 102 | ], 103 | "height": 1024, 104 | "metadata": { 105 | "name": "slate", 106 | "license": "SIL OFL 1.1" 107 | }, 108 | "preferences": { 109 | "showGlyphs": true, 110 | "showQuickUse": true, 111 | "showQuickUse2": true, 112 | "showSVGs": true, 113 | "fontPref": { 114 | "prefix": "icon-", 115 | "metadata": { 116 | "fontFamily": "slate", 117 | "majorVersion": 1, 118 | "minorVersion": 0, 119 | "description": "Based on FontAwesome", 120 | "license": "SIL OFL 1.1" 121 | }, 122 | "metrics": { 123 | "emSize": 1024, 124 | "baseline": 6.25, 125 | "whitespace": 50 126 | }, 127 | "resetPoint": 58880, 128 | "showSelector": false, 129 | "selector": "class", 130 | "classSelector": ".icon", 131 | "showMetrics": false, 132 | "showMetadata": true, 133 | "showVersion": true, 134 | "ie7": false 135 | }, 136 | "imagePref": { 137 | "prefix": "icon-", 138 | "png": true, 139 | "useClassSelector": true, 140 | "color": 4473924, 141 | "bgColor": 16777215 142 | }, 143 | "historySize": 100, 144 | "showCodes": true, 145 | "gridSize": 16, 146 | "showLiga": false 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/monokai_sublime_slate.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- # 2 | # frozen_string_literal: true 3 | 4 | # this is based on https://github.com/rouge-ruby/rouge/blob/master/lib/rouge/themes/monokai_sublime.rb 5 | # but without the added background, and changed styling for JSON keys to be soft_yellow instead of white 6 | 7 | module Rouge 8 | module Themes 9 | class MonokaiSublimeSlate < CSSTheme 10 | name 'monokai.sublime.slate' 11 | 12 | palette :black => '#000000' 13 | palette :bright_green => '#a6e22e' 14 | palette :bright_pink => '#f92672' 15 | palette :carmine => '#960050' 16 | palette :dark => '#49483e' 17 | palette :dark_grey => '#888888' 18 | palette :dark_red => '#aa0000' 19 | palette :dimgrey => '#75715e' 20 | palette :emperor => '#555555' 21 | palette :grey => '#999999' 22 | palette :light_grey => '#aaaaaa' 23 | palette :light_violet => '#ae81ff' 24 | palette :soft_cyan => '#66d9ef' 25 | palette :soft_yellow => '#e6db74' 26 | palette :very_dark => '#1e0010' 27 | palette :whitish => '#f8f8f2' 28 | palette :orange => '#f6aa11' 29 | palette :white => '#ffffff' 30 | 31 | style Generic::Heading, :fg => :grey 32 | style Literal::String::Regex, :fg => :orange 33 | style Generic::Output, :fg => :dark_grey 34 | style Generic::Prompt, :fg => :emperor 35 | style Generic::Strong, :bold => false 36 | style Generic::Subheading, :fg => :light_grey 37 | style Name::Builtin, :fg => :orange 38 | style Comment::Multiline, 39 | Comment::Preproc, 40 | Comment::Single, 41 | Comment::Special, 42 | Comment, :fg => :dimgrey 43 | style Error, 44 | Generic::Error, 45 | Generic::Traceback, :fg => :carmine 46 | style Generic::Deleted, 47 | Generic::Inserted, 48 | Generic::Emph, :fg => :dark 49 | style Keyword::Constant, 50 | Keyword::Declaration, 51 | Keyword::Reserved, 52 | Name::Constant, 53 | Keyword::Type, :fg => :soft_cyan 54 | style Literal::Number::Float, 55 | Literal::Number::Hex, 56 | Literal::Number::Integer::Long, 57 | Literal::Number::Integer, 58 | Literal::Number::Oct, 59 | Literal::Number, 60 | Literal::String::Char, 61 | Literal::String::Escape, 62 | Literal::String::Symbol, :fg => :light_violet 63 | style Literal::String::Doc, 64 | Literal::String::Double, 65 | Literal::String::Backtick, 66 | Literal::String::Heredoc, 67 | Literal::String::Interpol, 68 | Literal::String::Other, 69 | Literal::String::Single, 70 | Literal::String, :fg => :soft_yellow 71 | style Name::Attribute, 72 | Name::Class, 73 | Name::Decorator, 74 | Name::Exception, 75 | Name::Function, :fg => :bright_green 76 | style Name::Variable::Class, 77 | Name::Namespace, 78 | Name::Entity, 79 | Name::Builtin::Pseudo, 80 | Name::Variable::Global, 81 | Name::Variable::Instance, 82 | Name::Variable, 83 | Text::Whitespace, 84 | Text, 85 | Name, :fg => :white 86 | style Name::Label, :fg => :bright_pink 87 | style Operator::Word, 88 | Name::Tag, 89 | Keyword, 90 | Keyword::Namespace, 91 | Keyword::Pseudo, 92 | Operator, :fg => :bright_pink 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/multilang.rb: -------------------------------------------------------------------------------- 1 | module Multilang 2 | def block_code(code, full_lang_name) 3 | if full_lang_name 4 | parts = full_lang_name.split('--') 5 | rouge_lang_name = (parts) ? parts[0] : "" # just parts[0] here causes null ref exception when no language specified 6 | super(code, rouge_lang_name).sub("highlight #{rouge_lang_name}") do |match| 7 | match + " tab-" + full_lang_name 8 | end 9 | else 10 | super(code, full_lang_name) 11 | end 12 | end 13 | end 14 | 15 | require 'middleman-core/renderers/redcarpet' 16 | Middleman::Renderers::MiddlemanRedcarpetHTML.send :include, Multilang 17 | -------------------------------------------------------------------------------- /lib/nesting_unique_head.rb: -------------------------------------------------------------------------------- 1 | # Nested unique header generation 2 | require 'middleman-core/renderers/redcarpet' 3 | 4 | class NestingUniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML 5 | def initialize 6 | super 7 | @@headers_history = {} if !defined?(@@headers_history) 8 | end 9 | 10 | def header(text, header_level) 11 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize 12 | @@headers_history[header_level] = text.parameterize 13 | 14 | if header_level > 1 15 | for i in (header_level - 1).downto(1) 16 | friendly_text.prepend("#{@@headers_history[i]}-") if @@headers_history.key?(i) 17 | end 18 | end 19 | 20 | return "#{text}" 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/toc_data.rb: -------------------------------------------------------------------------------- 1 | require 'nokogiri' 2 | 3 | def toc_data(page_content) 4 | html_doc = Nokogiri::HTML::DocumentFragment.parse(page_content) 5 | 6 | # get a flat list of headers 7 | headers = [] 8 | html_doc.css('h1, h2, h3').each do |header| 9 | headers.push({ 10 | id: header.attribute('id').to_s, 11 | content: header.children, 12 | title: header.children.to_s.gsub(/<[^>]*>/, ''), 13 | level: header.name[1].to_i, 14 | children: [] 15 | }) 16 | end 17 | 18 | [3,2].each do |header_level| 19 | header_to_nest = nil 20 | headers = headers.reject do |header| 21 | if header[:level] == header_level 22 | header_to_nest[:children].push header if header_to_nest 23 | true 24 | else 25 | header_to_nest = header if header[:level] < header_level 26 | false 27 | end 28 | end 29 | end 30 | headers 31 | end 32 | -------------------------------------------------------------------------------- /lib/unique_head.rb: -------------------------------------------------------------------------------- 1 | # Unique header generation 2 | require 'middleman-core/renderers/redcarpet' 3 | require 'digest' 4 | class UniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML 5 | def initialize 6 | super 7 | @head_count = {} 8 | end 9 | def header(text, header_level) 10 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize 11 | if friendly_text.strip.length == 0 12 | # Looks like parameterize removed the whole thing! It removes many unicode 13 | # characters like Chinese and Russian. To get a unique URL, let's just 14 | # URI escape the whole header 15 | friendly_text = Digest::SHA1.hexdigest(text)[0,10] 16 | end 17 | @head_count[friendly_text] ||= 0 18 | @head_count[friendly_text] += 1 19 | if @head_count[friendly_text] > 1 20 | friendly_text += "-#{@head_count[friendly_text]}" 21 | end 22 | return "#{text}" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /slate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit #abort if any command fails 3 | 4 | me=$(basename "$0") 5 | 6 | help_message="\ 7 | Usage: $me [] [] 8 | Run commands related to the slate process. 9 | 10 | Commands: 11 | 12 | serve Run the middleman server process, useful for 13 | development. 14 | build Run the build process. 15 | deploy Will build and deploy files to branch. Use 16 | --no-build to only deploy. 17 | 18 | Global Options: 19 | 20 | -h, --help Show this help information. 21 | -v, --verbose Increase verbosity. Useful for debugging. 22 | 23 | Deploy options: 24 | -e, --allow-empty Allow deployment of an empty directory. 25 | -m, --message MESSAGE Specify the message used when committing on the 26 | deploy branch. 27 | -n, --no-hash Don't append the source commit's hash to the deploy 28 | commit's message. 29 | --no-build Do not build the source files. 30 | " 31 | 32 | 33 | run_serve() { 34 | exec bundle exec middleman serve --watcher-force-polling 35 | } 36 | 37 | run_build() { 38 | bundle exec middleman build --clean --watcher-disable 39 | } 40 | 41 | parse_args() { 42 | # Set args from a local environment file. 43 | if [ -e ".env" ]; then 44 | source .env 45 | fi 46 | 47 | command= 48 | 49 | # Parse arg flags 50 | # If something is exposed as an environment variable, set/overwrite it 51 | # here. Otherwise, set/overwrite the internal variable instead. 52 | while : ; do 53 | if [[ $1 = "-h" || $1 = "--help" ]]; then 54 | echo "$help_message" 55 | exit 0 56 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then 57 | verbose=true 58 | shift 59 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then 60 | allow_empty=true 61 | shift 62 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then 63 | commit_message=$2 64 | shift 2 65 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then 66 | GIT_DEPLOY_APPEND_HASH=false 67 | shift 68 | elif [[ $1 = "--no-build" ]]; then 69 | no_build=true 70 | shift 71 | elif [[ $1 = "serve" || $1 = "build" || $1 = "deploy" ]]; then 72 | if [ ! -z "${command}" ]; then 73 | >&2 echo "You can only specify one command." 74 | exit 1 75 | fi 76 | command=$1 77 | shift 78 | elif [ -z $1 ]; then 79 | break 80 | fi 81 | done 82 | 83 | if [ -z "${command}" ]; then 84 | >&2 echo "Command not specified." 85 | exit 1 86 | fi 87 | 88 | # Set internal option vars from the environment and arg flags. All internal 89 | # vars should be declared here, with sane defaults if applicable. 90 | 91 | # Source directory & target branch. 92 | deploy_directory=build 93 | deploy_branch=gh-pages 94 | 95 | #if no user identity is already set in the current git environment, use this: 96 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh} 97 | default_email=${GIT_DEPLOY_EMAIL:-} 98 | 99 | #repository to deploy to. must be readable and writable. 100 | repo=origin 101 | 102 | #append commit hash to the end of message by default 103 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true} 104 | } 105 | 106 | main() { 107 | enable_expanded_output 108 | 109 | if ! git diff --exit-code --quiet --cached; then 110 | echo Aborting due to uncommitted changes in the index >&2 111 | return 1 112 | fi 113 | 114 | commit_title=`git log -n 1 --format="%s" HEAD` 115 | commit_hash=` git log -n 1 --format="%H" HEAD` 116 | 117 | #default commit message uses last title if a custom one is not supplied 118 | if [[ -z $commit_message ]]; then 119 | commit_message="publish: $commit_title" 120 | fi 121 | 122 | #append hash to commit message unless no hash flag was found 123 | if [ $append_hash = true ]; then 124 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash" 125 | fi 126 | 127 | previous_branch=`git rev-parse --abbrev-ref HEAD` 128 | 129 | if [ ! -d "$deploy_directory" ]; then 130 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2 131 | return 1 132 | fi 133 | 134 | # must use short form of flag in ls for compatibility with macOS and BSD 135 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then 136 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2 137 | return 1 138 | fi 139 | 140 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then 141 | # deploy_branch exists in $repo; make sure we have the latest version 142 | 143 | disable_expanded_output 144 | git fetch --force $repo $deploy_branch:$deploy_branch 145 | enable_expanded_output 146 | fi 147 | 148 | # check if deploy_branch exists locally 149 | if git show-ref --verify --quiet "refs/heads/$deploy_branch" 150 | then incremental_deploy 151 | else initial_deploy 152 | fi 153 | 154 | restore_head 155 | } 156 | 157 | initial_deploy() { 158 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch 159 | git --work-tree "$deploy_directory" add --all 160 | commit+push 161 | } 162 | 163 | incremental_deploy() { 164 | #make deploy_branch the current branch 165 | git symbolic-ref HEAD refs/heads/$deploy_branch 166 | #put the previously committed contents of deploy_branch into the index 167 | git --work-tree "$deploy_directory" reset --mixed --quiet 168 | git --work-tree "$deploy_directory" add --all 169 | 170 | set +o errexit 171 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$? 172 | set -o errexit 173 | case $diff in 174 | 0) echo No changes to files in $deploy_directory. Skipping commit.;; 175 | 1) commit+push;; 176 | *) 177 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to main, use: git symbolic-ref HEAD refs/heads/main && git reset --mixed >&2 178 | return $diff 179 | ;; 180 | esac 181 | } 182 | 183 | commit+push() { 184 | set_user_id 185 | git --work-tree "$deploy_directory" commit -m "$commit_message" 186 | 187 | disable_expanded_output 188 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token 189 | git push --quiet $repo $deploy_branch 190 | enable_expanded_output 191 | } 192 | 193 | #echo expanded commands as they are executed (for debugging) 194 | enable_expanded_output() { 195 | if [ $verbose ]; then 196 | set -o xtrace 197 | set +o verbose 198 | fi 199 | } 200 | 201 | #this is used to avoid outputting the repo URL, which may contain a secret token 202 | disable_expanded_output() { 203 | if [ $verbose ]; then 204 | set +o xtrace 205 | set -o verbose 206 | fi 207 | } 208 | 209 | set_user_id() { 210 | if [[ -z `git config user.name` ]]; then 211 | git config user.name "$default_username" 212 | fi 213 | if [[ -z `git config user.email` ]]; then 214 | git config user.email "$default_email" 215 | fi 216 | } 217 | 218 | restore_head() { 219 | if [[ $previous_branch = "HEAD" ]]; then 220 | #we weren't on any branch before, so just set HEAD back to the commit it was on 221 | git update-ref --no-deref HEAD $commit_hash $deploy_branch 222 | else 223 | git symbolic-ref HEAD refs/heads/$previous_branch 224 | fi 225 | 226 | git reset --mixed 227 | } 228 | 229 | filter() { 230 | sed -e "s|$repo|\$repo|g" 231 | } 232 | 233 | sanitize() { 234 | "$@" 2> >(filter 1>&2) | filter 235 | } 236 | 237 | parse_args "$@" 238 | 239 | if [ "${command}" = "serve" ]; then 240 | run_serve 241 | elif [[ "${command}" = "build" ]]; then 242 | run_build 243 | elif [[ ${command} = "deploy" ]]; then 244 | if [[ ${no_build} != true ]]; then 245 | run_build 246 | fi 247 | main "$@" 248 | fi 249 | -------------------------------------------------------------------------------- /source/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slatedocs/slate/97c8dd4cc9c75bf04e67a21d683d139a58326db2/source/fonts/slate.eot -------------------------------------------------------------------------------- /source/fonts/slate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /source/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slatedocs/slate/97c8dd4cc9c75bf04e67a21d683d139a58326db2/source/fonts/slate.ttf -------------------------------------------------------------------------------- /source/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slatedocs/slate/97c8dd4cc9c75bf04e67a21d683d139a58326db2/source/fonts/slate.woff -------------------------------------------------------------------------------- /source/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slatedocs/slate/97c8dd4cc9c75bf04e67a21d683d139a58326db2/source/fonts/slate.woff2 -------------------------------------------------------------------------------- /source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slatedocs/slate/97c8dd4cc9c75bf04e67a21d683d139a58326db2/source/images/logo.png -------------------------------------------------------------------------------- /source/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slatedocs/slate/97c8dd4cc9c75bf04e67a21d683d139a58326db2/source/images/navbar.png -------------------------------------------------------------------------------- /source/includes/_errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | 6 | 7 | The Kittn API uses the following error codes: 8 | 9 | 10 | Error Code | Meaning 11 | ---------- | ------- 12 | 400 | Bad Request -- Your request is invalid. 13 | 401 | Unauthorized -- Your API key is wrong. 14 | 403 | Forbidden -- The kitten requested is hidden for administrators only. 15 | 404 | Not Found -- The specified kitten could not be found. 16 | 405 | Method Not Allowed -- You tried to access a kitten with an invalid method. 17 | 406 | Not Acceptable -- You requested a format that isn't json. 18 | 410 | Gone -- The kitten requested has been removed from our servers. 19 | 418 | I'm a teapot. 20 | 429 | Too Many Requests -- You're requesting too many kittens! Slow down! 21 | 500 | Internal Server Error -- We had a problem with our server. Try again later. 22 | 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. 23 | -------------------------------------------------------------------------------- /source/index.html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: API Reference 3 | 4 | language_tabs: # must be one of https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers 5 | - shell 6 | - ruby 7 | - python 8 | - javascript 9 | 10 | toc_footers: 11 | - Sign Up for a Developer Key 12 | - Documentation Powered by Slate 13 | 14 | includes: 15 | - errors 16 | 17 | search: true 18 | 19 | code_clipboard: true 20 | 21 | meta: 22 | - name: description 23 | content: Documentation for the Kittn API 24 | --- 25 | 26 | # Introduction 27 | 28 | Welcome to the Kittn API! You can use our API to access Kittn API endpoints, which can get information on various cats, kittens, and breeds in our database. 29 | 30 | We have language bindings in Shell, Ruby, Python, and JavaScript! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right. 31 | 32 | This example API documentation page was created with [Slate](https://github.com/slatedocs/slate). Feel free to edit it and use it as a base for your own API's documentation. 33 | 34 | # Authentication 35 | 36 | > To authorize, use this code: 37 | 38 | ```ruby 39 | require 'kittn' 40 | 41 | api = Kittn::APIClient.authorize!('meowmeowmeow') 42 | ``` 43 | 44 | ```python 45 | import kittn 46 | 47 | api = kittn.authorize('meowmeowmeow') 48 | ``` 49 | 50 | ```shell 51 | # With shell, you can just pass the correct header with each request 52 | curl "api_endpoint_here" \ 53 | -H "Authorization: meowmeowmeow" 54 | ``` 55 | 56 | ```javascript 57 | const kittn = require('kittn'); 58 | 59 | let api = kittn.authorize('meowmeowmeow'); 60 | ``` 61 | 62 | > Make sure to replace `meowmeowmeow` with your API key. 63 | 64 | Kittn uses API keys to allow access to the API. You can register a new Kittn API key at our [developer portal](http://example.com/developers). 65 | 66 | Kittn expects for the API key to be included in all API requests to the server in a header that looks like the following: 67 | 68 | `Authorization: meowmeowmeow` 69 | 70 | 73 | 74 | # Kittens 75 | 76 | ## Get All Kittens 77 | 78 | ```ruby 79 | require 'kittn' 80 | 81 | api = Kittn::APIClient.authorize!('meowmeowmeow') 82 | api.kittens.get 83 | ``` 84 | 85 | ```python 86 | import kittn 87 | 88 | api = kittn.authorize('meowmeowmeow') 89 | api.kittens.get() 90 | ``` 91 | 92 | ```shell 93 | curl "http://example.com/api/kittens" \ 94 | -H "Authorization: meowmeowmeow" 95 | ``` 96 | 97 | ```javascript 98 | const kittn = require('kittn'); 99 | 100 | let api = kittn.authorize('meowmeowmeow'); 101 | let kittens = api.kittens.get(); 102 | ``` 103 | 104 | > The above command returns JSON structured like this: 105 | 106 | ```json 107 | [ 108 | { 109 | "id": 1, 110 | "name": "Fluffums", 111 | "breed": "calico", 112 | "fluffiness": 6, 113 | "cuteness": 7 114 | }, 115 | { 116 | "id": 2, 117 | "name": "Max", 118 | "breed": "unknown", 119 | "fluffiness": 5, 120 | "cuteness": 10 121 | } 122 | ] 123 | ``` 124 | 125 | This endpoint retrieves all kittens. 126 | 127 | ### HTTP Request 128 | 129 | `GET http://example.com/api/kittens` 130 | 131 | ### Query Parameters 132 | 133 | Parameter | Default | Description 134 | --------- | ------- | ----------- 135 | include_cats | false | If set to true, the result will also include cats. 136 | available | true | If set to false, the result will include kittens that have already been adopted. 137 | 138 | 141 | 142 | ## Get a Specific Kitten 143 | 144 | ```ruby 145 | require 'kittn' 146 | 147 | api = Kittn::APIClient.authorize!('meowmeowmeow') 148 | api.kittens.get(2) 149 | ``` 150 | 151 | ```python 152 | import kittn 153 | 154 | api = kittn.authorize('meowmeowmeow') 155 | api.kittens.get(2) 156 | ``` 157 | 158 | ```shell 159 | curl "http://example.com/api/kittens/2" \ 160 | -H "Authorization: meowmeowmeow" 161 | ``` 162 | 163 | ```javascript 164 | const kittn = require('kittn'); 165 | 166 | let api = kittn.authorize('meowmeowmeow'); 167 | let max = api.kittens.get(2); 168 | ``` 169 | 170 | > The above command returns JSON structured like this: 171 | 172 | ```json 173 | { 174 | "id": 2, 175 | "name": "Max", 176 | "breed": "unknown", 177 | "fluffiness": 5, 178 | "cuteness": 10 179 | } 180 | ``` 181 | 182 | This endpoint retrieves a specific kitten. 183 | 184 | 185 | 186 | ### HTTP Request 187 | 188 | `GET http://example.com/kittens/` 189 | 190 | ### URL Parameters 191 | 192 | Parameter | Description 193 | --------- | ----------- 194 | ID | The ID of the kitten to retrieve 195 | 196 | ## Delete a Specific Kitten 197 | 198 | ```ruby 199 | require 'kittn' 200 | 201 | api = Kittn::APIClient.authorize!('meowmeowmeow') 202 | api.kittens.delete(2) 203 | ``` 204 | 205 | ```python 206 | import kittn 207 | 208 | api = kittn.authorize('meowmeowmeow') 209 | api.kittens.delete(2) 210 | ``` 211 | 212 | ```shell 213 | curl "http://example.com/api/kittens/2" \ 214 | -X DELETE \ 215 | -H "Authorization: meowmeowmeow" 216 | ``` 217 | 218 | ```javascript 219 | const kittn = require('kittn'); 220 | 221 | let api = kittn.authorize('meowmeowmeow'); 222 | let max = api.kittens.delete(2); 223 | ``` 224 | 225 | > The above command returns JSON structured like this: 226 | 227 | ```json 228 | { 229 | "id": 2, 230 | "deleted" : ":(" 231 | } 232 | ``` 233 | 234 | This endpoint deletes a specific kitten. 235 | 236 | ### HTTP Request 237 | 238 | `DELETE http://example.com/kittens/` 239 | 240 | ### URL Parameters 241 | 242 | Parameter | Description 243 | --------- | ----------- 244 | ID | The ID of the kitten to delete 245 | 246 | -------------------------------------------------------------------------------- /source/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require ./all_nosearch 2 | //= require ./app/_search 3 | -------------------------------------------------------------------------------- /source/javascripts/all_nosearch.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_copy 3 | //= require ./app/_toc 4 | //= require ./app/_lang 5 | 6 | function adjustLanguageSelectorWidth() { 7 | const elem = $('.dark-box > .lang-selector'); 8 | elem.width(elem.parent().width()); 9 | } 10 | 11 | $(function() { 12 | loadToc($('#toc'), '.toc-link', '.toc-list-h2', 10); 13 | setupLanguages($('body').data('languages')); 14 | $('.content').imagesLoaded( function() { 15 | window.recacheHeights(); 16 | window.refreshToc(); 17 | }); 18 | 19 | $(window).resize(function() { 20 | adjustLanguageSelectorWidth(); 21 | }); 22 | adjustLanguageSelectorWidth(); 23 | }); 24 | 25 | window.onpopstate = function() { 26 | activateLanguage(getLanguageFromQueryString()); 27 | }; 28 | -------------------------------------------------------------------------------- /source/javascripts/app/_copy.js: -------------------------------------------------------------------------------- 1 | function copyToClipboard(container) { 2 | const el = document.createElement('textarea'); 3 | el.value = container.textContent.replace(/\n$/, ''); 4 | document.body.appendChild(el); 5 | el.select(); 6 | document.execCommand('copy'); 7 | document.body.removeChild(el); 8 | } 9 | 10 | function setupCodeCopy() { 11 | $('pre.highlight').prepend('
Copy to Clipboard
'); 12 | $('.copy-clipboard').on('click', function() { 13 | copyToClipboard(this.parentNode.children[1]); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /source/javascripts/app/_lang.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | 3 | /* 4 | Copyright 2008-2013 Concur Technologies, Inc. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); you may 7 | not use this file except in compliance with the License. You may obtain 8 | a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | License for the specific language governing permissions and limitations 16 | under the License. 17 | */ 18 | ;(function () { 19 | 'use strict'; 20 | 21 | var languages = []; 22 | 23 | window.setupLanguages = setupLanguages; 24 | window.activateLanguage = activateLanguage; 25 | window.getLanguageFromQueryString = getLanguageFromQueryString; 26 | 27 | function activateLanguage(language) { 28 | if (!language) return; 29 | if (language === "") return; 30 | 31 | $(".lang-selector a").removeClass('active'); 32 | $(".lang-selector a[data-language-name='" + language + "']").addClass('active'); 33 | for (var i=0; i < languages.length; i++) { 34 | $(".highlight.tab-" + languages[i]).hide(); 35 | $(".lang-specific." + languages[i]).hide(); 36 | } 37 | $(".highlight.tab-" + language).show(); 38 | $(".lang-specific." + language).show(); 39 | 40 | window.recacheHeights(); 41 | 42 | // scroll to the new location of the position 43 | if ($(window.location.hash).get(0)) { 44 | $(window.location.hash).get(0).scrollIntoView(true); 45 | } 46 | } 47 | 48 | // parseURL and stringifyURL are from https://github.com/sindresorhus/query-string 49 | // MIT licensed 50 | // https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license 51 | function parseURL(str) { 52 | if (typeof str !== 'string') { 53 | return {}; 54 | } 55 | 56 | str = str.trim().replace(/^(\?|#|&)/, ''); 57 | 58 | if (!str) { 59 | return {}; 60 | } 61 | 62 | return str.split('&').reduce(function (ret, param) { 63 | var parts = param.replace(/\+/g, ' ').split('='); 64 | var key = parts[0]; 65 | var val = parts[1]; 66 | 67 | key = decodeURIComponent(key); 68 | // missing `=` should be `null`: 69 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 70 | val = val === undefined ? null : decodeURIComponent(val); 71 | 72 | if (!ret.hasOwnProperty(key)) { 73 | ret[key] = val; 74 | } else if (Array.isArray(ret[key])) { 75 | ret[key].push(val); 76 | } else { 77 | ret[key] = [ret[key], val]; 78 | } 79 | 80 | return ret; 81 | }, {}); 82 | }; 83 | 84 | function stringifyURL(obj) { 85 | return obj ? Object.keys(obj).sort().map(function (key) { 86 | var val = obj[key]; 87 | 88 | if (Array.isArray(val)) { 89 | return val.sort().map(function (val2) { 90 | return encodeURIComponent(key) + '=' + encodeURIComponent(val2); 91 | }).join('&'); 92 | } 93 | 94 | return encodeURIComponent(key) + '=' + encodeURIComponent(val); 95 | }).join('&') : ''; 96 | }; 97 | 98 | // gets the language set in the query string 99 | function getLanguageFromQueryString() { 100 | if (location.search.length >= 1) { 101 | var language = parseURL(location.search).language; 102 | if (language) { 103 | return language; 104 | } else if (jQuery.inArray(location.search.substr(1), languages) != -1) { 105 | return location.search.substr(1); 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | 112 | // returns a new query string with the new language in it 113 | function generateNewQueryString(language) { 114 | var url = parseURL(location.search); 115 | if (url.language) { 116 | url.language = language; 117 | return stringifyURL(url); 118 | } 119 | return language; 120 | } 121 | 122 | // if a button is clicked, add the state to the history 123 | function pushURL(language) { 124 | if (!history) { return; } 125 | var hash = window.location.hash; 126 | if (hash) { 127 | hash = hash.replace(/^#+/, ''); 128 | } 129 | history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash); 130 | 131 | // save language as next default 132 | if (localStorage) { 133 | localStorage.setItem("language", language); 134 | } 135 | } 136 | 137 | function setupLanguages(l) { 138 | var defaultLanguage = null; 139 | if (localStorage) { 140 | defaultLanguage = localStorage.getItem("language"); 141 | } 142 | 143 | languages = l; 144 | 145 | var presetLanguage = getLanguageFromQueryString(); 146 | if (presetLanguage && languages.includes(presetLanguage)) { 147 | // the language is in the URL, so use that language! 148 | activateLanguage(presetLanguage); 149 | 150 | if (localStorage) { 151 | localStorage.setItem("language", presetLanguage); 152 | } 153 | } else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) { 154 | // the language was the last selected one saved in localstorage, so use that language! 155 | activateLanguage(defaultLanguage); 156 | } else { 157 | // no language selected, so use the default 158 | activateLanguage(languages[0]); 159 | } 160 | } 161 | 162 | // if we click on a language tab, activate that language 163 | $(function() { 164 | $(".lang-selector a").on("click", function() { 165 | var language = $(this).data("language-name"); 166 | pushURL(language); 167 | activateLanguage(language); 168 | return false; 169 | }); 170 | }); 171 | })(); 172 | -------------------------------------------------------------------------------- /source/javascripts/app/_search.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_lunr 2 | //= require ../lib/_jquery 3 | //= require ../lib/_jquery.highlight 4 | ;(function () { 5 | 'use strict'; 6 | 7 | var content, searchResults; 8 | var highlightOpts = { element: 'span', className: 'search-highlight' }; 9 | var searchDelay = 0; 10 | var timeoutHandle = 0; 11 | var index; 12 | 13 | function populate() { 14 | index = lunr(function(){ 15 | 16 | this.ref('id'); 17 | this.field('title', { boost: 10 }); 18 | this.field('body'); 19 | this.pipeline.add(lunr.trimmer, lunr.stopWordFilter); 20 | var lunrConfig = this; 21 | 22 | $('h1, h2').each(function() { 23 | var title = $(this); 24 | var body = title.nextUntil('h1, h2'); 25 | lunrConfig.add({ 26 | id: title.prop('id'), 27 | title: title.text(), 28 | body: body.text() 29 | }); 30 | }); 31 | 32 | }); 33 | determineSearchDelay(); 34 | } 35 | 36 | $(populate); 37 | $(bind); 38 | 39 | function determineSearchDelay() { 40 | if (index.tokenSet.toArray().length>5000) { 41 | searchDelay = 300; 42 | } 43 | } 44 | 45 | function bind() { 46 | content = $('.content'); 47 | searchResults = $('.search-results'); 48 | 49 | $('#input-search').on('keyup',function(e) { 50 | var wait = function() { 51 | return function(executingFunction, waitTime){ 52 | clearTimeout(timeoutHandle); 53 | timeoutHandle = setTimeout(executingFunction, waitTime); 54 | }; 55 | }(); 56 | wait(function(){ 57 | search(e); 58 | }, searchDelay); 59 | }); 60 | } 61 | 62 | function search(event) { 63 | 64 | var searchInput = $('#input-search')[0]; 65 | 66 | unhighlight(); 67 | searchResults.addClass('visible'); 68 | 69 | // ESC clears the field 70 | if (event.keyCode === 27) searchInput.value = ''; 71 | 72 | if (searchInput.value) { 73 | var results = index.search(searchInput.value).filter(function(r) { 74 | return r.score > 0.0001; 75 | }); 76 | 77 | if (results.length) { 78 | searchResults.empty(); 79 | $.each(results, function (index, result) { 80 | var elem = document.getElementById(result.ref); 81 | searchResults.append("
  • " + $(elem).text() + "
  • "); 82 | }); 83 | highlight.call(searchInput); 84 | } else { 85 | searchResults.html('
  • '); 86 | $('.search-results li').text('No Results Found for "' + searchInput.value + '"'); 87 | } 88 | } else { 89 | unhighlight(); 90 | searchResults.removeClass('visible'); 91 | } 92 | } 93 | 94 | function highlight() { 95 | if (this.value) content.highlight(this.value, highlightOpts); 96 | } 97 | 98 | function unhighlight() { 99 | content.unhighlight(highlightOpts); 100 | } 101 | })(); 102 | 103 | -------------------------------------------------------------------------------- /source/javascripts/app/_toc.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | //= require ../lib/_imagesloaded.min 3 | ;(function () { 4 | 'use strict'; 5 | 6 | var htmlPattern = /<[^>]*>/g; 7 | var loaded = false; 8 | 9 | var debounce = function(func, waitTime) { 10 | var timeout = false; 11 | return function() { 12 | if (timeout === false) { 13 | setTimeout(function() { 14 | func(); 15 | timeout = false; 16 | }, waitTime); 17 | timeout = true; 18 | } 19 | }; 20 | }; 21 | 22 | var closeToc = function() { 23 | $(".toc-wrapper").removeClass('open'); 24 | $("#nav-button").removeClass('open'); 25 | }; 26 | 27 | function loadToc($toc, tocLinkSelector, tocListSelector, scrollOffset) { 28 | var headerHeights = {}; 29 | var pageHeight = 0; 30 | var windowHeight = 0; 31 | var originalTitle = document.title; 32 | 33 | var recacheHeights = function() { 34 | headerHeights = {}; 35 | pageHeight = $(document).height(); 36 | windowHeight = $(window).height(); 37 | 38 | $toc.find(tocLinkSelector).each(function() { 39 | var targetId = $(this).attr('href'); 40 | if (targetId[0] === "#") { 41 | headerHeights[targetId] = $("#" + $.escapeSelector(targetId.substring(1))).offset().top; 42 | } 43 | }); 44 | }; 45 | 46 | var refreshToc = function() { 47 | var currentTop = $(document).scrollTop() + scrollOffset; 48 | 49 | if (currentTop + windowHeight >= pageHeight) { 50 | // at bottom of page, so just select last header by making currentTop very large 51 | // this fixes the problem where the last header won't ever show as active if its content 52 | // is shorter than the window height 53 | currentTop = pageHeight + 1000; 54 | } 55 | 56 | var best = null; 57 | for (var name in headerHeights) { 58 | if ((headerHeights[name] < currentTop && headerHeights[name] > headerHeights[best]) || best === null) { 59 | best = name; 60 | } 61 | } 62 | 63 | // Catch the initial load case 64 | if (currentTop == scrollOffset && !loaded) { 65 | best = window.location.hash; 66 | loaded = true; 67 | } 68 | 69 | var $best = $toc.find("[href='" + best + "']").first(); 70 | if (!$best.hasClass("active")) { 71 | // .active is applied to the ToC link we're currently on, and its parent
      s selected by tocListSelector 72 | // .active-expanded is applied to the ToC links that are parents of this one 73 | $toc.find(".active").removeClass("active"); 74 | $toc.find(".active-parent").removeClass("active-parent"); 75 | $best.addClass("active"); 76 | $best.parents(tocListSelector).addClass("active").siblings(tocLinkSelector).addClass('active-parent'); 77 | $best.siblings(tocListSelector).addClass("active"); 78 | $toc.find(tocListSelector).filter(":not(.active)").slideUp(150); 79 | $toc.find(tocListSelector).filter(".active").slideDown(150); 80 | if (window.history.replaceState) { 81 | window.history.replaceState(null, "", best); 82 | } 83 | var thisTitle = $best.data("title"); 84 | if (thisTitle !== undefined && thisTitle.length > 0) { 85 | document.title = thisTitle.replace(htmlPattern, "") + " – " + originalTitle; 86 | } else { 87 | document.title = originalTitle; 88 | } 89 | } 90 | }; 91 | 92 | var makeToc = function() { 93 | recacheHeights(); 94 | refreshToc(); 95 | 96 | $("#nav-button").click(function() { 97 | $(".toc-wrapper").toggleClass('open'); 98 | $("#nav-button").toggleClass('open'); 99 | return false; 100 | }); 101 | $(".page-wrapper").click(closeToc); 102 | $(".toc-link").click(closeToc); 103 | 104 | // reload immediately after scrolling on toc click 105 | $toc.find(tocLinkSelector).click(function() { 106 | setTimeout(function() { 107 | refreshToc(); 108 | }, 0); 109 | }); 110 | 111 | $(window).scroll(debounce(refreshToc, 200)); 112 | $(window).resize(debounce(recacheHeights, 200)); 113 | }; 114 | 115 | makeToc(); 116 | 117 | window.recacheHeights = recacheHeights; 118 | window.refreshToc = refreshToc; 119 | } 120 | 121 | window.loadToc = loadToc; 122 | })(); 123 | -------------------------------------------------------------------------------- /source/javascripts/lib/_energize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * energize.js v0.1.0 3 | * 4 | * Speeds up click events on mobile devices. 5 | * https://github.com/davidcalhoun/energize.js 6 | */ 7 | 8 | (function() { // Sandbox 9 | /** 10 | * Don't add to non-touch devices, which don't need to be sped up 11 | */ 12 | if(!('ontouchstart' in window)) return; 13 | 14 | var lastClick = {}, 15 | isThresholdReached, touchstart, touchmove, touchend, 16 | click, closest; 17 | 18 | /** 19 | * isThresholdReached 20 | * 21 | * Compare touchstart with touchend xy coordinates, 22 | * and only fire simulated click event if the coordinates 23 | * are nearby. (don't want clicking to be confused with a swipe) 24 | */ 25 | isThresholdReached = function(startXY, xy) { 26 | return Math.abs(startXY[0] - xy[0]) > 5 || Math.abs(startXY[1] - xy[1]) > 5; 27 | }; 28 | 29 | /** 30 | * touchstart 31 | * 32 | * Save xy coordinates when the user starts touching the screen 33 | */ 34 | touchstart = function(e) { 35 | this.startXY = [e.touches[0].clientX, e.touches[0].clientY]; 36 | this.threshold = false; 37 | }; 38 | 39 | /** 40 | * touchmove 41 | * 42 | * Check if the user is scrolling past the threshold. 43 | * Have to check here because touchend will not always fire 44 | * on some tested devices (Kindle Fire?) 45 | */ 46 | touchmove = function(e) { 47 | // NOOP if the threshold has already been reached 48 | if(this.threshold) return false; 49 | 50 | this.threshold = isThresholdReached(this.startXY, [e.touches[0].clientX, e.touches[0].clientY]); 51 | }; 52 | 53 | /** 54 | * touchend 55 | * 56 | * If the user didn't scroll past the threshold between 57 | * touchstart and touchend, fire a simulated click. 58 | * 59 | * (This will fire before a native click) 60 | */ 61 | touchend = function(e) { 62 | // Don't fire a click if the user scrolled past the threshold 63 | if(this.threshold || isThresholdReached(this.startXY, [e.changedTouches[0].clientX, e.changedTouches[0].clientY])) { 64 | return; 65 | } 66 | 67 | /** 68 | * Create and fire a click event on the target element 69 | * https://developer.mozilla.org/en/DOM/event.initMouseEvent 70 | */ 71 | var touch = e.changedTouches[0], 72 | evt = document.createEvent('MouseEvents'); 73 | evt.initMouseEvent('click', true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); 74 | evt.simulated = true; // distinguish from a normal (nonsimulated) click 75 | e.target.dispatchEvent(evt); 76 | }; 77 | 78 | /** 79 | * click 80 | * 81 | * Because we've already fired a click event in touchend, 82 | * we need to listed for all native click events here 83 | * and suppress them as necessary. 84 | */ 85 | click = function(e) { 86 | /** 87 | * Prevent ghost clicks by only allowing clicks we created 88 | * in the click event we fired (look for e.simulated) 89 | */ 90 | var time = Date.now(), 91 | timeDiff = time - lastClick.time, 92 | x = e.clientX, 93 | y = e.clientY, 94 | xyDiff = [Math.abs(lastClick.x - x), Math.abs(lastClick.y - y)], 95 | target = closest(e.target, 'A') || e.target, // needed for standalone apps 96 | nodeName = target.nodeName, 97 | isLink = nodeName === 'A', 98 | standAlone = window.navigator.standalone && isLink && e.target.getAttribute("href"); 99 | 100 | lastClick.time = time; 101 | lastClick.x = x; 102 | lastClick.y = y; 103 | 104 | /** 105 | * Unfortunately Android sometimes fires click events without touch events (seen on Kindle Fire), 106 | * so we have to add more logic to determine the time of the last click. Not perfect... 107 | * 108 | * Older, simpler check: if((!e.simulated) || standAlone) 109 | */ 110 | if((!e.simulated && (timeDiff < 500 || (timeDiff < 1500 && xyDiff[0] < 50 && xyDiff[1] < 50))) || standAlone) { 111 | e.preventDefault(); 112 | e.stopPropagation(); 113 | if(!standAlone) return false; 114 | } 115 | 116 | /** 117 | * Special logic for standalone web apps 118 | * See http://stackoverflow.com/questions/2898740/iphone-safari-web-app-opens-links-in-new-window 119 | */ 120 | if(standAlone) { 121 | window.location = target.getAttribute("href"); 122 | } 123 | 124 | /** 125 | * Add an energize-focus class to the targeted link (mimics :focus behavior) 126 | * TODO: test and/or remove? Does this work? 127 | */ 128 | if(!target || !target.classList) return; 129 | target.classList.add("energize-focus"); 130 | window.setTimeout(function(){ 131 | target.classList.remove("energize-focus"); 132 | }, 150); 133 | }; 134 | 135 | /** 136 | * closest 137 | * @param {HTMLElement} node current node to start searching from. 138 | * @param {string} tagName the (uppercase) name of the tag you're looking for. 139 | * 140 | * Find the closest ancestor tag of a given node. 141 | * 142 | * Starts at node and goes up the DOM tree looking for a 143 | * matching nodeName, continuing until hitting document.body 144 | */ 145 | closest = function(node, tagName){ 146 | var curNode = node; 147 | 148 | while(curNode !== document.body) { // go up the dom until we find the tag we're after 149 | if(!curNode || curNode.nodeName === tagName) { return curNode; } // found 150 | curNode = curNode.parentNode; // not found, so keep going up 151 | } 152 | 153 | return null; // not found 154 | }; 155 | 156 | /** 157 | * Add all delegated event listeners 158 | * 159 | * All the events we care about bubble up to document, 160 | * so we can take advantage of event delegation. 161 | * 162 | * Note: no need to wait for DOMContentLoaded here 163 | */ 164 | document.addEventListener('touchstart', touchstart, false); 165 | document.addEventListener('touchmove', touchmove, false); 166 | document.addEventListener('touchend', touchend, false); 167 | document.addEventListener('click', click, true); // TODO: why does this use capture? 168 | 169 | })(); -------------------------------------------------------------------------------- /source/javascripts/lib/_imagesloaded.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * imagesLoaded PACKAGED v4.1.4 3 | * JavaScript is all like "You images are done yet or what?" 4 | * MIT License 5 | */ 6 | 7 | !function(e,t){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",t):"object"==typeof module&&module.exports?module.exports=t():e.EvEmitter=t()}("undefined"!=typeof window?window:this,function(){function e(){}var t=e.prototype;return t.on=function(e,t){if(e&&t){var i=this._events=this._events||{},n=i[e]=i[e]||[];return n.indexOf(t)==-1&&n.push(t),this}},t.once=function(e,t){if(e&&t){this.on(e,t);var i=this._onceEvents=this._onceEvents||{},n=i[e]=i[e]||{};return n[t]=!0,this}},t.off=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){var n=i.indexOf(t);return n!=-1&&i.splice(n,1),this}},t.emitEvent=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){i=i.slice(0),t=t||[];for(var n=this._onceEvents&&this._onceEvents[e],o=0;o (default options) 16 | * $('#content').highlight('lorem'); 17 | * 18 | * // search for and highlight more terms at once 19 | * // so you can save some time on traversing DOM 20 | * $('#content').highlight(['lorem', 'ipsum']); 21 | * $('#content').highlight('lorem ipsum'); 22 | * 23 | * // search only for entire word 'lorem' 24 | * $('#content').highlight('lorem', { wordsOnly: true }); 25 | * 26 | * // don't ignore case during search of term 'lorem' 27 | * $('#content').highlight('lorem', { caseSensitive: true }); 28 | * 29 | * // wrap every occurrance of term 'ipsum' in content 30 | * // with 31 | * $('#content').highlight('ipsum', { element: 'em', className: 'important' }); 32 | * 33 | * // remove default highlight 34 | * $('#content').unhighlight(); 35 | * 36 | * // remove custom highlight 37 | * $('#content').unhighlight({ element: 'em', className: 'important' }); 38 | * 39 | * 40 | * Copyright (c) 2009 Bartek Szopka 41 | * 42 | * Licensed under MIT license. 43 | * 44 | */ 45 | 46 | jQuery.extend({ 47 | highlight: function (node, re, nodeName, className) { 48 | if (node.nodeType === 3) { 49 | var match = node.data.match(re); 50 | if (match) { 51 | var highlight = document.createElement(nodeName || 'span'); 52 | highlight.className = className || 'highlight'; 53 | var wordNode = node.splitText(match.index); 54 | wordNode.splitText(match[0].length); 55 | var wordClone = wordNode.cloneNode(true); 56 | highlight.appendChild(wordClone); 57 | wordNode.parentNode.replaceChild(highlight, wordNode); 58 | return 1; //skip added node in parent 59 | } 60 | } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children 61 | !/(script|style)/i.test(node.tagName) && // ignore script and style nodes 62 | !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted 63 | for (var i = 0; i < node.childNodes.length; i++) { 64 | i += jQuery.highlight(node.childNodes[i], re, nodeName, className); 65 | } 66 | } 67 | return 0; 68 | } 69 | }); 70 | 71 | jQuery.fn.unhighlight = function (options) { 72 | var settings = { className: 'highlight', element: 'span' }; 73 | jQuery.extend(settings, options); 74 | 75 | return this.find(settings.element + "." + settings.className).each(function () { 76 | var parent = this.parentNode; 77 | parent.replaceChild(this.firstChild, this); 78 | parent.normalize(); 79 | }).end(); 80 | }; 81 | 82 | jQuery.fn.highlight = function (words, options) { 83 | var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false }; 84 | jQuery.extend(settings, options); 85 | 86 | if (words.constructor === String) { 87 | words = [words]; 88 | } 89 | words = jQuery.grep(words, function(word, i){ 90 | return word != ''; 91 | }); 92 | words = jQuery.map(words, function(word, i) { 93 | return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 94 | }); 95 | if (words.length == 0) { return this; }; 96 | 97 | var flag = settings.caseSensitive ? "" : "i"; 98 | var pattern = "(" + words.join("|") + ")"; 99 | if (settings.wordsOnly) { 100 | pattern = "\\b" + pattern + "\\b"; 101 | } 102 | var re = new RegExp(pattern, flag); 103 | 104 | return this.each(function () { 105 | jQuery.highlight(this, re, settings.element, settings.className); 106 | }); 107 | }; 108 | 109 | -------------------------------------------------------------------------------- /source/layouts/layout.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright 2008-2013 Concur Technologies, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | not use this file except in compliance with the License. You may obtain 6 | a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations 14 | under the License. 15 | %> 16 | <% language_tabs = current_page.data.language_tabs || [] %> 17 | <% page_content = yield %> 18 | <% 19 | if current_page.data.includes 20 | current_page.data.includes.each do |include| 21 | page_content += partial("includes/#{include}") 22 | end 23 | end 24 | %> 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | <% if current_page.data.key?('meta') %> 33 | <% current_page.data.meta.each do |meta| %> 34 | 36 | <%= "#{key}=\"#{value}\"" %> 37 | <% end %> 38 | > 39 | <% end %> 40 | <% end %> 41 | <%= current_page.data.title || "API Documentation" %> 42 | 43 | 46 | 52 | <%= stylesheet_link_tag :screen, media: :screen %> 53 | <%= stylesheet_link_tag :print, media: :print %> 54 | <% if current_page.data.search %> 55 | <%= javascript_include_tag "all" %> 56 | <% else %> 57 | <%= javascript_include_tag "all_nosearch" %> 58 | <% end %> 59 | 60 | <% if current_page.data.code_clipboard %> 61 | 64 | <% end %> 65 | 66 | 67 | 68 | 69 | 70 | NAV 71 | <%= image_tag('navbar.png') %> 72 | 73 | 74 |
      75 | <%= image_tag "logo.png", class: 'logo' %> 76 | <% if language_tabs.any? %> 77 |
      78 | <% language_tabs.each do |lang| %> 79 | <% if lang.is_a? Hash %> 80 | <%= lang.values.first %> 81 | <% else %> 82 | <%= lang %> 83 | <% end %> 84 | <% end %> 85 |
      86 | <% end %> 87 | <% if current_page.data.search %> 88 | 91 |
        92 | <% end %> 93 |
          94 | <% toc_data(page_content).each do |h1| %> 95 |
        • 96 | <%= h1[:content] %> 97 | <% if h1[:children].length > 0 %> 98 |
            99 | <% h1[:children].each do |h2| %> 100 |
          • 101 | <%= h2[:content] %> 102 |
          • 103 | <% end %> 104 |
          105 | <% end %> 106 |
        • 107 | <% end %> 108 |
        109 | <% if current_page.data.toc_footers %> 110 | 115 | <% end %> 116 |
        117 |
        118 |
        119 |
        120 | <%= page_content %> 121 |
        122 |
        123 | <% if language_tabs.any? %> 124 |
        125 | <% language_tabs.each do |lang| %> 126 | <% if lang.is_a? Hash %> 127 | <%= lang.values.first %> 128 | <% else %> 129 | <%= lang %> 130 | <% end %> 131 | <% end %> 132 |
        133 | <% end %> 134 |
        135 |
        136 | 137 | 138 | -------------------------------------------------------------------------------- /source/stylesheets/_icon-font.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'slate'; 3 | src:font-url('slate.eot?-syv14m'); 4 | src:font-url('slate.eot?#iefix-syv14m') format('embedded-opentype'), 5 | font-url('slate.woff2?-syv14m') format('woff2'), 6 | font-url('slate.woff?-syv14m') format('woff'), 7 | font-url('slate.ttf?-syv14m') format('truetype'), 8 | font-url('slate.svg?-syv14m#slate') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | %icon { 14 | font-family: 'slate'; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | } 22 | 23 | %icon-exclamation-sign { 24 | @extend %icon; 25 | content: "\e600"; 26 | } 27 | %icon-info-sign { 28 | @extend %icon; 29 | content: "\e602"; 30 | } 31 | %icon-ok-sign { 32 | @extend %icon; 33 | content: "\e606"; 34 | } 35 | %icon-search { 36 | @extend %icon; 37 | content: "\e607"; 38 | } 39 | -------------------------------------------------------------------------------- /source/stylesheets/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | -------------------------------------------------------------------------------- /source/stylesheets/_rtl.scss: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // RTL Styles Variables 3 | //////////////////////////////////////////////////////////////////////////////// 4 | 5 | $default: auto; 6 | 7 | //////////////////////////////////////////////////////////////////////////////// 8 | // TABLE OF CONTENTS 9 | //////////////////////////////////////////////////////////////////////////////// 10 | 11 | #toc>ul>li>a>span { 12 | float: left; 13 | } 14 | 15 | .toc-wrapper { 16 | transition: right 0.3s ease-in-out !important; 17 | left: $default !important; 18 | #{right}: 0; 19 | } 20 | 21 | .toc-h2 { 22 | padding-#{right}: $nav-padding + $nav-indent; 23 | } 24 | 25 | #nav-button { 26 | #{right}: 0; 27 | transition: right 0.3s ease-in-out; 28 | &.open { 29 | right: $nav-width 30 | } 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////// 34 | // PAGE LAYOUT AND CODE SAMPLE BACKGROUND 35 | //////////////////////////////////////////////////////////////////////////////// 36 | .page-wrapper { 37 | margin-#{left}: $default !important; 38 | margin-#{right}: $nav-width; 39 | .dark-box { 40 | #{right}: $default; 41 | #{left}: 0; 42 | } 43 | } 44 | 45 | .lang-selector { 46 | width: $default !important; 47 | a { 48 | float: right; 49 | } 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////// 53 | // CODE SAMPLE STYLES 54 | //////////////////////////////////////////////////////////////////////////////// 55 | .content { 56 | &>h1, 57 | &>h2, 58 | &>h3, 59 | &>h4, 60 | &>h5, 61 | &>h6, 62 | &>p, 63 | &>table, 64 | &>ul, 65 | &>ol, 66 | &>aside, 67 | &>dl { 68 | margin-#{left}: $examples-width; 69 | margin-#{right}: $default !important; 70 | } 71 | &>ul, 72 | &>ol { 73 | padding-#{right}: $main-padding + 15px; 74 | } 75 | table { 76 | th, 77 | td { 78 | text-align: right; 79 | } 80 | } 81 | dd { 82 | margin-#{right}: 15px; 83 | } 84 | aside { 85 | aside:before { 86 | padding-#{left}: 0.5em; 87 | } 88 | .search-highlight { 89 | background: linear-gradient(to top right, #F7E633 0%, #F1D32F 100%); 90 | } 91 | } 92 | pre, 93 | blockquote { 94 | float: left !important; 95 | clear: left !important; 96 | } 97 | } 98 | 99 | //////////////////////////////////////////////////////////////////////////////// 100 | // TYPOGRAPHY 101 | //////////////////////////////////////////////////////////////////////////////// 102 | h1, 103 | h2, 104 | h3, 105 | h4, 106 | h5, 107 | h6, 108 | p, 109 | aside { 110 | text-align: right; 111 | direction: rtl; 112 | } 113 | 114 | .toc-wrapper { 115 | text-align: right; 116 | direction: rtl; 117 | font-weight: 100 !important; 118 | } 119 | 120 | 121 | //////////////////////////////////////////////////////////////////////////////// 122 | // RESPONSIVE DESIGN 123 | //////////////////////////////////////////////////////////////////////////////// 124 | @media (max-width: $tablet-width) { 125 | .toc-wrapper { 126 | #{right}: -$nav-width; 127 | &.open { 128 | #{right}: 0; 129 | } 130 | } 131 | .page-wrapper { 132 | margin-#{right}: 0; 133 | } 134 | } 135 | 136 | @media (max-width: $phone-width) { 137 | %left-col { 138 | margin-#{left}: 0; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /source/stylesheets/_variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2008-2013 Concur Technologies, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | not use this file except in compliance with the License. You may obtain 6 | a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations 14 | under the License. 15 | */ 16 | 17 | 18 | //////////////////////////////////////////////////////////////////////////////// 19 | // CUSTOMIZE SLATE 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // Use these settings to help adjust the appearance of Slate 22 | 23 | 24 | // BACKGROUND COLORS 25 | //////////////////// 26 | $nav-bg: #2E3336 !default; 27 | $examples-bg: #2E3336 !default; 28 | $code-bg: #1E2224 !default; 29 | $code-annotation-bg: #191D1F !default; 30 | $nav-subitem-bg: #1E2224 !default; 31 | $nav-active-bg: #0F75D4 !default; 32 | $nav-active-parent-bg: #1E2224 !default; // parent links of the current section 33 | $lang-select-border: #000 !default; 34 | $lang-select-bg: #1E2224 !default; 35 | $lang-select-active-bg: $examples-bg !default; // feel free to change this to blue or something 36 | $lang-select-pressed-bg: #111 !default; // color of language tab bg when mouse is pressed 37 | $main-bg: #F3F7F9 !default; 38 | $aside-notice-bg: #8fbcd4 !default; 39 | $aside-warning-bg: #c97a7e !default; 40 | $aside-success-bg: #6ac174 !default; 41 | $search-notice-bg: #c97a7e !default; 42 | 43 | 44 | // TEXT COLORS 45 | //////////////////// 46 | $main-text: #333 !default; // main content text color 47 | $nav-text: #fff !default; 48 | $nav-active-text: #fff !default; 49 | $nav-active-parent-text: #fff !default; // parent links of the current section 50 | $lang-select-text: #fff !default; // color of unselected language tab text 51 | $lang-select-active-text: #fff !default; // color of selected language tab text 52 | $lang-select-pressed-text: #fff !default; // color of language tab text when mouse is pressed 53 | 54 | 55 | // SIZES 56 | //////////////////// 57 | $nav-width: 230px !default; // width of the navbar 58 | $examples-width: 50% !default; // portion of the screen taken up by code examples 59 | $logo-margin: 0px !default; // margin below logo 60 | $main-padding: 28px !default; // padding to left and right of content & examples 61 | $nav-padding: 15px !default; // padding to left and right of navbar 62 | $nav-v-padding: 10px !default; // padding used vertically around search boxes and results 63 | $nav-indent: 10px !default; // extra padding for ToC subitems 64 | $code-annotation-padding: 13px !default; // padding inside code annotations 65 | $h1-margin-bottom: 21px !default; // padding under the largest header tags 66 | $tablet-width: 930px !default; // min width before reverting to tablet size 67 | $phone-width: $tablet-width - $nav-width !default; // min width before reverting to mobile size 68 | 69 | 70 | // FONTS 71 | //////////////////// 72 | %default-font { 73 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 74 | font-size: 14px; 75 | } 76 | 77 | %header-font { 78 | @extend %default-font; 79 | font-weight: bold; 80 | } 81 | 82 | %code-font { 83 | font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; 84 | font-size: 12px; 85 | line-height: 1.5; 86 | } 87 | 88 | 89 | // OTHER 90 | //////////////////// 91 | $nav-footer-border-color: #666 !default; 92 | $search-box-border-color: #666 !default; 93 | 94 | 95 | //////////////////////////////////////////////////////////////////////////////// 96 | // INTERNAL 97 | //////////////////////////////////////////////////////////////////////////////// 98 | // These settings are probably best left alone. 99 | 100 | %break-words { 101 | word-break: break-all; 102 | hyphens: auto; 103 | } 104 | -------------------------------------------------------------------------------- /source/stylesheets/print.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'variables'; 4 | @import 'icon-font'; 5 | 6 | /* 7 | Copyright 2008-2013 Concur Technologies, Inc. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); you may 10 | not use this file except in compliance with the License. You may obtain 11 | a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 18 | License for the specific language governing permissions and limitations 19 | under the License. 20 | */ 21 | 22 | $print-color: #999; 23 | $print-color-light: #ccc; 24 | $print-font-size: 12px; 25 | 26 | body { 27 | @extend %default-font; 28 | } 29 | 30 | .tocify, .toc-footer, .lang-selector, .search, #nav-button { 31 | display: none; 32 | } 33 | 34 | .tocify-wrapper>img { 35 | margin: 0 auto; 36 | display: block; 37 | } 38 | 39 | .content { 40 | font-size: 12px; 41 | 42 | pre, code { 43 | @extend %code-font; 44 | @extend %break-words; 45 | border: 1px solid $print-color; 46 | border-radius: 5px; 47 | font-size: 0.8em; 48 | } 49 | 50 | pre { 51 | code { 52 | border: 0; 53 | } 54 | } 55 | 56 | pre { 57 | padding: 1.3em; 58 | } 59 | 60 | code { 61 | padding: 0.2em; 62 | } 63 | 64 | table { 65 | border: 1px solid $print-color; 66 | tr { 67 | border-bottom: 1px solid $print-color; 68 | } 69 | td,th { 70 | padding: 0.7em; 71 | } 72 | } 73 | 74 | p { 75 | line-height: 1.5; 76 | } 77 | 78 | a { 79 | text-decoration: none; 80 | color: #000; 81 | } 82 | 83 | h1 { 84 | @extend %header-font; 85 | font-size: 2.5em; 86 | padding-top: 0.5em; 87 | padding-bottom: 0.5em; 88 | margin-top: 1em; 89 | margin-bottom: $h1-margin-bottom; 90 | border: 2px solid $print-color-light; 91 | border-width: 2px 0; 92 | text-align: center; 93 | } 94 | 95 | h2 { 96 | @extend %header-font; 97 | font-size: 1.8em; 98 | margin-top: 2em; 99 | border-top: 2px solid $print-color-light; 100 | padding-top: 0.8em; 101 | } 102 | 103 | h1+h2, h1+div+h2 { 104 | border-top: none; 105 | padding-top: 0; 106 | margin-top: 0; 107 | } 108 | 109 | h3, h4 { 110 | @extend %header-font; 111 | font-size: 0.8em; 112 | margin-top: 1.5em; 113 | margin-bottom: 0.8em; 114 | text-transform: uppercase; 115 | } 116 | 117 | h5, h6 { 118 | text-transform: uppercase; 119 | } 120 | 121 | aside { 122 | padding: 1em; 123 | border: 1px solid $print-color-light; 124 | border-radius: 5px; 125 | margin-top: 1.5em; 126 | margin-bottom: 1.5em; 127 | line-height: 1.6; 128 | } 129 | 130 | aside:before { 131 | vertical-align: middle; 132 | padding-right: 0.5em; 133 | font-size: 14px; 134 | } 135 | 136 | aside.notice:before { 137 | @extend %icon-info-sign; 138 | } 139 | 140 | aside.warning:before { 141 | @extend %icon-exclamation-sign; 142 | } 143 | 144 | aside.success:before { 145 | @extend %icon-ok-sign; 146 | } 147 | } 148 | 149 | .copy-clipboard { 150 | @media print { 151 | display: none 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /source/stylesheets/screen.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'variables'; 4 | @import 'icon-font'; 5 | // @import 'rtl'; // uncomment to switch to RTL format 6 | 7 | /* 8 | Copyright 2008-2013 Concur Technologies, Inc. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); you may 11 | not use this file except in compliance with the License. You may obtain 12 | a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | License for the specific language governing permissions and limitations 20 | under the License. 21 | */ 22 | 23 | //////////////////////////////////////////////////////////////////////////////// 24 | // GENERAL STUFF 25 | //////////////////////////////////////////////////////////////////////////////// 26 | 27 | html, body { 28 | color: $main-text; 29 | padding: 0; 30 | margin: 0; 31 | -webkit-font-smoothing: antialiased; 32 | -moz-osx-font-smoothing: grayscale; 33 | @extend %default-font; 34 | background-color: $main-bg; 35 | height: 100%; 36 | -webkit-text-size-adjust: none; /* Never autoresize text */ 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////// 40 | // TABLE OF CONTENTS 41 | //////////////////////////////////////////////////////////////////////////////// 42 | 43 | #toc > ul > li > a > span { 44 | float: right; 45 | background-color: #2484FF; 46 | border-radius: 40px; 47 | width: 20px; 48 | } 49 | 50 | .toc-wrapper { 51 | transition: left 0.3s ease-in-out; 52 | 53 | overflow-y: auto; 54 | overflow-x: hidden; 55 | position: fixed; 56 | z-index: 30; 57 | top: 0; 58 | left: 0; 59 | bottom: 0; 60 | width: $nav-width; 61 | background-color: $nav-bg; 62 | font-size: 13px; 63 | font-weight: bold; 64 | 65 | // language selector for mobile devices 66 | .lang-selector { 67 | display: none; 68 | a { 69 | padding-top: 0.5em; 70 | padding-bottom: 0.5em; 71 | } 72 | } 73 | 74 | // This is the logo at the top of the ToC 75 | .logo { 76 | display: block; 77 | max-width: 100%; 78 | margin-bottom: $logo-margin; 79 | } 80 | 81 | &>.search { 82 | position: relative; 83 | 84 | input { 85 | background: $nav-bg; 86 | border-width: 0 0 1px 0; 87 | border-color: $search-box-border-color; 88 | padding: 6px 0 6px 20px; 89 | box-sizing: border-box; 90 | margin: $nav-v-padding $nav-padding; 91 | width: $nav-width - ($nav-padding*2); 92 | outline: none; 93 | color: $nav-text; 94 | border-radius: 0; /* ios has a default border radius */ 95 | } 96 | 97 | &:before { 98 | position: absolute; 99 | top: 17px; 100 | left: $nav-padding; 101 | color: $nav-text; 102 | @extend %icon-search; 103 | } 104 | } 105 | 106 | .search-results { 107 | margin-top: 0; 108 | box-sizing: border-box; 109 | height: 0; 110 | overflow-y: auto; 111 | overflow-x: hidden; 112 | transition-property: height, margin; 113 | transition-duration: 180ms; 114 | transition-timing-function: ease-in-out; 115 | background: $nav-subitem-bg; 116 | &.visible { 117 | height: 30%; 118 | margin-bottom: 1em; 119 | } 120 | 121 | li { 122 | margin: 1em $nav-padding; 123 | line-height: 1; 124 | } 125 | 126 | a { 127 | color: $nav-text; 128 | text-decoration: none; 129 | 130 | &:hover { 131 | text-decoration: underline; 132 | } 133 | } 134 | } 135 | 136 | 137 | // The Table of Contents is composed of multiple nested 138 | // unordered lists. These styles remove the default 139 | // styling of an unordered list because it is ugly. 140 | ul, li { 141 | list-style: none; 142 | margin: 0; 143 | padding: 0; 144 | line-height: 28px; 145 | } 146 | 147 | li { 148 | color: $nav-text; 149 | transition-property: background; 150 | transition-timing-function: linear; 151 | transition-duration: 200ms; 152 | } 153 | 154 | // This is the currently selected ToC entry 155 | .toc-link.active { 156 | background-color: $nav-active-bg; 157 | color: $nav-active-text; 158 | } 159 | 160 | // this is parent links of the currently selected ToC entry 161 | .toc-link.active-parent { 162 | background-color: $nav-active-parent-bg; 163 | color: $nav-active-parent-text; 164 | } 165 | 166 | .toc-list-h2 { 167 | display: none; 168 | background-color: $nav-subitem-bg; 169 | font-weight: 500; 170 | } 171 | 172 | .toc-h2 { 173 | padding-left: $nav-padding + $nav-indent; 174 | font-size: 12px; 175 | } 176 | 177 | .toc-footer { 178 | padding: 1em 0; 179 | margin-top: 1em; 180 | border-top: 1px dashed $nav-footer-border-color; 181 | 182 | li,a { 183 | color: $nav-text; 184 | text-decoration: none; 185 | } 186 | 187 | a:hover { 188 | text-decoration: underline; 189 | } 190 | 191 | li { 192 | font-size: 0.8em; 193 | line-height: 1.7; 194 | text-decoration: none; 195 | } 196 | } 197 | } 198 | 199 | .toc-link, .toc-footer li { 200 | padding: 0 $nav-padding 0 $nav-padding; 201 | display: block; 202 | overflow-x: hidden; 203 | white-space: nowrap; 204 | text-overflow: ellipsis; 205 | text-decoration: none; 206 | color: $nav-text; 207 | transition-property: background; 208 | transition-timing-function: linear; 209 | transition-duration: 130ms; 210 | } 211 | 212 | // button to show navigation on mobile devices 213 | #nav-button { 214 | span { 215 | display: block; 216 | $side-pad: $main-padding / 2 - 8px; 217 | padding: $side-pad $side-pad $side-pad; 218 | background-color: rgba($main-bg, 0.7); 219 | transform-origin: 0 0; 220 | transform: rotate(-90deg) translate(-100%, 0); 221 | border-radius: 0 0 0 5px; 222 | } 223 | padding: 0 1.5em 5em 0; // increase touch size area 224 | display: none; 225 | position: fixed; 226 | top: 0; 227 | left: 0; 228 | z-index: 100; 229 | color: #000; 230 | text-decoration: none; 231 | font-weight: bold; 232 | opacity: 0.7; 233 | line-height: 16px; 234 | img { 235 | height: 16px; 236 | vertical-align: bottom; 237 | } 238 | 239 | transition: left 0.3s ease-in-out; 240 | 241 | &:hover { opacity: 1; } 242 | &.open {left: $nav-width} 243 | } 244 | 245 | 246 | //////////////////////////////////////////////////////////////////////////////// 247 | // PAGE LAYOUT AND CODE SAMPLE BACKGROUND 248 | //////////////////////////////////////////////////////////////////////////////// 249 | 250 | .page-wrapper { 251 | margin-left: $nav-width; 252 | position: relative; 253 | z-index: 10; 254 | background-color: $main-bg; 255 | min-height: 100%; 256 | 257 | padding-bottom: 1px; // prevent margin overflow 258 | 259 | // The dark box is what gives the code samples their dark background. 260 | // It sits essentially under the actual content block, which has a 261 | // transparent background. 262 | // I know, it's hackish, but it's the simplist way to make the left 263 | // half of the content always this background color. 264 | .dark-box { 265 | width: $examples-width; 266 | background-color: $examples-bg; 267 | position: absolute; 268 | right: 0; 269 | top: 0; 270 | bottom: 0; 271 | } 272 | 273 | .lang-selector { 274 | position: fixed; 275 | z-index: 50; 276 | border-bottom: 5px solid $lang-select-active-bg; 277 | } 278 | } 279 | 280 | .lang-selector { 281 | display: flex; 282 | background-color: $lang-select-bg; 283 | width: 100%; 284 | font-weight: bold; 285 | overflow-x: auto; 286 | a { 287 | display: inline; 288 | color: $lang-select-text; 289 | text-decoration: none; 290 | padding: 0 10px; 291 | line-height: 30px; 292 | outline: 0; 293 | 294 | &:active, &:focus { 295 | background-color: $lang-select-pressed-bg; 296 | color: $lang-select-pressed-text; 297 | } 298 | 299 | &.active { 300 | background-color: $lang-select-active-bg; 301 | color: $lang-select-active-text; 302 | } 303 | } 304 | 305 | &:after { 306 | content: ''; 307 | clear: both; 308 | display: block; 309 | } 310 | } 311 | 312 | //////////////////////////////////////////////////////////////////////////////// 313 | // CONTENT STYLES 314 | //////////////////////////////////////////////////////////////////////////////// 315 | // This is all the stuff with the light background in the left half of the page 316 | 317 | .content { 318 | // fixes webkit rendering bug for some: see #538 319 | -webkit-transform: translateZ(0); 320 | // to place content above the dark box 321 | position: relative; 322 | z-index: 30; 323 | 324 | &:after { 325 | content: ''; 326 | display: block; 327 | clear: both; 328 | } 329 | 330 | &>h1, &>h2, &>h3, &>h4, &>h5, &>h6, &>p, &>table, &>ul, &>ol, &>aside, &>dl { 331 | margin-right: $examples-width; 332 | padding: 0 $main-padding; 333 | box-sizing: border-box; 334 | display: block; 335 | 336 | @extend %left-col; 337 | } 338 | 339 | &>ul, &>ol { 340 | padding-left: $main-padding + 15px; 341 | } 342 | 343 | // the div is the tocify hidden div for placeholding stuff 344 | &>h1, &>h2, &>div { 345 | clear:both; 346 | } 347 | 348 | h1 { 349 | @extend %header-font; 350 | font-size: 25px; 351 | padding-top: 0.5em; 352 | padding-bottom: 0.5em; 353 | margin-bottom: $h1-margin-bottom; 354 | margin-top: 2em; 355 | border-top: 1px solid #ccc; 356 | border-bottom: 1px solid #ccc; 357 | background-color: #fdfdfd; 358 | } 359 | 360 | h1:first-child, div:first-child + h1 { 361 | border-top-width: 0; 362 | margin-top: 0; 363 | } 364 | 365 | h2 { 366 | @extend %header-font; 367 | font-size: 19px; 368 | margin-top: 4em; 369 | margin-bottom: 0; 370 | border-top: 1px solid #ccc; 371 | padding-top: 1.2em; 372 | padding-bottom: 1.2em; 373 | background-image: linear-gradient(to bottom, rgba(#fff, 0.2), rgba(#fff, 0)); 374 | } 375 | 376 | // h2s right after h1s should bump right up 377 | // against the h1s. 378 | h1 + h2, h1 + div + h2 { 379 | margin-top: $h1-margin-bottom * -1; 380 | border-top: none; 381 | } 382 | 383 | h3, h4, h5, h6 { 384 | @extend %header-font; 385 | font-size: 15px; 386 | margin-top: 2.5em; 387 | margin-bottom: 0.8em; 388 | } 389 | 390 | h4, h5, h6 { 391 | font-size: 10px; 392 | } 393 | 394 | hr { 395 | margin: 2em 0; 396 | border-top: 2px solid $examples-bg; 397 | border-bottom: 2px solid $main-bg; 398 | } 399 | 400 | table { 401 | margin-bottom: 1em; 402 | overflow: auto; 403 | th,td { 404 | text-align: left; 405 | vertical-align: top; 406 | line-height: 1.6; 407 | code { 408 | white-space: nowrap; 409 | } 410 | } 411 | 412 | th { 413 | padding: 5px 10px; 414 | border-bottom: 1px solid #ccc; 415 | vertical-align: bottom; 416 | } 417 | 418 | td { 419 | padding: 10px; 420 | } 421 | 422 | tr:last-child { 423 | border-bottom: 1px solid #ccc; 424 | } 425 | 426 | tr:nth-child(odd)>td { 427 | background-color: lighten($main-bg,4.2%); 428 | } 429 | 430 | tr:nth-child(even)>td { 431 | background-color: lighten($main-bg,2.4%); 432 | } 433 | } 434 | 435 | dt { 436 | font-weight: bold; 437 | } 438 | 439 | dd { 440 | margin-left: 15px; 441 | } 442 | 443 | p, li, dt, dd { 444 | line-height: 1.6; 445 | margin-top: 0; 446 | } 447 | 448 | img { 449 | max-width: 100%; 450 | } 451 | 452 | code { 453 | background-color: rgba(0,0,0,0.05); 454 | padding: 3px; 455 | border-radius: 3px; 456 | @extend %break-words; 457 | @extend %code-font; 458 | } 459 | 460 | pre>code { 461 | background-color: transparent; 462 | padding: 0; 463 | } 464 | 465 | aside { 466 | padding-top: 1em; 467 | padding-bottom: 1em; 468 | margin-top: 1.5em; 469 | margin-bottom: 1.5em; 470 | background: $aside-notice-bg; 471 | line-height: 1.6; 472 | 473 | &.warning { 474 | background-color: $aside-warning-bg; 475 | } 476 | 477 | &.success { 478 | background-color: $aside-success-bg; 479 | } 480 | } 481 | 482 | aside:before { 483 | vertical-align: middle; 484 | padding-right: 0.5em; 485 | font-size: 14px; 486 | } 487 | 488 | aside.notice:before { 489 | @extend %icon-info-sign; 490 | } 491 | 492 | aside.warning:before { 493 | @extend %icon-exclamation-sign; 494 | } 495 | 496 | aside.success:before { 497 | @extend %icon-ok-sign; 498 | } 499 | 500 | .search-highlight { 501 | padding: 2px; 502 | margin: -3px; 503 | border-radius: 4px; 504 | border: 1px solid #F7E633; 505 | background: linear-gradient(to top left, #F7E633 0%, #F1D32F 100%); 506 | } 507 | } 508 | 509 | //////////////////////////////////////////////////////////////////////////////// 510 | // CODE SAMPLE STYLES 511 | //////////////////////////////////////////////////////////////////////////////// 512 | // This is all the stuff that appears in the right half of the page 513 | 514 | .content { 515 | &>div.highlight { 516 | clear:none; 517 | } 518 | 519 | pre, blockquote { 520 | background-color: $code-bg; 521 | color: #fff; 522 | 523 | margin: 0; 524 | width: $examples-width; 525 | 526 | float:right; 527 | clear:right; 528 | 529 | box-sizing: border-box; 530 | 531 | @extend %right-col; 532 | 533 | &>p { margin: 0; } 534 | 535 | a { 536 | color: #fff; 537 | text-decoration: none; 538 | border-bottom: dashed 1px #ccc; 539 | } 540 | } 541 | 542 | pre { 543 | @extend %code-font; 544 | padding-top: 2em; 545 | padding-bottom: 2em; 546 | padding: 2em $main-padding; 547 | } 548 | 549 | blockquote { 550 | &>p { 551 | background-color: $code-annotation-bg; 552 | padding: $code-annotation-padding 2em; 553 | color: #eee; 554 | } 555 | } 556 | } 557 | 558 | //////////////////////////////////////////////////////////////////////////////// 559 | // RESPONSIVE DESIGN 560 | //////////////////////////////////////////////////////////////////////////////// 561 | // These are the styles for phones and tablets 562 | // There are also a couple styles disperesed 563 | 564 | @media (max-width: $tablet-width) { 565 | .toc-wrapper { 566 | left: -$nav-width; 567 | 568 | &.open { 569 | left: 0; 570 | } 571 | } 572 | 573 | .page-wrapper { 574 | margin-left: 0; 575 | } 576 | 577 | #nav-button { 578 | display: block; 579 | } 580 | 581 | .toc-link { 582 | padding-top: 0.3em; 583 | padding-bottom: 0.3em; 584 | } 585 | } 586 | 587 | @media (max-width: $phone-width) { 588 | .dark-box { 589 | display: none; 590 | } 591 | 592 | %left-col { 593 | margin-right: 0; 594 | } 595 | 596 | .toc-wrapper .lang-selector { 597 | display: block; 598 | } 599 | 600 | .page-wrapper .lang-selector { 601 | display: none; 602 | } 603 | 604 | %right-col { 605 | width: auto; 606 | float: none; 607 | } 608 | 609 | %right-col + %left-col { 610 | margin-top: $main-padding; 611 | } 612 | 613 | .highlight + p { 614 | margin-top: 20px; 615 | } 616 | } 617 | 618 | .highlight .c, .highlight .cm, .highlight .c1, .highlight .cs { 619 | color: #909090; 620 | } 621 | 622 | .highlight, .highlight .w { 623 | background-color: $code-bg; 624 | } 625 | 626 | .copy-clipboard { 627 | float: right; 628 | fill: #9DAAB6; 629 | cursor: pointer; 630 | opacity: 0.4; 631 | height: 18px; 632 | width: 18px; 633 | } 634 | 635 | .copy-clipboard:hover { 636 | opacity: 0.8; 637 | } 638 | --------------------------------------------------------------------------------