diff --git a/.deploy.sh b/.deploy.sh new file mode 100644 index 0000000..e6af902 --- /dev/null +++ b/.deploy.sh @@ -0,0 +1,7 @@ +#!/bin/bash +if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" ]]; then + cp CNAME public + git clone https://github.com/davisp/ghp-import.git && + ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -b master -r https://"$GH_TOKEN"@github.com/actix/actix.github.io.git _site && + echo "Uploaded documentation" +fi diff --git a/.gitignore b/.gitignore index b84bff7..c5864e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -.DS_Store - -build/ -_site/ +public +tmp diff --git a/.travis.yml b/.travis.yml index b7f84f9..e4d65ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,17 @@ language: rust sudo: false -dist: trusty -# build website +install: + - curl -L https://github.com/gohugoio/hugo/releases/download/v0.40.3/hugo_0.40.3_Linux-64bit.tar.gz | + tar xzvf - + script: - - export PATH=$PATH:~/.cargo/bin - - | - if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" ]]; then - curl -sL https://github.com/cobalt-org/cobalt.rs/releases/download/v0.12.1/cobalt-v0.12.1-x86_64-unknown-linux-gnu.tar.gz | tar xvz -C $HOME/.cargo/bin && - cobalt build && cp CNAME ./_site/ && - git clone https://github.com/davisp/ghp-import.git && - ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -b master -r https://"$GH_TOKEN"@github.com/actix/actix.github.io.git _site && - echo "Uploaded documentation" - fi + - ./hugo_0.40.3_Linux-64bit/hugo_0.18.1_linux_amd64 + +deploy: + provider: script + script: bash .deploy.sh + skip_cleanup: true + on: + branch: master + condition: $TRAVIS_PULL_REQUEST = "false" diff --git a/CNAME b/CNAME index d22c381..7b11496 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -actix.rs \ No newline at end of file +actix.rs diff --git a/LICENSE b/LICENSE deleted file mode 100644 index dbc4744..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2017-NOW Actix Organization and Contributors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..58fb29a --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2018 Carl Lerche + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index f87e8c9..7097c5a 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,27 @@ -# actix-theme -The Actix website template made with [Cobalt](https://cobalt-org.github.io/) +# Actix Website +The work in progress website for the actix project based on tokio's website. -# Contribute. -So you want make actix-website more beautiful. -```bash -$ cobalt -V // Cobalt 0.11.1 -$ git clone https://github.com/actix/actix-website.git -$ cd actix-website -// modify index.liquid or tutorials/community/more markdown file. -// also add or modify markdown files in docs/blog DIR. -$ cobalt serve // it will get '_site' DIR, so only need put files in this '_site' DIR to [actix.github.io](https://github.com/actix/actix.github.io) +## Getting Started + +Building the website depends on [Hugo](http://gohugo.io). So, first make sure +that you have it installed. If on OS X and using Homebrew, run the following: + +```sh +brew update && brew install hugo ``` + +Then, get the website running locally: + +```sh +git clone https://github.com/mitsuhiko/actix-website +cd website +hugo server +``` + +Then visit [http://localhost:1313](http://localhost:1313). + +# License + +Pretty murky. Right now a massive clone of the tokio website. Will get this +figured out as we go along. diff --git a/_cobalt.yml b/_cobalt.yml deleted file mode 100644 index f00fab3..0000000 --- a/_cobalt.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Build options -source: "." -template_extensions: - - md - - liquid -include_drafts: false -ignore: - - .git/* - - build/* - - README.md -destination: _site - -# Site options -site: - title: ~ - description: ~ - base_url: ~ - data: ~ - -# Page/Post options -default: - excerpt_separator: "\n\n" - is_draft: false -syntax_highlight: - theme: "base16-ocean.dark" -assets: - sass: - style: Nested -pages: - default: {} -posts: - title: ~ - description: ~ - dir: posts - drafts_dir: _drafts - order: Desc - rss: ~ - jsonfeed: ~ - default: {} \ No newline at end of file diff --git a/_includes/footer.liquid b/_includes/footer.liquid deleted file mode 100644 index a19f7b2..0000000 --- a/_includes/footer.liquid +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/_includes/head.liquid b/_includes/head.liquid deleted file mode 100644 index 5d69d0b..0000000 --- a/_includes/head.liquid +++ /dev/null @@ -1,7 +0,0 @@ - - - -{{ page.title }} - - - diff --git a/_includes/header.liquid b/_includes/header.liquid deleted file mode 100644 index 669f5c9..0000000 --- a/_includes/header.liquid +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/_layouts/blog.liquid b/_layouts/blog.liquid deleted file mode 100644 index 76b7782..0000000 --- a/_layouts/blog.liquid +++ /dev/null @@ -1,30 +0,0 @@ - - - - {% include "head.liquid" %} - - -
- {% include "header.liquid" %} -
-
-
-
- -
-
- {{ page.content }} -
-
-
-
- - - diff --git a/_layouts/default.liquid b/_layouts/default.liquid deleted file mode 100644 index 8a52c9d..0000000 --- a/_layouts/default.liquid +++ /dev/null @@ -1,17 +0,0 @@ - - - - {% include "head.liquid" %} - - -
- {% include "header.liquid" %} -
-
- {{ page.content }} -
- - - diff --git a/_layouts/docs.liquid b/_layouts/docs.liquid deleted file mode 100644 index a459fd5..0000000 --- a/_layouts/docs.liquid +++ /dev/null @@ -1,42 +0,0 @@ - - - - {% include "head.liquid" %} - - -
- {% include "header.liquid" %} -
-
-
-
- -
-
- {{ page.content }} -
-
-
-
- - - diff --git a/_layouts/post.liquid b/_layouts/post.liquid deleted file mode 100644 index 3baaad7..0000000 --- a/_layouts/post.liquid +++ /dev/null @@ -1,17 +0,0 @@ - - - - {% include "head.liquid" %} - - -
- {% include "header.liquid" %} -
-
- {{ content }} -
- - - diff --git a/artwork/logo.afdesign b/artwork/logo.afdesign new file mode 100644 index 0000000..cf5bac7 Binary files /dev/null and b/artwork/logo.afdesign differ diff --git a/blog/Blog-example.md b/blog/Blog-example.md deleted file mode 100644 index 5b0e4e3..0000000 --- a/blog/Blog-example.md +++ /dev/null @@ -1,8 +0,0 @@ -title: Blog::Blog Example -layout: blog.liquid -permalink: /blog/2018/Blog-example.html ---- - -## Basics Example - -The words is comming. diff --git a/blog/index.md b/blog/index.md deleted file mode 100644 index b7e5434..0000000 --- a/blog/index.md +++ /dev/null @@ -1,13 +0,0 @@ -title: Blog -layout: blog.liquid -permalink: /blog/index.html ---- - -## Documentation - -Welcome to the Actix-web Blog! - -If you feel like contributing further, you can fork that repo, -branch from `source`, and submit a pull request. - -Contributions are always welcome! diff --git a/community.md b/community.md deleted file mode 100644 index e126aeb..0000000 --- a/community.md +++ /dev/null @@ -1,15 +0,0 @@ -title: Community -layout: default.liquid -permalink: /community.html ---- -
-
- - -## Examples - -The words is comming. - - -
-
diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..f791a39 --- /dev/null +++ b/config.toml @@ -0,0 +1,11 @@ +baseurl = "https://actix.rs" +title = "actix" +languageCode = "en-us" +canonifyURLs = true +googleAnalytics = "UA-110322332-1" +pygmentsUseClasses = true +pygmentsCodeFences = true + +[params] +actixVersion = "0.5" +actixWebVersion = "0.6" diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..efab9cd --- /dev/null +++ b/content/_index.md @@ -0,0 +1,3 @@ +--- +title: Welcome +--- diff --git a/content/code/_index.md b/content/code/_index.md new file mode 100644 index 0000000..8ddf1d7 --- /dev/null +++ b/content/code/_index.md @@ -0,0 +1,19 @@ +--- +title: Code +description: Browse and download the sources +--- + +# Browse the Code + +All of actix is open source and can be found on our github organization: [actix +on github](https://github.com/actix) + +Here are the most important projects and the link to their github repositories +and related resources: + +* [actix](https://github.com/actix/actix) ([issues](https://github.com/actix/actix/issues), [ci](https://travis-ci.org/actix/actix), [crate](https://crates.io/crates/actix), [api docs](https://docs.rs/actix)) +* [actix-web](https://github.com/actix/actix-web) ([issues](https://github.com/actix/actix-web/issues), [ci](https://travis-ci.org/actix/actix-web), [crate](https://crates.io/crates/actix-web), [api docs](https://docs.rs/actix-web)) +* [example code](https://github.com/actix/examples) +* [this website](https://github.com/actix/actix-website) + +Actix is dual licensed under the MIT and Apache 2 licenses. [Read license text](license/). diff --git a/content/code/license.md b/content/code/license.md new file mode 100644 index 0000000..a99e01a --- /dev/null +++ b/content/code/license.md @@ -0,0 +1,201 @@ +--- +title: License +--- + +Actix is dual licensed under MIT and Apache licenses. + +# MIT License + +Copyright (c) 2017 Nikolay Kim + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +# Apache License + +_Version 2.0, January 2004_ +http://www.apache.org/licenses/ + +### Terms and Conditions for use, reproduction, and distribution + +#### 1. Definitions + +“License” shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +“Licensor” shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +“Legal Entity” shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, “control” means **(i)** the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the +outstanding shares, or **(iii)** beneficial ownership of such entity. + +“You” (or “Your”) shall mean an individual or Legal Entity exercising +permissions granted by this License. + +“Source” form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +“Object” form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +“Work” shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +“Derivative Works” shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +“Contribution” shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +“submitted” means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as “Not a Contribution.” + +“Contributor” shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +#### 2. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +#### 3. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +#### 4. Redistribution + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +* **(a)** You must give any other recipients of the Work or Derivative Works a copy of +this License; and +* **(b)** You must cause any modified files to carry prominent notices stating that You +changed the files; and +* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +#### 5. Submission of Contributions + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +#### 6. Trademarks + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +#### 7. Disclaimer of Warranty + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +#### 8. Limitation of Liability + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +#### 9. Accepting Warranty or Additional Liability + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. diff --git a/content/community/_index.md b/content/community/_index.md new file mode 100644 index 0000000..a1cf50e --- /dev/null +++ b/content/community/_index.md @@ -0,0 +1,18 @@ +--- +title: Community +description: The best things in life are to be shared +--- + +# Join us + +Want to talk to others about questions? The [actix gitter +channel](https://gitter.im/actix/actix) is your best starting point. + +If you think you found a bug it's best to go to the +[github](https://github.com/actix) directly. There are two repositories +that you might want to report against. [actix](https://github.com/actix/actix) +for issues with the actor framework or [actix-web](https://github.com/actix/actix-web) +for the high level web framework. + +We're a welcoming community so don't be afraid to engage. Interactions +are [goverend by our code of conduct](coc/). diff --git a/content/community/coc.md b/content/community/coc.md new file mode 100644 index 0000000..065498b --- /dev/null +++ b/content/community/coc.md @@ -0,0 +1,49 @@ +--- +title: Contributor Covenant Code of Conduct +description: +--- + +# Our Pledge + +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. + +# Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +# Our Responsibilities + +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. + +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. + +# Scope + +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. + +# Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at fafhrd91@gmail.com. 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. + +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. + +# Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/content/docs/_index.md b/content/docs/_index.md new file mode 100644 index 0000000..f200d0d --- /dev/null +++ b/content/docs/_index.md @@ -0,0 +1,24 @@ +--- +title: Documentation +description: Guiding you through building apps with actix +menu: + docs_intro: + name: Welcome +weight: 10 +--- + +# Welcome to Actix + +Actix is your door to developing web services with Rust and this documentation +is going to guide you. + +This documentation currently covers mostly the `actix-web` part which is the +high level web framework build on top of the `actix` actor framework and the +[Tokio](https://tokio.rs/) async IO system. This is the part that is from an +API stability point of view the most stable. + +If you haven't used actix yet it's best to start with the [getting started +guide](getting-started/). If you already know your ways around and you need +specific information you might want to read the [actix-web API +docs](https://docs.rs/actix-web) (or the lower level [actix API +docs](https://docs.rs/actix)). diff --git a/content/docs/application.md b/content/docs/application.md new file mode 100644 index 0000000..621ab81 --- /dev/null +++ b/content/docs/application.md @@ -0,0 +1,137 @@ +--- +title: Application +menu: docs_basics +weight: 140 +--- + +# Writing an Application + +`actix-web` provides various primitives to build web servers and applications with Rust. +It provides routing, middlewares, pre-processing of requests, post-processing of responses, +websocket protocol handling, multipart streams, etc. + +All actix web servers are built around the `App` instance. It is used for +registering routes for resources and middlewares. It also stores application +state shared across all handlers within same application. + +Applications act as a namespace for all routes, i.e all routes for a specific application +have the same url path prefix. The application prefix always contains a leading "/" slash. +If a supplied prefix does not contain leading slash, it is automatically inserted. +The prefix should consist of value path segments. + +> For an application with prefix `/app`, +> any request with the paths `/app`, `/app/`, or `/app/test` would match; +> however, the path `/application` would not match. + +```rust +fn index(req: HttpRequest) -> &'static str { + "Hello world!" +} + +let app = App::new() + .prefix("/app") + .resource("/index.html", |r| r.method(Method::GET).f(index)) + .finish() +``` + +In this example, an application with the `/app` prefix and a `index.html` resource +are created. This resource is available through the `/app/index.html` url. + +> For more information, check the +> [URL Dispatch](./sec-6-url-dispatch.html#using-a-application-prefix-to-compose-applications) section. + +Multiple applications can be served with one server: + +```rust +use actix_web::{server, App, HttpResponse}; + +fn main() { + server::new(|| vec![ + App::new() + .prefix("/app1") + .resource("/", |r| r.f(|r| HttpResponse::Ok())), + App::new() + .prefix("/app2") + .resource("/", |r| r.f(|r| HttpResponse::Ok())), + App::new() + .resource("/", |r| r.f(|r| HttpResponse::Ok())), + ]); +} +``` + +All `/app1` requests route to the first application, `/app2` to the second, and all other to the third. +**Applications get matched based on registration order**. If an application with a more generic +prefix is registered before a less generic one, it would effectively block the less generic +application matching. For example, if an `App` with the prefix `"/"` was registered +as the first application, it would match all incoming requests. + +## State + +Application state is shared with all routes and resources within the same application. +When using an http actor,state can be accessed with the `HttpRequest::state()` as read-only, +but interior mutability with `RefCell` can be used to achieve state mutability. +State is also available for route matching predicates and middlewares. + +Let's write a simple application that uses shared state. We are going to store request count +in the state: + +```rust +use std::cell::Cell; +use actix_web::{App, HttpRequest, http}; + +// This struct represents state +struct AppState { + counter: Cell, +} + +fn index(req: HttpRequest) -> String { + let count = req.state().counter.get() + 1; // <- get count + req.state().counter.set(count); // <- store new count in state + + format!("Request number: {}", count) // <- response with count +} + +fn main() { + App::with_state(AppState{counter: Cell::new(0)}) + .resource("/", |r| r.method(http::Method::GET).f(index)) + .finish(); +} +``` + +> **Note**: http server accepts an application factory rather than an application +> instance. Http server constructs an application instance for each thread, thus application state +> must be constructed multiple times. If you want to share state between different threads, a +> shared object should be used, e.g. `Arc`. Application state does not need to be `Send` and `Sync`, +> but the application factory must be `Send` + `Sync`. + +## Combining applications with different state + +Combining multiple applications with different state is possible as well. + +[server::new](https://docs.rs/actix-web/*/actix_web/server/fn.new.html) requires the handler to have a single type. + +This limitation can easily be overcome with the [App::boxed](https://docs.rs/actix-web/*/actix_web/struct.App.html#method.boxed) method, which converts an App into a boxed trait object. + +```rust +use actix_web::{server, App, HttpResponse}; + +struct State1; +struct State2; + +fn main() { + server::new(|| { + vec![ + App::with_state(State1) + .prefix("/app1") + .resource("/", |r| r.f(|r| HttpResponse::Ok())) + .boxed(), + App::with_state(State2) + .prefix("/app2") + .resource("/", |r| r.f(|r| HttpResponse::Ok())) + .boxed() + ] + }) + .bind("127.0.0.1:8080").unwrap() + .run() +} +``` diff --git a/content/docs/autoreload.md b/content/docs/autoreload.md new file mode 100644 index 0000000..ceafcb0 --- /dev/null +++ b/content/docs/autoreload.md @@ -0,0 +1,76 @@ +--- +title: Autoreloading +menu: docs_patterns +weight: 1000 +--- + +# Auto-Reloading Development Server + +During development it can be very handy to have cargo automatically recompile +the code on change. This can be accomplished by using +[cargo-watch](https://github.com/passcod/cargo-watch). Because an actix app +will typically bind to a port for listening for incoming HTTP requests it makes +sense to combine this with the [listenfd](https://crates.io/crates/listenfd) +crate and the [systemfd](https://github.com/mitsuhiko/systemfd) utility to +ensure the socket is kept open while the app is compiling and reloading. + +`systemfd` will open a socket and pass it to `cargo-watch` which will watch for +changes and then invoke the compiler and run your actix app. The actix app +will then use `listenfd` to pick up the socket that `systemfd` opened. + +## Binaries Necessary + +For an automatic reloading experience you need to install `cargo-watch` and +`systemfd`. Both are written in rust and can be installed with `cargo install`: + +``` +cargo install systemfd cargo-watch +``` + +## Code Changes + +Additionally you need to slightly modify your actix app so that it can pick up +an external socket opened by `systemfd`. Add the listenfd dependency to your +app: + +```ini +[dependencices] +listenfd = "0.3" +``` + +Then modify your server code to only invoke `bind` as a fallback: + +```rust +extern crate listenfd; + +use listenfd::ListenFd; +use actix_web::{server, App, HttpRequest, Responder}; + +fn index(_req: HttpRequest) -> impl Responder { + "Hello World!" +} + +fn main() { + let mut listenfd = ListenFd::from_env(); + let mut server = server::new(|| { + App::new() + .resource("/", |r| r.f(index)) + }); + + server = if let Some(l) = listenfd.take_tcp_listener(0).unwrap() { + server.listen(l) + } else { + server.bind("127.0.0.1:3000").unwrap() + }; + + server.run(); +} +``` + +## Running the Server + +To now run the development server invoke this command: + +``` +systemfd -s http::3000 -- cargo watch -x run +``` diff --git a/content/docs/databases.md b/content/docs/databases.md new file mode 100644 index 0000000..f725c2e --- /dev/null +++ b/content/docs/databases.md @@ -0,0 +1,132 @@ +--- +title: Databases +menu: docs_patterns +weight: 1010 +--- + +# Diesel + +At the moment, Diesel 1.0 does not support asynchronous operations, +but it possible to use the `actix` synchronous actor system as a database interface api. + +Technically, sync actors are worker style actors. Multiple sync actors +can be run in parallel and process messages from same queue. Sync actors work in mpsc mode. + +Let's create a simple database api that can insert a new user row into a SQLite table. +We must define a sync actor and a connection that this actor will use. The same approach +can be used for other databases. + +```rust +use actix::prelude::*; + +struct DbExecutor(SqliteConnection); + +impl Actor for DbExecutor { + type Context = SyncContext; +} +``` + +This is the definition of our actor. Now, we must define the *create user* message and response. + +```rust +struct CreateUser { + name: String, +} + +impl Message for CreateUser { + type Result = Result; +} +``` + +We can send a `CreateUser` message to the `DbExecutor` actor, and as a result, we will receive a +`User` model instance. Next, we must define the handler implementation for this message. + +```rust +impl Handler for DbExecutor { + type Result = Result; + + fn handle(&mut self, msg: CreateUser, _: &mut Self::Context) -> Self::Result + { + use self::schema::users::dsl::*; + + // Create insertion model + let uuid = format!("{}", uuid::Uuid::new_v4()); + let new_user = models::NewUser { + id: &uuid, + name: &msg.name, + }; + + // normal diesel operations + diesel::insert_into(users) + .values(&new_user) + .execute(&self.0) + .expect("Error inserting person"); + + let mut items = users + .filter(id.eq(&uuid)) + .load::(&self.0) + .expect("Error loading person"); + + Ok(items.pop().unwrap()) + } +} +``` + +That's it! Now, we can use the *DbExecutor* actor from any http handler or middleware. +All we need is to start *DbExecutor* actors and store the address in a state where http handler +can access it. + +```rust +/// This is state where we will store *DbExecutor* address. +struct State { + db: Addr, +} + +fn main() { + let sys = actix::System::new("diesel-example"); + + // Start 3 parallel db executors + let addr = SyncArbiter::start(3, || { + DbExecutor(SqliteConnection::establish("test.db").unwrap()) + }); + + // Start http server + HttpServer::new(move || { + App::with_state(State{db: addr.clone()}) + .resource("/{name}", |r| r.method(Method::GET).a(index))}) + .bind("127.0.0.1:8080").unwrap() + .start().unwrap(); + + println!("Started http server: 127.0.0.1:8080"); + let _ = sys.run(); +} +``` + +We will use the address in a request handler. The handle returns a future object; +thus, we receive the message response asynchronously. +`Route::a()` must be used for async handler registration. + + +```rust +/// Async handler +fn index(req: HttpRequest) -> Box> { + let name = &req.match_info()["name"]; + + // Send message to `DbExecutor` actor + req.state().db.send(CreateUser{name: name.to_owned()}) + .from_err() + .and_then(|res| { + match res { + Ok(user) => Ok(HttpResponse::Ok().json(user)), + Err(_) => Ok(HttpResponse::InternalServerError().into()) + } + }) + .responder() +} +``` + +> A full example is available in the +> [examples directory](https://github.com/actix/examples/tree/master/diesel/). + +> More information on sync actors can be found in the +> [actix documentation](https://docs.rs/actix/0.5.0/actix/sync/index.html). diff --git a/content/docs/errors.md b/content/docs/errors.md new file mode 100644 index 0000000..3e7e508 --- /dev/null +++ b/content/docs/errors.md @@ -0,0 +1,238 @@ +--- +title: Errors +menu: docs_advanced +weight: 180 +--- + +# Errors + +Actix uses its own [`actix_web::error::Error`][actixerror] type and +[`actix_web::error::ResponseError`][responseerror] trait for error handling +from web handlers. + +If a handler returns an `Error` (referring to the [general Rust trait +`std::error::Error`][stderror]) in a `Result` that also implements the +`ResponseError` trait, actix will render that error as an HTTP response. +`ResponseError` has a single function called `error_response()` that returns +`HttpResponse`: + +```rust +pub trait ResponseError: Fail { + fn error_response(&self) -> HttpResponse { + HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR) + } +} +``` + +A `Responder` coerces compatible `Result`s into HTTP responses: + +```rust +impl> Responder for Result +``` + +`Error` in the code above is actix's error definition, and any errors that +implement `ResponseError` can be converted to one automatically. + +Actix-web provides `ResponseError` implementations for some common non-actix +errors. For example, if a handler responds with an `io::Error`, that error is +converted into an `HttpInternalServerError`: + +```rust +use std::io; + +fn index(req: HttpRequest) -> io::Result { + Ok(fs::NamedFile::open("static/index.html")?) +} +``` + +See [the actix-web API documentation](responseerrorimpls) for a full list of +foreign implementations for `ResponseError`. + +## An example of a custom error response + +Here's an example implementation for `ResponseError`: + +```rust +use actix_web::*; + +#[derive(Fail, Debug)] +#[fail(display="my error")] +struct MyError { + name: &'static str +} + +// Use default implementation for `error_response()` method +impl error::ResponseError for MyError {} + +fn index(req: HttpRequest) -> Result<&'static str, MyError> { + Err(MyError{name: "test"}) +} +``` + +`ResponseError` has a default implementation for `error_response()` that will +render a *500* (internal server error), and that's what will happen when the +`index` handler executes above. + +Override `error_response()` to produce more useful results: + +```rust +#[macro_use] extern crate failure; +use actix_web::{App, HttpRequest, HttpResponse, http, error}; + +#[derive(Fail, Debug)] +enum MyError { + #[fail(display="internal error")] + InternalError, + #[fail(display="bad request")] + BadClientData, + #[fail(display="timeout")] + Timeout, +} + +impl error::ResponseError for MyError { + fn error_response(&self) -> HttpResponse { + match *self { + MyError::InternalError => HttpResponse::new( + http::StatusCode::INTERNAL_SERVER_ERROR), + MyError::BadClientData => HttpResponse::new( + http::StatusCode::BAD_REQUEST), + MyError::Timeout => HttpResponse::new( + http::StatusCode::GATEWAY_TIMEOUT), + } + } +} + +fn index(req: HttpRequest) -> Result<&'static str, MyError> { + Err(MyError::BadClientData) +} +``` + +# Error helpers + +Actix provides a set of error helper functions that are useful for generating +specific HTTP error codes from other errors. Here we convert `MyError`, which +doesn't implement the `ResponseError` trait, to a *400* (bad request) using +`map_err`: + +```rust +# extern crate actix_web; +use actix_web::*; + +#[derive(Debug)] +struct MyError { + name: &'static str +} + +fn index(req: HttpRequest) -> Result<&'static str> { + let result: Result<&'static str, MyError> = Err(MyError{name: "test"}); + + Ok(result.map_err(|e| error::ErrorBadRequest(e.name))?) +} +``` + +See the [API documentation for actix-web's `error` module][errorhelpers] for a +full list of available error helpers. + +# Compatibility with failure + +Actix-web provides automatic compatibility with the [failure] library so that +errors deriving `fail` will be converted automatically to an actix error. Keep +in that those errors will render with the default *500* status code unless you +also provide your own `error_response()` implementation for them. + +# Error logging + +Actix logs all errors at the `WARN` log level. If an application's log level is +set to `DEBUG` and `RUST_BACKTRACE` is enabled, the backtrace is also logged. +These are configurable with environmental variables: + +``` +>> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run +``` + +The `Error` type uses the cause's error backtrace if available. If the +underlying failure does not provide a backtrace, a new backtrace is constructed +pointing to the point where the conversion occurred (rather than the origin of +the error). + +# Recommended practices in error handling + +It might be useful to think about dividing the errors an application produces +into two broad groups: those which are intended to be be user-facing, and those +which are not. + +An example of the former is that I might use failure to specify a `UserError` +enum which encapsulates a `ValidationError` to return whenever a user sends bad +input: + +```rust +#[macro_use] extern crate failure; +use actix_web::{HttpResponse, http, error}; + +#[derive(Fail, Debug)] +enum UserError { + #[fail(display="Validation error on field: {}", field)] + ValidationError { + field: String, + } +} + +impl error::ResponseError for UserError { + fn error_response(&self) -> HttpResponse { + match *self { + UserError::ValidationError { .. } => HttpResponse::new( + http::StatusCode::BAD_REQUEST), + } + } +} +``` + +This will behave exactly as intended because the error message defined with +`display` is written with the explicit intent to be read by a user. + +However, sending back an error's message isn't desirable for all errors -- +there are many failures that occur in a server environment where we'd probably +want the specifics to be hidden from the user. For example, if a database goes +down and client libraries start producing connect timeout errors, or if an HTML +template was improperly formatted and errors when rendered. In these cases, it +might be preferable to map the errors to a generic error suitable for user +consumption. + +Here's an example that maps an internal error to a user-facing `InternalError` +with a custom message: + +```rust +#[macro_use] extern crate failure; +use actix_web::{App, HttpRequest, HttpResponse, http, error, fs}; + +#[derive(Fail, Debug)] +enum UserError { + #[fail(display="An internal error occurred. Please try again later.")] + InternalError, +} + +impl error::ResponseError for UserError { + fn error_response(&self) -> HttpResponse { + match *self { + UserError::InternalError => HttpResponse::new( + http::StatusCode::INTERNAL_SERVER_ERROR), + } + } +} + +fn index(_req: HttpRequest) -> Result<&'static str, UserError> { + fs::NamedFile::open("static/index.html").map_err(|_e| UserError::InternalError)?; + Ok("success!") +} +``` + +By dividing errors into those which are user facing and those which are not, we +can ensure that we don't accidentally expose users to errors thrown by +application internals which they weren't meant to see. + +[actixerror]: ../../actix-web/actix_web/error/struct.Error.html +[errorhelpers]: ../../actix-web/actix_web/error/index.html#functions +[failure]: https://github.com/rust-lang-nursery/failure +[responseerror]: ../../actix-web/actix_web/error/trait.ResponseError.html +[responseerrorimpls]: ../../actix-web/actix_web/error/trait.ResponseError.html#foreign-impls +[stderror]: https://doc.rust-lang.org/std/error/trait.Error.html diff --git a/content/docs/extractors.md b/content/docs/extractors.md new file mode 100644 index 0000000..3654e3b --- /dev/null +++ b/content/docs/extractors.md @@ -0,0 +1,227 @@ +--- +title: Extractors +menu: docs_basics +weight: 170 +--- + +# Type-safe information extraction + +Actix provides facility for type-safe request information extraction. By default, +actix provides several extractor implementations. + +# Path + +[*Path*](../../actix-web/actix_web/struct.Path.html) provides information that can +be extracted from the Request's path. You can deserialize any variable +segment from the path. + +For instance, for resource that registered for `/users/{userid}/{friend}` path +two segments could be deserialized, `userid` and `friend`. This segments +could be extracted to a `tuple`, i.e. `Path<(u32, String)>` or structure +that implementd `Deserialize` trait from *serde* crate. + +```rust +use actix_web::{App, Path, Result, http}; + +/// extract path info from "/users/{userid}/{friend}" url +/// {userid} - - deserializes to a u32 +/// {friend} - deserializes to a String +fn index(info: Path<(u32, String)>) -> Result { + Ok(format!("Welcome {}! {}", info.1, info.0)) +} + +fn main() { + let app = App::new().resource( + "/users/{userid}/{friend}", // <- define path parameters + |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor +} +``` + +Remember! handler function that uses extractors has to be registered with +[*Route::with()*](../../actix-web/actix_web/dev/struct.Route.html#method.with) method. + +It is also possible to extract path information to a specific type that +implements `Deserialize` trait from *serde*. Here is equivalent example that uses *serde* +instead of *tuple* type. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Path, Result, http}; + +#[derive(Deserialize)] +struct Info { + userid: u32, + friend: String, +} + +/// extract path info using serde +fn index(info: Path) -> Result { + Ok(format!("Welcome {}!", info.friend)) +} + +fn main() { + let app = App::new().resource( + "/users/{userid}/{friend}", // <- define path parameters + |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor +} +``` + +# Query + +Same can be done with the request's query. +[*Query*](../../actix-web/actix_web/struct.Query.html) +type provides extraction functionality. Underneath it uses *serde_urlencoded* crate. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Query, http}; + +#[derive(Deserialize)] +struct Info { + username: String, +} + +// this handler get called only if the request's query contains `username` field +fn index(info: Query) -> String { + format!("Welcome {}!", info.username) +} + +fn main() { + let app = App::new().resource( + "/index.html", + |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor +} +``` + +# Json + +[*Json*](../../actix-web/actix_web/struct.Json.html) allows to deserialize +request body to a struct. To extract typed information from request's body, +the type `T` must implement the `Deserialize` trait from *serde*. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Json, Result, http}; + +#[derive(Deserialize)] +struct Info { + username: String, +} + +/// deserialize `Info` from request's body +fn index(info: Json) -> Result { + Ok(format!("Welcome {}!", info.username)) +} + +fn main() { + let app = App::new().resource( + "/index.html", + |r| r.method(http::Method::POST).with(index)); // <- use `with` extractor +} +``` + +Some extractors provide a way to configure extraction process. Json extractor +[*JsonConfig*](../../actix-web/actix_web/dev/struct.JsonConfig.html) type for configuration. +When you register handler `Route::with()` returns configuration instance. In case of +*Json* extractor it returns *JsonConfig*. You can configure max size of the json +payload and custom error handler function. + +Following example limits size of the payload to 4kb and uses custom error hander. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Json, HttpResponse, Result, http, error}; + +#[derive(Deserialize)] +struct Info { + username: String, +} + +/// deserialize `Info` from request's body, max payload size is 4kb +fn index(info: Json) -> Result { + Ok(format!("Welcome {}!", info.username)) +} + +fn main() { + let app = App::new().resource( + "/index.html", |r| { + r.method(http::Method::POST) + .with(index) + .limit(4096) // <- change json extractor configuration + .error_handler(|err, req| { // <- create custom error response + error::InternalError::from_response( + err, HttpResponse::Conflict().finish()).into() + }); + }); +} +``` + +# Form + +At the moment only url-encoded forms are supported. Url encoded body +could be extracted to a specific type. This type must implement +the `Deserialize` trait from *serde* crate. + +[*FormConfig*](../../actix-web/actix_web/dev/struct.FormConfig.html) allows +to configure extraction process. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Form, Result}; + +#[derive(Deserialize)] +struct FormData { + username: String, +} + +/// extract form data using serde +/// this handler get called only if content type is *x-www-form-urlencoded* +/// and content of the request could be deserialized to a `FormData` struct +fn index(form: Form) -> Result { + Ok(format!("Welcome {}!", form.username)) +} +# fn main() {} +``` + +# Multiple extractors + +Actix provides extractor implementation for tuples (up to 10 elements) +which elements provide `FromRequest` impl. + +For example we can use path extractor and query extractor at the same time. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Query, Path, http}; + +#[derive(Deserialize)] +struct Info { + username: String, +} + +fn index(data: (Path<(u32, String)>, Query)) -> String { + let (path, query) = data; + format!("Welcome {}!", query.username) +} + +fn main() { + let app = App::new().resource( + "/users/{userid}/{friend}", // <- define path parameters + |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor +} +``` + +# Other + +Actix also provides several other extractors: + +* [*State*](../../actix-web/actix_web/struct.State.html) - If you need + access to an application state. This is similar to a `HttpRequest::state()`. +* *HttpRequest* - *HttpRequest* itself is an extractor which returns self. + In case if you need access to the request. +* *String* - You can convert request's payload to a *String*. + [*Example*](../../actix-web/actix_web/trait.FromRequest.html#example-1) + is available in doc strings. +* *bytes::Bytes* - You can convert request's payload to a *Bytes*. + [*Example*](../../actix-web/actix_web/trait.FromRequest.html#example) + is available in doc strings. diff --git a/content/docs/getting-started.md b/content/docs/getting-started.md new file mode 100644 index 0000000..1802535 --- /dev/null +++ b/content/docs/getting-started.md @@ -0,0 +1,67 @@ +--- +title: Getting Started +menu: docs_basics +weight: 130 +--- + +# Getting Started + +Let’s write our first actix web application! + +## Hello, world! + +Start by creating a new binary-based Cargo project and changing into the new directory: + +```bash +cargo new hello-world --bin +cd hello-world +``` + +Now, add `actix-web` as dependencies of your project by ensuring your `Cargo.toml` +contains the following: + +```ini +[dependencies] +actix-web = "{{< actix-version "actix-web" >}}" +``` + +In order to implement a web server, we first need to create a request handler. + +A request handler is a function that accepts an `HttpRequest` instance as its only parameter +and returns a type that can be converted into `HttpResponse`: + +Filename: `src/main.rs` + +```rust +extern crate actix_web; +use actix_web::{HttpRequest, Responder, App, server}; + +fn index(req: _HttpRequest) -> Responder { + "Hello world!" +} +``` + +Next, create an `Application` instance and register the request handler with +the application's `resource` on a particular *HTTP method* and *path* and +after that, the application instance can be used with `HttpServer` to listen +for incoming connections. The server accepts a function that should return an +`HttpHandler` instance. For simplicity `server::new` could be used, this +function is shortcut for `HttpServer::new`: + +```rust +fn main() { + server::new(|| { + App::new() + .resource("/", |r| r.f(index)) + }) + .bind("127.0.0.1:8088").unwrap() + .run(); +} +``` + +That's it! Now, compile and run the program with `cargo run`. +Head over to ``http://localhost:8088/`` to see the results. + +If you want you can have an automatic reloading server during development +that recompiles on demand. To see how this can be accomplished have a look +at the [autoreload pattern](../autoreload/). diff --git a/content/docs/handlers.md b/content/docs/handlers.md new file mode 100644 index 0000000..9b7148a --- /dev/null +++ b/content/docs/handlers.md @@ -0,0 +1,292 @@ +--- +title: Handlers +menu: docs_basics +weight: 160 +--- + +# Request Handlers + +A request handler can be any object that implements +[*Handler*](../../actix-web/actix_web/dev/trait.Handler.html) trait. + +Request handling happens in two stages. First the handler object is called, +returning any object that implements the +[*Responder*](../../actix-web/actix_web/trait.Responder.html#foreign-impls) trait. +Then, `respond_to()` is called on the returned object, converting itself to a `AsyncResult` or `Error`. + +By default actix provides `Responder` implementations for some standard types, +such as `&'static str`, `String`, etc. + +> For a complete list of implementations, check +> [*Responder documentation*](../../actix-web/actix_web/trait.Responder.html#foreign-impls). + +Examples of valid handlers: + +```rust +fn index(req: HttpRequest) -> &'static str { + "Hello world!" +} +``` + +```rust +fn index(req: HttpRequest) -> String { + "Hello world!".to_owned() +} +``` + +You can also change the signature to return `impl Responder` which works well if more +complex types are involved. + +```rust +fn index(req: HttpRequest) -> impl Responder { + Bytes::from_static("Hello world!") +} +``` + +```rust,ignore +fn index(req: HttpRequest) -> Box> { + ... +} +``` + +*Handler* trait is generic over *S*, which defines the application state's type. +Application state is accessible from the handler with the `HttpRequest::state()` method; +however, state is accessible as a read-only reference. If you need mutable access to state, +it must be implemented. + +> **Note**: Alternatively, the handler can mutably access its own state because the `handle` method takes +> mutable reference to *self*. **Beware**, actix creates multiple copies +> of the application state and the handlers, unique for each thread. If you run your +> application in several threads, actix will create the same amount as number of threads +> of application state objects and handler objects. + +Here is an example of a handler that stores the number of processed requests: + +```rust +use actix_web::{App, HttpRequest, HttpResponse, dev::Handler}; + +struct MyHandler(usize); + +impl Handler for MyHandler { + type Result = HttpResponse; + + /// Handle request + fn handle(&mut self, req: HttpRequest) -> Self::Result { + self.0 += 1; + HttpResponse::Ok().into() + } +} +``` + +Although this handler will work, `self.0` will be different depending on the number of threads and +number of requests processed per thread. A proper implementation would use `Arc` and `AtomicUsize`. + +```rust +use actix_web::{server, App, HttpRequest, HttpResponse, dev::Handler}; +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; + +struct MyHandler(Arc); + +impl Handler for MyHandler { + type Result = HttpResponse; + + /// Handle request + fn handle(&mut self, req: HttpRequest) -> Self::Result { + self.0.fetch_add(1, Ordering::Relaxed); + HttpResponse::Ok().into() + } +} + +fn main() { + let sys = actix::System::new("example"); + + let inc = Arc::new(AtomicUsize::new(0)); + + server::new( + move || { + let cloned = inc.clone(); + App::new() + .resource("/", move |r| r.h(MyHandler(cloned))) + }) + .bind("127.0.0.1:8088").unwrap() + .start(); + + println!("Started http server: 127.0.0.1:8088"); + let _ = sys.run(); +} +``` + +> Be careful with synchronization primitives like `Mutex` or `RwLock`. The `actix-web` framework +> handles requests asynchronously. By blocking thread execution, all concurrent +> request handling processes would block. If you need to share or update some state +> from multiple threads, consider using the [actix](https://actix.github.io/actix/actix/) actor system. + +## Response with custom type + +To return a custom type directly from a handler function, the type needs to implement the `Responder` trait. + +Let's create a response for a custom type that serializes to an `application/json` response: + +```rust +# extern crate actix; +# extern crate actix_web; +extern crate serde; +extern crate serde_json; +#[macro_use] extern crate serde_derive; +use actix_web::{server, App, HttpRequest, HttpResponse, Error, Responder, http}; + +#[derive(Serialize)] +struct MyObj { + name: &'static str, +} + +/// Responder +impl Responder for MyObj { + type Item = HttpResponse; + type Error = Error; + + fn respond_to(self, req: &HttpRequest) -> Result { + let body = serde_json::to_string(&self)?; + + // Create response and set content type + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(body)) + } +} + +fn index(req: HttpRequest) -> impl Responder { + MyObj { name: "user" } +} + +fn main() { + let sys = actix::System::new("example"); + + server::new( + || App::new() + .resource("/", |r| r.method(http::Method::GET).f(index))) + .bind("127.0.0.1:8088").unwrap() + .start(); + + println!("Started http server: 127.0.0.1:8088"); + let _ = sys.run(); +} +``` + +## Async handlers + +There are two different types of async handlers. Response objects can be generated asynchronously +or more precisely, any type that implements the [*Responder*](../../actix-web/actix_web/trait.Responder.html) trait. + +In this case, the handler must return a `Future` object that resolves to the *Responder* type, i.e: + +```rust +use actix_web::*; +use bytes::Bytes; +use futures::stream::once; +use futures::future::{Future, result}; + +fn index(req: HttpRequest) -> Box> { + + result(Ok(HttpResponse::Ok() + .content_type("text/html") + .body(format!("Hello!")))) + .responder() +} + +fn index2(req: HttpRequest) -> Box> { + result(Ok("Welcome!")) + .responder() +} + +fn main() { + App::new() + .resource("/async", |r| r.route().a(index)) + .resource("/", |r| r.route().a(index2)) + .finish(); +} +``` + +Or the response body can be generated asynchronously. In this case, body +must implement the stream trait `Stream`, i.e: + +```rust +use actix_web::*; +use bytes::Bytes; +use futures::stream::once; + +fn index(req: HttpRequest) -> HttpResponse { + let body = once(Ok(Bytes::from_static(b"test"))); + + HttpResponse::Ok() + .content_type("application/json") + .body(Body::Streaming(Box::new(body))) +} + +fn main() { + App::new() + .resource("/async", |r| r.f(index)) + .finish(); +} +``` + +Both methods can be combined. (i.e Async response with streaming body) + +It is possible to return a `Result` where the `Result::Item` type can be `Future`. +In this example, the `index` handler can return an error immediately or return a +future that resolves to a `HttpResponse`. + +```rust +use actix_web::*; +use bytes::Bytes; +use futures::stream::once; +use futures::future::{Future, result}; + +fn index(req: HttpRequest) -> Result>, Error> { + if is_error() { + Err(error::ErrorBadRequest("bad request")) + } else { + Ok(Box::new( + result(Ok(HttpResponse::Ok() + .content_type("text/html") + .body(format!("Hello!")))))) + } +} +``` + +## Different return types (Either) + +Sometimes, you need to return different types of responses. For example, +you can error check and return errors, return async responses, or any result that requires two different types. + +For this case, the [*Either*](../../actix-web/actix_web/enum.Either.html) type can be used. +`Either` allows combining two different responder types into a single type. + +```rust +use futures::future::{Future, result}; +use actix_web::{Either, Error, HttpResponse}; + +type RegisterResult = Either>>; + +fn index(req: HttpRequest) -> impl Responder { + if is_a_variant() { // <- choose variant A + Either::A( + HttpResponse::BadRequest().body("Bad data")) + } else { + Either::B( // <- variant B + result(Ok(HttpResponse::Ok() + .content_type("text/html") + .body(format!("Hello!")))).responder()) + } +} +``` + +## Tokio core handle + +Any `actix-web` handler runs within a properly configured +[actix system](https://actix.github.io/actix/actix/struct.System.html) +and [arbiter](https://actix.github.io/actix/actix/struct.Arbiter.html). +You can always get access to the tokio handle via the +[Arbiter::handle()](https://actix.github.io/actix/actix/struct.Arbiter.html#method.handle) +method. diff --git a/content/docs/http2.md b/content/docs/http2.md new file mode 100644 index 0000000..85ab4a5 --- /dev/null +++ b/content/docs/http2.md @@ -0,0 +1,50 @@ +--- +title: HTTP/2.0 +menu: docs_proto +weight: 250 +--- + +`actix-web` automatically upgrades connections to *HTTP/2.0* if possible. + +# Negotiation + +*HTTP/2.0* protocol over tls without prior knowledge requires +[tls alpn](https://tools.ietf.org/html/rfc7301). + +> Currently, only `rust-openssl` has support. + +`alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the +[serve_tls](../../actix-web/actix_web/server/struct.HttpServer.html#method.serve_tls) method. + +```toml +[dependencies] +actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["alpn"] } +openssl = { version = "0.10", features = ["v110"] } +``` + +```rust +use std::fs::File; +use actix_web::*; +use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype}; + +fn main() { + // load ssl keys + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + builder.set_private_key_file("key.pem", SslFiletype::PEM).unwrap(); + builder.set_certificate_chain_file("cert.pem").unwrap(); + + HttpServer::new( + || App::new() + .resource("/index.html", |r| r.f(index))) + .bind("127.0.0.1:8080").unwrap(); + .serve_ssl(builder).unwrap(); +} +``` + +Upgrades to *HTTP/2.0* schema described in +[rfc section 3.2](https://http2.github.io/http2-spec/#rfc.section.3.2) is not supported. +Starting *HTTP/2* with prior knowledge is supported for both clear text connection +and tls connection. [rfc section 3.4](https://http2.github.io/http2-spec/#rfc.section.3.4) + +> Check out [examples/tls](https://github.com/actix/examples/tree/master/tls) +> for a concrete example. diff --git a/content/docs/installation.md b/content/docs/installation.md new file mode 100644 index 0000000..542cb35 --- /dev/null +++ b/content/docs/installation.md @@ -0,0 +1,52 @@ +--- +title: Installation +menu: docs_intro +weight: 110 +--- + +# Installing Rust + +Since `actix-web` is a Rust framework you will need Rust to get started with it. +If you don't have it yet we recommend you use `rustup` to manage your Rust +installation. The [official rust +guide](https://doc.rust-lang.org/book/second-edition/ch01-01-installation.html) +has a wonderful section on getting started. + +We currently require at least Rust 1.24 so make sure you run `rustup update` +to have the latest and greatest Rust version available. In particular this +guide will assume that you actually run Rust 1.26 or later. + +# Installing `actix-web` + +Thank's to Rust's `cargo` package manger you won't need to explicitly install +`actix-web`. Just depend on it and you're ready to go. For the unlikely +case that you want to use the development version of actix-web you can +depend on the git repository directly. + +Release version: + +```ini +[dependencies] +actix-web = "{{< actix-version "actix-web" >}}" +``` + +Development version: + +```ini +[dependencies] +actix-web = { git = "https://github.com/actix/actix-web } +``` + +# Diving In + +There are two paths you can take here. You can follow the guide along or if +you are very impatient you might want to have a look at our +[extensive example repository](https://github.com/actix/examples) and run the +included examples. Here for instance is how you run the included `basics` +example: + +``` +git clone https://github.com/actix/examples +cd examples/basics +cargo run +``` diff --git a/content/docs/middleware.md b/content/docs/middleware.md new file mode 100644 index 0000000..e93a16a --- /dev/null +++ b/content/docs/middleware.md @@ -0,0 +1,250 @@ +--- +title: Middlewares +menu: docs_advanced +weight: 220 +--- + +# Middleware + +Actix's middleware system allows us to add additional behavior to request/response processing. +Middleware can hook into an incoming request process, enabling us to modify requests +as well as halt request processing to return a response early. + +Middleware can also hook into response processing. + +Typically, middleware is involved in the following actions: + +* Pre-process the Request +* Post-process a Response +* Modify application state +* Access external services (redis, logging, sessions) + +Middleware is registered for each application and executed in same order as +registration. In general, a *middleware* is a type that implements the +[*Middleware trait*](../../actix-web/actix_web/middleware/trait.Middleware.html). +Each method in this trait has a default implementation. Each method can return +a result immediately or a *future* object. + +The following demonstrates using middleware to add request and response headers: + +```rust +use http::{header, HttpTryFrom}; +use actix_web::{App, HttpRequest, HttpResponse, Result}; +use actix_web::middleware::{Middleware, Started, Response}; + +struct Headers; // <- Our middleware + +/// Middleware implementation, middlewares are generic over application state, +/// so you can access state with `HttpRequest::state()` method. +impl Middleware for Headers { + + /// Method is called when request is ready. It may return + /// future, which should resolve before next middleware get called. + fn start(&self, req: &mut HttpRequest) -> Result { + req.headers_mut().insert( + header::CONTENT_TYPE, header::HeaderValue::from_static("text/plain")); + Ok(Started::Done) + } + + /// Method is called when handler returns response, + /// but before sending http message to peer. + fn response(&self, req: &mut HttpRequest, mut resp: HttpResponse) + -> Result + { + resp.headers_mut().insert( + header::HeaderName::try_from("X-VERSION").unwrap(), + header::HeaderValue::from_static("0.2")); + Ok(Response::Done(resp)) + } +} + +fn main() { + App::new() + // Register middleware, this method can be called multiple times + .middleware(Headers) + .resource("/", |r| r.f(|_| HttpResponse::Ok())); +} +``` + +> Actix provides several useful middlewares, such as *logging*, *user sessions*, etc. + +# Logging + +Logging is implemented as a middleware. +It is common to register a logging middleware as the first middleware for the application. +Logging middleware must be registered for each application. + +The `Logger` middleware uses the standard log crate to log information. You should enable logger +for *actix_web* package to see access log ([env_logger](https://docs.rs/env_logger/*/env_logger/) +or similar). + +## Usage + +Create `Logger` middleware with the specified `format`. +Default `Logger` can be created with `default` method, it uses the default format: + +```ignore + %a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T +``` + +```rust +extern crate env_logger; +use actix_web::App; +use actix_web::middleware::Logger; + +fn main() { + std::env::set_var("RUST_LOG", "actix_web=info"); + env_logger::init(); + + App::new() + .middleware(Logger::default()) + .middleware(Logger::new("%a %{User-Agent}i")) + .finish(); +} +``` + +The following is an example of the default logging format: + +``` +INFO:actix_web::middleware::logger: 127.0.0.1:59934 [02/Dec/2017:00:21:43 -0800] "GET / HTTP/1.1" 302 0 "-" "curl/7.54.0" 0.000397 +INFO:actix_web::middleware::logger: 127.0.0.1:59947 [02/Dec/2017:00:22:40 -0800] "GET /index.html HTTP/1.1" 200 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:57.0) Gecko/20100101 Firefox/57.0" 0.000646 +``` + +## Format + + `%%` The percent sign + + `%a` Remote IP-address (IP-address of proxy if using reverse proxy) + + `%t` Time when the request was started to process + + `%P` The process ID of the child that serviced the request + + `%r` First line of request + + `%s` Response status code + + `%b` Size of response in bytes, including HTTP headers + + `%T` Time taken to serve the request, in seconds with floating fraction in .06f format + + `%D` Time taken to serve the request, in milliseconds + + `%{FOO}i` request.headers['FOO'] + + `%{FOO}o` response.headers['FOO'] + + `%{FOO}e` os.environ['FOO'] + +## Default headers + +To set default response headers, the `DefaultHeaders` middleware can be used. The +*DefaultHeaders* middleware does not set the header if response headers already contain +a specified header. + +```rust +use actix_web::{http, middleware, App, HttpResponse}; + +fn main() { + let app = App::new() + .middleware( + middleware::DefaultHeaders::new() + .header("X-Version", "0.2")) + .resource("/test", |r| { + r.method(http::Method::GET).f(|req| HttpResponse::Ok()); + r.method(http::Method::HEAD).f(|req| HttpResponse::MethodNotAllowed()); + }) + .finish(); +} +``` + +## User sessions + +Actix provides a general solution for session management. The +[**SessionStorage**](../../actix-web/actix_web/middleware/session/struct.SessionStorage.html) middleware can be +used with different backend types to store session data in different backends. + +> By default, only cookie session backend is implemented. Other backend implementations +> can be added. + +[**CookieSessionBackend**](../../actix-web/actix_web/middleware/session/struct.CookieSessionBackend.html) +uses cookies as session storage. `CookieSessionBackend` creates sessions which +are limited to storing fewer than 4000 bytes of data, as the payload must fit into a +single cookie. An internal server error is generated if a session contains more than 4000 bytes. + +A cookie may have a security policy of *signed* or *private*. Each has a respective `CookieSessionBackend` constructor. + +A *signed* cookie may be viewed but not modified by the client. A *private* cookie may neither be viewed nor modified by the client. + +The constructors take a key as an argument. This is the private key for cookie session - when this value is changed, all session data is lost. + +In general, you create a +`SessionStorage` middleware and initialize it with specific backend implementation, +such as a `CookieSessionBackend`. To access session data, +[*HttpRequest::session()*](../../actix-web/actix_web/middleware/session/trait.RequestSession.html#tymethod.session) + must be used. This method returns a +[*Session*](../../actix-web/actix_web/middleware/session/struct.Session.html) object, which allows us to get or set +session data. + +```rust +use actix_web::{server, App, HttpRequest, Result}; +use actix_web::middleware::session::{RequestSession, SessionStorage, CookieSessionBackend}; + +fn index(mut req: HttpRequest) -> Result<&'static str> { + // access session data + if let Some(count) = req.session().get::("counter")? { + println!("SESSION value: {}", count); + req.session().set("counter", count+1)?; + } else { + req.session().set("counter", 1)?; + } + + Ok("Welcome!") +} + +fn main() { + let sys = actix::System::new("basic-example"); + server::new( + || App::new().middleware( + SessionStorage::new( + CookieSessionBackend::signed(&[0; 32]) + .secure(false) + ))) + .bind("127.0.0.1:59880").unwrap() + .start(); + let _ = sys.run(); +} +``` + +# Error handlers + +`ErrorHandlers` middleware allows us to provide custom handlers for responses. + +You can use the `ErrorHandlers::handler()` method to register a custom error handler +for a specific status code. You can modify an existing response or create a completly new +one. The error handler can return a response immediately or return a future that resolves +into a response. + +```rust +use actix_web::{ + App, HttpRequest, HttpResponse, Result, + http, middleware::Response, middleware::ErrorHandlers}; + +fn render_500(_: &mut HttpRequest, resp: HttpResponse) -> Result { + let mut builder = resp.into_builder(); + builder.header(http::header::CONTENT_TYPE, "application/json"); + Ok(Response::Done(builder.into())) +} + +fn main() { + let app = App::new() + .middleware( + ErrorHandlers::new() + .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500)) + .resource("/test", |r| { + r.method(http::Method::GET).f(|_| HttpResponse::Ok()); + r.method(http::Method::HEAD).f(|_| HttpResponse::MethodNotAllowed()); + }) + .finish(); +} +``` diff --git a/content/docs/request.md b/content/docs/request.md new file mode 100644 index 0000000..ba7b29c --- /dev/null +++ b/content/docs/request.md @@ -0,0 +1,207 @@ +--- +title: Requests +menu: docs_advanced +weight: 200 +--- + +# Content Encoding + +Actix automatically *decompresses* payloads. The following codecs are supported: + +* Brotli +* Gzip +* Deflate +* Identity + +If request headers contain a `Content-Encoding` header, the request payload is decompressed +according to the header value. Multiple codecs are not supported, +i.e: `Content-Encoding: br, gzip`. + +# JSON Request + +There are several options for json body deserialization. + +The first option is to use *Json* extractor. First, you define a handler function +that accepts `Json` as a parameter, then, you use the `.with()` method for registering +this handler. It is also possible to accept arbitrary valid json object by +using `serde_json::Value` as a type `T`. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Json, Result, http}; + +#[derive(Deserialize)] +struct Info { + username: String, +} + +/// extract `Info` using serde +fn index(info: Json) -> Result { + Ok(format!("Welcome {}!", info.username)) +} + +fn main() { + let app = App::new().resource( + "/index.html", + |r| r.method(http::Method::POST).with(index)); // <- use `with` extractor +} +``` + +Another option is to use *HttpRequest::json()*. This method returns a +[*JsonBody*](../../actix-web/actix_web/dev/struct.JsonBody.html) object which resolves into +the deserialized value. + +```rust +#[derive(Debug, Serialize, Deserialize)] +struct MyObj { + name: String, + number: i32, +} + +fn index(mut req: HttpRequest) -> Box> { + req.json().from_err() + .and_then(|val: MyObj| { + println!("model: {:?}", val); + Ok(HttpResponse::Ok().json(val)) // <- send response + }) + .responder() +} +``` + +You may also manually load the payload into memory and then deserialize it. + +In the following example, we will deserialize a *MyObj* struct. We need to load the request +body first and then deserialize the json into an object. + +```rust +extern crate serde_json; +use futures::{Future, Stream}; + +#[derive(Serialize, Deserialize)] +struct MyObj {name: String, number: i32} + +fn index(req: HttpRequest) -> Box> { + // `concat2` will asynchronously read each chunk of the request body and + // return a single, concatenated, chunk + req.concat2() + // `Future::from_err` acts like `?` in that it coerces the error type from + // the future into the final error type + .from_err() + // `Future::and_then` can be used to merge an asynchronous workflow with a + // synchronous workflow + .and_then(|body| { + let obj = serde_json::from_slice::(&body)?; + Ok(HttpResponse::Ok().json(obj)) + }) + .responder() +} +``` + +> A complete example for both options is available in +> [examples directory](https://github.com/actix/examples/tree/master/json/). + +# Chunked transfer encoding + +Actix automatically decodes *chunked* encoding. `HttpRequest::payload()` already contains +the decoded byte stream. If the request payload is compressed with one of the supported +compression codecs (br, gzip, deflate), then the byte stream is decompressed. + +# Multipart body + +Actix provides multipart stream support. +[*Multipart*](../../actix-web/actix_web/multipart/struct.Multipart.html) is implemented as +a stream of multipart items. Each item can be a +[*Field*](../../actix-web/actix_web/multipart/struct.Field.html) or a nested +*Multipart* stream.`HttpResponse::multipart()` returns the *Multipart* stream +for the current request. + +The following demonstrates multipart stream handling for a simple form: + +```rust +use actix_web::*; + +fn index(req: HttpRequest) -> Box> { + // get multipart and iterate over multipart items + req.multipart() + .and_then(|item| { + match item { + multipart::MultipartItem::Field(field) => { + println!("==== FIELD ==== {:?} {:?}", + field.headers(), + field.content_type()); + Either::A( + field.map(|chunk| { + println!("-- CHUNK: \n{}", + std::str::from_utf8(&chunk).unwrap());}) + .fold((), |_, _| result(Ok(())))) + }, + multipart::MultipartItem::Nested(mp) => { + Either::B(result(Ok(()))) + } + } + }) +} +``` + +> A full example is available in the +> [examples directory](https://github.com/actix/examples/tree/master/multipart/). + +# Urlencoded body + +Actix provides support for *application/x-www-form-urlencoded* encoded bodies. +`HttpResponse::urlencoded()` returns a +[*UrlEncoded*](../../actix-web/actix_web/dev/struct.UrlEncoded.html) future, which resolves +to the deserialized instance. The type of the instance must implement the +`Deserialize` trait from *serde*. + +The *UrlEncoded* future can resolve into an error in several cases: + +* content type is not `application/x-www-form-urlencoded` +* transfer encoding is `chunked`. +* content-length is greater than 256k +* payload terminates with error. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::*; +use futures::future::{Future, ok}; + +#[derive(Deserialize)] +struct FormData { + username: String, +} + +fn index(mut req: HttpRequest) -> Box> { + req.urlencoded::() // <- get UrlEncoded future + .from_err() + .and_then(|data| { // <- deserialized instance + println!("USERNAME: {:?}", data.username); + ok(HttpResponse::Ok().into()) + }) + .responder() +} +# fn main() {} +``` + +# Streaming request + +*HttpRequest* is a stream of `Bytes` objects. It can be used to read the request +body payload. + +In the following example, we read and print the request payload chunk by chunk: + +```rust +use actix_web::*; +use futures::{Future, Stream}; + + +fn index(mut req: HttpRequest) -> Box> { + req.from_err() + .fold((), |_, chunk| { + println!("Chunk: {:?}", chunk); + result::<_, error::PayloadError>(Ok(())) + }) + .map(|_| HttpResponse::Ok().finish()) + .responder() +} +``` diff --git a/content/docs/response.md b/content/docs/response.md new file mode 100644 index 0000000..6bceded --- /dev/null +++ b/content/docs/response.md @@ -0,0 +1,140 @@ +--- +title: Responses +menu: docs_advanced +weight: 210 +--- + +# Response + +A builder-like pattern is used to construct an instance of `HttpResponse`. +`HttpResponse` provides several methods that return a `HttpResponseBuilder` instance, +which implements various convenience methods for building responses. + +> Check the [documentation](../../actix-web/actix_web/dev/struct.HttpResponseBuilder.html) +> for type descriptions. + +The methods `.body`, `.finish`, and `.json` finalize response creation and +return a constructed *HttpResponse* instance. If this methods is called on the same +builder instance multiple times, the builder will panic. + +```rust +use actix_web::{HttpRequest, HttpResponse, http::ContentEncoding}; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok() + .content_encoding(ContentEncoding::Br) + .content_type("plain/text") + .header("X-Hdr", "sample") + .body("data") +} +``` + +# Content encoding + +Actix automatically *compresses* payloads. The following codecs are supported: + +* Brotli +* Gzip +* Deflate +* Identity + +Response payload is compressed based on the *content_encoding* parameter. +By default, `ContentEncoding::Auto` is used. If `ContentEncoding::Auto` is selected, +then the compression depends on the request's `Accept-Encoding` header. + +> `ContentEncoding::Identity` can be used to disable compression. +> If another content encoding is selected, the compression is enforced for that codec. + +For example, to enable `brotli` use `ContentEncoding::Br`: + +```rust +use actix_web::{HttpRequest, HttpResponse, http::ContentEncoding}; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok() + .content_encoding(ContentEncoding::Br) + .body("data") +} +``` + +In this case we explicitly disable content compression +by setting content encoding to a `Identity` value: + +```rust +use actix_web::{HttpRequest, HttpResponse, http::ContentEncoding}; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok() + // v- disable compression + .content_encoding(ContentEncoding::Identity) + .body("data") +} +``` + +Also it is possible to set default content encoding on application level, by +default `ContentEncoding::Auto` is used, which implies automatic content compression +negotiation. + +```rust +use actix_web::{App, HttpRequest, HttpResponse, http::ContentEncoding}; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok() + .body("data") +} + +fn main() { + let app = App::new() + // v- disable compression for all routes + .default_encoding(ContentEncoding::Identity) + .resource("/index.html", |r| r.with(index)); +} +``` + +# JSON Response + +The `Json` type allows to respond with well-formed JSON data: simply return a value of +type Json where `T` is the type of a structure to serialize into *JSON*. +The type `T` must implement the `Serialize` trait from *serde*. + +```rust +# extern crate actix_web; +#[macro_use] extern crate serde_derive; +use actix_web::{App, HttpRequest, Json, Result, http::Method}; + +#[derive(Serialize)] +struct MyObj { + name: String, +} + +fn index(req: HttpRequest) -> Result> { + Ok(Json(MyObj{name: req.match_info().query("name")?})) +} + +fn main() { + App::new() + .resource(r"/a/{name}", |r| r.method(Method::GET).f(index)) + .finish(); +} +``` + +# Chunked transfer encoding + +Chunked encoding on a response can be enabled with `HttpResponseBuilder::chunked()`. +This takes effect only for `Body::Streaming(BodyStream)` or `Body::StreamingContext` bodies. +If the response payload compression is enabled and a streaming body is used, chunked encoding +is enabled automatically. + +> Enabling chunked encoding for *HTTP/2.0* responses is forbidden. + +```rust +use actix_web::*; +use bytes::Bytes; +use futures::stream::once; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok() + .chunked() + .body(Body::Streaming(Box::new(once(Ok(Bytes::from_static(b"data")))))) +} +``` diff --git a/content/docs/sentry.md b/content/docs/sentry.md new file mode 100644 index 0000000..fe899b3 --- /dev/null +++ b/content/docs/sentry.md @@ -0,0 +1,85 @@ +--- +title: Sentry +menu: docs_patterns +weight: 1020 +--- + +# Sentry Crash Reporting + +[Sentry](https://sentry.io/) is a crash reporting system that supports the +failure crate which is the base of the actix error reporting. With a +middleware it's possible to automatically report server errors to sentry. + +# Middleware + +This middleware captures any error in the server error range (500 - 599) +and sends the attached error to sentry with its stacktrace. + +```rust +use actix_web::{HttpRequest, HttpResponse, Error}; +use actix_web::middleware::{Middleware, Response}; +use failure::Fail; +use sentry::with_client_and_scope; +use sentry::protocol::{Event, Level}; +use sentry::integrations::failure::exception_from_single_fail; + +/// Reports certain failures to sentry. +pub struct CaptureSentryError; + +impl Middleware for CaptureSentryError { + fn response(&self, _: &mut HttpRequest, mut resp: HttpResponse) + -> Result + { + if resp.status().is_server_error() { + if let Some(error) = resp.error() { + report_actix_error_to_sentry(error); + } + } + Ok(Response::Done(resp)) + } +} + +pub fn report_actix_error_to_sentry(err: &Error) { + with_client_and_scope(|client, scope| { + let mut exceptions = vec![ + exception_from_single_fail(err.cause(), Some(err.backtrace())), + ]; + let mut ptr: Option<&Fail> = err.cause().cause(); + while let Some(cause) = ptr { + exceptions.push(exception_from_single_fail(cause, cause.backtrace())); + ptr = Some(cause); + } + exceptions.reverse(); + client.capture_event( + Event { + exceptions: exceptions, + level: Level::Error, + ..Default::default() + }, + Some(scope), + ) + }); +} +``` + +# Middleware Usage + +To use the middleware the [sentry crate](https://crates.io/crates/sentry) needs to be +initialized and configured. Additionally it makes sense to also register the panic handler +to be informed about hard panics. + +```rust +extern crate sentry; + +use std::env; + +fn main() { + sentry::init("SENTRY_DSN_GOES_HERE"); + env::set_var("RUST_BACKTRACE", "1"); + sentry::integrations::panic::register_panic_handler(); + + let mut app = App::with_state(state) + .middleware(CaptureSentryError) + // ... +} +``` diff --git a/content/docs/server.md b/content/docs/server.md new file mode 100644 index 0000000..c37df48 --- /dev/null +++ b/content/docs/server.md @@ -0,0 +1,217 @@ +--- +title: Server +menu: docs_basics +weight: 150 +--- + +# The HTTP Server + +The [**HttpServer**](../../actix-web/actix_web/server/struct.HttpServer.html) type is responsible for +serving http requests. + +`HttpServer` accepts an application factory as a parameter, and the +application factory must have `Send` + `Sync` boundaries. More about that in the +*multi-threading* section. + +To bind to a specific socket address, `bind()` must be used, and it may be +called multiple times. To bind ssl socket `bind_ssl()` or `bind_tls()` should be used. +To start the http server, one of the start methods. + +- use `start()` for a server + +`HttpServer` is an actix actor. It must be initialized within a properly configured actix system: + +```rust +use actix_web::{server::HttpServer, App, HttpResponse}; + +fn main() { + let sys = actix::System::new("guide"); + + HttpServer::new(|| { + App::new() + .resource("/", |r| r.f(|_| HttpResponse::Ok())) + }) + .bind("127.0.0.1:59080").unwrap() + .start(); + + let _ = sys.run(); +} +``` + +> It is possible to start a server in a separate thread with the `run()` method. In that +> case the server spawns a new thread and creates a new actix system in it. To stop +> this server, send a `StopServer` message. + +`HttpServer` is implemented as an actix actor. It is possible to communicate with the server +via a messaging system. Start method, e.g. `start()`, returns the +address of the started http server. It accepts several messages: + +- `PauseServer` - Pause accepting incoming connections +- `ResumeServer` - Resume accepting incoming connections +- `StopServer` - Stop incoming connection processing, stop all workers and exit + +```rust +use std::thread; +use std::sync::mpsc; +use actix_web::{server, App, HttpResponse}; + +fn main() { + let (tx, rx) = mpsc::channel(); + + thread::spawn(move || { + let sys = actix::System::new("http-server"); + let addr = server::new(|| { + App::new() + .resource("/", |r| r.f(|_| HttpResponse::Ok())) + }) + .bind("127.0.0.1:0").expect("Can not bind to 127.0.0.1:0") + .shutdown_timeout(60) // <- Set shutdown timeout to 60 seconds + .start(); + let _ = tx.send(addr); + let _ = sys.run(); + }); + + let addr = rx.recv().unwrap(); + let _ = addr.send( + server::StopServer{graceful:true}).wait(); // <- Send `StopServer` message to server. +} +``` + +## Multi-threading + +`HttpServer` automatically starts an number of http workers, by default +this number is equal to number of logical CPUs in the system. This number +can be overridden with the `HttpServer::workers()` method. + +```rust +use actix_web::{App, HttpResponse, server::HttpServer}; + +fn main() { + HttpServer::new(|| { + App::new() + .resource("/", |r| r.f(|_| HttpResponse::Ok())) + }) + .workers(4); // <- Start 4 workers +} +``` + +The server creates a separate application instance for each created worker. Application state +is not shared between threads. To share state, `Arc` could be used. + +> Application state does not need to be `Send` and `Sync`, +> but factories must be `Send` + `Sync`. + +## SSL + +There are two features for ssl server: `tls` and `alpn`. The `tls` feature is +for `native-tls` integration and `alpn` is for `openssl`. + +```toml +[dependencies] +actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["alpn"] } +``` + +```rust +use std::fs::File; +use actix_web::*; + +fn main() { + // load ssl keys + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + builder.set_private_key_file("key.pem", SslFiletype::PEM).unwrap(); + builder.set_certificate_chain_file("cert.pem").unwrap(); + + server::new(|| { + App::new() + .resource("/index.html", |r| r.f(index)) + }) + .bind_ssl("127.0.0.1:8080", builder).unwrap() + .serve(); +} +``` + +> **Note**: the *HTTP/2.0* protocol requires +> [tls alpn](https://tools.ietf.org/html/rfc7301). +> At the moment, only `openssl` has `alpn` support. +> For a full example, check out +> [examples/tls](https://github.com/actix/examples/tree/master/tls). + +To create the key.pem and cert.pem use the command. **Fill in your own subject** +```bash +$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \ + -days 365 -sha256 -subj "/C=CN/ST=Fujian/L=Xiamen/O=TVlinux/OU=Org/CN=muro.lxd" +``` +To remove the password, then copy nopass.pen to key.pem +```bash +$ openssl rsa -in key.pem -out nopass.pem +``` + +## Keep-Alive + +Actix can wait for requests on a keep-alive connection. + +> *keep alive* connection behavior is defined by server settings. + +- `75`, `Some(75)`, `KeepAlive::Timeout(75)` - enable 75 second *keep alive* timer. +- `None` or `KeepAlive::Disabled` - disable *keep alive*. +- `KeepAlive::Tcp(75)` - use `SO_KEEPALIVE` socket option. + +```rust +use actix_web::{server, App, HttpResponse}; + +fn main() { + server::new(|| + App::new() + .resource("/", |r| r.f(|_| HttpResponse::Ok()))) + .keep_alive(75); // <- Set keep-alive to 75 seconds + + server::new(|| + App::new() + .resource("/", |r| r.f(|_| HttpResponse::Ok()))) + .keep_alive(server::KeepAlive::Tcp(75)); // <- Use `SO_KEEPALIVE` socket option. + + server::new(|| + App::new() + .resource("/", |r| r.f(|_| HttpResponse::Ok()))) + .keep_alive(None); // <- Disable keep-alive +} +``` + +If the first option is selected, then *keep alive* state is +calculated based on the response's *connection-type*. By default +`HttpResponse::connection_type` is not defined. In that case *keep alive* is +defined by the request's http version. + +> *keep alive* is **off** for *HTTP/1.0* and is **on** for *HTTP/1.1* and *HTTP/2.0*. + +*Connection type* can be change with `HttpResponseBuilder::connection_type()` method. + +```rust +use actix_web::{HttpRequest, HttpResponse, http}; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok() + .connection_type(http::ConnectionType::Close) // <- Close connection + .force_close() // <- Alternative method + .finish() +} +``` + +## Graceful shutdown + +`HttpServer` supports graceful shutdown. After receiving a stop signal, workers +have a specific amount of time to finish serving requests. Any workers still alive after the +timeout are force-dropped. By default the shutdown timeout is set to 30 seconds. +You can change this parameter with the `HttpServer::shutdown_timeout()` method. + +You can send a stop message to the server with the server address and specify if you want +graceful shutdown or not. The `start()` methods returns address of the server. + +`HttpServer` handles several OS signals. *CTRL-C* is available on all OSs, +other signals are available on unix systems. + +- *SIGINT* - Force shutdown workers +- *SIGTERM* - Graceful shutdown workers +- *SIGQUIT* - Force shutdown workers + +> It is possible to disable signal handling with `HttpServer::disable_signals()` method. diff --git a/content/docs/static-files.md b/content/docs/static-files.md new file mode 100644 index 0000000..2ccac19 --- /dev/null +++ b/content/docs/static-files.md @@ -0,0 +1,56 @@ +--- +title: Static Files +menu: docs_advanced +weight: 230 +--- + +# Individual file + +It is possible to serve static files with a custom path pattern and `NamedFile`. To +match a path tail, we can use a `[.*]` regex. + +```rust +use std::path::PathBuf; +use actix_web::{App, HttpRequest, Result, http::Method, fs::NamedFile}; + +fn index(req: HttpRequest) -> Result { + let path: PathBuf = req.match_info().query("tail")?; + Ok(NamedFile::open(path)?) +} + +fn main() { + App::new() + .resource(r"/a/{tail:.*}", |r| r.method(Method::GET).f(index)) + .finish(); +} +``` + +# Directory + +To serve files from specific directories and sub-directories, `StaticFiles` can be used. +`StaticFiles` must be registered with an `App::handler()` method, otherwise +it will be unable to serve sub-paths. + +```rust +use actix_web::{App, fs}; + +fn main() { + App::new() + .handler( + "/static", + fs::StaticFiles::new(".") + .show_files_listing()) + .finish(); +} +``` + +The parameter is the base directory. By default files listing for sub-directories +is disabled. Attempt to load directory listing will return *404 Not Found* response. +To enable files listing, use +[*StaticFiles::show_files_listing()*](../../actix-web/actix_web/fs/struct.StaticFiles.html#method.show_files_listing) +method. + +Instead of showing files listing for directory, it is possible to redirect +to a specific index file. Use the +[*StaticFiles::index_file()*](../../actix-web/actix_web/fs/struct.StaticFiles.html#method.index_file) +method to configure this redirect. diff --git a/content/docs/testing.md b/content/docs/testing.md new file mode 100644 index 0000000..bcbe485 --- /dev/null +++ b/content/docs/testing.md @@ -0,0 +1,178 @@ +--- +title: Testing +menu: docs_advanced +weight: 210 +--- + +# Testing + +Every application should be well tested. Actix provides tools to perform unit and +integration tests. + +# Unit Tests + +For unit testing, actix provides a request builder type and a simple handler runner. +[*TestRequest*](../../actix-web/actix_web/test/struct.TestRequest.html) +implements a builder-like pattern. +You can generate a `HttpRequest` instance with `finish()`, or you can +run your handler with `run()` or `run_async()`. + +```rust +use actix_web::{http, test, HttpRequest, HttpResponse, HttpMessage}; + +fn index(req: HttpRequest) -> HttpResponse { + if let Some(hdr) = req.headers().get(http::header::CONTENT_TYPE) { + if let Ok(s) = hdr.to_str() { + return HttpResponse::Ok().into() + } + } + HttpResponse::BadRequest().into() +} + +fn main() { + let resp = test::TestRequest::with_header("content-type", "text/plain") + .run(index) + .unwrap(); + assert_eq!(resp.status(), http::StatusCode::OK); + + let resp = test::TestRequest::default() + .run(index) + .unwrap(); + assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST); +} +``` + +# Integration tests + +There are several methods for testing your application. Actix provides +[*TestServer*](../../actix-web/actix_web/test/struct.TestServer.html), which can be used +to run the application with specific handlers in a real http server. + +`TestServer::get()`, `TestServer::post()`, and `TestServer::client()` +methods can be used to send requests to the test server. + +A simple form `TestServer` can be configured to use a handler. +`TestServer::new` method accepts a configuration function, and the only argument +for this function is a *test application* instance. + +> Check the [api documentation](../../actix-web/actix_web/test/struct.TestApp.html) +> for more information. + +```rust +use actix_web::{HttpRequest, HttpMessage}; +use actix_web::test::TestServer; +use std::str; + +fn index(req: HttpRequest) -> &'static str { + "Hello world!" +} + +fn main() { + // start new test server + let mut srv = TestServer::new(|app| app.handler(index)); + + let request = srv.get().finish().unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert!(response.status().is_success()); + + let bytes = srv.execute(response.body()).unwrap(); + let body = str::from_utf8(&bytes).unwrap(); + assert_eq!(body, "Hello world!"); +} +``` + +The other option is to use an application factory. In this case, you need to pass the factory +function the same way as you would for real http server configuration. + +```rust +use actix_web::{http, test, App, HttpRequest, HttpResponse}; + +fn index(req: HttpRequest) -> HttpResponse { + HttpResponse::Ok().into() +} + +/// This function get called by http server. +fn create_app() -> App { + App::new() + .resource("/test", |r| r.h(index)) +} + +fn main() { + let mut srv = test::TestServer::with_factory(create_app); + + let request = srv.client( + http::Method::GET, "/test").finish().unwrap(); + let response = srv.execute(request.send()).unwrap(); + + assert!(response.status().is_success()); +} +``` + +If you need more complex application configuration, use the `TestServer::build_with_state()` +method. For example, you may need to initialize application state or start `SyncActor`'s for diesel +interation. This method accepts a closure that constructs the application state, +and it runs when the actix system is configured. Thus, you can initialize any additional actors. + +```rust +#[test] +fn test() { + let srv = TestServer::build_with_state(|| { + // we can start diesel actors + let addr = SyncArbiter::start(3, || { + DbExecutor(SqliteConnection::establish("test.db").unwrap()) + }); + // then we can construct custom state, or it could be `()` + MyState{addr: addr} + }) + + // register server handlers and start test server + .start(|app| { + app.resource( + "/{username}/index.html", |r| r.with( + |p: Path| format!("Welcome {}!", p.username))); + }); + + // now we can run our test code +); +``` + +# WebSocket server tests + +It is possible to register a *handler* with `TestApp::handler()`, which +initiates a web socket connection. *TestServer* provides the method `ws()`, which connects to +the websocket server and returns ws reader and writer objects. *TestServer* also +provides an `execute()` method, which runs future objects to completion and returns +result of the future computation. + +The following example demonstrates how to test a websocket handler: + +```rust +use actix_web::*; +use futures::Stream; + +struct Ws; // <- WebSocket actor + +impl Actor for Ws { + type Context = ws::WebsocketContext; +} + +impl StreamHandler for Ws { + fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) { + match msg { + ws::Message::Text(text) => ctx.text(text), + _ => (), + } + } +} + +fn main() { + let mut srv = test::TestServer::new( + |app| app.handler(|req| ws::start(req, Ws))); + + let (reader, mut writer) = srv.ws().unwrap(); + writer.text("text"); + + let (item, reader) = srv.execute(reader.into_future()).unwrap(); + assert_eq!(item, Some(ws::Message::Text("text".to_owned()))); +} +``` diff --git a/content/docs/url-dispatch.md b/content/docs/url-dispatch.md new file mode 100644 index 0000000..ac300b6 --- /dev/null +++ b/content/docs/url-dispatch.md @@ -0,0 +1,629 @@ +--- +title: URL Dispatch +menu: docs_advanced +weight: 190 +--- + +# URL Dispatch + +URL dispatch provides a simple way for mapping URLs to `Handler` code using a simple pattern +matching language. If one of the patterns matches the path information associated with a request, +a particular handler object is invoked. + +> A handler is a specific object that implements the +> `Handler` trait, defined in your application, that receives the request and returns +> a response object. More information is available in the +> [handler section](sec-4-handler.html). + +# Resource configuration + +Resource configuration is the act of adding a new resources to an application. +A resource has a name, which acts as an identifier to be used for URL generation. +The name also allows developers to add routes to existing resources. +A resource also has a pattern, meant to match against the *PATH* portion of a *URL*. +It does not match against the *QUERY* portion (the portion following the scheme and +port, e.g., */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*). + +The [*App::route()*](../../actix-web/actix_web/struct.App.html#method.route) method provides +simple way of registering routes. This method adds a single route to application +routing table. This method accepts a *path pattern*, +*http method* and a handler function. `route()` method could be called multiple times +for the same path, in that case, multiple routes register for the same resource path. + +```rust +use actix_web::{App, HttpRequest, HttpResponse, http::Method}; + +fn index(req: HttpRequest) -> HttpResponse { + unimplemented!() +} + +fn main() { + App::new() + .route("/user/{name}", Method::GET, index) + .route("/user/{name}", Method::POST, index) + .finish(); +} +``` + +While *App::route()* provides simple way of registering routes, to access +complete resource configuration, different method has to be used. +The [*App::resource()*](../../actix-web/actix_web/struct.App.html#method.resource) method +adds a single resource to application routing table. This method accepts a *path pattern* +and a resource configuration function. + +```rust +use actix_web::{App, HttpRequest, HttpResponse, http::Method}; + +fn index(req: HttpRequest) -> HttpResponse { + unimplemented!() +} + +fn main() { + App::new() + .resource("/prefix", |r| r.f(index)) + .resource("/user/{name}", + |r| r.method(Method::GET).f(|req| HttpResponse::Ok())) + .finish(); +} +``` + +The *Configuration function* has the following type: + +```rust +FnOnce(&mut Resource<_>) -> () +``` + +The *Configuration function* can set a name and register specific routes. +If a resource does not contain any route or does not have any matching routes, it +returns *NOT FOUND* http response. + +## Configuring a Route + +Resource contains a set of routes. Each route in turn has a set of predicates and a handler. +New routes can be created with `Resource::route()` method which returns a reference +to new *Route* instance. By default the *route* does not contain any predicates, so matches +all requests and the default handler is `HttpNotFound`. + +The application routes incoming requests based on route criteria which are defined during +resource registration and route registration. Resource matches all routes it contains in +the order the routes were registered via `Resource::route()`. + +> A *Route* can contain any number of *predicates* but only one handler. + +```rust +fn main() { + App::new() + .resource("/path", |resource| + resource.route() + .filter(pred::Get()) + .filter(pred::Header("content-type", "text/plain")) + .f(|req| HttpResponse::Ok()) + ) + .finish(); +} +``` + +In this example, `HttpResponse::Ok()` is returned for *GET* requests. +If a request contains `Content-Type` header, the value of this header is *text/plain*, +and path equals to `/path`, Resource calls handle of the first matching route. + +If a resource can not match any route, a "NOT FOUND" response is returned. + +[*ResourceHandler::route()*](../../actix-web/actix_web/dev/struct.ResourceHandler.html#method.route) returns a +[*Route*](../../actix-web/actix_web/dev/struct.Route.html) object. Route can be configured with a +builder-like pattern. Following configuration methods are available: + +* [*Route::filter()*](../../actix-web/actix_web/dev/struct.Route.html#method.filter) + registers a new predicate. Any number of predicates can be registered for each route. +* [*Route::f()*](../../actix-web/actix_web/dev/struct.Route.html#method.f) registers + handler function for this route. Only one handler can be registered. + Usually handler registration + is the last config operation. Handler function can be a function or closure + and has the type + `Fn(HttpRequest) -> R + 'static` +* [*Route::h()*](../../actix-web/actix_web/dev/struct.Route.html#method.h) registers + a handler object that implements the `Handler` trait. This is + similar to `f()` method - only one handler can + be registered. Handler registration is the last config operation. +* [*Route::a()*](../../actix-web/actix_web/dev/struct.Route.html#method.a) registers + an async handler function for this route. Only one handler can be registered. + Handler registration is the last config operation. Handler function can + be a function or closure and has the type + `Fn(HttpRequest) -> Future + 'static` + +# Route matching + +The main purpose of route configuration is to match (or not match) the request's `path` +against a URL path pattern. `path` represents the path portion of the URL that was requested. + +The way that *actix* does this is very simple. When a request enters the system, +for each resource configuration declaration present in the system, actix checks +the request's path against the pattern declared. This checking happens in the order that +the routes were declared via `App::resource()` method. If resource can not be found, +the *default resource* is used as the matched resource. + +When a route configuration is declared, it may contain route predicate arguments. All route +predicates associated with a route declaration must be `true` for the route configuration to +be used for a given request during a check. If any predicate in the set of route predicate +arguments provided to a route configuration returns `false` during a check, that route is +skipped and route matching continues through the ordered set of routes. + +If any route matches, the route matching process stops and the handler associated with +the route is invoked. If no route matches after all route patterns are exhausted, a *NOT FOUND* response get returned. + +# Resource pattern syntax + +The syntax of the pattern matching language used by actix in the pattern +argument is straightforward. + +The pattern used in route configuration may start with a slash character. If the pattern +does not start with a slash character, an implicit slash will be prepended +to it at matching time. For example, the following patterns are equivalent: + +``` +{foo}/bar/baz +``` + +and: + +``` +/{foo}/bar/baz +``` + +A *variable part* (replacement marker) is specified in the form *{identifier}*, +where this means "accept any characters up to the next slash character and use this +as the name in the `HttpRequest.match_info()` object". + +A replacement marker in a pattern matches the regular expression `[^{}/]+`. + +A match_info is the `Params` object representing the dynamic parts extracted from a +*URL* based on the routing pattern. It is available as *request.match_info*. For example, the +following pattern defines one literal segment (foo) and two replacement markers (baz, and bar): + +``` +foo/{baz}/{bar} +``` + +The above pattern will match these URLs, generating the following match information: + +``` +foo/1/2 -> Params {'baz':'1', 'bar':'2'} +foo/abc/def -> Params {'baz':'abc', 'bar':'def'} +``` + +It will not match the following patterns however: + +``` +foo/1/2/ -> No match (trailing slash) +bar/abc/def -> First segment literal mismatch +``` + +The match for a segment replacement marker in a segment will be done only up to +the first non-alphanumeric character in the segment in the pattern. So, for instance, +if this route pattern was used: + +``` +foo/{name}.html +``` + +The literal path */foo/biz.html* will match the above route pattern, and the match result +will be `Params{'name': 'biz'}`. However, the literal path */foo/biz* will not match, +because it does not contain a literal *.html* at the end of the segment represented +by *{name}.html* (it only contains biz, not biz.html). + +To capture both segments, two replacement markers can be used: + +``` +foo/{name}.{ext} +``` + +The literal path */foo/biz.html* will match the above route pattern, and the match +result will be *Params{'name': 'biz', 'ext': 'html'}*. This occurs because there is a +literal part of *.* (period) between the two replacement markers *{name}* and *{ext}*. + +Replacement markers can optionally specify a regular expression which will be used to decide +whether a path segment should match the marker. To specify that a replacement marker should +match only a specific set of characters as defined by a regular expression, you must use a +slightly extended form of replacement marker syntax. Within braces, the replacement marker +name must be followed by a colon, then directly thereafter, the regular expression. The default +regular expression associated with a replacement marker *[^/]+* matches one or more characters +which are not a slash. For example, under the hood, the replacement marker *{foo}* can more +verbosely be spelled as *{foo:[^/]+}*. You can change this to be an arbitrary regular expression +to match an arbitrary sequence of characters, such as *{foo:\d+}* to match only digits. + +Segments must contain at least one character in order to match a segment replacement marker. +For example, for the URL */abc/*: + +* */abc/{foo}* will not match. +* */{foo}/* will match. + +> **Note**: path will be URL-unquoted and decoded into valid unicode string before +> matching pattern and values representing matched path segments will be URL-unquoted too. + +So for instance, the following pattern: + +``` +foo/{bar} +``` + +When matching the following URL: + +``` +http://example.com/foo/La%20Pe%C3%B1a +``` + +The matchdict will look like so (the value is URL-decoded): + +``` +Params{'bar': 'La Pe\xf1a'} +``` + +Literal strings in the path segment should represent the decoded value of the +path provided to actix. You don't want to use a URL-encoded value in the pattern. +For example, rather than this: + +``` +/Foo%20Bar/{baz} +``` + +You'll want to use something like this: + +``` +/Foo Bar/{baz} +``` + +It is possible to get "tail match". For this purpose custom regex has to be used. + +``` +foo/{bar}/{tail:.*} +``` + +The above pattern will match these URLs, generating the following match information: + +``` +foo/1/2/ -> Params{'bar':'1', 'tail': '2/'} +foo/abc/def/a/b/c -> Params{'bar':u'abc', 'tail': 'def/a/b/c'} +``` + +# Match information + +All values representing matched path segments are available in +[`HttpRequest::match_info`](../actix_web/struct.HttpRequest.html#method.match_info). +Specific values can be retrieved with +[`Params::get()`](../actix_web/dev/struct.Params.html#method.get). + +Any matched parameter can be deserialized into a specific type if the type +implements the `FromParam` trait. For example most standard integer types +the trait, i.e.: + +```rust +use actix_web::*; + +fn index(req: HttpRequest) -> Result { + let v1: u8 = req.match_info().query("v1")?; + let v2: u8 = req.match_info().query("v2")?; + Ok(format!("Values {} {}", v1, v2)) +} + +fn main() { + App::new() + .resource(r"/a/{v1}/{v2}/", |r| r.f(index)) + .finish(); +} +``` + +For this example for path '/a/1/2/', values v1 and v2 will resolve to "1" and "2". + +It is possible to create a `PathBuf` from a tail path parameter. The returned `PathBuf` is +percent-decoded. If a segment is equal to "..", the previous segment (if +any) is skipped. + +For security purposes, if a segment meets any of the following conditions, +an `Err` is returned indicating the condition met: + +* Decoded segment starts with any of: `.` (except `..`), `*` +* Decoded segment ends with any of: `:`, `>`, `<` +* Decoded segment contains any of: `/` +* On Windows, decoded segment contains any of: '\' +* Percent-encoding results in invalid UTF8. + +As a result of these conditions, a `PathBuf` parsed from request path parameter is +safe to interpolate within, or use as a suffix of, a path without additional checks. + +```rust +use std::path::PathBuf; +use actix_web::{App, HttpRequest, Result, http::Method}; + +fn index(req: HttpRequest) -> Result { + let path: PathBuf = req.match_info().query("tail")?; + Ok(format!("Path {:?}", path)) +} + +fn main() { + App::new() + .resource(r"/a/{tail:.*}", |r| r.method(Method::GET).f(index)) + .finish(); +} +``` + +List of `FromParam` implementations can be found in +[api docs](../../actix-web/actix_web/dev/trait.FromParam.html#foreign-impls) + +## Path information extractor + +Actix provides functionality for type safe path information extraction. +[*Path*](../../actix-web/actix_web/struct.Path.html) extracts information, destination type +could be defined in several different forms. Simplest approach is to use +`tuple` type. Each element in tuple must correpond to one element from +path pattern. i.e. you can match path pattern `/{id}/{username}/` against +`Pyth<(u32, String)>` type, but `Path<(String, String, String)>` type will +always fail. + +```rust +use actix_web::{App, Path, Result, http::Method}; + +// extract path info using serde +fn index(info: Path<(String, u32)>) -> Result { + Ok(format!("Welcome {}! id: {}", info.0, info.1)) +} + +fn main() { + let app = App::new() + .resource("/{username}/{id}/index.html", // <- define path parameters + |r| r.method(Method::GET).with(index)); +} +``` + + +It also possible to extract path pattern information to a struct. In this case, +this struct must implement *serde's *`Deserialize` trait. + +```rust +#[macro_use] extern crate serde_derive; +use actix_web::{App, Path, Result, http::Method}; + +#[derive(Deserialize)] +struct Info { + username: String, +} + +// extract path info using serde +fn index(info: Path) -> Result { + Ok(format!("Welcome {}!", info.username)) +} + +fn main() { + let app = App::new() + .resource("/{username}/index.html", // <- define path parameters + |r| r.method(Method::GET).with(index)); +} +``` + +[*Query*](../../actix-web/actix_web/struct.Query.html) provides similar +functionality for request query parameters. + +# Generating resource URLs + +Use the [*HttpRequest.url_for()*](../../actix-web/actix_web/struct.HttpRequest.html#method.url_for) +method to generate URLs based on resource patterns. For example, if you've configured a +resource with the name "foo" and the pattern "{a}/{b}/{c}", you might do this: + +```rust +fn index(req: HttpRequest) -> Result { + let url = req.url_for("foo", &["1", "2", "3"])?; // <- generate url for "foo" resource + Ok(HttpResponse::Found() + .header(header::LOCATION, url.as_str()) + .finish()) +} + +fn main() { + let app = App::new() + .resource("/test/{a}/{b}/{c}", |r| { + r.name("foo"); // <- set resource name, then it could be used in `url_for` + r.method(Method::GET).f(|_| HttpResponse::Ok()); + }) + .route("/test/", Method::GET, index) + .finish(); +} +``` + +This would return something like the string *http://example.com/test/1/2/3* (at least if +the current protocol and hostname implied http://example.com). +`url_for()` method returns [*Url object*](https://docs.rs/url/1.7.0/url/struct.Url.html) so you +can modify this url (add query parameters, anchor, etc). +`url_for()` could be called only for *named* resources otherwise error get returned. + +# External resources + +Resources that are valid URLs, can be registered as external resources. They are useful +for URL generation purposes only and are never considered for matching at request time. + +```rust +# extern crate actix_web; +use actix_web::{App, HttpRequest, HttpResponse, Error}; + +fn index(mut req: HttpRequest) -> Result { + let url = req.url_for("youtube", &["oHg5SJYRHA0"])?; + assert_eq!(url.as_str(), "https://youtube.com/watch/oHg5SJYRHA0"); + Ok(HttpResponse::Ok().into()) +} + +fn main() { + let app = App::new() + .resource("/index.html", |r| r.f(index)) + .external_resource("youtube", "https://youtube.com/watch/{video_id}") + .finish(); +} +``` + +# Path normalization and redirecting to slash-appended routes + +By normalizing it means: + +* Add a trailing slash to the path. +* Double slashes are replaced by one. + +The handler returns as soon as it finds a path that resolves +correctly. The order if all enable is 1) merge, 2) both merge and append +and 3) append. If the path resolves with +at least one of those conditions, it will redirect to the new path. + +If *append* is *true*, append slash when needed. If a resource is +defined with trailing slash and the request doesn't have one, it will +be appended automatically. + +If *merge* is *true*, merge multiple consecutive slashes in the path into one. + +This handler designed to be used as a handler for application's *default resource*. + +```rust +use actix_web::http::NormalizePath; + +fn main() { + let app = App::new() + .resource("/resource/", |r| r.f(index)) + .default_resource(|r| r.h(NormalizePath::default())) + .finish(); +} +``` + +In this example `/resource`, `//resource///` will be redirected to `/resource/`. + +In this example, the path normalization handler is registered for all methods, +but you should not rely on this mechanism to redirect *POST* requests. The redirect of the +slash-appending *Not Found* will turn a *POST* request into a GET, losing any +*POST* data in the original request. + +It is possible to register path normalization only for *GET* requests only: + +```rust +use actix_web::{App, HttpRequest, http::Method, http::NormalizePath}; + +fn main() { + let app = App::new() + .resource("/resource/", |r| r.f(index)) + .default_resource(|r| r.method(Method::GET).h(NormalizePath::default())) + .finish(); +} +``` + +## Using an Application Prefix to Compose Applications + +The `App::prefix()` method allows to set a specific application prefix. +This prefix represents a resource prefix that will be prepended to all resource patterns added +by the resource configuration. This can be used to help mount a set of routes at a different +location than the included callable's author intended while still maintaining the same +resource names. + +For example: + +```rust +fn show_users(req: HttpRequest) -> HttpResponse { + unimplemented!() +} + +fn main() { + App::new() + .prefix("/users") + .resource("/show", |r| r.f(show_users)) + .finish(); +} +``` + +In the above example, the *show_users* route will have an effective route pattern of +*/users/show* instead of */show* because the application's prefix argument will be prepended +to the pattern. The route will then only match if the URL path is */users/show*, +and when the `HttpRequest.url_for()` function is called with the route name show_users, +it will generate a URL with that same path. + +# Custom route predicates + +You can think of a predicate as a simple function that accepts a *request* object reference +and returns *true* or *false*. Formally, a predicate is any object that implements the +[`Predicate`](../actix_web/pred/trait.Predicate.html) trait. Actix provides +several predicates, you can check +[functions section](../../actix-web/actix_web/pred/index.html#functions) of api docs. + +Here is a simple predicate that check that a request contains a specific *header*: + +```rust +use actix_web::{http, pred::Predicate, App, HttpMessage, HttpRequest}; + +struct ContentTypeHeader; + +impl Predicate for ContentTypeHeader { + + fn check(&self, req: &mut HttpRequest) -> bool { + req.headers().contains_key(http::header::CONTENT_TYPE) + } +} + +fn main() { + App::new() + .resource("/index.html", |r| + r.route() + .filter(ContentTypeHeader) + .f(|_| HttpResponse::Ok())); +} +``` + +In this example, *index* handler will be called only if request contains *CONTENT-TYPE* header. + +Predicates have access to the application's state via `HttpRequest::state()`. +Also predicates can store extra information in +[request extensions](../../actix-web/actix_web/struct.HttpRequest.html#method.extensions). + +## Modifying predicate values + +You can invert the meaning of any predicate value by wrapping it in a `Not` predicate. +For example, if you want to return "METHOD NOT ALLOWED" response for all methods +except "GET": + +```rust +use actix_web::{pred, App, HttpResponse}; + +fn main() { + App::new() + .resource("/index.html", |r| + r.route() + .filter(pred::Not(pred::Get())) + .f(|req| HttpResponse::MethodNotAllowed())) + .finish(); +} +``` + +The `Any` predicate accepts a list of predicates and matches if any of the supplied +predicates match. i.e: + +```rust +pred::Any(pred::Get()).or(pred::Post()) +``` + +The `All` predicate accepts a list of predicates and matches if all of the supplied +predicates match. i.e: + +```rust +pred::All(pred::Get()).and(pred::Header("content-type", "plain/text")) +``` + +# Changing the default Not Found response + +If the path pattern can not be found in the routing table or a resource can not find matching +route, the default resource is used. The default response is *NOT FOUND*. +It is possible to override the *NOT FOUND* response with `App::default_resource()`. +This method accepts a *configuration function* same as normal resource configuration +with `App::resource()` method. + +```rust +use actix_web::{App, HttpResponse, http::Method, pred}; + +fn main() { + App::new() + .default_resource(|r| { + r.method(Method::GET).f(|req| HttpResponse::NotFound()); + r.route().filter(pred::Not(pred::Get())) + .f(|req| HttpResponse::MethodNotAllowed()); + }) + .finish(); +} +``` diff --git a/content/docs/websockets.md b/content/docs/websockets.md new file mode 100644 index 0000000..b284a36 --- /dev/null +++ b/content/docs/websockets.md @@ -0,0 +1,50 @@ +--- +title: Websockets +menu: docs_proto +weight: 240 +--- + +Actix supports WebSockets out-of-the-box. It is possible to convert a request's `Payload` +to a stream of [*ws::Message*](../../actix-web/actix_web/ws/enum.Message.html) with +a [*ws::WsStream*](../../actix-web/actix_web/ws/struct.WsStream.html) and then use stream +combinators to handle actual messages, but it is simpler to handle websocket communications +with an http actor. + +The following is an example of a simple websocket echo server: + +```rust +use actix::*; +use actix_web::*; + +/// Define http actor +struct Ws; + +impl Actor for Ws { + type Context = ws::WebsocketContext; +} + +/// Handler for ws::Message message +impl StreamHandler for Ws { + + fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) { + match msg { + ws::Message::Ping(msg) => ctx.pong(&msg), + ws::Message::Text(text) => ctx.text(text), + ws::Message::Binary(bin) => ctx.binary(bin), + _ => (), + } + } +} + +fn main() { + App::new() + .resource("/ws/", |r| r.f(|req| ws::start(req, Ws))) + .finish(); +} +``` + +> A simple websocket echo server example is available in the +> [examples directory](https://github.com/actix/examples/tree/master/websocket/). + +> An example chat server with the ability to chat over a websocket or tcp connection +> is available in [websocket-chat directory](https://github.com/actix/examples/tree/master/websocket-chat/) diff --git a/content/docs/whatis.md b/content/docs/whatis.md new file mode 100644 index 0000000..d65e041 --- /dev/null +++ b/content/docs/whatis.md @@ -0,0 +1,27 @@ +--- +title: What is Actix +menu: docs_intro +weight: 100 +--- + +# Actix is Multiple Things + +Actix is a few things. The base of it is a powerful actor system for Rust on +top of which the `actix-web` system is built. This is what you are most likely +going to work with. What `actix-web` gives you is a fun and very fast web +development framework. + +We call `actix-web` a small and pragmatic framework. For all intents and purposes +it's a microframework with a few twists. If you are already a Rust programmer +you will probably find yourself at home quickly, but even if you are coming from +another programming language you should find actix-web easy to pick up. + +An application developed with `actix-web` will expose an HTTP server contained +within a native executable. You can put this behind another HTTP server like +nginx or serve it up as such. Even in the complete absence of another HTTP +server `actix-web` is powerful enough to provide HTTP 1 and HTTP 2 support as +well as SSL/TLS. This makes it useful for building small services ready for +distribution. + +Most importantly: `actix-web` runs on Rust 1.24 or later and it works with +stable releases. diff --git a/docs/API-example.md b/docs/API-example.md deleted file mode 100644 index 3f012be..0000000 --- a/docs/API-example.md +++ /dev/null @@ -1,7 +0,0 @@ -title: Docs::API Example -layout: docs.liquid -permalink: /docs/API/API-example.html ---- -## API Example - -The words is comming. diff --git a/docs/Advance-example.md b/docs/Advance-example.md deleted file mode 100644 index 1e6ad63..0000000 --- a/docs/Advance-example.md +++ /dev/null @@ -1,8 +0,0 @@ -title: Docs::Advance Example -layout: docs.liquid -permalink: /docs/Advance/Advance-example.html ---- - -## Advance Example - -The words is comming. diff --git a/docs/Basics-example.md b/docs/Basics-example.md deleted file mode 100644 index e66557c..0000000 --- a/docs/Basics-example.md +++ /dev/null @@ -1,8 +0,0 @@ -title: Docs::Basics Example -layout: docs.liquid -permalink: /docs/Basics/Basics-example.html ---- - -## Basics Example - -The words is comming. diff --git a/docs/Reference-example.md b/docs/Reference-example.md deleted file mode 100644 index db4ad6c..0000000 --- a/docs/Reference-example.md +++ /dev/null @@ -1,8 +0,0 @@ -title: Docs::Reference Example -layout: docs.liquid -permalink: /docs/Reference/Reference-example.html ---- - -## Reference Example - -The words is comming. diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 71a052a..0000000 --- a/docs/index.md +++ /dev/null @@ -1,13 +0,0 @@ -title: Docs -layout: docs.liquid -permalink: /docs/index.html ---- - -## Documentation - -Welcome to the Actix-web docs! - -If you feel like contributing further, you can fork that repo, -branch from `source`, and submit a pull request. - -Contributions are always welcome! diff --git a/index.liquid b/index.liquid deleted file mode 100644 index 985f1ac..0000000 --- a/index.liquid +++ /dev/null @@ -1,37 +0,0 @@ -title: Actix web framework -layout: default.liquid -permalink: /index.html ---- - -
-
-
-

Actix web framework

-

Actix web is a simple, pragmatic and extremely fast web framework for Rust.

-
-
-
-
-

Type Safe

-

Forget about stringly typed objects, - from request to response, everything has types.

-
-
-

Feature rich

-

Actix provides a lot of features out of box. - WebSockets, Http/2, pipelining etc.

-
-
-

Extensible

-

Easily create your own libraries that any Actix application can use.

-
- -
-
-
-
diff --git a/layouts/code/baseof.html b/layouts/code/baseof.html new file mode 100644 index 0000000..0b36380 --- /dev/null +++ b/layouts/code/baseof.html @@ -0,0 +1,23 @@ +{{ partial "header" . }} +{{ $currentURL := .URL }} + +
+
+

{{ .Title }}

+ {{ if .Description }} +

{{ .Description }}

+ {{ end }} +
+
+ +
+
+
+
+ {{ block "main" . }}{{ end }} +
+
+
+
+ +{{ partial "footer" . }} diff --git a/layouts/code/code.html b/layouts/code/code.html new file mode 100644 index 0000000..e0e8308 --- /dev/null +++ b/layouts/code/code.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/layouts/code/single.html b/layouts/code/single.html new file mode 100644 index 0000000..5fb6c3f --- /dev/null +++ b/layouts/code/single.html @@ -0,0 +1,4 @@ +{{ define "main" }} +
+
+

{{ .Title }}

+ {{ if .Description }} +

{{ .Description }}

+ {{ end }} +
+
+ +
+
+
+
+ {{ block "main" . }}{{ end }} +
+
+
+
+ +{{ partial "footer" . }} diff --git a/layouts/community/community.html b/layouts/community/community.html new file mode 100644 index 0000000..e0e8308 --- /dev/null +++ b/layouts/community/community.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/layouts/community/single.html b/layouts/community/single.html new file mode 100644 index 0000000..07d833f --- /dev/null +++ b/layouts/community/single.html @@ -0,0 +1,4 @@ +{{ define "main" }} +
+
+

{{ .Title }}

+ {{ if .Description }} +

{{ .Description }}

+ {{ end }} +
+
+ +
+
+
+ + + +
+
+
+ {{ block "main" . }}{{ end }} + + + {{ with .PrevInSection }}{{ end }} +
+
+
+
+ +{{ partial "footer" . }} diff --git a/layouts/docs/docs.html b/layouts/docs/docs.html new file mode 100644 index 0000000..e0e8308 --- /dev/null +++ b/layouts/docs/docs.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/layouts/docs/single.html b/layouts/docs/single.html new file mode 100644 index 0000000..e0e8308 --- /dev/null +++ b/layouts/docs/single.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..faf9ca9 --- /dev/null +++ b/layouts/index.html @@ -0,0 +1,64 @@ +{{ partial "header" . }} + +
+
+ +

rust's powerful actor system and most fun web framework

+
+
+ +
+
+
+
+

+ + Type Safe +

+

Forget about stringly typed objects, from request to response, everything has types.

+ +

+ + Feature Rich +

+

Actix provides a lot of features out of box. WebSockets, HTTP/2, pipelining etc.

+ +

+ + Extensible +

+

Easily create your own libraries that any Actix application can use.

+ +

+ + Blazingly Fast +

+

Actix is blazingly fast. Check yourself.

+
+
+
+
+ {{ highlight `extern crate actix_web; +use actix_web::{server, App, HttpRequest, Responder}; + +fn greet(req: HttpRequest) -> impl Responder { + let to = req.match_info().get("name").unwrap_or("World"); + format!("Hello {}!", to) +} + +fn main() { + server::new(|| { + App::new() + .resource("/", |r| r.f(greet)) + .resource("/{name}", |r| r.f(greet)) + }) + .bind("127.0.0.1:8000") + .expect("Can not bind to port 8000") + .run(); +}` "rust" "" }} +
+
+
+
+ +{{ partial "footer" . }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..dd7011b --- /dev/null +++ b/layouts/partials/footer.html @@ -0,0 +1,18 @@ +
+ +
+ + + + + + {{ template "_internal/google_analytics.html" . }} + + diff --git a/layouts/partials/header.html b/layouts/partials/header.html new file mode 100644 index 0000000..fc58484 --- /dev/null +++ b/layouts/partials/header.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + {{ .Title }} + + + diff --git a/layouts/shortcodes/actix-version.html b/layouts/shortcodes/actix-version.html new file mode 100644 index 0000000..28efc3c --- /dev/null +++ b/layouts/shortcodes/actix-version.html @@ -0,0 +1,5 @@ +{{- if eq (.Get 0) "actix" -}} + {{- .Page.Site.Params.actixVersion -}} +{{- else if eq (.Get 0) "actix-web" -}} + {{- .Page.Site.Params.actixWebVersion -}} +{{- end -}} diff --git a/layouts/shortcodes/actix-web-version.html b/layouts/shortcodes/actix-web-version.html new file mode 100644 index 0000000..5a2a580 --- /dev/null +++ b/layouts/shortcodes/actix-web-version.html @@ -0,0 +1 @@ +0.6 diff --git a/more.md b/more.md deleted file mode 100644 index da8fb33..0000000 --- a/more.md +++ /dev/null @@ -1,15 +0,0 @@ -title: More -layout: default.liquid -permalink: /more.html ---- -
-
- - -## Examples - -The words is comming. - - -
-
\ No newline at end of file diff --git a/public/css/styles.css b/public/css/styles.css deleted file mode 100644 index 1e3c865..0000000 --- a/public/css/styles.css +++ /dev/null @@ -1,328 +0,0 @@ -:root { - --grey: #f5f5f5; - --text-color: #413e3e; - --black: #000000; - --white: #ffffff; - --new: rgb(82, 29, 79); - --font-stack: helvetica, arial, sans-serif; -} - -*, *:before, *:after { - box-sizing: border-box; - padding:0px; margin:0px; -} - -body { - font-family: var(--font-stack); - line-height: 1.4rem; - color: var(--text-color); - -} - -a { - color: var(--text-color); - text-decoration: none; -} -a:hover { color: var(--new) ;text-decoration:none; } - -ul, ol, li { - list-style: none; -} - -/* ----------------------------------------nav----------------------------------------*/ -#lnav { - position: fixed; - width: 100%; - line-height: 60px; - zoom:1; - display: flex; - background-color: var(--white); - justify-content: space-between; - border-bottom: 1px solid #dfdcdc; - box-shadow: 0 3px 3px rgba(200, 216, 206, 0.12), 0 3px 3px rgba(97, 107, 100, 0.24); -} -#line { - position: fixed; - zoom:1; - display: flex; - width: 100%; - height: 4px; - background-color: var(--black); -} -#lnav h1 #home { - font-size: 33px; - margin: auto 1vw; - font-weight: bold; -} -#lnav label { - float: right; - font-size: 26px; - font-weight: bold; - margin: auto 2vw; -} -#lnav h1 img { - width: 2.8rem; - height: 2.8rem; - margin-top: -0.25rem; - vertical-align:middle; -} - -/* ----------------------------------------section----------------------------------------*/ -section { - min-height: 100vh; -} -section.docs aside ul li a, section.blog aside ul li a { - display: inline-block; - margin-left: 0.8rem; - text-decoration: none; - transition: all 0.15s ease-in-out; -} - -section.docs aside ul li a.active, -section.docs aside ul li a:hover, -section.docs aside ul li a:active, -section.docs aside ul li a:focus, -section.blog aside ul li a.active, -section.blog aside ul li a:hover, -section.blog aside ul li a:active, -section.blog aside ul li a:focus { - color: var(--new); - border-left: 3px solid var(--new); - padding: 0.25rem 0.5rem; -} -section.docs aside p, section.blog aside p { - font-size: 1.2rem; - font-weight: bold; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: var(--new); - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - text-shadow: none; -} - -code { - padding: 2px 4px; - font-size: 90%; - background-color: #f5f5f5; - border-radius: 4px; - border: 1px solid #ccc; - color: var(--new); - text-shadow: none; -} - -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; - border: 0; -} - -/* ----------------------------------------footer----------------------------------------*/ -footer{ - text-align: center; - justify-content: center; - border-top: 2px solid var(--new); -} -footer a { - color: var(--new); - font-weight: bold; -} -footer p { - margin: 0; - font-weight: lighter; - padding: 1rem 0; -} - -/* ----------------------------------------home page----------------------------------------*/ -#top { - padding: 2rem; - text-align: center; - line-height: 3rem; - border: 2px solid var(--grey); -} -#top h1 { - font-size: 2.2rem; -} -#top p { - font-size: 1.1rem; -} -#top button { - margin-right: 18px; - font-size: 18px; - padding: 8px 22px; - border: none; -} - -#Features { - margin: 2rem auto; - padding: 1rem 2rem; - border: 2px solid var(--grey); -} -#Features #feature { - padding-bottom: 1rem; -} -#Features article { - padding-top: 1rem; -} -#Features article h3 { - font-size: 1.3rem; - padding-bottom: 0.5rem; -} - - -/* ----------------------------------------mobile----------------------------------------*/ -@media only screen and (max-width: 600px) { - #lnav h1 img { - margin-left: 1vw; - } - #rnav { - padding-top: 3.6rem; - height: 0; - display: block; - overflow: hidden; - - } - #rnav li a { - display:block; - font-weight: bold; - border-bottom: 1px solid #d8d8d8; - padding: 0.5rem 1rem; - } - #top { - margin: 0 auto; - padding: 3.5rem 2rem 5rem 2rem; -} - section { - margin: 0 auto ; - padding-top: 1rem; - width: 94%; - } - #hr { - width: 100%; - height: 0.25rem; - margin: 0.6rem 0; - background-color: var(--black); - } -} -/* ----------------------------------------table----------------------------------------*/ -@media only screen and (min-width: 600px) and (max-width: 1000px) { - #menu { - display: none; - } - #lnav h1 img { - margin-left: 5vw; - } - - #rnav { - position: fixed; - right: 0; - line-height: 60px; - padding-right: 5vw; - } - - #rnav li { - display: inline-block; - } - #rnav li a { - font-size: 20px; - font-weight: bold; - padding-left: 2vw; - } - section { - margin: 0 auto; - padding-top: 5rem; - width: 85%; - } - - section.docs .inner, section.blog .inner { - display: flex; - } - section.docs aside, section.blog aside { - flex: 0 1 30%; - } - - section.docs main, section.blog main { - flex: 0 1 70%; - } - #hr { - display: none; - } - .columns { - display: flex; - } - - .columns.three > article { - flex: 0 1 33%; - margin-right: 1.5%; - } - - .columns.three > article:last-child { - margin-right: 0; - } -} - -/* ----------------------------------------desktop----------------------------------------*/ -@media only screen and (min-width: 1000px) { - #menu { - display: none; - } - #lnav h1 img { - margin-left: 11vw; - } - #rnav { - position: fixed; - right: 0; - line-height: 60px; - padding-right: 10vw; - } - - #rnav li { - display: inline-block; - } - #rnav li a { - font-size: 20px; - font-weight: bold; - padding-left: 2vw; - } - section { - margin: 0 auto; - padding-top: 5.5rem; - width: 75%; - } - section.docs .inner, section.blog .inner { - display: flex; - } - section.docs aside, section.blog aside { - flex: 0 1 30%; - } - section.docs main, section.blog main { - flex: 0 1 70%; - } - #hr { - display: none; - } - .columns { - display: flex; - } - - .columns.four > article { - flex: 0 1 25%; - margin-right: 1.5%; - } - - .columns.four > article:last-child { - margin-right: 0; - } -} diff --git a/public/imgs/ACTIX.png b/public/imgs/ACTIX.png deleted file mode 100644 index 1e2509a..0000000 Binary files a/public/imgs/ACTIX.png and /dev/null differ diff --git a/public/imgs/favicon.ico b/public/imgs/favicon.ico deleted file mode 100644 index 1eac423..0000000 Binary files a/public/imgs/favicon.ico and /dev/null differ diff --git a/public/js/nav.js b/public/js/nav.js deleted file mode 100644 index 78ba358..0000000 --- a/public/js/nav.js +++ /dev/null @@ -1,14 +0,0 @@ -var menu = document.getElementById('menu'); -menu.addEventListener('click', function() { - var nav = document.getElementById('rnav'); - if (nav.style.height == 'auto') { - nav.style.height = '0'; - }else{ - nav.style.height = 'auto'; - } - - // they are same - // manv.style.height = 'auto'; - // manv.setAttribute('style', 'height: auto !important'); - // manv.style.setProperty( 'height',' auto', 'important'); -}, false); \ No newline at end of file diff --git a/static/css/actix.css b/static/css/actix.css new file mode 100644 index 0000000..5bdc426 --- /dev/null +++ b/static/css/actix.css @@ -0,0 +1,496 @@ +@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600|Roboto+Mono'); + +body { + font-family: 'Source Sans Pro', sans-serif; +} + +a { + color: #156060; +} + +a:hover { + color: #003B3B; +} + +table, td { + border: 1px solid black; +} + +td { + padding: 4px; +} + +img { + max-width: 100%; +} + +/* + * + * ===== Content ==== + * + */ + +.actix-content { + line-height: 1.75rem; +} + +.actix-content h1 { + margin-top: 2rem; + margin-bottom: 1.5rem; + font-size: 2.2rem; +} + +.actix-content h1:first-child { + margin-top: 0; +} + +.actix-content h2, .actix-content h3 { + margin-top: 2rem; + margin-bottom: 1rem; +} + +.actix-content hr { + margin: 2rem 0; +} + +.actix-content figure { + margin: 2.5rem auto; + max-width: 80%; +} + +.actix-content figure figcaption { + font-size: 90%; + color: #818a91; + text-align: right; +} + +.actix-content figure img { + max-width: 100%; +} + +.actix-next { + text-align: right; +} + +.github-edit .fa { + font-family: inherit; +} + +.github-edit .fa:before { + font-family: "FontAwesome"; + display: inline-block; + font-style: normal; + font-weight: normal; + line-height: 1; + text-decoration: inherit; +} + +.github-edit { + text-align: right; + padding-bottom: 1rem; +} + + +/* + * + * ===== Navbar ===== + * + */ + + .navbar-nav { + display: flex; + } + + .navbar-nav .nav-item { + margin-left: 1rem; + margin-right: 1rem; + } + +.navbar-nav .nav-link { + padding-top: 0; + padding-bottom: 0; +} + +.navbar-brand { + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + width: 52px; + height: auto; +} + +@keyframes spin-logo { 100% { transform: rotate(360deg); } } + +.navbar-brand img { + animation: spin-logo 30s linear infinite; +} + +.navbar-light { + background: #eee; +} + +.navbar-toggle { + padding: .25rem .35rem; + font-size: 1.25rem; + line-height: 1; + height: 2.6rem; + width: 2.8rem; + background: 0 0; + border: 1px solid transparent; + border-radius: .25rem; +} + +.navbar-light .navbar-toggle { + border-color: rgba(0, 0, 0, 0.1); + color: rgba(0, 0, 0, 0.9); + margin-top: 4px; +} + +/* reset border and change color outline */ +.navbar-light .navbar-toggle:focus { + outline: none; + border-color: #888; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: no-repeat center center; + -webkit-background-size: 100% 100%; + background-size: 100% 100%; + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E"); +} + +.navbar-nav li { + line-height: 60px; + height: 60px; + padding-top: 0; +} + +.leftnav li { + margin: 1rem 0rem; +} + +.leftnav li a { + color: #888; +} + +.leftnav li.active { + margin: -0.5rem 0 -.5rem -1rem; + padding: 0.5rem 0 0.5rem 1rem; + background: #dceaea; +} + +.leftnav li.active a { + color: #156060; +} + +.leftnav h5 { + margin: 2rem 0 1rem 0; +} + +.leftnav h5:first-child { + margin-top: 0; +} + +.leftnav a { + font-weight: 600; +} + +.in .navbar-nav .nav-item { + text-align: left; +} + +.navbar-toggleable-md .navbar-nav { + margin-top: 0; + margin-bottom: 0; + margin-left: auto; + margin-right: auto; +} +.navbar-toggleable-md .navbar-brand { + margin-top: 0; +} + +/* + * + * ===== Page header ===== + * + */ + +.actix-pageheader, .jumbotron { + background-image: url(/img/jumbotron.jpg); + background-size: cover; + background-color: #156060; + color: #fff; +} + +.jumbotron { + border-radius: 0; + padding: 4rem 1rem; +} + +.actix-jumbotron { + margin-left: auto; + margin-right: auto; + max-width: 700px; + text-align: center; +} + +.jumbotron .actix-logo { + max-height: 10rem; +} + +.jumbotron .lead { + font-size: 1.5rem; + margin: 2rem 0 0 0; +} + +.actix-pageheader { + padding: 1rem 1rem; + margin-bottom: 2.5rem; +} + +.actix-pageheader h1 { + font-weight: 300; + font-size: 3rem; +} + +.actix-pageheader .lead { + color: #DADADA; + font-size: 1.5rem; + margin-bottom: 0; +} + +@media (min-width: 576px) { + .actix-pageheader { + padding: 2rem 0rem; + } +} + +/* + * + * ===== Home ===== + * + */ + +.actix-home { + margin: 0 auto; + width: auto; + max-width: 1000px; +} + +.actix-features h2 { + font-size: 1.5rem; + margin-top: 2.25rem; + margin-bottom: 0.8rem; +} + +.actix-features .fa { + margin-right: 0.4rem; + color: #156060; +} + +.actix-features p { + font-size: 1rem; +} + +.final-pitch { + text-align: center; +} + +/* + * + * ===== Footer ===== + * + */ + +.actix-footer { + padding: 4rem 0; + margin-top: 4rem; + font-size: 85%; + line-height: 35px; +} + +.actix-footer-gray { + padding-left: 1rem; + padding-right: 1rem; + margin: 0 auto; +} + +.actix-footer-social a .fa { + font-size: 35px; +} + +.actix-footer-social a .fa-github { + margin-left: 35px; +} + +/* + * + * ===== Misc ===== + * + */ +p.uplink { + margin: 0; + float: right; +} + +/* + * + * ===== Highlight ===== + * + */ + +code { + color: #006a70; +} + +pre, code { + font-family: 'Roboto Mono', monospace; +} + +pre { + display: block; + overflow-x: auto; + margin: 2rem 0rem; + padding: 1rem; + background: #f7f7f7; + font-size: 90%; + line-height: 1.4rem; +} + +/* Show section header on hover */ + +h2:hover a:after, +h3:hover a:after, +h4:hover a:after, +h5:hover a:after { + content: '\2002\00a7\2002'; +} + +h2:hover a, +h3:hover a, +h4:hover a, +h5:hover a { + text-decoration: none; +} + +@media (min-width:520px) { + .jumbotron { + padding: 4rem; + } +} + + +/* + * + * ===== Utilities ===== + * + */ + + .d-flex { + display: flex; + } + + .justify-content-between { + justify-content: space-between; + } + + /* + * + * ===== Media queries ===== + * + */ + + + @media (min-width: 768px) { + .bootstrap-vertical-nav .navbar .navbar-collapse { + padding: 0; + max-height: none; + } + .bootstrap-vertical-nav .navbar ul { + float: none; + } + .bootstrap-vertical-nav .navbar ul:not { + display: block; + } + .bootstrap-vertical-nav .navbar li { + float: none; + display: block; + } + + .bootstrap-vertical-nav .navbar-nav .nav-item+.nav-item { + margin-left: 0; + } +} + + @media screen and (min-width: 480px) { + .hidden-lg-up { + display: none !important; + } + .navbar-collapse { + display: flex !important; + } +} + + @media screen and (max-width: 479px) { + .hd-lg-down { + display: none !important; + } + .navbar-toggleable-md > .container { + padding-right: 0; + padding-left: 0; + } + + .navbar-brand { + margin-top: 0 !important; + margin-right: 1rem !important; + } + + .navbar-nav { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0 !important; + margin-top: 0 !important; + list-style: none; + } + + .navbar-nav .nav-link { + padding: 0; + } + + .navbar-nav li { + line-height: 36px; + height: 36px; + padding-top: 0; + } + + .navbar-nav .nav-item + .nav-item { + margin-left: 0; + } + + .actix-footer-gray { + text-align: center; + flex-direction: column; + } + + .actix-footer-social a .fa-github { + margin-right: 1rem; + } +} + +@media (min-width: 992px) { + .actix-footer-gray { + width: 960px; + } +} + +@media (min-width: 1200px) { + .actix-footer-gray { + width: 1140px; + } +} diff --git a/static/css/bootstrap-reboot.css b/static/css/bootstrap-reboot.css new file mode 100644 index 0000000..9a35223 --- /dev/null +++ b/static/css/bootstrap-reboot.css @@ -0,0 +1,2 @@ +/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}@-ms-viewport{width:device-width}html{font-size:16px;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;line-height:1.5;color:#373a3c;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #818a91}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}a{color:#0275d8;text-decoration:none}a:focus,a:hover{color:#014c8c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle}[role=button]{cursor:pointer}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse;background-color:transparent}caption{padding-top:.75rem;padding-bottom:.75rem;color:#818a91;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,select,textarea{line-height:inherit}input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit}input[type=search]{-webkit-appearance:none}output{display:inline-block}[hidden]{display:none!important} +/*# sourceMappingURL=bootstrap-reboot.min.css.map */ \ No newline at end of file diff --git a/static/css/bootstrap.css b/static/css/bootstrap.css new file mode 100644 index 0000000..06cf582 --- /dev/null +++ b/static/css/bootstrap.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com) + * Copyright 2011-2016 The Bootstrap Authors + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}@media print{*,::after,::before,::first-letter,blockquote::first-line,div::first-line,li::first-line,p::first-line{text-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.tag{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}@-ms-viewport{width:device-width}html{font-size:16px;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;line-height:1.5;color:#373a3c;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #818a91}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}a{color:#0275d8;text-decoration:none}a:focus,a:hover{color:#014c8c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle}[role=button]{cursor:pointer}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse;background-color:transparent}caption{padding-top:.75rem;padding-bottom:.75rem;color:#818a91;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,select,textarea{line-height:inherit}input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit}input[type=search]{-webkit-appearance:none}output{display:inline-block}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300}.display-2{font-size:5.5rem;font-weight:300}.display-3{font-size:4.5rem;font-weight:300}.display-4{font-size:3.5rem;font-weight:300}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:5px}.initialism{font-size:90%;text-transform:uppercase}.blockquote{padding:.5rem 1rem;margin-bottom:1rem;font-size:1.25rem;border-left:.25rem solid #eceeef}.blockquote-footer{display:block;font-size:80%;color:#818a91}.blockquote-footer::before{content:"\2014 \00A0"}.blockquote-reverse{padding-right:1rem;padding-left:0;text-align:right;border-right:.25rem solid #eceeef;border-left:0}.blockquote-reverse .blockquote-footer::before{content:""}.blockquote-reverse .blockquote-footer::after{content:"\00A0 \2014"}dl.row>dd+dt{clear:left}.carousel-inner>.carousel-item>a>img,.carousel-inner>.carousel-item>img,.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #ddd;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#818a91}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}code{padding:.2rem .4rem;font-size:90%;color:#bd4147;background-color:#f7f7f9;border-radius:.25rem}kbd{padding:.2rem .4rem;font-size:90%;color:#fff;background-color:#333;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;margin-top:0;margin-bottom:1rem;font-size:90%;color:#373a3c}pre code{padding:0;font-size:inherit;color:inherit;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px}.container::after{content:"";display:table;clear:both}@media (min-width:576px){.container{width:540px;max-width:100%}}@media (min-width:768px){.container{width:720px;max-width:100%}}@media (min-width:992px){.container{width:960px;max-width:100%}}@media (min-width:1200px){.container{width:1140px;max-width:100%}}.container-fluid{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px}.container-fluid::after{content:"";display:table;clear:both}.row{margin-right:-15px;margin-left:-15px}.row::after{content:"";display:table;clear:both}@media (min-width:576px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:768px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:992px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:1200px){.row{margin-right:-15px;margin-left:-15px}}.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}@media (min-width:576px){.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{padding-right:15px;padding-left:15px}}@media (min-width:768px){.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{padding-right:15px;padding-left:15px}}@media (min-width:992px){.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{padding-right:15px;padding-left:15px}}.col-xs-1{float:left;width:8.333333%}.col-xs-2{float:left;width:16.666667%}.col-xs-3{float:left;width:25%}.col-xs-4{float:left;width:33.333333%}.col-xs-5{float:left;width:41.666667%}.col-xs-6{float:left;width:50%}.col-xs-7{float:left;width:58.333333%}.col-xs-8{float:left;width:66.666667%}.col-xs-9{float:left;width:75%}.col-xs-10{float:left;width:83.333333%}.col-xs-11{float:left;width:91.666667%}.col-xs-12{float:left;width:100%}.pull-xs-0{right:auto}.pull-xs-1{right:8.333333%}.pull-xs-2{right:16.666667%}.pull-xs-3{right:25%}.pull-xs-4{right:33.333333%}.pull-xs-5{right:41.666667%}.pull-xs-6{right:50%}.pull-xs-7{right:58.333333%}.pull-xs-8{right:66.666667%}.pull-xs-9{right:75%}.pull-xs-10{right:83.333333%}.pull-xs-11{right:91.666667%}.pull-xs-12{right:100%}.push-xs-0{left:auto}.push-xs-1{left:8.333333%}.push-xs-2{left:16.666667%}.push-xs-3{left:25%}.push-xs-4{left:33.333333%}.push-xs-5{left:41.666667%}.push-xs-6{left:50%}.push-xs-7{left:58.333333%}.push-xs-8{left:66.666667%}.push-xs-9{left:75%}.push-xs-10{left:83.333333%}.push-xs-11{left:91.666667%}.push-xs-12{left:100%}.offset-xs-1{margin-left:8.333333%}.offset-xs-2{margin-left:16.666667%}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:33.333333%}.offset-xs-5{margin-left:41.666667%}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:58.333333%}.offset-xs-8{margin-left:66.666667%}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:83.333333%}.offset-xs-11{margin-left:91.666667%}@media (min-width:576px){.col-sm-1{float:left;width:8.333333%}.col-sm-2{float:left;width:16.666667%}.col-sm-3{float:left;width:25%}.col-sm-4{float:left;width:33.333333%}.col-sm-5{float:left;width:41.666667%}.col-sm-6{float:left;width:50%}.col-sm-7{float:left;width:58.333333%}.col-sm-8{float:left;width:66.666667%}.col-sm-9{float:left;width:75%}.col-sm-10{float:left;width:83.333333%}.col-sm-11{float:left;width:91.666667%}.col-sm-12{float:left;width:100%}.pull-sm-0{right:auto}.pull-sm-1{right:8.333333%}.pull-sm-2{right:16.666667%}.pull-sm-3{right:25%}.pull-sm-4{right:33.333333%}.pull-sm-5{right:41.666667%}.pull-sm-6{right:50%}.pull-sm-7{right:58.333333%}.pull-sm-8{right:66.666667%}.pull-sm-9{right:75%}.pull-sm-10{right:83.333333%}.pull-sm-11{right:91.666667%}.pull-sm-12{right:100%}.push-sm-0{left:auto}.push-sm-1{left:8.333333%}.push-sm-2{left:16.666667%}.push-sm-3{left:25%}.push-sm-4{left:33.333333%}.push-sm-5{left:41.666667%}.push-sm-6{left:50%}.push-sm-7{left:58.333333%}.push-sm-8{left:66.666667%}.push-sm-9{left:75%}.push-sm-10{left:83.333333%}.push-sm-11{left:91.666667%}.push-sm-12{left:100%}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md-1{float:left;width:8.333333%}.col-md-2{float:left;width:16.666667%}.col-md-3{float:left;width:25%}.col-md-4{float:left;width:33.333333%}.col-md-5{float:left;width:41.666667%}.col-md-6{float:left;width:50%}.col-md-7{float:left;width:58.333333%}.col-md-8{float:left;width:66.666667%}.col-md-9{float:left;width:75%}.col-md-10{float:left;width:83.333333%}.col-md-11{float:left;width:91.666667%}.col-md-12{float:left;width:100%}.pull-md-0{right:auto}.pull-md-1{right:8.333333%}.pull-md-2{right:16.666667%}.pull-md-3{right:25%}.pull-md-4{right:33.333333%}.pull-md-5{right:41.666667%}.pull-md-6{right:50%}.pull-md-7{right:58.333333%}.pull-md-8{right:66.666667%}.pull-md-9{right:75%}.pull-md-10{right:83.333333%}.pull-md-11{right:91.666667%}.pull-md-12{right:100%}.push-md-0{left:auto}.push-md-1{left:8.333333%}.push-md-2{left:16.666667%}.push-md-3{left:25%}.push-md-4{left:33.333333%}.push-md-5{left:41.666667%}.push-md-6{left:50%}.push-md-7{left:58.333333%}.push-md-8{left:66.666667%}.push-md-9{left:75%}.push-md-10{left:83.333333%}.push-md-11{left:91.666667%}.push-md-12{left:100%}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg-1{float:left;width:8.333333%}.col-lg-2{float:left;width:16.666667%}.col-lg-3{float:left;width:25%}.col-lg-4{float:left;width:33.333333%}.col-lg-5{float:left;width:41.666667%}.col-lg-6{float:left;width:50%}.col-lg-7{float:left;width:58.333333%}.col-lg-8{float:left;width:66.666667%}.col-lg-9{float:left;width:75%}.col-lg-10{float:left;width:83.333333%}.col-lg-11{float:left;width:91.666667%}.col-lg-12{float:left;width:100%}.pull-lg-0{right:auto}.pull-lg-1{right:8.333333%}.pull-lg-2{right:16.666667%}.pull-lg-3{right:25%}.pull-lg-4{right:33.333333%}.pull-lg-5{right:41.666667%}.pull-lg-6{right:50%}.pull-lg-7{right:58.333333%}.pull-lg-8{right:66.666667%}.pull-lg-9{right:75%}.pull-lg-10{right:83.333333%}.pull-lg-11{right:91.666667%}.pull-lg-12{right:100%}.push-lg-0{left:auto}.push-lg-1{left:8.333333%}.push-lg-2{left:16.666667%}.push-lg-3{left:25%}.push-lg-4{left:33.333333%}.push-lg-5{left:41.666667%}.push-lg-6{left:50%}.push-lg-7{left:58.333333%}.push-lg-8{left:66.666667%}.push-lg-9{left:75%}.push-lg-10{left:83.333333%}.push-lg-11{left:91.666667%}.push-lg-12{left:100%}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl-1{float:left;width:8.333333%}.col-xl-2{float:left;width:16.666667%}.col-xl-3{float:left;width:25%}.col-xl-4{float:left;width:33.333333%}.col-xl-5{float:left;width:41.666667%}.col-xl-6{float:left;width:50%}.col-xl-7{float:left;width:58.333333%}.col-xl-8{float:left;width:66.666667%}.col-xl-9{float:left;width:75%}.col-xl-10{float:left;width:83.333333%}.col-xl-11{float:left;width:91.666667%}.col-xl-12{float:left;width:100%}.pull-xl-0{right:auto}.pull-xl-1{right:8.333333%}.pull-xl-2{right:16.666667%}.pull-xl-3{right:25%}.pull-xl-4{right:33.333333%}.pull-xl-5{right:41.666667%}.pull-xl-6{right:50%}.pull-xl-7{right:58.333333%}.pull-xl-8{right:66.666667%}.pull-xl-9{right:75%}.pull-xl-10{right:83.333333%}.pull-xl-11{right:91.666667%}.pull-xl-12{right:100%}.push-xl-0{left:auto}.push-xl-1{left:8.333333%}.push-xl-2{left:16.666667%}.push-xl-3{left:25%}.push-xl-4{left:33.333333%}.push-xl-5{left:41.666667%}.push-xl-6{left:50%}.push-xl-7{left:58.333333%}.push-xl-8{left:66.666667%}.push-xl-9{left:75%}.push-xl-10{left:83.333333%}.push-xl-11{left:91.666667%}.push-xl-12{left:100%}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #eceeef}.table thead th{vertical-align:bottom;border-bottom:2px solid #eceeef}.table tbody+tbody{border-top:2px solid #eceeef}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #eceeef}.table-bordered td,.table-bordered th{border:1px solid #eceeef}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table-success,.table-success>td,.table-success>th{background-color:#dff0d8}.table-hover .table-success:hover{background-color:#d0e9c6}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#d0e9c6}.table-info,.table-info>td,.table-info>th{background-color:#d9edf7}.table-hover .table-info:hover{background-color:#c4e3f3}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#c4e3f3}.table-warning,.table-warning>td,.table-warning>th{background-color:#fcf8e3}.table-hover .table-warning:hover{background-color:#faf2cc}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#faf2cc}.table-danger,.table-danger>td,.table-danger>th{background-color:#f2dede}.table-hover .table-danger:hover{background-color:#ebcccc}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#ebcccc}.thead-inverse th{color:#fff;background-color:#373a3c}.thead-default th{color:#55595c;background-color:#eceeef}.table-inverse{color:#eceeef;background-color:#373a3c}.table-inverse td,.table-inverse th,.table-inverse thead th{border-color:#55595c}.table-inverse.table-bordered{border:0}.table-responsive{display:block;width:100%;min-height:0%;overflow-x:auto}.table-reflow thead{float:left}.table-reflow tbody{display:block;white-space:nowrap}.table-reflow td,.table-reflow th{border-top:1px solid #eceeef;border-left:1px solid #eceeef}.table-reflow td:last-child,.table-reflow th:last-child{border-right:1px solid #eceeef}.table-reflow tbody:last-child tr:last-child td,.table-reflow tbody:last-child tr:last-child th,.table-reflow tfoot:last-child tr:last-child td,.table-reflow tfoot:last-child tr:last-child th,.table-reflow thead:last-child tr:last-child td,.table-reflow thead:last-child tr:last-child th{border-bottom:1px solid #eceeef}.table-reflow tr{float:left}.table-reflow tr td,.table-reflow tr th{display:block!important;border:1px solid #eceeef}.form-control{display:block;width:100%;padding:.5rem .75rem;font-size:1rem;line-height:1.25;color:#55595c;background-color:#fff;background-image:none;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#55595c;background-color:#fff;border-color:#66afe9;outline:0}.form-control::-webkit-input-placeholder{color:#999;opacity:1}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999;opacity:1}.form-control::placeholder{color:#999;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#eceeef;opacity:1}.form-control:disabled{cursor:not-allowed}select.form-control:not([size]):not([multiple]){height:calc(2.5rem - 2px)}select.form-control:focus::-ms-value{color:#55595c;background-color:#fff}.form-control-file,.form-control-range{display:block}.col-form-label{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0}.col-form-label-lg{padding-top:.75rem;padding-bottom:.75rem;font-size:1.25rem}.col-form-label-sm{padding-top:.25rem;padding-bottom:.25rem;font-size:.875rem}.col-form-legend{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;font-size:1rem}.form-control-static{padding-top:.5rem;padding-bottom:.5rem;line-height:1.25;border:solid transparent;border-width:1px 0}.form-control-static.form-control-lg,.form-control-static.form-control-sm,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-sm>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),.input-group-sm>select.input-group-addon:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:1.8125rem}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.input-group-lg>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),.input-group-lg>select.input-group-addon:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:3.166667rem}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-check{position:relative;display:block;margin-bottom:.75rem}.form-check+.form-check{margin-top:-.25rem}.form-check.disabled .form-check-label{color:#818a91;cursor:not-allowed}.form-check-label{padding-left:1.25rem;margin-bottom:0;cursor:pointer}.form-check-input{position:absolute;margin-top:.25rem;margin-left:-1.25rem}.form-check-input:only-child{position:static}.form-check-inline{position:relative;display:inline-block;padding-left:1.25rem;margin-bottom:0;vertical-align:middle;cursor:pointer}.form-check-inline+.form-check-inline{margin-left:.75rem}.form-check-inline.disabled{color:#818a91;cursor:not-allowed}.form-control-feedback{margin-top:.25rem}.form-control-danger,.form-control-success,.form-control-warning{padding-right:2.25rem;background-repeat:no-repeat;background-position:center right .625rem;-webkit-background-size:1.25rem 1.25rem;background-size:1.25rem 1.25rem}.has-success .custom-control,.has-success .form-check-inline,.has-success .form-check-label,.has-success .form-control-feedback,.has-success .form-control-label{color:#5cb85c}.has-success .form-control{border-color:#5cb85c}.has-success .form-control:focus{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #a3d7a3;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #a3d7a3}.has-success .input-group-addon{color:#5cb85c;border-color:#5cb85c;background-color:#eaf6ea}.has-success .form-control-success{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#5cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E")}.has-warning .custom-control,.has-warning .form-check-inline,.has-warning .form-check-label,.has-warning .form-control-feedback,.has-warning .form-control-label{color:#f0ad4e}.has-warning .form-control{border-color:#f0ad4e}.has-warning .form-control:focus{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #f8d9ac;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #f8d9ac}.has-warning .input-group-addon{color:#f0ad4e;border-color:#f0ad4e;background-color:#fff}.has-warning .form-control-warning{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E")}.has-danger .custom-control,.has-danger .form-check-inline,.has-danger .form-check-label,.has-danger .form-control-feedback,.has-danger .form-control-label{color:#d9534f}.has-danger .form-control{border-color:#d9534f}.has-danger .form-control:focus{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #eba5a3;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #eba5a3}.has-danger .input-group-addon{color:#d9534f;border-color:#d9534f;background-color:#fdf7f7}.has-danger .form-control-danger{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E")}@media (min-width:576px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;width:auto;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .form-control-label{margin-bottom:0;vertical-align:middle}.form-inline .form-check{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .form-check-label{padding-left:0}.form-inline .form-check-input{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.btn{display:inline-block;font-weight:400;line-height:1.25;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.5rem 1rem;font-size:1rem;border-radius:.25rem}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:focus,.btn:hover{text-decoration:none}.btn.focus{text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0}.btn.disabled,.btn:disabled{cursor:not-allowed;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-primary:hover{color:#fff;background-color:#025aa5;border-color:#01549b}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#025aa5;border-color:#01549b}.btn-primary.active,.btn-primary:active,.open>.btn-primary.dropdown-toggle{color:#fff;background-color:#025aa5;border-color:#01549b;background-image:none}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.btn-primary.dropdown-toggle.focus,.open>.btn-primary.dropdown-toggle:focus,.open>.btn-primary.dropdown-toggle:hover{color:#fff;background-color:#014682;border-color:#01315a}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary:disabled.focus,.btn-primary:disabled:focus{background-color:#0275d8;border-color:#0275d8}.btn-primary.disabled:hover,.btn-primary:disabled:hover{background-color:#0275d8;border-color:#0275d8}.btn-secondary{color:#373a3c;background-color:#fff;border-color:#ccc}.btn-secondary:hover{color:#373a3c;background-color:#e6e6e6;border-color:#adadad}.btn-secondary.focus,.btn-secondary:focus{color:#373a3c;background-color:#e6e6e6;border-color:#adadad}.btn-secondary.active,.btn-secondary:active,.open>.btn-secondary.dropdown-toggle{color:#373a3c;background-color:#e6e6e6;border-color:#adadad;background-image:none}.btn-secondary.active.focus,.btn-secondary.active:focus,.btn-secondary.active:hover,.btn-secondary:active.focus,.btn-secondary:active:focus,.btn-secondary:active:hover,.open>.btn-secondary.dropdown-toggle.focus,.open>.btn-secondary.dropdown-toggle:focus,.open>.btn-secondary.dropdown-toggle:hover{color:#373a3c;background-color:#d4d4d4;border-color:#8c8c8c}.btn-secondary.disabled.focus,.btn-secondary.disabled:focus,.btn-secondary:disabled.focus,.btn-secondary:disabled:focus{background-color:#fff;border-color:#ccc}.btn-secondary.disabled:hover,.btn-secondary:disabled:hover{background-color:#fff;border-color:#ccc}.btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#2aabd2}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#2aabd2}.btn-info.active,.btn-info:active,.open>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#2aabd2;background-image:none}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.btn-info.dropdown-toggle.focus,.open>.btn-info.dropdown-toggle:focus,.open>.btn-info.dropdown-toggle:hover{color:#fff;background-color:#269abc;border-color:#1f7e9a}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info:disabled.focus,.btn-info:disabled:focus{background-color:#5bc0de;border-color:#5bc0de}.btn-info.disabled:hover,.btn-info:disabled:hover{background-color:#5bc0de;border-color:#5bc0de}.btn-success{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#419641}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#419641}.btn-success.active,.btn-success:active,.open>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;border-color:#419641;background-image:none}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.btn-success.dropdown-toggle.focus,.open>.btn-success.dropdown-toggle:focus,.open>.btn-success.dropdown-toggle:hover{color:#fff;background-color:#398439;border-color:#2d672d}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success:disabled.focus,.btn-success:disabled:focus{background-color:#5cb85c;border-color:#5cb85c}.btn-success.disabled:hover,.btn-success:disabled:hover{background-color:#5cb85c;border-color:#5cb85c}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#eb9316}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#eb9316}.btn-warning.active,.btn-warning:active,.open>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;border-color:#eb9316;background-image:none}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.btn-warning.dropdown-toggle.focus,.open>.btn-warning.dropdown-toggle:focus,.open>.btn-warning.dropdown-toggle:hover{color:#fff;background-color:#d58512;border-color:#b06d0f}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning:disabled.focus,.btn-warning:disabled:focus{background-color:#f0ad4e;border-color:#f0ad4e}.btn-warning.disabled:hover,.btn-warning:disabled:hover{background-color:#f0ad4e;border-color:#f0ad4e}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#c12e2a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#c12e2a}.btn-danger.active,.btn-danger:active,.open>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;border-color:#c12e2a;background-image:none}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.btn-danger.dropdown-toggle.focus,.open>.btn-danger.dropdown-toggle:focus,.open>.btn-danger.dropdown-toggle:hover{color:#fff;background-color:#ac2925;border-color:#8b211e}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger:disabled.focus,.btn-danger:disabled:focus{background-color:#d9534f;border-color:#d9534f}.btn-danger.disabled:hover,.btn-danger:disabled:hover{background-color:#d9534f;border-color:#d9534f}.btn-outline-primary{color:#0275d8;background-image:none;background-color:transparent;border-color:#0275d8}.btn-outline-primary:hover{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-primary.focus,.btn-outline-primary:focus{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-primary.active,.btn-outline-primary:active,.open>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-primary.active.focus,.btn-outline-primary.active:focus,.btn-outline-primary.active:hover,.btn-outline-primary:active.focus,.btn-outline-primary:active:focus,.btn-outline-primary:active:hover,.open>.btn-outline-primary.dropdown-toggle.focus,.open>.btn-outline-primary.dropdown-toggle:focus,.open>.btn-outline-primary.dropdown-toggle:hover{color:#fff;background-color:#014682;border-color:#01315a}.btn-outline-primary.disabled.focus,.btn-outline-primary.disabled:focus,.btn-outline-primary:disabled.focus,.btn-outline-primary:disabled:focus{border-color:#43a7fd}.btn-outline-primary.disabled:hover,.btn-outline-primary:disabled:hover{border-color:#43a7fd}.btn-outline-secondary{color:#ccc;background-image:none;background-color:transparent;border-color:#ccc}.btn-outline-secondary:hover{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-secondary.focus,.btn-outline-secondary:focus{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-secondary.active,.btn-outline-secondary:active,.open>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-secondary.active.focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.active:hover,.btn-outline-secondary:active.focus,.btn-outline-secondary:active:focus,.btn-outline-secondary:active:hover,.open>.btn-outline-secondary.dropdown-toggle.focus,.open>.btn-outline-secondary.dropdown-toggle:focus,.open>.btn-outline-secondary.dropdown-toggle:hover{color:#fff;background-color:#a1a1a1;border-color:#8c8c8c}.btn-outline-secondary.disabled.focus,.btn-outline-secondary.disabled:focus,.btn-outline-secondary:disabled.focus,.btn-outline-secondary:disabled:focus{border-color:#fff}.btn-outline-secondary.disabled:hover,.btn-outline-secondary:disabled:hover{border-color:#fff}.btn-outline-info{color:#5bc0de;background-image:none;background-color:transparent;border-color:#5bc0de}.btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info.focus,.btn-outline-info:focus{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info.active,.btn-outline-info:active,.open>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info.active.focus,.btn-outline-info.active:focus,.btn-outline-info.active:hover,.btn-outline-info:active.focus,.btn-outline-info:active:focus,.btn-outline-info:active:hover,.open>.btn-outline-info.dropdown-toggle.focus,.open>.btn-outline-info.dropdown-toggle:focus,.open>.btn-outline-info.dropdown-toggle:hover{color:#fff;background-color:#269abc;border-color:#1f7e9a}.btn-outline-info.disabled.focus,.btn-outline-info.disabled:focus,.btn-outline-info:disabled.focus,.btn-outline-info:disabled:focus{border-color:#b0e1ef}.btn-outline-info.disabled:hover,.btn-outline-info:disabled:hover{border-color:#b0e1ef}.btn-outline-success{color:#5cb85c;background-image:none;background-color:transparent;border-color:#5cb85c}.btn-outline-success:hover{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-success.focus,.btn-outline-success:focus{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-success.active,.btn-outline-success:active,.open>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-success.active.focus,.btn-outline-success.active:focus,.btn-outline-success.active:hover,.btn-outline-success:active.focus,.btn-outline-success:active:focus,.btn-outline-success:active:hover,.open>.btn-outline-success.dropdown-toggle.focus,.open>.btn-outline-success.dropdown-toggle:focus,.open>.btn-outline-success.dropdown-toggle:hover{color:#fff;background-color:#398439;border-color:#2d672d}.btn-outline-success.disabled.focus,.btn-outline-success.disabled:focus,.btn-outline-success:disabled.focus,.btn-outline-success:disabled:focus{border-color:#a3d7a3}.btn-outline-success.disabled:hover,.btn-outline-success:disabled:hover{border-color:#a3d7a3}.btn-outline-warning{color:#f0ad4e;background-image:none;background-color:transparent;border-color:#f0ad4e}.btn-outline-warning:hover{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-warning.focus,.btn-outline-warning:focus{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-warning.active,.btn-outline-warning:active,.open>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-warning.active.focus,.btn-outline-warning.active:focus,.btn-outline-warning.active:hover,.btn-outline-warning:active.focus,.btn-outline-warning:active:focus,.btn-outline-warning:active:hover,.open>.btn-outline-warning.dropdown-toggle.focus,.open>.btn-outline-warning.dropdown-toggle:focus,.open>.btn-outline-warning.dropdown-toggle:hover{color:#fff;background-color:#d58512;border-color:#b06d0f}.btn-outline-warning.disabled.focus,.btn-outline-warning.disabled:focus,.btn-outline-warning:disabled.focus,.btn-outline-warning:disabled:focus{border-color:#f8d9ac}.btn-outline-warning.disabled:hover,.btn-outline-warning:disabled:hover{border-color:#f8d9ac}.btn-outline-danger{color:#d9534f;background-image:none;background-color:transparent;border-color:#d9534f}.btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-outline-danger.focus,.btn-outline-danger:focus{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-outline-danger.active,.btn-outline-danger:active,.open>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-outline-danger.active.focus,.btn-outline-danger.active:focus,.btn-outline-danger.active:hover,.btn-outline-danger:active.focus,.btn-outline-danger:active:focus,.btn-outline-danger:active:hover,.open>.btn-outline-danger.dropdown-toggle.focus,.open>.btn-outline-danger.dropdown-toggle:focus,.open>.btn-outline-danger.dropdown-toggle:hover{color:#fff;background-color:#ac2925;border-color:#8b211e}.btn-outline-danger.disabled.focus,.btn-outline-danger.disabled:focus,.btn-outline-danger:disabled.focus,.btn-outline-danger:disabled:focus{border-color:#eba5a3}.btn-outline-danger.disabled:hover,.btn-outline-danger:disabled:hover{border-color:#eba5a3}.btn-link{font-weight:400;color:#0275d8;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link:disabled{background-color:transparent}.btn-link,.btn-link:active,.btn-link:focus{border-color:transparent}.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#014c8c;text-decoration:underline;background-color:transparent}.btn-link:disabled:focus,.btn-link:disabled:hover{color:#818a91;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height;-o-transition-property:height;transition-property:height}.dropdown,.dropup{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.3em;vertical-align:middle;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-left:.3em solid transparent}.dropdown-toggle:focus{outline:0}.dropup .dropdown-toggle::after{border-top:0;border-bottom:.3em solid}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#373a3c;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-divider{height:1px;margin:.5rem 0;overflow:hidden;background-color:#e5e5e5}.dropdown-item{display:block;width:100%;padding:3px 1.5rem;clear:both;font-weight:400;color:#373a3c;text-align:inherit;white-space:nowrap;background:0 0;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#2b2d2f;text-decoration:none;background-color:#f5f5f5}.dropdown-item.active,.dropdown-item.active:focus,.dropdown-item.active:hover{color:#fff;text-decoration:none;background-color:#0275d8;outline:0}.dropdown-item.disabled,.dropdown-item.disabled:focus,.dropdown-item.disabled:hover{color:#818a91}.dropdown-item.disabled:focus,.dropdown-item.disabled:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:"progid:DXImageTransform.Microsoft.gradient(enabled = false)"}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#818a91;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:.3em solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:.125rem}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left;margin-bottom:0}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:2}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-.5rem}.btn-toolbar::after{content:"";display:table;clear:both}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:.5rem}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn+.dropdown-toggle-split::after{margin-left:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:1.125rem;padding-left:1.125rem}.btn .caret{margin-left:0}.btn-group-lg>.btn .caret,.btn-lg .caret{border-width:.3em .3em 0;border-bottom-width:0}.dropup .btn-group-lg>.btn .caret,.dropup .btn-lg .caret{border-width:0 .3em .3em}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group::after{content:"";display:table;clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;width:100%;display:table;border-collapse:separate}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:active,.input-group .form-control:focus,.input-group .form-control:hover{z-index:3}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.25;color:#55595c;text-align:center;background-color:#eceeef;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.input-group-addon.form-control-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-addon.form-control-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:not(:last-child),.input-group-addon:not(:last-child),.input-group-btn:not(:first-child)>.btn-group:not(:last-child)>.btn,.input-group-btn:not(:first-child)>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group>.btn,.input-group-btn:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:not(:last-child){border-right:0}.input-group .form-control:not(:first-child),.input-group-addon:not(:first-child),.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group>.btn,.input-group-btn:not(:first-child)>.dropdown-toggle,.input-group-btn:not(:last-child)>.btn-group:not(:first-child)>.btn,.input-group-btn:not(:last-child)>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.form-control+.input-group-addon:not(:first-child){border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:3}.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group{margin-right:-1px}.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group{z-index:2;margin-left:-1px}.input-group-btn:not(:first-child)>.btn-group:active,.input-group-btn:not(:first-child)>.btn-group:focus,.input-group-btn:not(:first-child)>.btn-group:hover,.input-group-btn:not(:first-child)>.btn:active,.input-group-btn:not(:first-child)>.btn:focus,.input-group-btn:not(:first-child)>.btn:hover{z-index:3}.custom-control{position:relative;display:inline-block;padding-left:1.5rem;cursor:pointer}.custom-control+.custom-control{margin-left:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-indicator{color:#fff;background-color:#0074d9}.custom-control-input:focus~.custom-control-indicator{-webkit-box-shadow:0 0 0 .075rem #fff,0 0 0 .2rem #0074d9;box-shadow:0 0 0 .075rem #fff,0 0 0 .2rem #0074d9}.custom-control-input:active~.custom-control-indicator{color:#fff;background-color:#84c6ff}.custom-control-input:disabled~.custom-control-indicator{cursor:not-allowed;background-color:#eee}.custom-control-input:disabled~.custom-control-description{color:#767676;cursor:not-allowed}.custom-control-indicator{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#ddd;background-repeat:no-repeat;background-position:center center;-webkit-background-size:50% 50%;background-size:50% 50%}.custom-checkbox .custom-control-indicator{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-indicator{background-color:#0074d9;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-radio .custom-control-indicator{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#fff'/%3E%3C/svg%3E")}.custom-controls-stacked .custom-control{float:left;clear:left}.custom-controls-stacked .custom-control+.custom-control{margin-left:0}.custom-select{display:inline-block;max-width:100%;height:calc(2.5rem - 2px);padding:.375rem 1.75rem .375rem .75rem;padding-right:.75rem\9;color:#55595c;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center;background-image:none\9;-webkit-background-size:8px 10px;background-size:8px 10px;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-moz-appearance:none;-webkit-appearance:none}.custom-select:focus{border-color:#51a7e8;outline:0}.custom-select:focus::-ms-value{color:#55595c;background-color:#fff}.custom-select:disabled{color:#818a91;cursor:not-allowed;background-color:#eceeef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-file{position:relative;display:inline-block;max-width:100%;height:2.5rem;cursor:pointer}.custom-file-input{min-width:14rem;max-width:100%;margin:0;filter:alpha(opacity=0);opacity:0}.custom-file-control{position:absolute;top:0;right:0;left:0;z-index:5;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#555;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff;border:1px solid #ddd;border-radius:.25rem}.custom-file-control:lang(en)::after{content:"Choose file..."}.custom-file-control::before{position:absolute;top:-1px;right:-1px;bottom:-1px;z-index:6;display:block;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#555;background-color:#eee;border:1px solid #ddd;border-radius:0 .25rem .25rem 0}.custom-file-control:lang(en)::before{content:"Browse"}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:inline-block}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#818a91}.nav-link.disabled,.nav-link.disabled:focus,.nav-link.disabled:hover{color:#818a91;cursor:not-allowed;background-color:transparent}.nav-inline .nav-item{display:inline-block}.nav-inline .nav-item+.nav-item,.nav-inline .nav-link+.nav-link{margin-left:1rem}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs::after{content:"";display:table;clear:both}.nav-tabs .nav-item{float:left;margin-bottom:-1px}.nav-tabs .nav-item+.nav-item{margin-left:.2rem}.nav-tabs .nav-link{display:block;padding:.5em 1em;border:1px solid transparent;border-top-right-radius:.25rem;border-top-left-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#eceeef #eceeef #ddd}.nav-tabs .nav-link.disabled,.nav-tabs .nav-link.disabled:focus,.nav-tabs .nav-link.disabled:hover{color:#818a91;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.open .nav-link,.nav-tabs .nav-item.open .nav-link:focus,.nav-tabs .nav-item.open .nav-link:hover,.nav-tabs .nav-link.active,.nav-tabs .nav-link.active:focus,.nav-tabs .nav-link.active:hover{color:#55595c;background-color:#fff;border-color:#ddd #ddd transparent}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.nav-pills::after{content:"";display:table;clear:both}.nav-pills .nav-item{float:left}.nav-pills .nav-item+.nav-item{margin-left:.2rem}.nav-pills .nav-link{display:block;padding:.5em 1em;border-radius:.25rem}.nav-pills .nav-item.open .nav-link,.nav-pills .nav-item.open .nav-link:focus,.nav-pills .nav-item.open .nav-link:hover,.nav-pills .nav-link.active,.nav-pills .nav-link.active:focus,.nav-pills .nav-link.active:hover{color:#fff;cursor:default;background-color:#0275d8}.nav-stacked .nav-item{display:block;float:none}.nav-stacked .nav-item+.nav-item{margin-top:.2rem;margin-left:0}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;padding:.5rem 1rem}.navbar::after{content:"";display:table;clear:both}@media (min-width:576px){.navbar{border-radius:.25rem}}.navbar-full{z-index:1000}@media (min-width:576px){.navbar-full{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:576px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0}.navbar-fixed-bottom{bottom:0}.navbar-sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1030;width:100%}@media (min-width:576px){.navbar-sticky-top{border-radius:0}}.navbar-brand{float:left;padding-top:.25rem;padding-bottom:.25rem;margin-right:1rem;font-size:1.25rem;line-height:inherit}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-divider{float:left;width:1px;padding-top:.425rem;padding-bottom:.425rem;margin-right:1rem;margin-left:1rem;overflow:hidden}.navbar-divider::before{content:"\00a0"}.navbar-text{display:inline-block;padding-top:.425rem;padding-bottom:.425rem}.navbar-toggler{width:2.5em;height:2em;padding:.5rem .75rem;font-size:1.25rem;line-height:1;background:transparent no-repeat center center;-webkit-background-size:24px 24px;background-size:24px 24px;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggleable-xs::after{content:"";display:table;clear:both}@media (max-width:575px){.navbar-toggleable-xs .navbar-brand{display:block;float:none;margin-top:.5rem;margin-right:0}.navbar-toggleable-xs .navbar-nav{margin-top:.5rem;margin-bottom:.5rem}.navbar-toggleable-xs .navbar-nav .dropdown-menu{position:static;float:none}}@media (min-width:576px){.navbar-toggleable-xs{display:block}}.navbar-toggleable-sm::after{content:"";display:table;clear:both}@media (max-width:767px){.navbar-toggleable-sm .navbar-brand{display:block;float:none;margin-top:.5rem;margin-right:0}.navbar-toggleable-sm .navbar-nav{margin-top:.5rem;margin-bottom:.5rem}.navbar-toggleable-sm .navbar-nav .dropdown-menu{position:static;float:none}}@media (min-width:768px){.navbar-toggleable-sm{display:block}}.navbar-toggleable-md::after{content:"";display:table;clear:both}@media (max-width:991px){.navbar-toggleable-md .navbar-brand{display:block;float:none;margin-top:.5rem;margin-right:0}.navbar-toggleable-md .navbar-nav{margin-top:.5rem;margin-bottom:.5rem}.navbar-toggleable-md .navbar-nav .dropdown-menu{position:static;float:none}}@media (min-width:992px){.navbar-toggleable-md{display:block}}.navbar-toggleable-lg::after{content:"";display:table;clear:both}@media (max-width:1199px){.navbar-toggleable-lg .navbar-brand{display:block;float:none;margin-top:.5rem;margin-right:0}.navbar-toggleable-lg .navbar-nav{margin-top:.5rem;margin-bottom:.5rem}.navbar-toggleable-lg .navbar-nav .dropdown-menu{position:static;float:none}}@media (min-width:1200px){.navbar-toggleable-lg{display:block}}.navbar-toggleable-xl{display:block}.navbar-toggleable-xl::after{content:"";display:table;clear:both}.navbar-toggleable-xl .navbar-brand{display:block;float:none;margin-top:.5rem;margin-right:0}.navbar-toggleable-xl .navbar-nav{margin-top:.5rem;margin-bottom:.5rem}.navbar-toggleable-xl .navbar-nav .dropdown-menu{position:static;float:none}.navbar-nav .nav-item{float:left}.navbar-nav .nav-link{display:block;padding-top:.425rem;padding-bottom:.425rem}.navbar-nav .nav-link+.nav-link{margin-left:1rem}.navbar-nav .nav-item+.nav-item{margin-left:1rem}.navbar-light .navbar-brand,.navbar-light .navbar-toggler{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover,.navbar-light .navbar-toggler:focus,.navbar-light .navbar-toggler:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .active>.nav-link:focus,.navbar-light .navbar-nav .active>.nav-link:hover,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.active:focus,.navbar-light .navbar-nav .nav-link.active:hover,.navbar-light .navbar-nav .nav-link.open,.navbar-light .navbar-nav .nav-link.open:focus,.navbar-light .navbar-nav .nav-link.open:hover,.navbar-light .navbar-nav .open>.nav-link,.navbar-light .navbar-nav .open>.nav-link:focus,.navbar-light .navbar-nav .open>.nav-link:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");border-color:rgba(0,0,0,.1)}.navbar-light .navbar-divider{background-color:rgba(0,0,0,.075)}.navbar-dark .navbar-brand,.navbar-dark .navbar-toggler{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-toggler:focus,.navbar-dark .navbar-toggler:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .active>.nav-link:focus,.navbar-dark .navbar-nav .active>.nav-link:hover,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.active:focus,.navbar-dark .navbar-nav .nav-link.active:hover,.navbar-dark .navbar-nav .nav-link.open,.navbar-dark .navbar-nav .nav-link.open:focus,.navbar-dark .navbar-nav .nav-link.open:hover,.navbar-dark .navbar-nav .open>.nav-link,.navbar-dark .navbar-nav .open>.nav-link:focus,.navbar-dark .navbar-nav .open>.nav-link:hover{color:#fff}.navbar-dark .navbar-toggler{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-divider{background-color:rgba(255,255,255,.075)}.navbar-toggleable-xs::after{content:"";display:table;clear:both}@media (max-width:575px){.navbar-toggleable-xs .navbar-nav .nav-item{float:none;margin-left:0}}@media (min-width:576px){.navbar-toggleable-xs{display:block!important}}.navbar-toggleable-sm::after{content:"";display:table;clear:both}@media (max-width:767px){.navbar-toggleable-sm .navbar-nav .nav-item{float:none;margin-left:0}}@media (min-width:768px){.navbar-toggleable-sm{display:block!important}}.navbar-toggleable-md::after{content:"";display:table;clear:both}@media (max-width:991px){.navbar-toggleable-md .navbar-nav .nav-item{float:none;margin-left:0}}@media (min-width:992px){.navbar-toggleable-md{display:block!important}}.card{position:relative;display:block;margin-bottom:.75rem;background-color:#fff;border-radius:.25rem;border:1px solid rgba(0,0,0,.125)}.card-block{padding:1.25rem}.card-block::after{content:"";display:table;clear:both}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card>.list-group:first-child .list-group-item:first-child{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:#f5f5f5;border-bottom:1px solid rgba(0,0,0,.125)}.card-header::after{content:"";display:table;clear:both}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:#f5f5f5;border-top:1px solid rgba(0,0,0,.125)}.card-footer::after{content:"";display:table;clear:both}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-primary{background-color:#0275d8;border-color:#0275d8}.card-primary .card-footer,.card-primary .card-header{background-color:transparent}.card-success{background-color:#5cb85c;border-color:#5cb85c}.card-success .card-footer,.card-success .card-header{background-color:transparent}.card-info{background-color:#5bc0de;border-color:#5bc0de}.card-info .card-footer,.card-info .card-header{background-color:transparent}.card-warning{background-color:#f0ad4e;border-color:#f0ad4e}.card-warning .card-footer,.card-warning .card-header{background-color:transparent}.card-danger{background-color:#d9534f;border-color:#d9534f}.card-danger .card-footer,.card-danger .card-header{background-color:transparent}.card-outline-primary{background-color:transparent;border-color:#0275d8}.card-outline-secondary{background-color:transparent;border-color:#ccc}.card-outline-info{background-color:transparent;border-color:#5bc0de}.card-outline-success{background-color:transparent;border-color:#5cb85c}.card-outline-warning{background-color:transparent;border-color:#f0ad4e}.card-outline-danger{background-color:transparent;border-color:#d9534f}.card-inverse .card-footer,.card-inverse .card-header{border-color:rgba(255,255,255,.2)}.card-inverse .card-blockquote,.card-inverse .card-footer,.card-inverse .card-header,.card-inverse .card-title{color:#fff}.card-inverse .card-blockquote .blockquote-footer,.card-inverse .card-link,.card-inverse .card-subtitle,.card-inverse .card-text{color:rgba(255,255,255,.65)}.card-inverse .card-link:focus,.card-inverse .card-link:hover{color:#fff}.card-blockquote{padding:0;margin-bottom:0;border-left:0}.card-img{border-radius:calc(.25rem - 1px)}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img-top{border-top-right-radius:calc(.25rem - 1px);border-top-left-radius:calc(.25rem - 1px)}.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}@media (min-width:576px){.card-deck{display:table;width:100%;margin-bottom:.75rem;table-layout:fixed;border-spacing:1.25rem 0}.card-deck .card{display:table-cell;margin-bottom:0;vertical-align:top}.card-deck-wrapper{margin-right:-1.25rem;margin-left:-1.25rem}}@media (min-width:576px){.card-group{display:table;width:100%;table-layout:fixed}.card-group .card{display:table-cell;vertical-align:top}.card-group .card+.card{margin-left:0;border-left:0}.card-group .card:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.card-group .card:first-child .card-img-top{border-top-right-radius:0}.card-group .card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group .card:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.card-group .card:last-child .card-img-top{border-top-left-radius:0}.card-group .card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group .card:not(:first-child):not(:last-child){border-radius:0}.card-group .card:not(:first-child):not(:last-child) .card-img-bottom,.card-group .card:not(:first-child):not(:last-child) .card-img-top{border-radius:0}}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem}.card-columns .card{display:inline-block;width:100%}}.breadcrumb{padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#eceeef;border-radius:.25rem}.breadcrumb::after{content:"";display:table;clear:both}.breadcrumb-item{float:left}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;padding-left:.5rem;color:#818a91;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#818a91}.pagination{display:inline-block;padding-left:0;margin-top:1rem;margin-bottom:1rem;border-radius:.25rem}.page-item{display:inline}.page-item:first-child .page-link{margin-left:0;border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link,.page-item.active .page-link:focus,.page-item.active .page-link:hover{z-index:2;color:#fff;cursor:default;background-color:#0275d8;border-color:#0275d8}.page-item.disabled .page-link,.page-item.disabled .page-link:focus,.page-item.disabled .page-link:hover{color:#818a91;pointer-events:none;cursor:not-allowed;background-color:#fff;border-color:#ddd}.page-link{position:relative;float:left;padding:.5rem .75rem;margin-left:-1px;color:#0275d8;text-decoration:none;background-color:#fff;border:1px solid #ddd}.page-link:focus,.page-link:hover{color:#014c8c;background-color:#eceeef;border-color:#ddd}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:.3rem;border-top-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:.3rem;border-top-right-radius:.3rem}.pagination-sm .page-link{padding:.275rem .75rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.tag{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.tag:empty{display:none}.btn .tag{position:relative;top:-1px}a.tag:focus,a.tag:hover{color:#fff;text-decoration:none;cursor:pointer}.tag-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.tag-default{background-color:#818a91}.tag-default[href]:focus,.tag-default[href]:hover{background-color:#687077}.tag-primary{background-color:#0275d8}.tag-primary[href]:focus,.tag-primary[href]:hover{background-color:#025aa5}.tag-success{background-color:#5cb85c}.tag-success[href]:focus,.tag-success[href]:hover{background-color:#449d44}.tag-info{background-color:#5bc0de}.tag-info[href]:focus,.tag-info[href]:hover{background-color:#31b0d5}.tag-warning{background-color:#f0ad4e}.tag-warning[href]:focus,.tag-warning[href]:hover{background-color:#ec971f}.tag-danger{background-color:#d9534f}.tag-danger[href]:focus,.tag-danger[href]:hover{background-color:#c9302c}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#eceeef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-hr{border-top-color:#d0d5d8}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:2.5rem}.alert-dismissible .close{position:relative;top:-.125rem;right:-1.25rem;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d0e9c6;color:#3c763d}.alert-success hr{border-top-color:#c1e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bcdff1;color:#31708f}.alert-info hr{border-top-color:#a6d5ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faf2cc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7ecb5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebcccc;color:#a94442}.alert-danger hr{border-top-color:#e4b9b9}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:block;width:100%;height:1rem;margin-bottom:1rem}.progress[value]{background-color:#eee;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem}.progress[value]::-ms-fill{background-color:#0074d9;border:0}.progress[value]::-moz-progress-bar{background-color:#0074d9;border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.progress[value]::-webkit-progress-value{background-color:#0074d9;border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.progress[value="100"]::-moz-progress-bar{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.progress[value="100"]::-webkit-progress-value{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.progress[value]::-webkit-progress-bar{background-color:#eee;border-radius:.25rem}.progress[value],base::-moz-progress-bar{background-color:#eee;border-radius:.25rem}@media screen and (min-width:0\0){.progress{background-color:#eee;border-radius:.25rem}.progress-bar{display:inline-block;height:1rem;text-indent:-999rem;background-color:#0074d9;border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.progress[width="100%"]{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}}.progress-striped[value]::-webkit-progress-value{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.progress-striped[value]::-moz-progress-bar{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-striped[value]::-ms-fill{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}@media screen and (min-width:0\0){.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}}.progress-animated[value]::-webkit-progress-value{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-animated[value]::-moz-progress-bar{animation:progress-bar-stripes 2s linear infinite}@media screen and (min-width:0\0){.progress-animated .progress-bar-striped{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}}.progress-success[value]::-webkit-progress-value{background-color:#5cb85c}.progress-success[value]::-moz-progress-bar{background-color:#5cb85c}.progress-success[value]::-ms-fill{background-color:#5cb85c}@media screen and (min-width:0\0){.progress-success .progress-bar{background-color:#5cb85c}}.progress-info[value]::-webkit-progress-value{background-color:#5bc0de}.progress-info[value]::-moz-progress-bar{background-color:#5bc0de}.progress-info[value]::-ms-fill{background-color:#5bc0de}@media screen and (min-width:0\0){.progress-info .progress-bar{background-color:#5bc0de}}.progress-warning[value]::-webkit-progress-value{background-color:#f0ad4e}.progress-warning[value]::-moz-progress-bar{background-color:#f0ad4e}.progress-warning[value]::-ms-fill{background-color:#f0ad4e}@media screen and (min-width:0\0){.progress-warning .progress-bar{background-color:#f0ad4e}}.progress-danger[value]::-webkit-progress-value{background-color:#d9534f}.progress-danger[value]::-moz-progress-bar{background-color:#d9534f}.progress-danger[value]::-ms-fill{background-color:#d9534f}@media screen and (min-width:0\0){.progress-danger .progress-bar{background-color:#d9534f}}.media,.media-body{overflow:hidden}.media-body{width:10000px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right{padding-left:10px}.media-left{padding-right:10px}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:0}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#818a91;cursor:not-allowed;background-color:#eceeef}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#818a91}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;text-decoration:none;background-color:#0275d8;border-color:#0275d8}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#a8d6fe}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-item-action{width:100%;color:#555;text-align:inherit}.list-group-item-action .list-group-item-heading{color:#333}.list-group-item-action:focus,.list-group-item-action:hover{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9{padding-bottom:42.857143%}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.embed-responsive-1by1{padding-bottom:100%}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.in{opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header::after{content:"";display:table;clear:both}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.5}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer::after{content:"";display:table;clear:both}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:600px;margin:30px auto}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.in{opacity:.9}.tooltip.bs-tether-element-attached-bottom,.tooltip.tooltip-top{padding:5px 0;margin-top:-3px}.tooltip.bs-tether-element-attached-bottom .tooltip-inner::before,.tooltip.tooltip-top .tooltip-inner::before{bottom:0;left:50%;margin-left:-5px;content:"";border-width:5px 5px 0;border-top-color:#000}.tooltip.bs-tether-element-attached-left,.tooltip.tooltip-right{padding:0 5px;margin-left:3px}.tooltip.bs-tether-element-attached-left .tooltip-inner::before,.tooltip.tooltip-right .tooltip-inner::before{top:50%;left:0;margin-top:-5px;content:"";border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.bs-tether-element-attached-top,.tooltip.tooltip-bottom{padding:5px 0;margin-top:3px}.tooltip.bs-tether-element-attached-top .tooltip-inner::before,.tooltip.tooltip-bottom .tooltip-inner::before{top:0;left:50%;margin-left:-5px;content:"";border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bs-tether-element-attached-right,.tooltip.tooltip-left{padding:0 5px;margin-left:-3px}.tooltip.bs-tether-element-attached-right .tooltip-inner::before,.tooltip.tooltip-left .tooltip-inner::before{top:50%;right:0;margin-top:-5px;content:"";border-width:5px 0 5px 5px;border-left-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.tooltip-inner::before{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;padding:1px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;font-size:.875rem;word-wrap:break-word;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover.bs-tether-element-attached-bottom,.popover.popover-top{margin-top:-10px}.popover.bs-tether-element-attached-bottom::after,.popover.bs-tether-element-attached-bottom::before,.popover.popover-top::after,.popover.popover-top::before{left:50%;border-bottom-width:0}.popover.bs-tether-element-attached-bottom::before,.popover.popover-top::before{bottom:-11px;margin-left:-11px;border-top-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-bottom::after,.popover.popover-top::after{bottom:-10px;margin-left:-10px;border-top-color:#fff}.popover.bs-tether-element-attached-left,.popover.popover-right{margin-left:10px}.popover.bs-tether-element-attached-left::after,.popover.bs-tether-element-attached-left::before,.popover.popover-right::after,.popover.popover-right::before{top:50%;border-left-width:0}.popover.bs-tether-element-attached-left::before,.popover.popover-right::before{left:-11px;margin-top:-11px;border-right-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-left::after,.popover.popover-right::after{left:-10px;margin-top:-10px;border-right-color:#fff}.popover.bs-tether-element-attached-top,.popover.popover-bottom{margin-top:10px}.popover.bs-tether-element-attached-top::after,.popover.bs-tether-element-attached-top::before,.popover.popover-bottom::after,.popover.popover-bottom::before{left:50%;border-top-width:0}.popover.bs-tether-element-attached-top::before,.popover.popover-bottom::before{top:-11px;margin-left:-11px;border-bottom-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-top::after,.popover.popover-bottom::after{top:-10px;margin-left:-10px;border-bottom-color:#f7f7f7}.popover.bs-tether-element-attached-top .popover-title::before,.popover.popover-bottom .popover-title::before{position:absolute;top:0;left:50%;display:block;width:20px;margin-left:-10px;content:"";border-bottom:1px solid #f7f7f7}.popover.bs-tether-element-attached-right,.popover.popover-left{margin-left:-10px}.popover.bs-tether-element-attached-right::after,.popover.bs-tether-element-attached-right::before,.popover.popover-left::after,.popover.popover-left::before{top:50%;border-right-width:0}.popover.bs-tether-element-attached-right::before,.popover.popover-left::before{right:-11px;margin-top:-11px;border-left-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-right::after,.popover.popover-left::after{right:-10px;margin-top:-10px;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:.2375rem .2375rem 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover::after,.popover::before{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover::before{content:"";border-width:11px}.popover::after{content:"";border-width:10px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.carousel-item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.carousel-item>a>img,.carousel-inner>.carousel-item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.carousel-item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.carousel-item.active.right,.carousel-inner>.carousel-item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.carousel-item.active.left,.carousel-inner>.carousel-item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.carousel-item.active,.carousel-inner>.carousel-item.next.left,.carousel-inner>.carousel-item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);opacity:.5}.carousel-control.left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;width:20px;height:20px;margin-top:-10px;font-family:serif;line-height:1}.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-prev::before{content:"\2039"}.carousel-control .icon-next::before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:transparent;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media (min-width:576px){.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .icon-prev{margin-left:-15px}.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-faded{background-color:#f7f7f9}.bg-primary{background-color:#0275d8!important}a.bg-primary:focus,a.bg-primary:hover{background-color:#025aa5!important}.bg-success{background-color:#5cb85c!important}a.bg-success:focus,a.bg-success:hover{background-color:#449d44!important}.bg-info{background-color:#5bc0de!important}a.bg-info:focus,a.bg-info:hover{background-color:#31b0d5!important}.bg-warning{background-color:#f0ad4e!important}a.bg-warning:focus,a.bg-warning:hover{background-color:#ec971f!important}.bg-danger{background-color:#d9534f!important}a.bg-danger:focus,a.bg-danger:hover{background-color:#c9302c!important}.bg-inverse{background-color:#373a3c!important}a.bg-inverse:focus,a.bg-inverse:hover{background-color:#1f2021!important}.rounded{border-radius:.25rem}.rounded-top{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.rounded-right{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.rounded-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-left{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-circle{border-radius:50%}.clearfix::after{content:"";display:table;clear:both}.d-block{display:block!important}.d-inline-block{display:inline-block!important}.d-inline{display:inline!important}.float-xs-left{float:left!important}.float-xs-right{float:right!important}.float-xs-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.w-100{width:100%!important}.h-100{height:100%!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.m-0{margin:0 0!important}.mt-0{margin-top:0!important}.mr-0{margin-right:0!important}.mb-0{margin-bottom:0!important}.ml-0{margin-left:0!important}.mx-0{margin-right:0!important;margin-left:0!important}.my-0{margin-top:0!important;margin-bottom:0!important}.m-1{margin:1rem 1rem!important}.mt-1{margin-top:1rem!important}.mr-1{margin-right:1rem!important}.mb-1{margin-bottom:1rem!important}.ml-1{margin-left:1rem!important}.mx-1{margin-right:1rem!important;margin-left:1rem!important}.my-1{margin-top:1rem!important;margin-bottom:1rem!important}.m-2{margin:1.5rem 1.5rem!important}.mt-2{margin-top:1.5rem!important}.mr-2{margin-right:1.5rem!important}.mb-2{margin-bottom:1.5rem!important}.ml-2{margin-left:1.5rem!important}.mx-2{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-2{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-3{margin:3rem 3rem!important}.mt-3{margin-top:3rem!important}.mr-3{margin-right:3rem!important}.mb-3{margin-bottom:3rem!important}.ml-3{margin-left:3rem!important}.mx-3{margin-right:3rem!important;margin-left:3rem!important}.my-3{margin-top:3rem!important;margin-bottom:3rem!important}.p-0{padding:0 0!important}.pt-0{padding-top:0!important}.pr-0{padding-right:0!important}.pb-0{padding-bottom:0!important}.pl-0{padding-left:0!important}.px-0{padding-right:0!important;padding-left:0!important}.py-0{padding-top:0!important;padding-bottom:0!important}.p-1{padding:1rem 1rem!important}.pt-1{padding-top:1rem!important}.pr-1{padding-right:1rem!important}.pb-1{padding-bottom:1rem!important}.pl-1{padding-left:1rem!important}.px-1{padding-right:1rem!important;padding-left:1rem!important}.py-1{padding-top:1rem!important;padding-bottom:1rem!important}.p-2{padding:1.5rem 1.5rem!important}.pt-2{padding-top:1.5rem!important}.pr-2{padding-right:1.5rem!important}.pb-2{padding-bottom:1.5rem!important}.pl-2{padding-left:1.5rem!important}.px-2{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-2{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-3{padding:3rem 3rem!important}.pt-3{padding-top:3rem!important}.pr-3{padding-right:3rem!important}.pb-3{padding-bottom:3rem!important}.pl-3{padding-left:3rem!important}.px-3{padding-right:3rem!important;padding-left:3rem!important}.py-3{padding-top:3rem!important;padding-bottom:3rem!important}.pos-f-t{position:fixed;top:0;right:0;left:0;z-index:1030}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-xs-left{text-align:left!important}.text-xs-right{text-align:right!important}.text-xs-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-normal{font-weight:400}.font-weight-bold{font-weight:700}.font-italic{font-style:italic}.text-white{color:#fff!important}.text-muted{color:#818a91!important}a.text-muted:focus,a.text-muted:hover{color:#687077!important}.text-primary{color:#0275d8!important}a.text-primary:focus,a.text-primary:hover{color:#025aa5!important}.text-success{color:#5cb85c!important}a.text-success:focus,a.text-success:hover{color:#449d44!important}.text-info{color:#5bc0de!important}a.text-info:focus,a.text-info:hover{color:#31b0d5!important}.text-warning{color:#f0ad4e!important}a.text-warning:focus,a.text-warning:hover{color:#ec971f!important}.text-danger{color:#d9534f!important}a.text-danger:focus,a.text-danger:hover{color:#c9302c!important}.text-gray-dark{color:#373a3c!important}a.text-gray-dark:focus,a.text-gray-dark:hover{color:#1f2021!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.invisible{visibility:hidden!important}.hidden-xs-up{display:none!important}@media (max-width:575px){.hidden-xs-down{display:none!important}}@media (min-width:576px){.hidden-sm-up{display:none!important}}@media (max-width:767px){.hidden-sm-down{display:none!important}}@media (min-width:768px){.hidden-md-up{display:none!important}}@media (max-width:991px){.hidden-md-down{display:none!important}}@media (min-width:992px){.hidden-lg-up{display:none!important}}@media (max-width:1199px){.hidden-lg-down{display:none!important}}@media (min-width:1200px){.hidden-xl-up{display:none!important}}.hidden-xl-down{display:none!important}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/static/css/font-awesome.min.css b/static/css/font-awesome.min.css new file mode 100644 index 0000000..540440c --- /dev/null +++ b/static/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/static/css/highlight.css b/static/css/highlight.css new file mode 100644 index 0000000..7237ae1 --- /dev/null +++ b/static/css/highlight.css @@ -0,0 +1,66 @@ +/* Error */ .chroma .err { } +/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } +/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; } +/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc } +/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; } +/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; } +/* Keyword */ .chroma .k { color: #006a70; font-weight: bold } +/* KeywordConstant */ .chroma .kc { color: #006a70; font-weight: bold } +/* KeywordDeclaration */ .chroma .kd { color: #006a70; font-weight: bold } +/* KeywordNamespace */ .chroma .kn { color: #006a70; font-weight: bold } +/* KeywordPseudo */ .chroma .kp { color: #006a70 } +/* KeywordReserved */ .chroma .kr { color: #006a70; font-weight: bold } +/* KeywordType */ .chroma .kt { color: #902000 } +/* NameAttribute */ .chroma .na { color: #197a7a } +/* NameBuiltin */ .chroma .nb { color: #006a70 } +/* NameClass */ .chroma .nc { color: #137ea5; font-weight: bold } +/* NameConstant */ .chroma .no { color: #60add5 } +/* NameDecorator */ .chroma .nd { color: #555555; font-weight: bold } +/* NameEntity */ .chroma .ni { color: #d55537; font-weight: bold } +/* NameException */ .chroma .ne { color: #006a70 } +/* NameFunction */ .chroma .nf { color: #06287e } +/* NameLabel */ .chroma .nl { color: #002070; font-weight: bold } +/* NameNamespace */ .chroma .nn { color: #137ea5; font-weight: bold } +/* NameTag */ .chroma .nt { color: #062873; font-weight: bold } +/* NameVariable */ .chroma .nv { color: #bb60d5 } +/* LiteralString */ .chroma .s { color: #197a7a } +/* LiteralStringAffix */ .chroma .sa { color: #197a7a } +/* LiteralStringBacktick */ .chroma .sb { color: #197a7a } +/* LiteralStringChar */ .chroma .sc { color: #197a7a } +/* LiteralStringDelimiter */ .chroma .dl { color: #197a7a } +/* LiteralStringDoc */ .chroma .sd { color: #197a7a; font-style: italic } +/* LiteralStringDouble */ .chroma .s2 { color: #197a7a } +/* LiteralStringEscape */ .chroma .se { color: #197a7a; font-weight: bold } +/* LiteralStringHeredoc */ .chroma .sh { color: #197a7a } +/* LiteralStringInterpol */ .chroma .si { color: #70a0d0; font-style: italic } +/* LiteralStringOther */ .chroma .sx { color: #c65d09 } +/* LiteralStringRegex */ .chroma .sr { color: #235388 } +/* LiteralStringSingle */ .chroma .s1 { color: #197a7a } +/* LiteralStringSymbol */ .chroma .ss { color: #517918 } +/* LiteralNumber */ .chroma .m { color: #40a070 } +/* LiteralNumberBin */ .chroma .mb { color: #40a070 } +/* LiteralNumberFloat */ .chroma .mf { color: #40a070 } +/* LiteralNumberHex */ .chroma .mh { color: #40a070 } +/* LiteralNumberInteger */ .chroma .mi { color: #40a070 } +/* LiteralNumberIntegerLong */ .chroma .il { color: #40a070 } +/* LiteralNumberOct */ .chroma .mo { color: #40a070 } +/* Operator */ .chroma .o { color: #666666 } +/* OperatorWord */ .chroma .ow { color: #006a70; font-weight: bold } +/* Comment */ .chroma .c { color: #60a0b0; font-style: italic } +/* CommentHashbang */ .chroma .ch { color: #60a0b0; font-style: italic } +/* CommentMultiline */ .chroma .cm { color: #60a0b0; font-style: italic } +/* CommentSingle */ .chroma .c1 { color: #60a0b0; font-style: italic } +/* CommentSpecial */ .chroma .cs { color: #60a0b0; background-color: #fff0f0 } +/* CommentPreproc */ .chroma .cp { color: #006a70 } +/* CommentPreprocFile */ .chroma .cpf { color: #006a70 } +/* GenericDeleted */ .chroma .gd { color: #a00000 } +/* GenericEmph */ .chroma .ge { font-style: italic } +/* GenericError */ .chroma .gr { color: #ff0000 } +/* GenericHeading */ .chroma .gh { color: #000080; font-weight: bold } +/* GenericInserted */ .chroma .gi { color: #00a000 } +/* GenericOutput */ .chroma .go { color: #888888 } +/* GenericPrompt */ .chroma .gp { color: #c65d09; font-weight: bold } +/* GenericStrong */ .chroma .gs { font-weight: bold } +/* GenericSubheading */ .chroma .gu { color: #800080; font-weight: bold } +/* GenericTraceback */ .chroma .gt { color: #0044dd } +/* TextWhitespace */ .chroma .w { color: #bbbbbb } diff --git a/static/fonts/FontAwesome.otf b/static/fonts/FontAwesome.otf new file mode 100644 index 0000000..401ec0f Binary files /dev/null and b/static/fonts/FontAwesome.otf differ diff --git a/static/fonts/fontawesome-webfont.eot b/static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/static/fonts/fontawesome-webfont.eot differ diff --git a/static/fonts/fontawesome-webfont.svg b/static/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/static/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/fonts/fontawesome-webfont.ttf b/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/static/fonts/fontawesome-webfont.ttf differ diff --git a/static/fonts/fontawesome-webfont.woff b/static/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/static/fonts/fontawesome-webfont.woff differ diff --git a/static/fonts/fontawesome-webfont.woff2 b/static/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/static/fonts/fontawesome-webfont.woff2 differ diff --git a/static/img/diagrams/cheatsheet-for-futures.html b/static/img/diagrams/cheatsheet-for-futures.html new file mode 100644 index 0000000..def4c34 --- /dev/null +++ b/static/img/diagrams/cheatsheet-for-futures.html @@ -0,0 +1,53 @@ + + + + + + Cheatsheet for Futures + +
// Constructing leaf futures
+fn empty ()             -> Future<T, E>
+fn ok    (T)            -> Future<T, E>
+fn err   (E)            -> Future<T, E>
+fn result(Result<T, E>) -> Future<T, E>
+
+// General future constructor
+fn poll_fn(FnMut(thread_local!(Task)) -> Poll<T, E>) -> Future<T, E>
+
+// Mapping futures
+fn Future::map     (Future<T, E>, FnOnce(T) -> U) -> Future<U, E>
+fn Future::map_err (Future<T, E>, FnOnce(E) -> F) -> Future<T, F>
+fn Future::from_err(Future<T, Into<E>>)           -> Future<T, E>
+
+// Chaining (sequencing) futures
+fn Future::then    (Future<T, E>, FnOnce(Result<T, E>) -> IntoFuture<U, F>) -> Future<U, F>
+fn Future::and_then(Future<T, E>, FnOnce(T)            -> IntoFuture<U, E>) -> Future<U, E>
+fn Future::or_else (Future<T, E>, FnOnce(E)            -> IntoFuture<T, F>) -> Future<T, F>
+fn Future::flatten (Future<Future<T, E>, Into<E>>)                          -> Future<T, E>
+
+// Joining (waiting) futures
+fn Future::join (Future<T, E>, IntoFuture<U, E>)                                                       -> Future<(T, U),          E>
+fn Future::join3(Future<T, E>, IntoFuture<U, E>, IntoFuture<V, E>)                                     -> Future<(T, U, V),       E>
+fn Future::join4(Future<T, E>, IntoFuture<U, E>, IntoFuture<V, E>, IntoFuture<W, E>)                   -> Future<(T, U, V, W),    E>
+fn Future::join5(Future<T, E>, IntoFuture<U, E>, IntoFuture<V, E>, IntoFuture<W, E>, IntoFuture<X, E>) -> Future<(T, U, V, W, X), E>
+fn join_all     (IntoIterator<IntoFuture<T, E>>)                                                       -> Future<Vec<T>,          E>
+
+// Selecting (racing) futures
+fn Future::select (Future<T, E>, IntoFuture<T, E>) -> Future<(T, Future<T, E>), (E, Future<T, E>)>
+fn Future::select2(Future<T, E>, IntoFuture<U, F>) -> Future<Either<(T, Future<U, F>), (U, Future<T, E>)>, Either<(E, Future<U, F>), (F, Future<T, E>)>>
+fn select_all     (IntoIterator<IntoFuture<T, E>>) -> Future<(T, usize, Vec<Future<T, E>>), (E, usize, Vec<Future<T, E>>)>
+fn select_ok      (IntoIterator<IntoFuture<T, E>>) -> Future<(T, Vec<Future<T, E>>), E>
+
+// Utility
+fn lazy         (FnOnce() -> IntoFuture<T, E>)             -> Future<T, E>
+fn loop_fn      (S, FnMut(S) -> IntoFuture<Loop<T, S>, E>) -> Future<T, E>
+
+// Miscellaneous
+fn Future::into_stream   (Future<T, E>)            -> Stream<T, E>
+fn Future::flatten_stream(Future<Stream<T, E>, E>) -> Stream<T, E>
+fn Future::fuse          (Future<T, E>)            -> Future<T, E>
+fn Future::catch_unwind  (Future<T, E>+UnwindSafe) -> Future<Result<T, E>, Any+Send>
+fn Future::shared        (Future<T, E>)            -> Future<SharedItem<T>, SharedError<E>>+Clone
+fn Future::wait          (Future<T, E>)            -> Result<T, E>
+
+ \ No newline at end of file diff --git a/static/img/diagrams/multiplexing.png b/static/img/diagrams/multiplexing.png new file mode 100644 index 0000000..dec5a20 Binary files /dev/null and b/static/img/diagrams/multiplexing.png differ diff --git a/static/img/diagrams/task-layout.png b/static/img/diagrams/task-layout.png new file mode 100644 index 0000000..47c05d6 Binary files /dev/null and b/static/img/diagrams/task-layout.png differ diff --git a/static/img/jumbotron.jpg b/static/img/jumbotron.jpg new file mode 100644 index 0000000..264fd5b Binary files /dev/null and b/static/img/jumbotron.jpg differ diff --git a/static/img/logo-large.png b/static/img/logo-large.png new file mode 100644 index 0000000..edf8466 Binary files /dev/null and b/static/img/logo-large.png differ diff --git a/static/img/logo-nav.png b/static/img/logo-nav.png new file mode 100644 index 0000000..a2eddea Binary files /dev/null and b/static/img/logo-nav.png differ diff --git a/static/img/logo.png b/static/img/logo.png new file mode 100644 index 0000000..49641b8 Binary files /dev/null and b/static/img/logo.png differ diff --git a/static/js/bootstrap.js b/static/js/bootstrap.js new file mode 100644 index 0000000..7759140 --- /dev/null +++ b/static/js/bootstrap.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com) + * Copyright 2011-2016 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){if("function"!=typeof b&&null!==b)throw new TypeError("Super expression must either be null or a function, not "+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}function c(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},e=function(){function a(a,b){for(var c=0;cthis._items.length-1||b<0)){if(this._isSliding)return void a(this._element).one(r.SLID,function(){return c.to(b)});if(d===b)return this.pause(),void this.cycle();var e=b>d?q.NEXT:q.PREVIOUS;this._slide(e,this._items[b])}},j.prototype.dispose=function(){a(this._element).off(i),a.removeData(this._element,h),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},j.prototype._getConfig=function(c){return c=a.extend({},o,c),f.typeCheckConfig(b,c,p),c},j.prototype._addEventListeners=function(){this._config.keyboard&&a(this._element).on(r.KEYDOWN,a.proxy(this._keydown,this)),"hover"!==this._config.pause||"ontouchstart"in document.documentElement||a(this._element).on(r.MOUSEENTER,a.proxy(this.pause,this)).on(r.MOUSELEAVE,a.proxy(this.cycle,this))},j.prototype._keydown=function(a){if(a.preventDefault(),!/input|textarea/i.test(a.target.tagName))switch(a.which){case m:this.prev();break;case n:this.next();break;default:return}},j.prototype._getItemIndex=function(b){return this._items=a.makeArray(a(b).parent().find(t.ITEM)),this._items.indexOf(b)},j.prototype._getItemByDirection=function(a,b){var c=a===q.NEXT,d=a===q.PREVIOUS,e=this._getItemIndex(b),f=this._items.length-1,g=d&&0===e||c&&e===f;if(g&&!this._config.wrap)return b;var h=a===q.PREVIOUS?-1:1,i=(e+h)%this._items.length;return i===-1?this._items[this._items.length-1]:this._items[i]},j.prototype._triggerSlideEvent=function(b,c){var d=a.Event(r.SLIDE,{relatedTarget:b,direction:c});return a(this._element).trigger(d),d},j.prototype._setActiveIndicatorElement=function(b){if(this._indicatorsElement){a(this._indicatorsElement).find(t.ACTIVE).removeClass(s.ACTIVE);var c=this._indicatorsElement.children[this._getItemIndex(b)];c&&a(c).addClass(s.ACTIVE)}},j.prototype._slide=function(b,c){var d=this,e=a(this._element).find(t.ACTIVE_ITEM)[0],g=c||e&&this._getItemByDirection(b,e),h=Boolean(this._interval),i=b===q.NEXT?s.LEFT:s.RIGHT;if(g&&a(g).hasClass(s.ACTIVE))return void(this._isSliding=!1);var j=this._triggerSlideEvent(g,i);if(!j.isDefaultPrevented()&&e&&g){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(g);var k=a.Event(r.SLID,{relatedTarget:g,direction:i});f.supportsTransitionEnd()&&a(this._element).hasClass(s.SLIDE)?(a(g).addClass(b),f.reflow(g),a(e).addClass(i),a(g).addClass(i),a(e).one(f.TRANSITION_END,function(){a(g).removeClass(i).removeClass(b),a(g).addClass(s.ACTIVE),a(e).removeClass(s.ACTIVE).removeClass(b).removeClass(i),d._isSliding=!1,setTimeout(function(){return a(d._element).trigger(k)},0)}).emulateTransitionEnd(l)):(a(e).removeClass(s.ACTIVE),a(g).addClass(s.ACTIVE),this._isSliding=!1,a(this._element).trigger(k)),h&&this.cycle()}},j._jQueryInterface=function(b){return this.each(function(){var c=a(this).data(h),e=a.extend({},o,a(this).data());"object"===("undefined"==typeof b?"undefined":d(b))&&a.extend(e,b);var f="string"==typeof b?b:e.slide;if(c||(c=new j(this,e),a(this).data(h,c)),"number"==typeof b)c.to(b);else if("string"==typeof f){if(void 0===c[f])throw new Error('No method named "'+f+'"');c[f]()}else e.interval&&(c.pause(),c.cycle())})},j._dataApiClickHandler=function(b){var c=f.getSelectorFromElement(this);if(c){var d=a(c)[0];if(d&&a(d).hasClass(s.CAROUSEL)){var e=a.extend({},a(d).data(),a(this).data()),g=this.getAttribute("data-slide-to");g&&(e.interval=!1),j._jQueryInterface.call(a(d),e),g&&a(d).data(h).to(g),b.preventDefault()}}},e(j,null,[{key:"VERSION",get:function(){return g}},{key:"Default",get:function(){return o}}]),j}();return a(document).on(r.CLICK_DATA_API,t.DATA_SLIDE,u._dataApiClickHandler),a(window).on(r.LOAD_DATA_API,function(){a(t.DATA_RIDE).each(function(){var b=a(this);u._jQueryInterface.call(b,b.data())})}),a.fn[b]=u._jQueryInterface,a.fn[b].Constructor=u,a.fn[b].noConflict=function(){return a.fn[b]=k,u._jQueryInterface},u}(jQuery),function(a){var b="collapse",g="4.0.0-alpha.5",h="bs.collapse",i="."+h,j=".data-api",k=a.fn[b],l=600,m={toggle:!0,parent:""},n={toggle:"boolean",parent:"string"},o={SHOW:"show"+i,SHOWN:"shown"+i,HIDE:"hide"+i,HIDDEN:"hidden"+i,CLICK_DATA_API:"click"+i+j},p={IN:"in",COLLAPSE:"collapse",COLLAPSING:"collapsing",COLLAPSED:"collapsed"},q={WIDTH:"width",HEIGHT:"height"},r={ACTIVES:".card > .in, .card > .collapsing",DATA_TOGGLE:'[data-toggle="collapse"]'},s=function(){function i(b,d){c(this,i),this._isTransitioning=!1,this._element=b,this._config=this._getConfig(d),this._triggerArray=a.makeArray(a('[data-toggle="collapse"][href="#'+b.id+'"],'+('[data-toggle="collapse"][data-target="#'+b.id+'"]'))),this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}return i.prototype.toggle=function(){a(this._element).hasClass(p.IN)?this.hide():this.show()},i.prototype.show=function(){var b=this;if(!this._isTransitioning&&!a(this._element).hasClass(p.IN)){var c=void 0,d=void 0;if(this._parent&&(c=a.makeArray(a(r.ACTIVES)),c.length||(c=null)),!(c&&(d=a(c).data(h),d&&d._isTransitioning))){var e=a.Event(o.SHOW);if(a(this._element).trigger(e),!e.isDefaultPrevented()){c&&(i._jQueryInterface.call(a(c),"hide"),d||a(c).data(h,null));var g=this._getDimension();a(this._element).removeClass(p.COLLAPSE).addClass(p.COLLAPSING),this._element.style[g]=0,this._element.setAttribute("aria-expanded",!0),this._triggerArray.length&&a(this._triggerArray).removeClass(p.COLLAPSED).attr("aria-expanded",!0),this.setTransitioning(!0);var j=function(){a(b._element).removeClass(p.COLLAPSING).addClass(p.COLLAPSE).addClass(p.IN),b._element.style[g]="",b.setTransitioning(!1),a(b._element).trigger(o.SHOWN)};if(!f.supportsTransitionEnd())return void j();var k=g[0].toUpperCase()+g.slice(1),m="scroll"+k;a(this._element).one(f.TRANSITION_END,j).emulateTransitionEnd(l),this._element.style[g]=this._element[m]+"px"}}}},i.prototype.hide=function(){var b=this;if(!this._isTransitioning&&a(this._element).hasClass(p.IN)){var c=a.Event(o.HIDE);if(a(this._element).trigger(c),!c.isDefaultPrevented()){var d=this._getDimension(),e=d===q.WIDTH?"offsetWidth":"offsetHeight";this._element.style[d]=this._element[e]+"px",f.reflow(this._element),a(this._element).addClass(p.COLLAPSING).removeClass(p.COLLAPSE).removeClass(p.IN),this._element.setAttribute("aria-expanded",!1),this._triggerArray.length&&a(this._triggerArray).addClass(p.COLLAPSED).attr("aria-expanded",!1),this.setTransitioning(!0);var g=function(){b.setTransitioning(!1),a(b._element).removeClass(p.COLLAPSING).addClass(p.COLLAPSE).trigger(o.HIDDEN)};return this._element.style[d]="",f.supportsTransitionEnd()?void a(this._element).one(f.TRANSITION_END,g).emulateTransitionEnd(l):void g()}}},i.prototype.setTransitioning=function(a){this._isTransitioning=a},i.prototype.dispose=function(){a.removeData(this._element,h),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},i.prototype._getConfig=function(c){return c=a.extend({},m,c),c.toggle=Boolean(c.toggle),f.typeCheckConfig(b,c,n),c},i.prototype._getDimension=function(){var b=a(this._element).hasClass(q.WIDTH);return b?q.WIDTH:q.HEIGHT},i.prototype._getParent=function(){var b=this,c=a(this._config.parent)[0],d='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]';return a(c).find(d).each(function(a,c){b._addAriaAndCollapsedClass(i._getTargetFromElement(c),[c])}),c},i.prototype._addAriaAndCollapsedClass=function(b,c){if(b){var d=a(b).hasClass(p.IN);b.setAttribute("aria-expanded",d),c.length&&a(c).toggleClass(p.COLLAPSED,!d).attr("aria-expanded",d)}},i._getTargetFromElement=function(b){var c=f.getSelectorFromElement(b);return c?a(c)[0]:null},i._jQueryInterface=function(b){return this.each(function(){var c=a(this),e=c.data(h),f=a.extend({},m,c.data(),"object"===("undefined"==typeof b?"undefined":d(b))&&b);if(!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||(e=new i(this,f),c.data(h,e)),"string"==typeof b){if(void 0===e[b])throw new Error('No method named "'+b+'"');e[b]()}})},e(i,null,[{key:"VERSION",get:function(){return g}},{key:"Default",get:function(){return m}}]),i}();return a(document).on(o.CLICK_DATA_API,r.DATA_TOGGLE,function(b){b.preventDefault();var c=s._getTargetFromElement(this),d=a(c).data(h),e=d?"toggle":a(this).data();s._jQueryInterface.call(a(c),e)}),a.fn[b]=s._jQueryInterface,a.fn[b].Constructor=s,a.fn[b].noConflict=function(){return a.fn[b]=k,s._jQueryInterface},s}(jQuery),function(a){var b="dropdown",d="4.0.0-alpha.5",g="bs.dropdown",h="."+g,i=".data-api",j=a.fn[b],k=27,l=38,m=40,n=3,o={HIDE:"hide"+h,HIDDEN:"hidden"+h,SHOW:"show"+h,SHOWN:"shown"+h,CLICK:"click"+h,CLICK_DATA_API:"click"+h+i,KEYDOWN_DATA_API:"keydown"+h+i},p={BACKDROP:"dropdown-backdrop",DISABLED:"disabled",OPEN:"open"},q={BACKDROP:".dropdown-backdrop",DATA_TOGGLE:'[data-toggle="dropdown"]',FORM_CHILD:".dropdown form",ROLE_MENU:'[role="menu"]',ROLE_LISTBOX:'[role="listbox"]',NAVBAR_NAV:".navbar-nav",VISIBLE_ITEMS:'[role="menu"] li:not(.disabled) a, [role="listbox"] li:not(.disabled) a'},r=function(){function b(a){c(this,b),this._element=a,this._addEventListeners()}return b.prototype.toggle=function(){if(this.disabled||a(this).hasClass(p.DISABLED))return!1;var c=b._getParentFromElement(this),d=a(c).hasClass(p.OPEN);if(b._clearMenus(),d)return!1;if("ontouchstart"in document.documentElement&&!a(c).closest(q.NAVBAR_NAV).length){var e=document.createElement("div");e.className=p.BACKDROP,a(e).insertBefore(this),a(e).on("click",b._clearMenus)}var f={relatedTarget:this},g=a.Event(o.SHOW,f);return a(c).trigger(g),!g.isDefaultPrevented()&&(this.focus(),this.setAttribute("aria-expanded","true"),a(c).toggleClass(p.OPEN),a(c).trigger(a.Event(o.SHOWN,f)),!1)},b.prototype.dispose=function(){a.removeData(this._element,g),a(this._element).off(h),this._element=null},b.prototype._addEventListeners=function(){a(this._element).on(o.CLICK,this.toggle)},b._jQueryInterface=function(c){return this.each(function(){var d=a(this).data(g);if(d||a(this).data(g,d=new b(this)),"string"==typeof c){if(void 0===d[c])throw new Error('No method named "'+c+'"');d[c].call(this)}})},b._clearMenus=function(c){if(!c||c.which!==n){var d=a(q.BACKDROP)[0];d&&d.parentNode.removeChild(d);for(var e=a.makeArray(a(q.DATA_TOGGLE)),f=0;f0&&h--,c.which===m&&hdocument.documentElement.clientHeight;!this._isBodyOverflowing&&a&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!a&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},j.prototype._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},j.prototype._checkScrollbar=function(){this._isBodyOverflowing=document.body.clientWidth=c){var d=this._targets[this._targets.length-1];this._activeTarget!==d&&this._activate(d)}if(this._activeTarget&&a=this._offsets[e]&&(void 0===this._offsets[e+1]||a .nav-item .fade, > .fade",ACTIVE:".active",ACTIVE_CHILD:"> .nav-item > .active, > .active",DATA_TOGGLE:'[data-toggle="tab"], [data-toggle="pill"]', +DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{relatedTarget:this._element}),i=a.Event(l.SHOW,{relatedTarget:d});if(d&&a(d).trigger(h),a(this._element).trigger(i),!i.isDefaultPrevented()&&!h.isDefaultPrevented()){g&&(c=a(g)[0]),this._activate(this._element,e);var j=function(){var c=a.Event(l.HIDDEN,{relatedTarget:b._element}),e=a.Event(l.SHOWN,{relatedTarget:d});a(d).trigger(c),a(b._element).trigger(e)};c?this._activate(c,c.parentNode,j):j()}}},b.prototype.dispose=function(){a.removeClass(this._element,g),this._element=null},b.prototype._activate=function(b,c,d){var e=a(c).find(n.ACTIVE_CHILD)[0],g=d&&f.supportsTransitionEnd()&&(e&&a(e).hasClass(m.FADE)||Boolean(a(c).find(n.FADE_CHILD)[0])),h=a.proxy(this._transitionComplete,this,b,e,g,d);e&&g?a(e).one(f.TRANSITION_END,h).emulateTransitionEnd(k):h(),e&&a(e).removeClass(m.IN)},b.prototype._transitionComplete=function(b,c,d,e){if(c){a(c).removeClass(m.ACTIVE);var g=a(c).find(n.DROPDOWN_ACTIVE_CHILD)[0];g&&a(g).removeClass(m.ACTIVE),c.setAttribute("aria-expanded",!1)}if(a(b).addClass(m.ACTIVE),b.setAttribute("aria-expanded",!0),d?(f.reflow(b),a(b).addClass(m.IN)):a(b).removeClass(m.FADE),b.parentNode&&a(b.parentNode).hasClass(m.DROPDOWN_MENU)){var h=a(b).closest(n.DROPDOWN)[0];h&&a(h).find(n.DROPDOWN_TOGGLE).addClass(m.ACTIVE),b.setAttribute("aria-expanded",!0)}e&&e()},b._jQueryInterface=function(c){return this.each(function(){var d=a(this),e=d.data(g);if(e||(e=e=new b(this),d.data(g,e)),"string"==typeof c){if(void 0===e[c])throw new Error('No method named "'+c+'"');e[c]()}})},e(b,null,[{key:"VERSION",get:function(){return d}}]),b}();return a(document).on(l.CLICK_DATA_API,n.DATA_TOGGLE,function(b){b.preventDefault(),o._jQueryInterface.call(a(this),"show")}),a.fn[b]=o._jQueryInterface,a.fn[b].Constructor=o,a.fn[b].noConflict=function(){return a.fn[b]=j,o._jQueryInterface},o}(jQuery),function(a){if(void 0===window.Tether)throw new Error("Bootstrap tooltips require Tether (http://tether.io/)");var b="tooltip",g="4.0.0-alpha.5",h="bs.tooltip",i="."+h,j=a.fn[b],k=150,l="bs-tether",m={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:"0 0",constraints:[]},n={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"string",constraints:"array"},o={TOP:"bottom center",RIGHT:"middle left",BOTTOM:"top center",LEFT:"middle right"},p={IN:"in",OUT:"out"},q={HIDE:"hide"+i,HIDDEN:"hidden"+i,SHOW:"show"+i,SHOWN:"shown"+i,INSERTED:"inserted"+i,CLICK:"click"+i,FOCUSIN:"focusin"+i,FOCUSOUT:"focusout"+i,MOUSEENTER:"mouseenter"+i,MOUSELEAVE:"mouseleave"+i},r={FADE:"fade",IN:"in"},s={TOOLTIP:".tooltip",TOOLTIP_INNER:".tooltip-inner"},t={element:!1,enabled:!1},u={HOVER:"hover",FOCUS:"focus",CLICK:"click",MANUAL:"manual"},v=function(){function j(a,b){c(this,j),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._tether=null,this.element=a,this.config=this._getConfig(b),this.tip=null,this._setListeners()}return j.prototype.enable=function(){this._isEnabled=!0},j.prototype.disable=function(){this._isEnabled=!1},j.prototype.toggleEnabled=function(){this._isEnabled=!this._isEnabled},j.prototype.toggle=function(b){if(b){var c=this.constructor.DATA_KEY,d=a(b.currentTarget).data(c);d||(d=new this.constructor(b.currentTarget,this._getDelegateConfig()),a(b.currentTarget).data(c,d)),d._activeTrigger.click=!d._activeTrigger.click,d._isWithActiveTrigger()?d._enter(null,d):d._leave(null,d)}else{if(a(this.getTipElement()).hasClass(r.IN))return void this._leave(null,this);this._enter(null,this)}},j.prototype.dispose=function(){clearTimeout(this._timeout),this.cleanupTether(),a.removeData(this.element,this.constructor.DATA_KEY),a(this.element).off(this.constructor.EVENT_KEY),this.tip&&a(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._tether=null,this.element=null,this.config=null,this.tip=null},j.prototype.show=function(){var b=this,c=a.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){a(this.element).trigger(c);var d=a.contains(this.element.ownerDocument.documentElement,this.element);if(c.isDefaultPrevented()||!d)return;var e=this.getTipElement(),g=f.getUID(this.constructor.NAME);e.setAttribute("id",g),this.element.setAttribute("aria-describedby",g),this.setContent(),this.config.animation&&a(e).addClass(r.FADE);var h="function"==typeof this.config.placement?this.config.placement.call(this,e,this.element):this.config.placement,i=this._getAttachment(h);a(e).data(this.constructor.DATA_KEY,this).appendTo(document.body),a(this.element).trigger(this.constructor.Event.INSERTED),this._tether=new Tether({attachment:i,element:e,target:this.element,classes:t,classPrefix:l,offset:this.config.offset,constraints:this.config.constraints,addTargetClasses:!1}),f.reflow(e),this._tether.position(),a(e).addClass(r.IN);var k=function(){var c=b._hoverState;b._hoverState=null,a(b.element).trigger(b.constructor.Event.SHOWN),c===p.OUT&&b._leave(null,b)};if(f.supportsTransitionEnd()&&a(this.tip).hasClass(r.FADE))return void a(this.tip).one(f.TRANSITION_END,k).emulateTransitionEnd(j._TRANSITION_DURATION);k()}},j.prototype.hide=function(b){var c=this,d=this.getTipElement(),e=a.Event(this.constructor.Event.HIDE),g=function(){c._hoverState!==p.IN&&d.parentNode&&d.parentNode.removeChild(d),c.element.removeAttribute("aria-describedby"),a(c.element).trigger(c.constructor.Event.HIDDEN),c.cleanupTether(),b&&b()};a(this.element).trigger(e),e.isDefaultPrevented()||(a(d).removeClass(r.IN),f.supportsTransitionEnd()&&a(this.tip).hasClass(r.FADE)?a(d).one(f.TRANSITION_END,g).emulateTransitionEnd(k):g(),this._hoverState="")},j.prototype.isWithContent=function(){return Boolean(this.getTitle())},j.prototype.getTipElement=function(){return this.tip=this.tip||a(this.config.template)[0]},j.prototype.setContent=function(){var b=a(this.getTipElement());this.setElementContent(b.find(s.TOOLTIP_INNER),this.getTitle()),b.removeClass(r.FADE).removeClass(r.IN),this.cleanupTether()},j.prototype.setElementContent=function(b,c){var e=this.config.html;"object"===("undefined"==typeof c?"undefined":d(c))&&(c.nodeType||c.jquery)?e?a(c).parent().is(b)||b.empty().append(c):b.text(a(c).text()):b[e?"html":"text"](c)},j.prototype.getTitle=function(){var a=this.element.getAttribute("data-original-title");return a||(a="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),a},j.prototype.cleanupTether=function(){this._tether&&this._tether.destroy()},j.prototype._getAttachment=function(a){return o[a.toUpperCase()]},j.prototype._setListeners=function(){var b=this,c=this.config.trigger.split(" ");c.forEach(function(c){if("click"===c)a(b.element).on(b.constructor.Event.CLICK,b.config.selector,a.proxy(b.toggle,b));else if(c!==u.MANUAL){var d=c===u.HOVER?b.constructor.Event.MOUSEENTER:b.constructor.Event.FOCUSIN,e=c===u.HOVER?b.constructor.Event.MOUSELEAVE:b.constructor.Event.FOCUSOUT;a(b.element).on(d,b.config.selector,a.proxy(b._enter,b)).on(e,b.config.selector,a.proxy(b._leave,b))}}),this.config.selector?this.config=a.extend({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},j.prototype._fixTitle=function(){var a=d(this.element.getAttribute("data-original-title"));(this.element.getAttribute("title")||"string"!==a)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},j.prototype._enter=function(b,c){var d=this.constructor.DATA_KEY;return c=c||a(b.currentTarget).data(d),c||(c=new this.constructor(b.currentTarget,this._getDelegateConfig()),a(b.currentTarget).data(d,c)),b&&(c._activeTrigger["focusin"===b.type?u.FOCUS:u.HOVER]=!0),a(c.getTipElement()).hasClass(r.IN)||c._hoverState===p.IN?void(c._hoverState=p.IN):(clearTimeout(c._timeout),c._hoverState=p.IN,c.config.delay&&c.config.delay.show?void(c._timeout=setTimeout(function(){c._hoverState===p.IN&&c.show()},c.config.delay.show)):void c.show())},j.prototype._leave=function(b,c){var d=this.constructor.DATA_KEY;if(c=c||a(b.currentTarget).data(d),c||(c=new this.constructor(b.currentTarget,this._getDelegateConfig()),a(b.currentTarget).data(d,c)),b&&(c._activeTrigger["focusout"===b.type?u.FOCUS:u.HOVER]=!1),!c._isWithActiveTrigger())return clearTimeout(c._timeout),c._hoverState=p.OUT,c.config.delay&&c.config.delay.hide?void(c._timeout=setTimeout(function(){c._hoverState===p.OUT&&c.hide()},c.config.delay.hide)):void c.hide()},j.prototype._isWithActiveTrigger=function(){for(var a in this._activeTrigger)if(this._activeTrigger[a])return!0;return!1},j.prototype._getConfig=function(c){return c=a.extend({},this.constructor.Default,a(this.element).data(),c),c.delay&&"number"==typeof c.delay&&(c.delay={show:c.delay,hide:c.delay}),f.typeCheckConfig(b,c,this.constructor.DefaultType),c},j.prototype._getDelegateConfig=function(){var a={};if(this.config)for(var b in this.config)this.constructor.Default[b]!==this.config[b]&&(a[b]=this.config[b]);return a},j._jQueryInterface=function(b){return this.each(function(){var c=a(this).data(h),e="object"===("undefined"==typeof b?"undefined":d(b))?b:null;if((c||!/dispose|hide/.test(b))&&(c||(c=new j(this,e),a(this).data(h,c)),"string"==typeof b)){if(void 0===c[b])throw new Error('No method named "'+b+'"');c[b]()}})},e(j,null,[{key:"VERSION",get:function(){return g}},{key:"Default",get:function(){return m}},{key:"NAME",get:function(){return b}},{key:"DATA_KEY",get:function(){return h}},{key:"Event",get:function(){return q}},{key:"EVENT_KEY",get:function(){return i}},{key:"DefaultType",get:function(){return n}}]),j}();return a.fn[b]=v._jQueryInterface,a.fn[b].Constructor=v,a.fn[b].noConflict=function(){return a.fn[b]=j,v._jQueryInterface},v}(jQuery));(function(f){var h="popover",i="4.0.0-alpha.5",j="bs.popover",k="."+j,l=f.fn[h],m=f.extend({},g.Default,{placement:"right",trigger:"click",content:"",template:''}),n=f.extend({},g.DefaultType,{content:"(string|element|function)"}),o={FADE:"fade",IN:"in"},p={TITLE:".popover-title",CONTENT:".popover-content"},q={HIDE:"hide"+k,HIDDEN:"hidden"+k,SHOW:"show"+k,SHOWN:"shown"+k,INSERTED:"inserted"+k,CLICK:"click"+k,FOCUSIN:"focusin"+k,FOCUSOUT:"focusout"+k,MOUSEENTER:"mouseenter"+k,MOUSELEAVE:"mouseleave"+k},r=function(g){function l(){return c(this,l),a(this,g.apply(this,arguments))}return b(l,g),l.prototype.isWithContent=function(){return this.getTitle()||this._getContent()},l.prototype.getTipElement=function(){return this.tip=this.tip||f(this.config.template)[0]},l.prototype.setContent=function(){var a=f(this.getTipElement());this.setElementContent(a.find(p.TITLE),this.getTitle()),this.setElementContent(a.find(p.CONTENT),this._getContent()),a.removeClass(o.FADE).removeClass(o.IN),this.cleanupTether()},l.prototype._getContent=function(){return this.element.getAttribute("data-content")||("function"==typeof this.config.content?this.config.content.call(this.element):this.config.content)},l._jQueryInterface=function(a){return this.each(function(){var b=f(this).data(j),c="object"===("undefined"==typeof a?"undefined":d(a))?a:null;if((b||!/destroy|hide/.test(a))&&(b||(b=new l(this,c),f(this).data(j,b)),"string"==typeof a)){if(void 0===b[a])throw new Error('No method named "'+a+'"');b[a]()}})},e(l,null,[{key:"VERSION",get:function(){return i}},{key:"Default",get:function(){return m}},{key:"NAME",get:function(){return h}},{key:"DATA_KEY",get:function(){return j}},{key:"Event",get:function(){return q}},{key:"EVENT_KEY",get:function(){return k}},{key:"DefaultType",get:function(){return n}}]),l}(g);return f.fn[h]=r._jQueryInterface,f.fn[h].Constructor=r,f.fn[h].noConflict=function(){return f.fn[h]=l,r._jQueryInterface},r})(jQuery)}(); \ No newline at end of file diff --git a/static/js/bootstrap.min.js b/static/js/bootstrap.min.js new file mode 100644 index 0000000..7759140 --- /dev/null +++ b/static/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com) + * Copyright 2011-2016 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){if("function"!=typeof b&&null!==b)throw new TypeError("Super expression must either be null or a function, not "+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}function c(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},e=function(){function a(a,b){for(var c=0;cthis._items.length-1||b<0)){if(this._isSliding)return void a(this._element).one(r.SLID,function(){return c.to(b)});if(d===b)return this.pause(),void this.cycle();var e=b>d?q.NEXT:q.PREVIOUS;this._slide(e,this._items[b])}},j.prototype.dispose=function(){a(this._element).off(i),a.removeData(this._element,h),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},j.prototype._getConfig=function(c){return c=a.extend({},o,c),f.typeCheckConfig(b,c,p),c},j.prototype._addEventListeners=function(){this._config.keyboard&&a(this._element).on(r.KEYDOWN,a.proxy(this._keydown,this)),"hover"!==this._config.pause||"ontouchstart"in document.documentElement||a(this._element).on(r.MOUSEENTER,a.proxy(this.pause,this)).on(r.MOUSELEAVE,a.proxy(this.cycle,this))},j.prototype._keydown=function(a){if(a.preventDefault(),!/input|textarea/i.test(a.target.tagName))switch(a.which){case m:this.prev();break;case n:this.next();break;default:return}},j.prototype._getItemIndex=function(b){return this._items=a.makeArray(a(b).parent().find(t.ITEM)),this._items.indexOf(b)},j.prototype._getItemByDirection=function(a,b){var c=a===q.NEXT,d=a===q.PREVIOUS,e=this._getItemIndex(b),f=this._items.length-1,g=d&&0===e||c&&e===f;if(g&&!this._config.wrap)return b;var h=a===q.PREVIOUS?-1:1,i=(e+h)%this._items.length;return i===-1?this._items[this._items.length-1]:this._items[i]},j.prototype._triggerSlideEvent=function(b,c){var d=a.Event(r.SLIDE,{relatedTarget:b,direction:c});return a(this._element).trigger(d),d},j.prototype._setActiveIndicatorElement=function(b){if(this._indicatorsElement){a(this._indicatorsElement).find(t.ACTIVE).removeClass(s.ACTIVE);var c=this._indicatorsElement.children[this._getItemIndex(b)];c&&a(c).addClass(s.ACTIVE)}},j.prototype._slide=function(b,c){var d=this,e=a(this._element).find(t.ACTIVE_ITEM)[0],g=c||e&&this._getItemByDirection(b,e),h=Boolean(this._interval),i=b===q.NEXT?s.LEFT:s.RIGHT;if(g&&a(g).hasClass(s.ACTIVE))return void(this._isSliding=!1);var j=this._triggerSlideEvent(g,i);if(!j.isDefaultPrevented()&&e&&g){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(g);var k=a.Event(r.SLID,{relatedTarget:g,direction:i});f.supportsTransitionEnd()&&a(this._element).hasClass(s.SLIDE)?(a(g).addClass(b),f.reflow(g),a(e).addClass(i),a(g).addClass(i),a(e).one(f.TRANSITION_END,function(){a(g).removeClass(i).removeClass(b),a(g).addClass(s.ACTIVE),a(e).removeClass(s.ACTIVE).removeClass(b).removeClass(i),d._isSliding=!1,setTimeout(function(){return a(d._element).trigger(k)},0)}).emulateTransitionEnd(l)):(a(e).removeClass(s.ACTIVE),a(g).addClass(s.ACTIVE),this._isSliding=!1,a(this._element).trigger(k)),h&&this.cycle()}},j._jQueryInterface=function(b){return this.each(function(){var c=a(this).data(h),e=a.extend({},o,a(this).data());"object"===("undefined"==typeof b?"undefined":d(b))&&a.extend(e,b);var f="string"==typeof b?b:e.slide;if(c||(c=new j(this,e),a(this).data(h,c)),"number"==typeof b)c.to(b);else if("string"==typeof f){if(void 0===c[f])throw new Error('No method named "'+f+'"');c[f]()}else e.interval&&(c.pause(),c.cycle())})},j._dataApiClickHandler=function(b){var c=f.getSelectorFromElement(this);if(c){var d=a(c)[0];if(d&&a(d).hasClass(s.CAROUSEL)){var e=a.extend({},a(d).data(),a(this).data()),g=this.getAttribute("data-slide-to");g&&(e.interval=!1),j._jQueryInterface.call(a(d),e),g&&a(d).data(h).to(g),b.preventDefault()}}},e(j,null,[{key:"VERSION",get:function(){return g}},{key:"Default",get:function(){return o}}]),j}();return a(document).on(r.CLICK_DATA_API,t.DATA_SLIDE,u._dataApiClickHandler),a(window).on(r.LOAD_DATA_API,function(){a(t.DATA_RIDE).each(function(){var b=a(this);u._jQueryInterface.call(b,b.data())})}),a.fn[b]=u._jQueryInterface,a.fn[b].Constructor=u,a.fn[b].noConflict=function(){return a.fn[b]=k,u._jQueryInterface},u}(jQuery),function(a){var b="collapse",g="4.0.0-alpha.5",h="bs.collapse",i="."+h,j=".data-api",k=a.fn[b],l=600,m={toggle:!0,parent:""},n={toggle:"boolean",parent:"string"},o={SHOW:"show"+i,SHOWN:"shown"+i,HIDE:"hide"+i,HIDDEN:"hidden"+i,CLICK_DATA_API:"click"+i+j},p={IN:"in",COLLAPSE:"collapse",COLLAPSING:"collapsing",COLLAPSED:"collapsed"},q={WIDTH:"width",HEIGHT:"height"},r={ACTIVES:".card > .in, .card > .collapsing",DATA_TOGGLE:'[data-toggle="collapse"]'},s=function(){function i(b,d){c(this,i),this._isTransitioning=!1,this._element=b,this._config=this._getConfig(d),this._triggerArray=a.makeArray(a('[data-toggle="collapse"][href="#'+b.id+'"],'+('[data-toggle="collapse"][data-target="#'+b.id+'"]'))),this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}return i.prototype.toggle=function(){a(this._element).hasClass(p.IN)?this.hide():this.show()},i.prototype.show=function(){var b=this;if(!this._isTransitioning&&!a(this._element).hasClass(p.IN)){var c=void 0,d=void 0;if(this._parent&&(c=a.makeArray(a(r.ACTIVES)),c.length||(c=null)),!(c&&(d=a(c).data(h),d&&d._isTransitioning))){var e=a.Event(o.SHOW);if(a(this._element).trigger(e),!e.isDefaultPrevented()){c&&(i._jQueryInterface.call(a(c),"hide"),d||a(c).data(h,null));var g=this._getDimension();a(this._element).removeClass(p.COLLAPSE).addClass(p.COLLAPSING),this._element.style[g]=0,this._element.setAttribute("aria-expanded",!0),this._triggerArray.length&&a(this._triggerArray).removeClass(p.COLLAPSED).attr("aria-expanded",!0),this.setTransitioning(!0);var j=function(){a(b._element).removeClass(p.COLLAPSING).addClass(p.COLLAPSE).addClass(p.IN),b._element.style[g]="",b.setTransitioning(!1),a(b._element).trigger(o.SHOWN)};if(!f.supportsTransitionEnd())return void j();var k=g[0].toUpperCase()+g.slice(1),m="scroll"+k;a(this._element).one(f.TRANSITION_END,j).emulateTransitionEnd(l),this._element.style[g]=this._element[m]+"px"}}}},i.prototype.hide=function(){var b=this;if(!this._isTransitioning&&a(this._element).hasClass(p.IN)){var c=a.Event(o.HIDE);if(a(this._element).trigger(c),!c.isDefaultPrevented()){var d=this._getDimension(),e=d===q.WIDTH?"offsetWidth":"offsetHeight";this._element.style[d]=this._element[e]+"px",f.reflow(this._element),a(this._element).addClass(p.COLLAPSING).removeClass(p.COLLAPSE).removeClass(p.IN),this._element.setAttribute("aria-expanded",!1),this._triggerArray.length&&a(this._triggerArray).addClass(p.COLLAPSED).attr("aria-expanded",!1),this.setTransitioning(!0);var g=function(){b.setTransitioning(!1),a(b._element).removeClass(p.COLLAPSING).addClass(p.COLLAPSE).trigger(o.HIDDEN)};return this._element.style[d]="",f.supportsTransitionEnd()?void a(this._element).one(f.TRANSITION_END,g).emulateTransitionEnd(l):void g()}}},i.prototype.setTransitioning=function(a){this._isTransitioning=a},i.prototype.dispose=function(){a.removeData(this._element,h),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},i.prototype._getConfig=function(c){return c=a.extend({},m,c),c.toggle=Boolean(c.toggle),f.typeCheckConfig(b,c,n),c},i.prototype._getDimension=function(){var b=a(this._element).hasClass(q.WIDTH);return b?q.WIDTH:q.HEIGHT},i.prototype._getParent=function(){var b=this,c=a(this._config.parent)[0],d='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]';return a(c).find(d).each(function(a,c){b._addAriaAndCollapsedClass(i._getTargetFromElement(c),[c])}),c},i.prototype._addAriaAndCollapsedClass=function(b,c){if(b){var d=a(b).hasClass(p.IN);b.setAttribute("aria-expanded",d),c.length&&a(c).toggleClass(p.COLLAPSED,!d).attr("aria-expanded",d)}},i._getTargetFromElement=function(b){var c=f.getSelectorFromElement(b);return c?a(c)[0]:null},i._jQueryInterface=function(b){return this.each(function(){var c=a(this),e=c.data(h),f=a.extend({},m,c.data(),"object"===("undefined"==typeof b?"undefined":d(b))&&b);if(!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||(e=new i(this,f),c.data(h,e)),"string"==typeof b){if(void 0===e[b])throw new Error('No method named "'+b+'"');e[b]()}})},e(i,null,[{key:"VERSION",get:function(){return g}},{key:"Default",get:function(){return m}}]),i}();return a(document).on(o.CLICK_DATA_API,r.DATA_TOGGLE,function(b){b.preventDefault();var c=s._getTargetFromElement(this),d=a(c).data(h),e=d?"toggle":a(this).data();s._jQueryInterface.call(a(c),e)}),a.fn[b]=s._jQueryInterface,a.fn[b].Constructor=s,a.fn[b].noConflict=function(){return a.fn[b]=k,s._jQueryInterface},s}(jQuery),function(a){var b="dropdown",d="4.0.0-alpha.5",g="bs.dropdown",h="."+g,i=".data-api",j=a.fn[b],k=27,l=38,m=40,n=3,o={HIDE:"hide"+h,HIDDEN:"hidden"+h,SHOW:"show"+h,SHOWN:"shown"+h,CLICK:"click"+h,CLICK_DATA_API:"click"+h+i,KEYDOWN_DATA_API:"keydown"+h+i},p={BACKDROP:"dropdown-backdrop",DISABLED:"disabled",OPEN:"open"},q={BACKDROP:".dropdown-backdrop",DATA_TOGGLE:'[data-toggle="dropdown"]',FORM_CHILD:".dropdown form",ROLE_MENU:'[role="menu"]',ROLE_LISTBOX:'[role="listbox"]',NAVBAR_NAV:".navbar-nav",VISIBLE_ITEMS:'[role="menu"] li:not(.disabled) a, [role="listbox"] li:not(.disabled) a'},r=function(){function b(a){c(this,b),this._element=a,this._addEventListeners()}return b.prototype.toggle=function(){if(this.disabled||a(this).hasClass(p.DISABLED))return!1;var c=b._getParentFromElement(this),d=a(c).hasClass(p.OPEN);if(b._clearMenus(),d)return!1;if("ontouchstart"in document.documentElement&&!a(c).closest(q.NAVBAR_NAV).length){var e=document.createElement("div");e.className=p.BACKDROP,a(e).insertBefore(this),a(e).on("click",b._clearMenus)}var f={relatedTarget:this},g=a.Event(o.SHOW,f);return a(c).trigger(g),!g.isDefaultPrevented()&&(this.focus(),this.setAttribute("aria-expanded","true"),a(c).toggleClass(p.OPEN),a(c).trigger(a.Event(o.SHOWN,f)),!1)},b.prototype.dispose=function(){a.removeData(this._element,g),a(this._element).off(h),this._element=null},b.prototype._addEventListeners=function(){a(this._element).on(o.CLICK,this.toggle)},b._jQueryInterface=function(c){return this.each(function(){var d=a(this).data(g);if(d||a(this).data(g,d=new b(this)),"string"==typeof c){if(void 0===d[c])throw new Error('No method named "'+c+'"');d[c].call(this)}})},b._clearMenus=function(c){if(!c||c.which!==n){var d=a(q.BACKDROP)[0];d&&d.parentNode.removeChild(d);for(var e=a.makeArray(a(q.DATA_TOGGLE)),f=0;f0&&h--,c.which===m&&hdocument.documentElement.clientHeight;!this._isBodyOverflowing&&a&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!a&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},j.prototype._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},j.prototype._checkScrollbar=function(){this._isBodyOverflowing=document.body.clientWidth=c){var d=this._targets[this._targets.length-1];this._activeTarget!==d&&this._activate(d)}if(this._activeTarget&&a=this._offsets[e]&&(void 0===this._offsets[e+1]||a .nav-item .fade, > .fade",ACTIVE:".active",ACTIVE_CHILD:"> .nav-item > .active, > .active",DATA_TOGGLE:'[data-toggle="tab"], [data-toggle="pill"]', +DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{relatedTarget:this._element}),i=a.Event(l.SHOW,{relatedTarget:d});if(d&&a(d).trigger(h),a(this._element).trigger(i),!i.isDefaultPrevented()&&!h.isDefaultPrevented()){g&&(c=a(g)[0]),this._activate(this._element,e);var j=function(){var c=a.Event(l.HIDDEN,{relatedTarget:b._element}),e=a.Event(l.SHOWN,{relatedTarget:d});a(d).trigger(c),a(b._element).trigger(e)};c?this._activate(c,c.parentNode,j):j()}}},b.prototype.dispose=function(){a.removeClass(this._element,g),this._element=null},b.prototype._activate=function(b,c,d){var e=a(c).find(n.ACTIVE_CHILD)[0],g=d&&f.supportsTransitionEnd()&&(e&&a(e).hasClass(m.FADE)||Boolean(a(c).find(n.FADE_CHILD)[0])),h=a.proxy(this._transitionComplete,this,b,e,g,d);e&&g?a(e).one(f.TRANSITION_END,h).emulateTransitionEnd(k):h(),e&&a(e).removeClass(m.IN)},b.prototype._transitionComplete=function(b,c,d,e){if(c){a(c).removeClass(m.ACTIVE);var g=a(c).find(n.DROPDOWN_ACTIVE_CHILD)[0];g&&a(g).removeClass(m.ACTIVE),c.setAttribute("aria-expanded",!1)}if(a(b).addClass(m.ACTIVE),b.setAttribute("aria-expanded",!0),d?(f.reflow(b),a(b).addClass(m.IN)):a(b).removeClass(m.FADE),b.parentNode&&a(b.parentNode).hasClass(m.DROPDOWN_MENU)){var h=a(b).closest(n.DROPDOWN)[0];h&&a(h).find(n.DROPDOWN_TOGGLE).addClass(m.ACTIVE),b.setAttribute("aria-expanded",!0)}e&&e()},b._jQueryInterface=function(c){return this.each(function(){var d=a(this),e=d.data(g);if(e||(e=e=new b(this),d.data(g,e)),"string"==typeof c){if(void 0===e[c])throw new Error('No method named "'+c+'"');e[c]()}})},e(b,null,[{key:"VERSION",get:function(){return d}}]),b}();return a(document).on(l.CLICK_DATA_API,n.DATA_TOGGLE,function(b){b.preventDefault(),o._jQueryInterface.call(a(this),"show")}),a.fn[b]=o._jQueryInterface,a.fn[b].Constructor=o,a.fn[b].noConflict=function(){return a.fn[b]=j,o._jQueryInterface},o}(jQuery),function(a){if(void 0===window.Tether)throw new Error("Bootstrap tooltips require Tether (http://tether.io/)");var b="tooltip",g="4.0.0-alpha.5",h="bs.tooltip",i="."+h,j=a.fn[b],k=150,l="bs-tether",m={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:"0 0",constraints:[]},n={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"string",constraints:"array"},o={TOP:"bottom center",RIGHT:"middle left",BOTTOM:"top center",LEFT:"middle right"},p={IN:"in",OUT:"out"},q={HIDE:"hide"+i,HIDDEN:"hidden"+i,SHOW:"show"+i,SHOWN:"shown"+i,INSERTED:"inserted"+i,CLICK:"click"+i,FOCUSIN:"focusin"+i,FOCUSOUT:"focusout"+i,MOUSEENTER:"mouseenter"+i,MOUSELEAVE:"mouseleave"+i},r={FADE:"fade",IN:"in"},s={TOOLTIP:".tooltip",TOOLTIP_INNER:".tooltip-inner"},t={element:!1,enabled:!1},u={HOVER:"hover",FOCUS:"focus",CLICK:"click",MANUAL:"manual"},v=function(){function j(a,b){c(this,j),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._tether=null,this.element=a,this.config=this._getConfig(b),this.tip=null,this._setListeners()}return j.prototype.enable=function(){this._isEnabled=!0},j.prototype.disable=function(){this._isEnabled=!1},j.prototype.toggleEnabled=function(){this._isEnabled=!this._isEnabled},j.prototype.toggle=function(b){if(b){var c=this.constructor.DATA_KEY,d=a(b.currentTarget).data(c);d||(d=new this.constructor(b.currentTarget,this._getDelegateConfig()),a(b.currentTarget).data(c,d)),d._activeTrigger.click=!d._activeTrigger.click,d._isWithActiveTrigger()?d._enter(null,d):d._leave(null,d)}else{if(a(this.getTipElement()).hasClass(r.IN))return void this._leave(null,this);this._enter(null,this)}},j.prototype.dispose=function(){clearTimeout(this._timeout),this.cleanupTether(),a.removeData(this.element,this.constructor.DATA_KEY),a(this.element).off(this.constructor.EVENT_KEY),this.tip&&a(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._tether=null,this.element=null,this.config=null,this.tip=null},j.prototype.show=function(){var b=this,c=a.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){a(this.element).trigger(c);var d=a.contains(this.element.ownerDocument.documentElement,this.element);if(c.isDefaultPrevented()||!d)return;var e=this.getTipElement(),g=f.getUID(this.constructor.NAME);e.setAttribute("id",g),this.element.setAttribute("aria-describedby",g),this.setContent(),this.config.animation&&a(e).addClass(r.FADE);var h="function"==typeof this.config.placement?this.config.placement.call(this,e,this.element):this.config.placement,i=this._getAttachment(h);a(e).data(this.constructor.DATA_KEY,this).appendTo(document.body),a(this.element).trigger(this.constructor.Event.INSERTED),this._tether=new Tether({attachment:i,element:e,target:this.element,classes:t,classPrefix:l,offset:this.config.offset,constraints:this.config.constraints,addTargetClasses:!1}),f.reflow(e),this._tether.position(),a(e).addClass(r.IN);var k=function(){var c=b._hoverState;b._hoverState=null,a(b.element).trigger(b.constructor.Event.SHOWN),c===p.OUT&&b._leave(null,b)};if(f.supportsTransitionEnd()&&a(this.tip).hasClass(r.FADE))return void a(this.tip).one(f.TRANSITION_END,k).emulateTransitionEnd(j._TRANSITION_DURATION);k()}},j.prototype.hide=function(b){var c=this,d=this.getTipElement(),e=a.Event(this.constructor.Event.HIDE),g=function(){c._hoverState!==p.IN&&d.parentNode&&d.parentNode.removeChild(d),c.element.removeAttribute("aria-describedby"),a(c.element).trigger(c.constructor.Event.HIDDEN),c.cleanupTether(),b&&b()};a(this.element).trigger(e),e.isDefaultPrevented()||(a(d).removeClass(r.IN),f.supportsTransitionEnd()&&a(this.tip).hasClass(r.FADE)?a(d).one(f.TRANSITION_END,g).emulateTransitionEnd(k):g(),this._hoverState="")},j.prototype.isWithContent=function(){return Boolean(this.getTitle())},j.prototype.getTipElement=function(){return this.tip=this.tip||a(this.config.template)[0]},j.prototype.setContent=function(){var b=a(this.getTipElement());this.setElementContent(b.find(s.TOOLTIP_INNER),this.getTitle()),b.removeClass(r.FADE).removeClass(r.IN),this.cleanupTether()},j.prototype.setElementContent=function(b,c){var e=this.config.html;"object"===("undefined"==typeof c?"undefined":d(c))&&(c.nodeType||c.jquery)?e?a(c).parent().is(b)||b.empty().append(c):b.text(a(c).text()):b[e?"html":"text"](c)},j.prototype.getTitle=function(){var a=this.element.getAttribute("data-original-title");return a||(a="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),a},j.prototype.cleanupTether=function(){this._tether&&this._tether.destroy()},j.prototype._getAttachment=function(a){return o[a.toUpperCase()]},j.prototype._setListeners=function(){var b=this,c=this.config.trigger.split(" ");c.forEach(function(c){if("click"===c)a(b.element).on(b.constructor.Event.CLICK,b.config.selector,a.proxy(b.toggle,b));else if(c!==u.MANUAL){var d=c===u.HOVER?b.constructor.Event.MOUSEENTER:b.constructor.Event.FOCUSIN,e=c===u.HOVER?b.constructor.Event.MOUSELEAVE:b.constructor.Event.FOCUSOUT;a(b.element).on(d,b.config.selector,a.proxy(b._enter,b)).on(e,b.config.selector,a.proxy(b._leave,b))}}),this.config.selector?this.config=a.extend({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},j.prototype._fixTitle=function(){var a=d(this.element.getAttribute("data-original-title"));(this.element.getAttribute("title")||"string"!==a)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},j.prototype._enter=function(b,c){var d=this.constructor.DATA_KEY;return c=c||a(b.currentTarget).data(d),c||(c=new this.constructor(b.currentTarget,this._getDelegateConfig()),a(b.currentTarget).data(d,c)),b&&(c._activeTrigger["focusin"===b.type?u.FOCUS:u.HOVER]=!0),a(c.getTipElement()).hasClass(r.IN)||c._hoverState===p.IN?void(c._hoverState=p.IN):(clearTimeout(c._timeout),c._hoverState=p.IN,c.config.delay&&c.config.delay.show?void(c._timeout=setTimeout(function(){c._hoverState===p.IN&&c.show()},c.config.delay.show)):void c.show())},j.prototype._leave=function(b,c){var d=this.constructor.DATA_KEY;if(c=c||a(b.currentTarget).data(d),c||(c=new this.constructor(b.currentTarget,this._getDelegateConfig()),a(b.currentTarget).data(d,c)),b&&(c._activeTrigger["focusout"===b.type?u.FOCUS:u.HOVER]=!1),!c._isWithActiveTrigger())return clearTimeout(c._timeout),c._hoverState=p.OUT,c.config.delay&&c.config.delay.hide?void(c._timeout=setTimeout(function(){c._hoverState===p.OUT&&c.hide()},c.config.delay.hide)):void c.hide()},j.prototype._isWithActiveTrigger=function(){for(var a in this._activeTrigger)if(this._activeTrigger[a])return!0;return!1},j.prototype._getConfig=function(c){return c=a.extend({},this.constructor.Default,a(this.element).data(),c),c.delay&&"number"==typeof c.delay&&(c.delay={show:c.delay,hide:c.delay}),f.typeCheckConfig(b,c,this.constructor.DefaultType),c},j.prototype._getDelegateConfig=function(){var a={};if(this.config)for(var b in this.config)this.constructor.Default[b]!==this.config[b]&&(a[b]=this.config[b]);return a},j._jQueryInterface=function(b){return this.each(function(){var c=a(this).data(h),e="object"===("undefined"==typeof b?"undefined":d(b))?b:null;if((c||!/dispose|hide/.test(b))&&(c||(c=new j(this,e),a(this).data(h,c)),"string"==typeof b)){if(void 0===c[b])throw new Error('No method named "'+b+'"');c[b]()}})},e(j,null,[{key:"VERSION",get:function(){return g}},{key:"Default",get:function(){return m}},{key:"NAME",get:function(){return b}},{key:"DATA_KEY",get:function(){return h}},{key:"Event",get:function(){return q}},{key:"EVENT_KEY",get:function(){return i}},{key:"DefaultType",get:function(){return n}}]),j}();return a.fn[b]=v._jQueryInterface,a.fn[b].Constructor=v,a.fn[b].noConflict=function(){return a.fn[b]=j,v._jQueryInterface},v}(jQuery));(function(f){var h="popover",i="4.0.0-alpha.5",j="bs.popover",k="."+j,l=f.fn[h],m=f.extend({},g.Default,{placement:"right",trigger:"click",content:"",template:''}),n=f.extend({},g.DefaultType,{content:"(string|element|function)"}),o={FADE:"fade",IN:"in"},p={TITLE:".popover-title",CONTENT:".popover-content"},q={HIDE:"hide"+k,HIDDEN:"hidden"+k,SHOW:"show"+k,SHOWN:"shown"+k,INSERTED:"inserted"+k,CLICK:"click"+k,FOCUSIN:"focusin"+k,FOCUSOUT:"focusout"+k,MOUSEENTER:"mouseenter"+k,MOUSELEAVE:"mouseleave"+k},r=function(g){function l(){return c(this,l),a(this,g.apply(this,arguments))}return b(l,g),l.prototype.isWithContent=function(){return this.getTitle()||this._getContent()},l.prototype.getTipElement=function(){return this.tip=this.tip||f(this.config.template)[0]},l.prototype.setContent=function(){var a=f(this.getTipElement());this.setElementContent(a.find(p.TITLE),this.getTitle()),this.setElementContent(a.find(p.CONTENT),this._getContent()),a.removeClass(o.FADE).removeClass(o.IN),this.cleanupTether()},l.prototype._getContent=function(){return this.element.getAttribute("data-content")||("function"==typeof this.config.content?this.config.content.call(this.element):this.config.content)},l._jQueryInterface=function(a){return this.each(function(){var b=f(this).data(j),c="object"===("undefined"==typeof a?"undefined":d(a))?a:null;if((b||!/destroy|hide/.test(a))&&(b||(b=new l(this,c),f(this).data(j,b)),"string"==typeof a)){if(void 0===b[a])throw new Error('No method named "'+a+'"');b[a]()}})},e(l,null,[{key:"VERSION",get:function(){return i}},{key:"Default",get:function(){return m}},{key:"NAME",get:function(){return h}},{key:"DATA_KEY",get:function(){return j}},{key:"Event",get:function(){return q}},{key:"EVENT_KEY",get:function(){return k}},{key:"DefaultType",get:function(){return n}}]),l}(g);return f.fn[h]=r._jQueryInterface,f.fn[h].Constructor=r,f.fn[h].noConflict=function(){return f.fn[h]=l,r._jQueryInterface},r})(jQuery)}(); \ No newline at end of file diff --git a/static/js/highlight.js b/static/js/highlight.js new file mode 100644 index 0000000..56fa8e8 --- /dev/null +++ b/static/js/highlight.js @@ -0,0 +1,2 @@ +/*! highlight.js v9.8.0 | BSD3 License | git.io/hljslicense */ +!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return R(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||R(i))return i}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){l+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):E(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"===e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function l(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?"":y.classPrefix,i='',i+n+o}function p(){var e,t,r,a;if(!E.k)return n(B);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)a+=n(B.substr(t,r.index-t)),e=g(E,r),e?(M+=e[1],a+=h(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return a+n(B.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=""}function v(e){k+=e.cN?h(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?B+=n:(a.rE||a.eE||(B+=n),b(),a.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var w,E=i||N,L={},k="";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,"",!0)+k);var B="",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substr(O,I.index-O),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},a=r;return t.filter(R).forEach(function(n){var t=l(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&"\n"===e?"
":y.tabReplace?n.replace(/\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n,t,r,o,s,p=i(e);a(p)||(y.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");w.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||"").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",y={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},I={"&":"&","<":"<",">":">"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("rust",function(e){var t="([uif](8|16|32|64|size))?",r="alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self Self sizeof static struct super trait true type typeof unsafe unsized use virtual while where yield move default int i8 i16 i32 i64 isize uint u8 u32 u64 usize float f32 f64 str char bool",n="Copy Send Sized Sync Drop Fn FnMut FnOnce drop Box ToOwned Clone PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator Option Result SliceConcatExt String ToString Vec assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules!";return{aliases:["rs"],k:{keyword:r,literal:"true false Some None Ok Err",built_in:n},l:e.IR+"!?",i:""}]}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\._]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"section",b:/^[\w]+:\s*$/},{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}}); \ No newline at end of file diff --git a/tutorials.md b/tutorials.md deleted file mode 100644 index fbcc1e2..0000000 --- a/tutorials.md +++ /dev/null @@ -1,16 +0,0 @@ -title: Tutorials -layout: default.liquid -permalink: /tutorials.html ---- -
-
- - - -## Examples - -The words is comming. - - -
-
\ No newline at end of file