diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 000000000..8013f263d --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "source/lib" +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..f0627b937 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[*.py] +indent_size = 4 diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..a8ac41464 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,4 @@ +{ + "extends": "theme-next", + "root": true +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..7ead58ec1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +source/lib/* linguist-vendored +scripts/merge.js linguist-vendored diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..d95bde0ee --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,94 @@ +
+ +# + +[NexT](https://github.com/theme-next/hexo-theme-next) is an elegant and powerful theme for [Hexo](https://hexo.io/). With it, you can build a static blog hosted on [GitHub Pages](https://pages.github.com/) to share your life and communicate with new friends. + +A CODE_OF_CONDUCT dictates how conversation during code updates, issue communication, and pull requests should happen within [NexT](https://github.com/theme-next/hexo-theme-next) repository. We expect all users to show respect and courtesy to others through our repositories. Anyone violating these rules will not be reviewed and will be blocked and expelled from our repositories immediately upon discovery. + +## Table Of Contents + +- [Our Pledge](#our-pledge) +- [Our Responsibilities](#our-responsibilities) +- [Our Standards](#our-standards) +- [Scope](#scope) +- [Enforcement](#enforcement) +- [Contacting Maintainers](#contacting-maintainers) +- [Attribution](#attribution) + +## Our Pledge + +As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +In the interest of fostering an open and welcoming environment, we are committed to making participation in our community a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual identity and orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +## Our Responsibilities + +Project maintainers have the right and responsibility to clarify the standards of acceptable behavior and are expected 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 block temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Our Standards + +As a project on GitHub, this project is overed by the [GitHub Community Guidelines](https://help.github.com/articles/github-community-guidelines/). Additionally, as a project hosted on npm, it is covered by [npm Inc's Code of Conduct](https://www.npmjs.com/policies/conduct). + +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 feedback. +* Focusing on what is best for the community. +* Showing empathy and kindness 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 + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. + +Depending on the violation, the maintainers may decide that violations of this code of conduct that have happened outside of the scope of the community may deem an individual unwelcome, and take appropriate action to maintain the comfort and safety of its members. + +## Enforcement + +If you see a Code of Conduct violation, follow these steps: + +1. Let the person know that what they did is not appropriate and ask them to stop and/or edit their message(s) or commits. That person should immediately stop the behavior and correct the issue. +2. If this doesn’t happen, or if you're uncomfortable speaking up, [contact the maintainers](#contacting-maintainers). When reporting, please include any relevant details, links, screenshots, context, or other information that may be used to better understand and resolve the situation. +3. As soon as available, a maintainer will look into the issue, and take further action. + +Once the maintainers get involved, they will follow a documented series of steps and do their best to preserve the well-being of project members. + +All complaints will be reviewed and investigated and will result in a response that is deemed necessary and 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. + +Thesehese are the steps maintainers will take for further enforcement, as needed: + +1. Repeat the request to stop. +2. If the person doubles down, they will have offending messages removed or edited by a maintainers given an official warning. The PR or Issue may be locked. +3. If the behavior continues or is repeated later, the person will be blocked from participating for 24 hours. +4. If the behavior continues or is repeated after the temporary block, a long-term (6-12 months) ban will be used. + +On top of this, maintainers may remove any offending messages, images, contributions, etc, as they deem necessary. Maintainers reserve full rights to skip any of these steps, at their discretion, if the violation is considered to be a serious and/or immediate threat to the well-being of members of the community. These include any threats, serious physical or verbal attacks, and other such behavior that would be completely unacceptable in any social setting that puts our members at risk. + +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. + +## Contacting Maintainers + +You may get in touch with the maintainer team through any of the following methods: + +* Through Email: + * [support@theme-next.org](mailto:support@theme-next.org) + +* Through Chat: + * [Gitter](https://gitter.im/theme-next) + * [Riot](https://riot.im/app/#/room/#NexT:matrix.org) + * [Telegram](https://t.me/joinchat/GUNHXA-vZkgSMuimL1VmMw) + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/) and [WeAllJS Code of Conduct](https://wealljs.org/code-of-conduct). diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..4d80ec2eb --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,142 @@ + + +# + +First of all, thanks for taking your time to contribute and help make our project even better than it is today! The following is a set of guidelines for contributing to [Theme-Next](https://github.com/theme-next) and its libs submodules. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. + +## Table Of Contents + +[How Can I Contribute?](#how-can-i-contribute) + + * [Before Submitting An Issue](#before-submitting-an-issue) + * [Reporting Bugs](#reporting-bugs) + * [Suggesting Enhancements](#suggesting-enhancements) + * [Submitting a Pull Request](#submitting-a-pull-request) + * [Creating Releases](#creating-releases) + +[Guides](#guides) + + * [Coding Rules](#coding-rules) + * [Coding Standards](#coding-standards) + * [Commit Messages Rules](#commit-messages-rules) + + +## How Can I Contribute? + +Main Theme-Next repository was rebased from [iissnan's](https://github.com/iissnan/hexo-theme-next) profile to [Theme-Next](https://github.com/theme-next) organization on GitHub. Most libraries under the `next/source/lib` directory was moved out to [external repos](https://github.com/theme-next) under NexT organization. Version 5 works fine at most cases, but for frequent users, you maybe need to [upgrade version 5 to 6](https://github.com/theme-next/hexo-theme-next/blob/master/docs/UPDATE-FROM-5.1.X.md) to get features and supports in new [Theme-Next](https://github.com/theme-next/hexo-theme-next) repository. + + +### Before Submitting An Issue + +If you just have a question, you'll get faster results by checking the FAQs for a list of common questions and problems (Work in progress) or the [«NexT» Documentation Site](https://theme-next.org/docs/) (Work in progress). + +Also, you can perform a [cursory search](https://github.com/theme-next/hexo-theme-next/search?q=&type=Issues&utf8=%E2%9C%93) to see if the problem has already been reported or solved. You don't want to duplicate effort. You might be able to find the cause of the problem and fix things yourself, or add comments to the existed issue. + +If you find a bug in the source code, most importantly, please check carefully if you can reproduce the problem [in the latest release version of Next](https://github.com/theme-next/hexo-theme-next/releases/latest). Then, you can help us by +[Reporting Bugs](#reporting-bugs) or [Suggesting Enhancements](#suggesting-enhancements) to our [ Repository](https://github.com/theme-next/hexo-theme-next). Even better, you can +[submit a Pull Request](#submitting-a-pull-request) with a fix. + + +### Reporting Bugs + +Before creating bug reports, please check [this list](#before-submitting-an-issue) as you might find out that you don't need to create one. After you've determined the repository your bug is related to, create an issue on that repository and provide the information as many details as possible by filling in [the required template](ISSUE_TEMPLATE.md). + +Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior, and find related reports: + +* Use a clear and descriptive title for the issue to identify the problem. +* Provide more context by answering these questions: + * Can you reproduce the problem? Can you reliably reproduce the issue? If not, provide details about how often the problem happens and under which conditions it normally happens. + * Did the problem start happening recently or was this always a problem? + * If the problem started happening recently, can you reproduce the problem in an older version of Next? What's the most recent version in which the problem doesn't happen? You can download older versions of Next from [the releases page](https://github.com/theme-next/hexo-theme-next/releases). + * Which version of Node, Hexo and Next are you using? You can get the exact version by running `node -v`, `hexo version` in your terminal, or copy the contents in site's`package.json`. + * Which packages do you have installed? You can get that list by copying the contents in site's`package.json`. +* Describe the exact steps which reproduce the problem in as many details as possible. When listing steps, don't just say what you did, but explain how you did it, e.g. which command exactly you used. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/creating-and-highlighting-code-blocks/) or [a permanent link to a code snippet](https://help.github.com/articles/creating-a-permanent-link-to-a-code-snippet/), or a [Gist link](https://gist.github.com/). +* Provide specific examples to demonstrate the steps. Include links to files (screenshots or GIFs) or live demo. +* Describe the behavior you observed after following the steps and point out what exactly is the problem with that behavior. +* Explain which behavior you expected to see instead and why. + +### Suggesting Enhancements + +Before creating enhancement suggestions, please check [this list](#before-submitting-an-issue) as you might find out that you don't need to create one. After you've determined the repository your enhancement suggestion is related to, create an issue on that repository and provide the information as many details as possible by filling in [the required template](ISSUE_TEMPLATE.md). + +Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions. + +* Use a clear and descriptive title for the issue to identify the suggestion. +* Describe the current behavior and explain which behavior you expected to see instead and Explain why this enhancement would be useful to most users. +* Provide specific examples to demonstrate the suggestion. Include links to files (screenshots or GIFs) or live demo. + +### Submitting a Pull Request + +Before creating a Pull Request (PR), please check [this list](#before-submitting-an-issue) as you might find out that you don't need to create one. After you've determined the repository your pull request is related to, create a pull request on that repository. The detailed document of creating a pull request can be found [here](https://help.github.com/articles/creating-a-pull-request/). + +1. On GitHub, navigate to the original page of the [hexo-theme-next](https://github.com/theme-next/hexo-theme-next). In the top-right corner of the page, click **Fork**. +2. Under the repository name in your forked repository, click **Clone or download**. In the `Clone with SSH` section, copy the clone URL for the repository. Open Git Bash, and change the current working directory to the location where you want the cloned directory to be made. Type `git clone`, and then paste the URL you copied. Press **Enter**. Your local clone will be created. + ```bash + $ git clone git@github.com:username/hexo-theme-next.git + ``` +3. Navigate into your new cloned repository. Switch branches to the compare branch of the pull request where the original changes were made. + ```bash + $ cd hexo-theme-next + $ git checkout -b patchname + ``` +4. After you commit your changes to the head branch of the pull request you can push your changes up to the original pull request directly. + ```bash + $ git add . + $ git commit -m "add commit messamge" + $ git push origin patchname + ``` +5. Navigate to the original repository you created your fork from. To the right of the Branch menu, click **New pull request**. On the Compare page, confirm that the base fork is the repository you'd like to merge changes into. Use the base branch drop-down menu to select the branch of the upstream repository you'd like to merge changes into. Use the head fork drop-down menu to select your fork, then use the compare branch drop-down menu to select the branch you made your changes in. Click **Create pull request** and type a title and description for your pull request. + +Following these guidelines helps maintainers and the community understand your pull request :pencil:: + +* Follow our [Coding Rules](#coding-rules) and [commit message conventions](#commit-messages-rules). +* Use a clear and descriptive title for the issue to identify the pull request. Do not include issue numbers in the PR title. +* Fill in [the required template](PULL_REQUEST_TEMPLATE.md) as many details as possible. +* All features or bug fixes must be tested in all schemes. And provide specific examples to demonstrate the pull request. Include links to files (screenshots or GIFs) or live demo. + +### Creating Releases + +Releases are a great way to ship projects on GitHub to your users. + +1. On GitHub, navigate to the main page of the repository. Under your repository name, click **Releases**. Click **Draft a new release**. +2. Type a version number for your release. Versions are based on [Git tags](https://git-scm.com/book/en/Git-Basics-Tagging). We recommend naming tags that fit within [About Major and Minor NexT versions](https://github.com/theme-next/hexo-theme-next/issues/187). +3. Select a branch that contains the project you want to release. Usually, you'll want to release against your `master` branch, unless you're releasing beta software. +4. Type a title and description that describes your release. + - Use the version as the title. + - The types of changes include **Breaking Changes**, **Updates**, **Features**, and **Bugfixes**. In the section of Breaking Changes, use multiple secondary headings, and use item list in other sections. + - Use the passive tense and subject-less sentences. + - All changes must be documented in release notes. If commits happen without pull request (minimal changes), just add this commit ID into release notes. If commits happen within pull request alreay, just add the related pull request ID including all possible commits. +5. If you'd like to include binary files along with your release, such as compiled programs, drag and drop or select files manually in the binaries box. +6. If the release is unstable, select **This is a pre-release** to notify users that it's not ready for production. If you're ready to publicize your release, click **Publish release**. Otherwise, click **Save draft** to work on it later. + +## Guides + +### Coding Rules + +This project and everyone participating in it is governed by the [Code of Conduct](CODE_OF_CONDUCT.md) to keep open and inclusive. By participating, you are expected to uphold this code. + +### Coding Standards + +To be continued. + +### Commit Messages Rules + +We have very precise rules over how our git commit messages can be formatted. Each commit message consists of a `type` and a `subject`. This leads to more +readable messages that are easy to follow when looking through the project history. + +- `type` describes the meaning of this commit including but not limited to the following items, and capitalize the first letter. + * `Build`: Changes that affect the build system or external dependencies + * `Ci`: Changes to our CI configuration files and scripts + * `Docs`: Documentation only changes + * `Feat`: A new feature + * `Fix`: A bug fix + * `Perf`: A code change that improves performance + * `Refactor`: A code change that neither fixes a bug nor adds a feature + * `Style`: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) + * `Revert`: Revert some existing commits + * `Release`: Commit a release for a conventional changelog project +- The `subject` contains a succinct description of the change, like `Update code highlighting in readme.md`. + * No dot (.) at the end. + * Use the imperative, present tense: "change" not "changed" nor "changes". diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..8332ad0da --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,84 @@ + + +### I agree and want to create new issue + + +- [ ] Yes, I was on [Hexo Docs page](https://hexo.io/docs/), especially on [Templates](https://hexo.io/docs/templates.html), [Variables](https://hexo.io/docs/variables.html), [Helpers](https://hexo.io/docs/helpers.html) and [Troubleshooting](https://hexo.io/docs/troubleshooting.html). +- [ ] Yes, I was on [NexT Documentation Site](http://theme-next.org/docs/). +- [ ] And yes, I already searched for current [issues](https://github.com/theme-next/hexo-theme-next/issues?utf8=%E2%9C%93&q=is%3Aissue) and this is not help to me. + +*** + +### Expected behavior + + +### Actual behavior + + +### Steps to reproduce the behavior +1. N/A +2. N/A +3. N/A + +* Link to demo site with this issue: N/A +* Link(s) to source code or any usefull link(s): N/A + +### Node.js and NPM Information + +``` + +``` + +### Package dependencies Information + +``` + +``` + +### Hexo Information + +#### Hexo version + +``` + +``` + +#### Hexo Configuration + +```yml + +``` + +### NexT Information + +**NexT Version:** + + +- [ ] Latest Master branch +- [ ] Latest Release version +- [ ] Old version + + +**NexT Scheme:** + + +- [ ] All schemes +- [ ] Muse +- [ ] Mist +- [ ] Pisces +- [ ] Gemini + + +#### NexT Configuration: + +```yml + +``` + +### Other Information diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..0dc55ece7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,87 @@ + + + + +## PR Checklist +**Please check if your PR fulfills the following requirements:** + +- [ ] The commit message follows [our guidelines](https://github.com/theme-next/hexo-theme-next/blob/master/.github/CONTRIBUTING.md). +- [ ] Tests for the changes have been added (for bug fixes / features). + - [ ] Muse | Mist have been tested. + - [ ] Pisces | Gemini have been tested. +- [ ] Docs have been added / updated (for bug fixes / features). + +## PR Type +**What kind of change does this PR introduce?** + +- [ ] Bugfix. +- [ ] Feature. +- [ ] Code style update (formatting, local variables). +- [ ] Refactoring (no functional changes, no api changes). +- [ ] Build related changes. +- [ ] CI related changes. +- [ ] Documentation content changes. +- [ ] Other... Please describe: + +## What is the current behavior? + + +Issue Number(s): N/A + +## What is the new behavior? +Description about this pull, in several words... + +* Screens with this changes: N/A +* Link to demo site with this changes: N/A + +### How to use? +In NexT `_config.yml`: +```yml +... +``` + +## Does this PR introduce a breaking change? +- [ ] Yes. +- [ ] No. + + + + + + diff --git a/.github/browserstack_logo.png b/.github/browserstack_logo.png new file mode 100644 index 000000000..0be37e77e Binary files /dev/null and b/.github/browserstack_logo.png differ diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 000000000..2f9eba51e --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,30 @@ +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale Issue or Pull Request is closed +daysUntilClose: 7 +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - bug + - discussion + - need-verify + - pending-reply + - feature-request + - enhancement + - question + - documentation + - backlog +# Label to use when marking as stale +staleLabel: stale +# Comment to post when marking as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because lack of + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when removing the stale label. Set to `false` to disable +unmarkComment: false +# Comment to post when closing a stale Issue or Pull Request. Set to `false` to disable +closeComment: false +# Limit to only `issues` or `pulls` +only: issues diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..26b5eab0b --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +.DS_Store +.idea/ +*.log +*.iml +yarn.lock +package-lock.json +node_modules/ + +# Ignore optional external libraries +source/lib/* + +# Track internal libraries & Ignore unused verdors files +source/lib/font-awesome/less/ +source/lib/font-awesome/scss/ +!source/lib/font-awesome/* + +!source/lib/jquery/ + +source/lib/ua-parser-js/* +!source/lib/ua-parser-js/dist/ + +!source/lib/velocity/ diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 000000000..303949dfe --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,6 @@ +linters: + eslint: + config: https://github.com/theme-next/eslint-config-theme-next/index.js +files: + ignore: + - 'bower_components/*' diff --git a/.stylintrc b/.stylintrc new file mode 100644 index 000000000..38e6ac14e --- /dev/null +++ b/.stylintrc @@ -0,0 +1,45 @@ +{ + "blocks": false, + "brackets": "always", + "colons": "always", + "colors": "always", + "commaSpace": "always", + "commentSpace": "always", + "cssLiteral": "never", + "customProperties": [], + "depthLimit": false, + "duplicates": true, + "efficient": "always", + "exclude": [], + "extendPref": false, + "globalDupe": false, + "groupOutputByFile": true, + "indentPref": false, + "leadingZero": "never", + "maxErrors": false, + "maxWarnings": false, + "mixed": false, + "mixins": [], + "namingConvention": "lowercase-dash", + "namingConventionStrict": false, + "none": "never", + "noImportant": true, + "parenSpace": false, + "placeholders": "always", + "prefixVarsWithDollar": "always", + "quotePref": false, + "reporterOptions": { + "columns": ["lineData", "severity", "description", "rule"], + "columnSplitter": " ", + "showHeaders": false, + "truncate": true + }, + "semicolons": "always", + "sortOrder": "grouped", + "stackedProperties": false, + "trailingWhitespace": "never", + "universal": false, + "valid": true, + "zeroUnits": "never", + "zIndexNormalize": false +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..9591f0b23 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: node_js +#node_js: node +node_js: lts/* + +cache: + directories: + - node_modules + +install: npm install + +before_script: + - npm install -g gulp + +addons: + browserstack: + username: "ivannginx1" + access_key: + secure: "NutOhdgtUdBUXMPZhy8X1F1Jq+tan1LeNOV0FArBt15SNlxtNArqhiyTi4XnG9MPruX4306aGF2RBrKso+OiGNRdGtRGngH613Q0GWNtlC/boMqnI7fHqLIyCs6S12y2uA8PK4Ifxg9bZ0VtCTYYbMy+p1KvBM//L12vmtfdnby8z5Qvex3tB3dLoPOR50CKkINHJVDLm+iVRFrdz4/83oDsulZSRRGIaxu5taDWPIcp3fYZtre2Nc+RXcsyFDyjN7U0Hvr5tKBbloJxXEQEBv2xLkMOtp85nmCPD06s1Il8Wus1ux3raVsfUyaW5FpNX37Jeb5e00RQUM1wgU5m75H6qiGwDvQswbugJG0i/a2nNfsgVmbrSZdMnkHcx2Uxmrw4ejyEP5NSrJSBi05Ck1fQ4UsZ4Qkdf1fd04SI0LpLWt43eoNO/7rHKsQoP4LCX9gxKUuC075NEBLODyJ529RYfA6dKKwwH6o0ZbOgASmCoAWaM65g4+FHRnJcKL/Kj9ZWklQtRa7/ynlHaA65jefFS2lB8Ut6d3rXDDBih9mIrwV1uUaEH96xgAN42bgU/vY6FGzNkDOYZqj4YfsepDM0wbOsslFie7JZq7iFjsYvrXqLvYUMk37AZwQ2Sb6uH4tIT4Qw/4oZfDzA1En3/8HdZJ28nKW/lzjwMSqheIY=" diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..2bff1aceb --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,63 @@ +#Copyright © 2017 «NexT».
+ +Detail attribution information for «NexT»
+ is contained in the 'docs/AUTHORS.md' file.
This license also available in text format.
+ +[AUTHORS]: docs/AUTHORS.md +[AGPL3]: docs/AGPL3.md +[AGPL3-7]: docs/AGPL3.md/#7-additional-terms +[AGPL3-15]: docs/AGPL3.md/#15-disclaimer-of-warranty diff --git a/README.md b/README.md new file mode 100644 index 000000000..ac8019351 --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ + + +# + +«NexT» is a high quality elegant Hexo theme. It is crafted from scratch, with love.
+ +[![gitter-image]][gitter-url] +[![riot-image]][riot-url] +[![t-chat-image]][t-chat-url] +[![t-news-image]][t-news-url] +[![lang-image]][lang-url] +[![travis-image]][travis-url] +[![rel-image]][releases-url] +[![hexo-image]][hexo-url] +[![lic-image]][lic-url] + +## Live Preview + +* :heart_decoration: Muse scheme: [LEAFERx](https://leaferx.online) | [XiaMo](https://notes.wanghao.work) | [OAwan](https://oawan.me) +* :six_pointed_star: Mist scheme: [Jeff](https://blog.zzbd.org) | [uchuhimo](http://uchuhimo.me) | [xirong](http://www.ixirong.com) +* :pisces: Pisces scheme: [Vi](http://notes.iissnan.com) | [Acris](https://acris.me) | [Rainy](https://rainylog.com) +* :gemini: Gemini scheme: [Ivan.Nginx](https://almostover.ru) | [Raincal](https://raincal.com) | [Dandy](https://dandyxu.me) + +More «NexT» examples [here](https://github.com/iissnan/hexo-theme-next/issues/119). + +## Installation + +Simplest way to install is by cloning whole repository: + + ```sh + $ cd hexo + $ git clone https://github.com/theme-next/hexo-theme-next themes/next + ``` + +Or you can see [detailed installation instructions][docs-installation-url] if you want any other variant. + +## Plugins + +In NexT config now you can find dependencies on each module which was moved to external repositories which can be found by [main organization link](https://github.com/theme-next). + +For example, you want to use `fancybox` in your site. Go to NexT config and see: + +```yml +# Fancybox +# Dependencies: https://github.com/theme-next/theme-next-fancybox +fancybox: false +``` + +Then turn on `fancybox` and go to «Dependencies» link with installation instructions of this module. + +### Exceptions + +If you use cdn for any plugins, you need to replace your cdn link. + +For example, you want to use `fancybox` and you configured a cdn link. Go to NexT config and see: + +```yml +vendors: + # ... + # Some contents... + # ... + fancybox: # Set or update fancybox cdn url. + fancybox_css: # Set or update fancybox cdn url. +``` + +Instead of defining [main organization link](https://github.com/theme-next) for updates. + +## Update + +You can update to latest master branch by the following command: + +```sh +$ cd themes/next +$ git pull +``` + +And if you see any error message during update (something like **«Commit your changes or stash them before you can merge»**), recommended to learn [Hexo data files][docs-data-files-url] feature.\ +Howbeit, you can bypass update errors by `Commit`, `Stash` or `Discard` local changes. See [here](https://stackoverflow.com/a/15745424/5861495) how to do it. + +**If you want to update from v5.1.x to v6.0.x, read [here][docs-update-5-1-x-url].** + +## Known Bugs + +For those who also encounter **«[Error: Cannot find module 'hexo-util'](https://github.com/iissnan/hexo-theme-next/issues/1490)»**, please check your NPM version. + +* `> 3`: Still not work? Please remove `node_modules` directory and reinstall using `npm install`. +* `< 3`: Please add `hexo-util` explicitly via `npm install --save-dev hexo-util` to you site package deps. + +## Contributing + +Contribution is welcome, feel free to open an issue and fork. Waiting for your pull request. + +## Third party applications + +* :triangular_flag_on_post: HexoEditor + +[browser-image]: https://img.shields.io/badge/browser-%20chrome%20%7C%20firefox%20%7C%20opera%20%7C%20safari%20%7C%20ie%20%3E%3D%209-lightgrey.svg +[browser-url]: https://www.browserstack.com + +[lang-image]: https://d322cqt584bo4o.cloudfront.net/theme-next/localized.svg "Add or improve translation in few seconds!" +[lang-url]: https://crwd.in/theme-next + +[gitter-image]: https://img.shields.io/badge/gitter-chat-orange.svg "Join to our Gitter room" +[gitter-url]: https://gitter.im/theme-next + +[riot-image]: https://img.shields.io/badge/riot-chat-DCAB08.svg "Join to our Riot room" +[riot-url]: https://riot.im/app/#/room/#NexT:matrix.org + +[t-chat-image]: https://img.shields.io/badge/telegram-chat-BAB210.svg "Join to our Telegram group" +[t-chat-url]: https://t.me/theme_next + +[t-news-image]: https://img.shields.io/badge/telegram-news-98B919.svg "Join to our Telegram news channel" +[t-news-url]: https://t.me/theme_next_news + +[travis-image]: https://travis-ci.org/theme-next/hexo-theme-next.svg?branch=master +[travis-url]: https://travis-ci.org/theme-next/hexo-theme-next?branch=master "Travis CI [Linux]" + +[hexo-image]: https://img.shields.io/badge/hexo-%3E%3D%203.5.0-blue.svg +[hexo-url]: http://hexo.io + +[lic-image]: https://img.shields.io/badge/license-%20AGPL-blue.svg +[lic-url]: https://github.com/theme-next/hexo-theme-next/blob/master/LICENSE.md + + +[rel-image]: https://badge.fury.io/gh/theme-next%2Fhexo-theme-next.svg + + +[download-latest-url]: https://github.com/theme-next/hexo-theme-next/archive/master.zip +[releases-latest-url]: https://github.com/theme-next/hexo-theme-next/releases/latest +[releases-url]: https://github.com/theme-next/hexo-theme-next/releases +[tags-url]: https://github.com/theme-next/hexo-theme-next/tags +[commits-url]: https://github.com/theme-next/hexo-theme-next/commits/master + +[docs-installation-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/INSTALLATION.md +[docs-data-files-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/DATA-FILES.md +[docs-update-5-1-x-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/UPDATE-FROM-5.1.X.md diff --git a/_config.yml b/_config.yml new file mode 100644 index 000000000..7b3107c58 --- /dev/null +++ b/_config.yml @@ -0,0 +1,973 @@ +# --------------------------------------------------------------- +# Theme Core Configuration Settings +# --------------------------------------------------------------- + +# If false, merge configs from `_data/next.yml` into default configuration (rewrite). +# If true, will fully override default configuration by options from `_data/next.yml` (override). Only for NexT settings. +# And if true, all config from default NexT `_config.yml` must be copied into `next.yml`. Use if you know what you are doing. +# Useful if you want to comment some options from NexT `_config.yml` by `next.yml` without editing default config. +override: false + +# Allow to cache content generation. Introduced in NexT v6.0.0. +cache: + enable: true + +# Redefine custom file paths. Introduced in NexT v6.0.2. +# If commented, will be used default custom file paths. + +# For example, you want to put your custom styles file +# outside theme directory in root `source/_data`, set +# `styles: source/_data/styles.styl` +#custom_file_path: + # Default paths: layout/_custom/* + #head: source/_data/head.swig + #header: source/_data/header.swig + #sidebar: source/_data/sidebar.swig + + # Default path: source/css/_variables/custom.styl + #variables: source/_data/variables.styl + # Default path: source/css/_mixins/custom.styl + #mixins: source/_data/mixins.styl + # Default path: source/css/_custom/custom.styl + #styles: source/_data/styles.styl + + +# --------------------------------------------------------------- +# Site Information Settings +# --------------------------------------------------------------- + +# To get or check favicons visit: https://realfavicongenerator.net +# Put your favicons into `hexo-site/source/` (recommend) or `hexo-site/themes/next/source/images/` directory. + +# Default NexT favicons placed in `hexo-site/themes/next/source/images/` directory. +# And if you want to place your icons in `hexo-site/source/` root directory, you must remove `/images` prefix from pathes. + +# For example, you put your favicons into `hexo-site/source/images` directory. +# Then need to rename & redefine they on any other names, otherwise icons from Next will rewrite your custom icons in Hexo. +favicon: + small: /images/favicon-16x16-next.png + medium: /images/favicon-32x32-next.png + apple_touch_icon: /images/apple-touch-icon-next.png + safari_pinned_tab: /images/logo.svg + #android_manifest: /images/manifest.json + #ms_browserconfig: /images/browserconfig.xml + +# Set rss to false to disable feed link. +# Leave rss as empty to use site's feed link, and install hexo-generator-feed: `npm install hexo-generator-feed --save`. +# Set rss to specific value if you have burned your feed already. +rss: + +footer: + # Specify the date when the site was setup. + # If not defined, current year will be used. + #since: 2015 + + # Icon between year and copyright info. + icon: + # Icon name in fontawesome, see: https://fontawesome.com/v4.7.0/icons + # `heart` is recommended with animation in red (#ff0000). + name: user + # If you want to animate the icon, set it to true. + animated: false + # Change the color of icon, using Hex Code. + color: "#808080" + + # If not defined, will be used `author` from Hexo main config. + copyright: + # ------------------------------------------------------------- + powered: + # Hexo link (Powered by Hexo). + enable: true + # Version info of Hexo after Hexo link (vX.X.X). + version: true + + theme: + # Theme & scheme info link (Theme - NexT.scheme). + enable: true + # Version info of NexT after scheme info (vX.X.X). + version: true + # ------------------------------------------------------------- + # Any custom text can be defined here. + #custom_text: Hosted by Coding Pages + +# --------------------------------------------------------------- +# SEO Settings +# --------------------------------------------------------------- + +# Canonical, set a canonical link tag in your hexo, you could use it for your SEO of blog. +# See: https://support.google.com/webmasters/answer/139066 +# Tips: Before you open this tag, remember set up your URL in hexo _config.yml ( ex. url: http://yourdomain.com ) +canonical: true + +# Change headers hierarchy on site-subtitle (will be main site description) and on all post/pages titles for better SEO-optimization. +seo: false + +# If true, will add site-subtitle to index page, added in main hexo config. +# subtitle: Subtitle +index_with_subtitle: false + + +# --------------------------------------------------------------- +# Menu Settings +# --------------------------------------------------------------- + +# When running the site in a subdirectory (e.g. domain.tld/blog), remove the leading slash from link value (/archives -> archives). +# Usage: `Key: /link/ || icon` +# Key is the name of menu item. If translate for this menu will find in languages - this translate will be loaded; if not - Key name will be used. Key is case-senstive. +# Value before `||` delimeter is the target link. +# Value after `||` delimeter is the name of FontAwesome icon. If icon (with or without delimeter) is not specified, question icon will be loaded. +menu: + home: / || home + #about: /about/ || user + #tags: /tags/ || tags + #categories: /categories/ || th + archives: /archives/ || archive + #schedule: /schedule/ || calendar + #sitemap: /sitemap.xml || sitemap + #commonweal: /404/ || heartbeat + +# Enable/Disable menu icons / item badges. +menu_settings: + icons: true + badges: false + +# --------------------------------------------------------------- +# Scheme Settings +# --------------------------------------------------------------- + +# Schemes +scheme: Muse +#scheme: Mist +#scheme: Pisces +#scheme: Gemini + + +# --------------------------------------------------------------- +# Sidebar Settings +# --------------------------------------------------------------- + +# Posts / Categories / Tags in sidebar. +site_state: true + +# Social Links. +# Usage: `Key: permalink || icon` +# Key is the link label showing to end users. +# Value before `||` delimeter is the target permalink. +# Value after `||` delimeter is the name of FontAwesome icon. If icon (with or without delimeter) is not specified, globe icon will be loaded. +#social: + #GitHub: https://github.com/yourname || github + #E-Mail: mailto:yourname@gmail.com || envelope + #Google: https://plus.google.com/yourname || google + #Twitter: https://twitter.com/yourname || twitter + #FB Page: https://www.facebook.com/yourname || facebook + #VK Group: https://vk.com/yourname || vk + #StackOverflow: https://stackoverflow.com/yourname || stack-overflow + #YouTube: https://youtube.com/yourname || youtube + #Instagram: https://instagram.com/yourname || instagram + #Skype: skype:yourname?call|chat || skype + +social_icons: + enable: true + icons_only: false + transition: false + # Dependencies: exturl: true in Tags Settings section below. + # To encrypt links above use https://www.base64encode.org + # Example encoded link: `GitHub: aHR0cHM6Ly9naXRodWIuY29tL3RoZW1lLW5leHQ= || github` + exturl: false + +# Follow me on GitHub banner in right-top corner. +# Usage: `permalink || title` +# Value before `||` delimeter is the target permalink. +# Value after `||` delimeter is the title and aria-label name. +#github_banner: https://github.com/yourname || Follow me on GitHub + +# Blog rolls +links_icon: link +links_title: Links +links_layout: block +#links_layout: inline +#links: + #Title: http://example.com/ + +# Sidebar Avatar +avatar: + # in theme directory(source/images): /images/avatar.gif + # in site directory(source/uploads): /uploads/avatar.gif + # You can also use other linking images. + url: #/images/avatar.gif + # If true, the avatar would be dispalyed in circle. + rounded: false + # The value of opacity should be choose from 0 to 1 to set the opacity of the avatar. + opacity: 1 + # If true, the avatar would be rotated with the cursor. + rotated: false + +# Table Of Contents in the Sidebar +toc: + enable: true + + # Automatically add list number to toc. + number: true + + # If true, all words will placed on next lines if header width longer then sidebar width. + wrap: false + +# Creative Commons 4.0 International License. +# http://creativecommons.org/ +# Available: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | zero +#creative_commons: by-nc-sa +#creative_commons: + +sidebar: + # Sidebar Position, available value: left | right (only for Pisces | Gemini). + position: left + #position: right + + # Sidebar Display, available value (only for Muse | Mist): + # - post expand on posts automatically. Default. + # - always expand for all pages automatically + # - hide expand only when click on the sidebar toggle icon. + # - remove Totally remove sidebar including sidebar toggle. + display: post + #display: always + #display: hide + #display: remove + + # Sidebar offset from top menubar in pixels (only for Pisces | Gemini). + offset: 12 + + # Back to top in sidebar (only for Pisces | Gemini). + b2t: false + + # Scroll percent label in b2t button. + scrollpercent: false + + # Enable sidebar on narrow view (only for Muse | Mist). + onmobile: false + + +# --------------------------------------------------------------- +# Post Settings +# --------------------------------------------------------------- + +# Automatically scroll page to section which is under mark. +scroll_to_more: true + +# Automatically saving scroll position on each post/page in cookies. +save_scroll: false + +# Automatically excerpt description in homepage as preamble text. +excerpt_description: true + +# Automatically Excerpt. Not recommend. +# Please use in the post to control excerpt accurately. +auto_excerpt: + enable: false + length: 150 + +# Post meta display settings +post_meta: + item_text: true + created_at: true + updated_at: + enabled: true + # If true, show updated date label only if `updated date` different from 'created date' (post edited in another day than was created). + # And if post will edited in same day as created, edited time will show in popup title under created time label. + # If false show anyway, but if post edited in same day, show only edited time. + another_day: true + categories: true + +# Post wordcount display settings +# Dependencies: https://github.com/theme-next/hexo-symbols-count-time +symbols_count_time: + separated_meta: true + item_text_post: true + item_text_total: false + awl: 4 + wpm: 275 + +codeblock: + # Manual define the border radius in codeblock + # Leave it empty for the default 1 + border_radius: + # Add copy button on codeblock + copy_button: + enable: false + # Show text copy result + show_result: false + +# Wechat Subscriber +#wechat_subscriber: + #enabled: true + #qcode: /path/to/your/wechatqcode ex. /uploads/wechat-qcode.jpg + #description: ex. subscribe to my blog by scanning my public wechat account + +# Reward +#reward_comment: Donate comment here +#wechatpay: /images/wechatpay.jpg +#alipay: /images/alipay.jpg +#bitcoin: /images/bitcoin.png + +# Related popular posts +# Dependencies: https://github.com/tea3/hexo-related-popular-posts +related_posts: + enable: false + title: # custom header, leave empty to use the default one + display_in_home: false + params: + maxCount: 5 + #PPMixingRate: 0.0 + #isDate: false + #isImage: false + #isExcerpt: false + +# Declare license on posts +post_copyright: + enable: false + license: CC BY-NC-SA 4.0 + +# Post edit +# Dependencies: https://github.com/hexojs/hexo-deployer-git +post_edit: + enable: false + url: https://github.com/theme-next/theme-next.org/_posts/tree/master/ # Link for view source. +# url: https://github.com/theme-next/theme-next.org/_posts/edit/master/ # Link for fork & edit. + + +# --------------------------------------------------------------- +# Misc Theme Settings +# --------------------------------------------------------------- + +# Reduce padding / margin indents on devices with narrow width. +mobile_layout_economy: false + +# Android Chrome header panel color ($brand-bg / $headband-bg => $black-deep). +android_chrome_color: "#222" + +# Custom Logo. +# !!Only available for Default Scheme currently. +# Options: +# enabled: [true/false] - Replace with specific image +# image: url-of-image - Images's url +custom_logo: + enabled: false + image: + +# Code Highlight theme +# Available values: normal | night | night eighties | night blue | night bright +# https://github.com/chriskempson/tomorrow-theme +highlight_theme: normal + +# Enable "cheers" for archive page. +cheers_enabled: true + +# Manual define the max content width +# !!Only available for Gemini Scheme currently +# Leave it empty for the default 75% (suggest not less than 1000px) +#max_content_width: 1000px + +# Manual define the sidebar width +# !!Only available for Gemini Scheme currently +# Leave it empty for the default 240 +sidebar_width: + +# --------------------------------------------------------------- +# Font Settings +# - Find fonts on Google Fonts (https://www.google.com/fonts) +# - All fonts set here will have the following styles: +# light, light italic, normal, normal italic, bold, bold italic +# - Be aware that setting too much fonts will cause site running slowly +# - Introduce in 5.0.1 +# --------------------------------------------------------------- +# CAUTION! Safari Version 10.1.2 bug: https://github.com/iissnan/hexo-theme-next/issues/1844 +# To avoid space between header and sidebar in Pisces / Gemini themes recommended to use Web Safe fonts for `global` (and `logo`): +# Arial | Tahoma | Helvetica | Times New Roman | Courier New | Verdana | Georgia | Palatino | Garamond | Comic Sans MS | Trebuchet MS +# --------------------------------------------------------------- +font: + enable: false + + # Uri of fonts host. E.g. //fonts.googleapis.com (Default). + host: + + # Font options: + # `external: true` will load this font family from `host` above. + # `family: Times New Roman`. Without any quotes. + # `size: xx`. Use `px` as unit. + + # Global font settings used for all elements in . + global: + external: true + family: Lato + size: + + # Font settings for Headlines (H1, H2, H3, H4, H5, H6). + # Fallback to `global` font settings. + headings: + external: true + family: + size: + + # Font settings for posts. + # Fallback to `global` font settings. + posts: + external: true + family: + + # Font settings for Logo. + # Fallback to `global` font settings. + logo: + external: true + family: + size: + + # Font settings for and code blocks.
+ codes:
+ external: true
+ family:
+ size:
+
+
+# ---------------------------------------------------------------
+# Third Party Services Settings
+# ---------------------------------------------------------------
+
+# Math Equations Render Support
+math:
+ enable: false
+
+ # Default(true) will load mathjax/katex script on demand
+ # That is it only render those page who has 'mathjax: true' in Front Matter.
+ # If you set it to false, it will load mathjax/katex srcipt EVERY PAGE.
+ per_page: true
+
+ engine: mathjax
+ #engine: katex
+
+ # hexo-rendering-pandoc (or hexo-renderer-kramed) needed to full MathJax support.
+ mathjax:
+ # Use 2.7.1 as default, jsdelivr as default CDN, works everywhere even in China
+ cdn: //cdn.jsdelivr.net/npm/mathjax@2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+ # For newMathJax CDN (cdnjs.cloudflare.com) with fallback to oldMathJax (cdn.mathjax.org).
+ #cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+ # For direct link to MathJax.js with CloudFlare CDN (cdnjs.cloudflare.com).
+ #cdn: //cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML
+ # For automatic detect latest version link to MathJax.js and get from Bootcss.
+ #cdn: //cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML
+
+ # hexo-renderer-markdown-it-plus (or hexo-renderer-markdown-it with markdown-it-katex plugin)
+ # needed to full Katex support.
+ katex:
+ # Use 0.7.1 as default, jsdelivr as default CDN, works everywhere even in China
+ cdn: //cdn.jsdelivr.net/npm/katex@0.7.1/dist/katex.min.css
+ # CDNJS, provided by cloudflare, maybe the best CDN, but not works in China
+ #cdn: //cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css
+ # Bootcss, works great in China, but not so well in other region
+ #cdn: //cdn.bootcss.com/KaTeX/0.7.1/katex.min.css
+
+# Han Support
+# Dependencies: https://github.com/theme-next/theme-next-han
+han: false
+
+# Pangu Support
+# Dependencies: https://github.com/theme-next/theme-next-pangu
+# For more information: https://github.com/vinta/pangu.js
+pangu: false
+
+# Swiftype Search API Key
+#swiftype_key:
+
+# Baidu Analytics ID
+#baidu_analytics:
+
+# Disqus
+disqus:
+ enable: false
+ shortname:
+ count: true
+ lazyload: false
+
+# Hypercomments
+#hypercomments_id:
+
+# changyan
+changyan:
+ enable: false
+ appid:
+ appkey:
+
+
+# Valine.
+# You can get your appid and appkey from https://leancloud.cn
+# more info please open https://valine.js.org
+valine:
+ enable: false
+ appid: # your leancloud application appid
+ appkey: # your leancloud application appkey
+ notify: false # mail notifier , https://github.com/xCss/Valine/wiki
+ verify: false # Verification code
+ placeholder: Just go go # comment box placeholder
+ avatar: mm # gravatar style
+ guest_info: nick,mail,link # custom comment header
+ pageSize: 10 # pagination size
+
+
+# Support for youyan comments system.
+# You can get your uid from http://www.uyan.cc
+#youyan_uid: your uid
+
+# Support for LiveRe comments system.
+# You can get your uid from https://livere.com/insight/myCode (General web site)
+#livere_uid: your uid
+
+# Gitment
+# Introduction: https://imsun.net/posts/gitment-introduction/
+gitment:
+ enable: false
+ mint: true # RECOMMEND, A mint on Gitment, to support count, language and proxy_gateway
+ count: true # Show comments count in post meta area
+ lazy: false # Comments lazy loading with a button
+ cleanly: false # Hide 'Powered by ...' on footer, and more
+ language: # Force language, or auto switch by theme
+ github_user: # MUST HAVE, Your Github Username
+ github_repo: # MUST HAVE, The name of the repo you use to store Gitment comments
+ client_id: # MUST HAVE, Github client id for the Gitment
+ client_secret: # EITHER this or proxy_gateway, Github access secret token for the Gitment
+ proxy_gateway: # Address of api proxy, See: https://github.com/aimingoo/intersect
+ redirect_protocol: # Protocol of redirect_uri with force_redirect_protocol when mint enabled
+
+# Baidu Share
+# Available value:
+# button | slide
+# Warning: Baidu Share does not support https.
+#baidushare:
+## type: button
+
+# Share
+# This plugin is more useful in China, make sure you known how to use it.
+# And you can find the use guide at official webiste: http://www.jiathis.com/.
+# Warning: JiaThis does not support https.
+#jiathis:
+ ##uid: Get this uid from http://www.jiathis.com/
+
+#add_this_id:
+
+# NeedMoreShare2
+# Dependencies: https://github.com/theme-next/theme-next-needmoreshare2
+# See: https://github.com/revir/need-more-share2
+# Also see: https://github.com/DzmVasileusky/needShareButton
+# iconStyle: default | box
+# boxForm: horizontal | vertical
+# position: top / middle / bottom + Left / Center / Right
+# networks: Weibo,Wechat,Douban,QQZone,Twitter,Linkedin,Mailto,Reddit,
+# Delicious,StumbleUpon,Pinterest,Facebook,GooglePlus,Slashdot,
+# Technorati,Posterous,Tumblr,GoogleBookmarks,Newsvine,
+# Evernote,Friendfeed,Vkontakte,Odnoklassniki,Mailru
+needmoreshare2:
+ enable: false
+ postbottom:
+ enable: false
+ options:
+ iconStyle: box
+ boxForm: horizontal
+ position: bottomCenter
+ networks: Weibo,Wechat,Douban,QQZone,Twitter,Facebook
+ float:
+ enable: false
+ options:
+ iconStyle: box
+ boxForm: horizontal
+ position: middleRight
+ networks: Weibo,Wechat,Douban,QQZone,Twitter,Facebook
+
+# Google Webmaster tools verification setting
+# See: https://www.google.com/webmasters/
+#google_site_verification:
+
+# Google Analytics
+#google_analytics:
+
+# Bing Webmaster tools verification setting
+# See: https://www.bing.com/webmaster/
+#bing_site_verification:
+
+# Yandex Webmaster tools verification setting
+# See: https://webmaster.yandex.ru/
+#yandex_site_verification:
+
+# CNZZ count
+#cnzz_siteid:
+
+# Application Insights
+# See https://azure.microsoft.com/en-us/services/application-insights/
+# application_insights:
+
+# Post widgets & FB/VK comments settings.
+# ---------------------------------------------------------------
+# Facebook SDK Support.
+# https://github.com/iissnan/hexo-theme-next/pull/410
+facebook_sdk:
+ enable: false
+ app_id: #
+ fb_admin: #
+ like_button: #true
+ webmaster: #true
+
+# Facebook comments plugin
+# This plugin depends on Facebook SDK.
+# If facebook_sdk.enable is false, Facebook comments plugin is unavailable.
+facebook_comments_plugin:
+ enable: false
+ num_of_posts: 10 # min posts num is 1
+ width: 100% # default width is 550px
+ scheme: light # default scheme is light (light or dark)
+
+# VKontakte API Support.
+# To get your AppID visit https://vk.com/editapp?act=create
+vkontakte_api:
+ enable: false
+ app_id: #
+ like: true
+ comments: true
+ num_of_posts: 10
+
+# Star rating support to each article.
+# To get your ID visit https://widgetpack.com
+rating:
+ enable: false
+ id: #
+ color: fc6423
+# ---------------------------------------------------------------
+
+# Show number of visitors to each article.
+# You can visit https://leancloud.cn get AppID and AppKey.
+leancloud_visitors:
+ enable: false
+ app_id: #
+ app_key: #
+ # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security
+ # If you don't care about security in lc counter and just want to use it directly
+ # (without hexo-leancloud-counter-security plugin), set the `security` to `false`.
+ security: true
+ betterPerformance: false
+
+# Another tool to show number of visitors to each article.
+# visit https://console.firebase.google.com/u/0/ to get apiKey and projectId
+# visit https://firebase.google.com/docs/firestore/ to get more information about firestore
+firestore:
+ enable: false
+ collection: articles #required, a string collection name to access firestore database
+ apiKey: #required
+ projectId: #required
+ bluebird: false #enable this if you want to include bluebird 3.5.1(core version) Promise polyfill
+
+# Show Views/Visitors of the website/page with busuanzi.
+# Get more information on http://ibruce.info/2015/04/04/busuanzi/
+busuanzi_count:
+ enable: false
+ total_visitors: true
+ total_visitors_icon: user
+ total_views: true
+ total_views_icon: eye
+ post_views: true
+ post_views_icon: eye
+
+
+# Tencent analytics ID
+# tencent_analytics:
+
+# Tencent MTA ID
+# tencent_mta:
+
+
+# Enable baidu push so that the blog will push the url to baidu automatically which is very helpful for SEO
+baidu_push: false
+
+# Google Calendar
+# Share your recent schedule to others via calendar page
+#
+# API Documentation:
+# https://developers.google.com/google-apps/calendar/v3/reference/events/list
+calendar:
+ enable: false
+ calendar_id:
+ api_key:
+ orderBy: startTime
+ offsetMax: 24
+ offsetMin: 4
+ timeZone:
+ showDeleted: false
+ singleEvents: true
+ maxResults: 250
+
+# Algolia Search
+# See: https://github.com/theme-next/hexo-theme-next/blob/master/docs/ALGOLIA-SEARCH.md
+# Dependencies: https://github.com/theme-next/theme-next-algolia-instant-search
+algolia_search:
+ enable: false
+ hits:
+ per_page: 10
+ labels:
+ input_placeholder: Search for Posts
+ hits_empty: "We didn't find any results for the search: ${query}"
+ hits_stats: "${hits} results found in ${time} ms"
+
+# Local search
+# Dependencies: https://github.com/theme-next/hexo-generator-searchdb
+local_search:
+ enable: false
+ # if auto, trigger search by changing input
+ # if manual, trigger search by pressing enter key or search button
+ trigger: auto
+ # show top n results per article, show all results by setting to -1
+ top_n_per_article: 1
+ # unescape html strings to the readable one
+ unescape: false
+
+# Bookmark Support
+# Dependencies: https://github.com/theme-next/theme-next-bookmark
+bookmark:
+ enable: false
+ # if auto
+ # - save the reading position when closing the page
+ # - or clicking the bookmark-icon
+ # if manual, only save it by clicking the bookmark-icon
+ save: auto
+
+
+# ---------------------------------------------------------------
+# Tags Settings
+# ---------------------------------------------------------------
+
+# External URL with BASE64 encrypt & decrypt.
+# Usage: {% exturl text url "title" %}
+# Alias: {% extlink text url "title" %}
+exturl: false
+
+# Note tag (bs-callout).
+note:
+ # Note tag style values:
+ # - simple bs-callout old alert style. Default.
+ # - modern bs-callout new (v2-v3) alert style.
+ # - flat flat callout style with background, like on Mozilla or StackOverflow.
+ # - disabled disable all CSS styles import of note tag.
+ style: simple
+ icons: false
+ border_radius: 3
+ # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6).
+ # Offset also applied to label tag variables. This option can work with disabled note tag.
+ light_bg_offset: 0
+
+# Label tag.
+label: true
+
+# Tabs tag.
+tabs:
+ enable: true
+ transition:
+ tabs: false
+ labels: true
+ border_radius: 0
+
+# Reading progress bar
+# Dependencies: https://github.com/theme-next/theme-next-reading-progress
+reading_progress:
+ enable: false
+ color: "#37c6c0"
+ height: 2px
+
+
+#! ---------------------------------------------------------------
+#! DO NOT EDIT THE FOLLOWING SETTINGS
+#! UNLESS YOU KNOW WHAT YOU ARE DOING
+#! ---------------------------------------------------------------
+
+# Use velocity to animate everything.
+motion:
+ enable: true
+ async: false
+ transition:
+ # Transition variants:
+ # fadeIn | fadeOut | flipXIn | flipXOut | flipYIn | flipYOut | flipBounceXIn | flipBounceXOut | flipBounceYIn | flipBounceYOut
+ # swoopIn | swoopOut | whirlIn | whirlOut | shrinkIn | shrinkOut | expandIn | expandOut
+ # bounceIn | bounceOut | bounceUpIn | bounceUpOut | bounceDownIn | bounceDownOut | bounceLeftIn | bounceLeftOut | bounceRightIn | bounceRightOut
+ # slideUpIn | slideUpOut | slideDownIn | slideDownOut | slideLeftIn | slideLeftOut | slideRightIn | slideRightOut
+ # slideUpBigIn | slideUpBigOut | slideDownBigIn | slideDownBigOut | slideLeftBigIn | slideLeftBigOut | slideRightBigIn | slideRightBigOut
+ # perspectiveUpIn | perspectiveUpOut | perspectiveDownIn | perspectiveDownOut | perspectiveLeftIn | perspectiveLeftOut | perspectiveRightIn | perspectiveRightOut
+ post_block: fadeIn
+ post_header: slideDownIn
+ post_body: slideDownIn
+ coll_header: slideLeftIn
+ # Only for Pisces | Gemini.
+ sidebar: slideUpIn
+
+# Fancybox. There is support for old version 2 and new version 3.
+# Please, choose only any one variant, do not need to install both.
+# For install 2.x: https://github.com/theme-next/theme-next-fancybox
+# For install 3.x: https://github.com/theme-next/theme-next-fancybox3
+fancybox: false
+
+# Added switch option for separated repo in 6.0.0.
+# Dependencies: https://github.com/theme-next/theme-next-fastclick
+fastclick: false
+
+# Added switch option for separated repo in 6.0.0.
+# Dependencies: https://github.com/theme-next/theme-next-jquery-lazyload
+lazyload: false
+
+# Progress bar in the top during page loading.
+# Dependencies: https://github.com/theme-next/theme-next-pace
+pace: false
+# Themes list:
+#pace-theme-big-counter
+#pace-theme-bounce
+#pace-theme-barber-shop
+#pace-theme-center-atom
+#pace-theme-center-circle
+#pace-theme-center-radar
+#pace-theme-center-simple
+#pace-theme-corner-indicator
+#pace-theme-fill-left
+#pace-theme-flash
+#pace-theme-loading-bar
+#pace-theme-mac-osx
+#pace-theme-minimal
+# For example
+# pace_theme: pace-theme-center-simple
+pace_theme: pace-theme-minimal
+
+# Canvas-nest
+# Dependencies: https://github.com/theme-next/theme-next-canvas-nest
+canvas_nest: false
+
+# JavaScript 3D library.
+# Dependencies: https://github.com/theme-next/theme-next-three
+# three_waves
+three_waves: false
+# canvas_lines
+canvas_lines: false
+# canvas_sphere
+canvas_sphere: false
+
+# Only fit scheme Pisces
+# Dependencies: https://github.com/theme-next/theme-next-canvas-ribbon
+# Canvas-ribbon
+# size: The width of the ribbon.
+# alpha: The transparency of the ribbon.
+# zIndex: The display level of the ribbon.
+canvas_ribbon:
+ enable: false
+ size: 300
+ alpha: 0.6
+ zIndex: -1
+
+# Script Vendors.
+# Set a CDN address for the vendor you want to customize.
+# For example
+# jquery: https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js
+# Be aware that you should use the same version as internal ones to avoid potential problems.
+# Please use the https protocol of CDN files when you enable https on your site.
+vendors:
+ # Internal path prefix. Please do not edit it.
+ _internal: lib
+
+ # Internal version: 2.1.3
+ jquery:
+
+ # Internal version: 2.1.5
+ # See: http://fancyapps.com/fancybox/
+ fancybox:
+ fancybox_css:
+
+ # Internal version: 1.0.6
+ # See: https://github.com/ftlabs/fastclick
+ fastclick:
+
+ # Internal version: 1.9.7
+ # See: https://github.com/tuupola/jquery_lazyload
+ lazyload:
+
+ # Internal version: 1.2.1
+ # See: http://VelocityJS.org
+ velocity:
+
+ # Internal version: 1.2.1
+ # See: http://VelocityJS.org
+ velocity_ui:
+
+ # Internal version: 0.7.9
+ # See: https://faisalman.github.io/ua-parser-js/
+ ua_parser:
+
+ # Internal version: 4.6.2
+ # See: http://fontawesome.io/
+ fontawesome:
+
+ # Internal version: 1
+ # https://www.algolia.com
+ algolia_instant_js:
+ algolia_instant_css:
+
+ # Internal version: 1.0.2
+ # See: https://github.com/HubSpot/pace
+ # Or use direct links below:
+ # pace: //cdn.bootcss.com/pace/1.0.2/pace.min.js
+ # pace_css: //cdn.bootcss.com/pace/1.0.2/themes/blue/pace-theme-flash.min.css
+ pace:
+ pace_css:
+
+ # Internal version: 1.0.0
+ # https://github.com/hustcc/canvas-nest.js
+ canvas_nest:
+
+ # three
+ three:
+
+ # three_waves
+ # https://github.com/jjandxa/three_waves
+ three_waves:
+
+ # three_waves
+ # https://github.com/jjandxa/canvas_lines
+ canvas_lines:
+
+ # three_waves
+ # https://github.com/jjandxa/canvas_sphere
+ canvas_sphere:
+
+ # Internal version: 1.0.0
+ # https://github.com/zproo/canvas-ribbon
+ canvas_ribbon:
+
+ # Internal version: 3.3.0
+ # https://github.com/ethantw/Han
+ Han:
+
+ # Internal version: 3.3.0
+ # https://github.com/vinta/pangu.js
+ pangu:
+
+ # needMoreShare2
+ # https://github.com/revir/need-more-share2
+ needmoreshare2_js:
+ needmoreshare2_css:
+
+ # bookmark
+ # Internal version: 1.0.0
+ # https://github.com/theme-next/theme-next-bookmark
+ bookmark:
+
+ # reading_progress
+ # Internal version: 1.0
+ # https://github.com/theme-next/theme-next-reading-progress
+ # Example: https://cdn.jsdelivr.net/gh/theme-next/theme-next-reading-progress@1.1/reading_progress.min.js
+ reading_progress:
+
+ # valine comment
+ # Example: https://cdn.jsdelivr.net/npm/valine@1.1.8/dist/Valine.min.js
+ valine:
+
+
+# Assets
+css: css
+js: js
+images: images
diff --git a/bower.json b/bower.json
new file mode 100644
index 000000000..0354dc066
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,31 @@
+{
+ "name": "theme-next",
+ "version": "6.3.0",
+ "homepage": "https://theme-next.org",
+ "authors": [
+ "NexT (https://theme-next.org)"
+ ],
+ "description": "Elegant theme for Hexo",
+ "repository": "https://github.com/theme-next/hexo-theme-next",
+ "keywords": [
+ "hexo",
+ "theme",
+ "next"
+ ],
+ "license": "AGPL",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "source/lib",
+ "test",
+ "tests",
+ "screenshots"
+ ],
+ "dependencies": {
+ "font-awesome": "fontawesome#*",
+ "jquery": "http://code.jquery.com/jquery-2.1.3.min.js",
+ "ua-parser-js": "~0.7.9",
+ "velocity": "~1.2.1"
+ }
+}
diff --git a/crowdin.yml b/crowdin.yml
new file mode 100644
index 000000000..be97306a8
--- /dev/null
+++ b/crowdin.yml
@@ -0,0 +1,9 @@
+files:
+ - source: /languages/en.yml
+ translation: /languages/%two_letters_code%.%file_extension%
+ languages_mapping:
+ two_letters_code:
+ zh-CN: zh-CN
+ zh-TW: zh-TW
+ zh-HK: zh-HK
+ pt-BR: pt-BR
diff --git a/docs/AGPL3.md b/docs/AGPL3.md
new file mode 100644
index 000000000..2dcf18c88
--- /dev/null
+++ b/docs/AGPL3.md
@@ -0,0 +1,649 @@
+# GNU Affero General Public License
+
+Version 3, 19 November 2007 Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+## Preamble
+
+The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+Developers that use our General Public Licenses protect your rights
+with two steps: **(1)** assert copyright on the software, and **(2)** offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+## TERMS AND CONDITIONS
+
+### 0. Definitions
+
+“This License” refers to version 3 of the GNU Affero General Public License.
+
+“Copyright” also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+“The Program” refers to any copyrightable work licensed under this
+License. Each licensee is addressed as “you”. “Licensees” and
+“recipients” may be individuals or organizations.
+
+To “modify” a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a “modified version” of the
+earlier work or a work “based on” the earlier work.
+
+A “covered work” means either the unmodified Program or a work based
+on the Program.
+
+To “propagate” a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To “convey” a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+An interactive user interface displays “Appropriate Legal Notices”
+to the extent that it includes a convenient and prominently visible
+feature that **(1)** displays an appropriate copyright notice, and **(2)**
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+### 1. Source Code
+
+The “source code” for a work means the preferred form of the work
+for making modifications to it. “Object code” means any non-source
+form of a work.
+
+A “Standard Interface” means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The “System Libraries” of an executable work include anything, other
+than the work as a whole, that **(a)** is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and **(b)** serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+“Major Component”, in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The “Corresponding Source” for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+The Corresponding Source for a work in source code form is that
+same work.
+
+### 2. Basic Permissions
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+### 3. Protecting Users' Legal Rights From Anti-Circumvention Law
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+### 4. Conveying Verbatim Copies
+
+You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+### 5. Conveying Modified Source Versions
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+* **a)** The work must carry prominent notices stating that you modified
+it, and giving a relevant date.
+* **b)** The work must carry prominent notices stating that it is
+released under this License and any conditions added under section 7.
+This requirement modifies the requirement in section 4 to
+“keep intact all notices”.
+* **c)** You must license the entire work, as a whole, under this
+License to anyone who comes into possession of a copy. This
+License will therefore apply, along with any applicable section 7
+additional terms, to the whole of the work, and all its parts,
+regardless of how they are packaged. This License gives no
+permission to license the work in any other way, but it does not
+invalidate such permission if you have separately received it.
+* **d)** If the work has interactive user interfaces, each must display
+Appropriate Legal Notices; however, if the Program has interactive
+interfaces that do not display Appropriate Legal Notices, your
+work need not make them do so.
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+“aggregate” if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+### 6. Conveying Non-Source Forms
+
+You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+* **a)** Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by the
+Corresponding Source fixed on a durable physical medium
+customarily used for software interchange.
+* **b)** Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by a
+written offer, valid for at least three years and valid for as
+long as you offer spare parts or customer support for that product
+model, to give anyone who possesses the object code either **(1)** a
+copy of the Corresponding Source for all the software in the
+product that is covered by this License, on a durable physical
+medium customarily used for software interchange, for a price no
+more than your reasonable cost of physically performing this
+conveying of source, or **(2)** access to copy the
+Corresponding Source from a network server at no charge.
+* **c)** Convey individual copies of the object code with a copy of the
+written offer to provide the Corresponding Source. This
+alternative is allowed only occasionally and noncommercially, and
+only if you received the object code with such an offer, in accord
+with subsection 6b.
+* **d)** Convey the object code by offering access from a designated
+place (gratis or for a charge), and offer equivalent access to the
+Corresponding Source in the same way through the same place at no
+further charge. You need not require recipients to copy the
+Corresponding Source along with the object code. If the place to
+copy the object code is a network server, the Corresponding Source
+may be on a different server (operated by you or a third party)
+that supports equivalent copying facilities, provided you maintain
+clear directions next to the object code saying where to find the
+Corresponding Source. Regardless of what server hosts the
+Corresponding Source, you remain obligated to ensure that it is
+available for as long as needed to satisfy these requirements.
+* **e)** Convey the object code using peer-to-peer transmission, provided
+you inform other peers where the object code and Corresponding
+Source of the work are being offered to the general public at no
+charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A “User Product” is either **(1)** a “consumer product”, which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or **(2)** anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, “normally used” refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+“Installation Information” for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+### 7. Additional Terms
+
+“Additional permissions” are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+* **a)** Disclaiming warranty or limiting liability differently from the
+terms of sections 15 and 16 of this License; or
+* **b)** Requiring preservation of specified reasonable legal notices or
+author attributions in that material or in the Appropriate Legal
+Notices displayed by works containing it; or
+* **c)** Prohibiting misrepresentation of the origin of that material, or
+requiring that modified versions of such material be marked in
+reasonable ways as different from the original version; or
+* **d)** Limiting the use for publicity purposes of names of licensors or
+authors of the material; or
+* **e)** Declining to grant rights under trademark law for use of some
+trade names, trademarks, or service marks; or
+* **f)** Requiring indemnification of licensors and authors of that
+material by anyone who conveys the material (or modified versions of
+it) with contractual assumptions of liability to the recipient, for
+any liability that these contractual assumptions directly impose on
+those licensors and authors.
+
+All other non-permissive additional terms are considered “further
+restrictions” within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+### 8. Termination
+
+You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated **(a)**
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and **(b)** permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+### 9. Acceptance Not Required for Having Copies
+
+You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+### 10. Automatic Licensing of Downstream Recipients
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+An “entity transaction” is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+### 11. Patents
+
+A “contributor” is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's “contributor version”.
+
+A contributor's “essential patent claims” are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, “control” includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a “patent license” is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To “grant” such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either **(1)** cause the Corresponding Source to be so
+available, or **(2)** arrange to deprive yourself of the benefit of the
+patent license for this particular work, or **(3)** arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. “Knowingly relying” means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is “discriminatory” if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license **(a)** in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or **(b)** primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+### 12. No Surrender of Others' Freedom
+
+If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+### 13. Remote Network Interaction; Use with the GNU General Public License
+
+Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+### 14. Revised Versions of this License
+
+The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License “or any later version” applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+### 15. Disclaimer of Warranty
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+### 16. Limitation of Liability
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+### 17. Interpretation of Sections 15 and 16
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+## END OF TERMS AND CONDITIONS
+
+### How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the “copyright” line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a “Source” link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+You should also get your employer (if you work as a programmer) or school,
+if any, to sign a “copyright disclaimer” for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+< >.
\ No newline at end of file
diff --git a/docs/ALGOLIA-SEARCH.md b/docs/ALGOLIA-SEARCH.md
new file mode 100644
index 000000000..46d1a3997
--- /dev/null
+++ b/docs/ALGOLIA-SEARCH.md
@@ -0,0 +1,87 @@
+Algolia Search
+
+
+NexT provides Algolia search plugin for index your hexo website content. To use this feature, make sure that the version of NexT you are using is after the v5.1.0 release. What you should note here is that only turn on `enable` of `algolia_search` in `next/_config.yml` cannot let you use the algolia search correctly, you need to install corresponding [Hexo Algolia](https://github.com/oncletom/hexo-algolia) plugin to seach your website with Algolia. Follow the steps described below to complete the installation of Algolia search.
+
+1. Register at [Algolia](https://www.algolia.com/), you can log in directly using GitHub or Google Account. Upon Customer’s initial sign-up for an Account, Customer will have a free, fourteen (14) day evaluation period (the “Evaluation Period”) for the Algolia Services commencing on the Effective Date, subject to the limitations on Algolia’s website. After that, Algolia offers a free, branded version for up to 10k records and 100k operations per month.
+
+1. If a tutorial pops up, you can skip it. Go straight to create an `Index` which will be used later.
+
+ ![](http://theme-next.iissnan.com/uploads/algolia/algolia-step-2.png)
+
+1. Algolia requires users to upload their search index data either manually or via provided APIs. Install and configure [Hexo Algolia](https://github.com/oncletom/hexo-algolia) in your Hexo directory. This plugin will index your site and upload selected data to Algolia.
+
+ ```
+ $ cd hexo
+ $ npm install --save hexo-algolia
+ ```
+
+1. Go to the `API Keys` page and find your credentials. You will need the `Application ID` and the `Search-only API key` in the following sections. The `Admin API key` need to keep confidential. Never store your Admin API Key as apiKey in the` _config.yml` file: it would give full control of your Algolia index to others and you don't want to face the consequences.
+
+ ![](https://user-images.githubusercontent.com/8521181/35479066-64e35aec-0428-11e8-91f9-1ec3afa45c5c.png)
+
+1. In the `API Keys` page, click the `ALL API KEYS` and the `edit` option in the created APIKEY to activate a pop-up box where you can setup authorizations and restrictions with a great level of precision. Check `Add records`, `Delete records`, `List indices`, `Delete index` features in ACL permissions that will be allowed for the given API key. And then click the `Update` button.
+
+ ![](https://user-images.githubusercontent.com/8521181/35479064-611aa0b4-0428-11e8-85a1-cfb449b486ec.png)
+ ![](https://user-images.githubusercontent.com/8521181/35479084-d4f7ac02-0428-11e8-95a6-c4e3b1bef47b.png)
+
+1. In your site's `_config.yml`, add the following configuration and replace the `applicationID` & `apiKey` & `indexName` with corresponding fields obtained at Algolia.
+
+ ```yml
+ algolia:
+ applicationID: 'Application ID'
+ apiKey: 'Search-only API key'
+ indexName: 'indexName'
+ chunkSize: 5000
+ ```
+
+1. Run the following command to upload index data, keep a weather eye out the output of the command.
+
+ ```
+ $ export HEXO_ALGOLIA_INDEXING_KEY=Search-Only API key # Use Git Bash
+ # set HEXO_ALGOLIA_INDEXING_KEY=Search-Only API key # Use Windows command line
+ $ hexo clean
+ $ hexo algolia
+ ```
+
+ ![](http://theme-next.iissnan.com/uploads/algolia/algolia-step-4.png)
+
+1. Change dir to NexT directory, and install module to `source/lib` directory.
+
+ ```
+ $ cd themes/next
+ $ git clone https://github.com/theme-next/theme-next-algolia-instant-search source/lib/algolia-instant-search
+ ```
+
+ If you want to use the CDN instead of clone this repo, then need to **set vendors** in NexT `_config.yml` file:
+ ```yml
+ vendors:
+ ...
+ # Internal version: 1
+ # https://www.algolia.com
+ algolia_instant_js: https://cdn.jsdelivr.net/npm/instantsearch.js@2.4.1/dist/instantsearch.js
+ algolia_instant_css: https://cdn.jsdelivr.net/npm/instantsearch.js@2.4.1/dist/instantsearch.min.css
+ ...
+ ```
+
+1. In `next/_config.yml`, turn on `enable` of `algolia_search`. At the same time, you need to **turn off other search plugins** like Local Search. You can also adjust the text in `labels` according to your needs.
+
+ ```yml
+ # Algolia Search
+ algolia_search:
+ enable: true
+ hits:
+ per_page: 10
+ labels:
+ input_placeholder: Search for Posts
+ hits_empty: "We didn't find any results for the search: ${query}"
+ hits_stats: "${hits} results found in ${time} ms"
+ ```
+
+Known Issues
+
+1. The latest version of the [Hexo-Algolia](https://github.com/oncletom/hexo-algolia) plugin removes the content indexing feature, given Algolia's free account limitation.
+
+1. The [Hexo-Algoliasearch](https://github.com/LouisBarranqueiro/hexo-algoliasearch) plugin provides content indexing functionality, but requires the replacement of keywords in the NEXT theme. The same problem exists with `Record Too Big` for Algolia's free account.
+ - Replace all `applicationID` in `source/js/src/algolia-search.js` with `appId`
+ - Replace all `applicationID` in `layout/_partials/head/head.swig` with `appId`
diff --git a/docs/AUTHORS.md b/docs/AUTHORS.md
new file mode 100644
index 000000000..f54eef7bb
--- /dev/null
+++ b/docs/AUTHORS.md
@@ -0,0 +1,87 @@
+# «NexT» Authors
+
+NexT theme was initially developed by:
+
+- **IIssNaN**: [NexT](https://github.com/iissnan/hexo-theme-next) (2014 - 2017)
+
+With collaborators from initially repository:
+
+- **Ivan.Nginx**: [DIFF highlight](https://github.com/iissnan/hexo-theme-next/pull/1079),
+ [HyperComments](https://github.com/iissnan/hexo-theme-next/pull/1155),
+ [`{% note %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1160),
+ [`seo` option](https://github.com/iissnan/hexo-theme-next/pull/1311),
+ [`{% button %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1328),
+ [VK API](https://github.com/iissnan/hexo-theme-next/pull/1381),
+ [WordCount plugin support](https://github.com/iissnan/hexo-theme-next/pull/1381),
+ [Yandex verification option](https://github.com/iissnan/hexo-theme-next/pull/1381),
+ [`{% exturl %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1438),
+ [`b2t` option](https://github.com/iissnan/hexo-theme-next/pull/1438),
+ [`scrollpercent` option](https://github.com/iissnan/hexo-theme-next/pull/1438),
+ [`save_scroll` option](https://github.com/iissnan/hexo-theme-next/pull/1574),
+ [Star rating](https://github.com/iissnan/hexo-theme-next/pull/1649),
+ [`mobile_layout_economy` option](https://github.com/iissnan/hexo-theme-next/pull/1697),
+ [`{% tabs %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1697),
+ [`{% label %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1697),
+ [**`Gemini`** scheme](https://github.com/iissnan/hexo-theme-next/pull/1697),
+ [Menu & Sidebar icons in 1 line](https://github.com/iissnan/hexo-theme-next/pull/1830),
+ [Sidebar scrollable](https://github.com/iissnan/hexo-theme-next/pull/1898),
+ [Responsive favicons](https://github.com/iissnan/hexo-theme-next/pull/1898)
+ and many other [PR's with fixes and enhancements](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aivan-nginx)
+- **Acris**: [Many PR's with fixes and updates](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3AAcris)
+
+And best contributors from initially repository:
+
+- **Rainy**: [Gentie comments](https://github.com/iissnan/hexo-theme-next/pull/1301),
+ [Han](https://github.com/iissnan/hexo-theme-next/pull/1598)
+ and many [PR's with fixes and optimizations](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Ageekrainy)
+- **Jeff**: [Local search](https://github.com/iissnan/hexo-theme-next/pull/694)
+ and many [PR's with fixes and improvements](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aflashlab)
+- **Haocen**: [Footer enhancements](https://github.com/iissnan/hexo-theme-next/pull/1886)
+ and some other [PR's with improvements](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3AHaocen)
+- **uchuhimo**: [Greatest enhancements for local search](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Auchuhimo)
+- **Kei**: [Change static file setting to support subdirectory](https://github.com/iissnan/hexo-theme-next/pull/4)
+- **Jolyon**: [Swiftype](https://github.com/iissnan/hexo-theme-next/pull/84)
+- **xirong**: [404 page](https://github.com/iissnan/hexo-theme-next/pull/126)
+- **PinkyJie**: [Fix Swiftype](https://github.com/iissnan/hexo-theme-next/pull/132)
+- **Tim Kuijsten**: [Split javascript into separate files](https://github.com/iissnan/hexo-theme-next/pull/152)
+- **iamwent**: [Friendly links](https://github.com/iissnan/hexo-theme-next/pull/250)
+- **arao lin**: [Option to lazyload images](https://github.com/iissnan/hexo-theme-next/pull/269)
+- **Konstantin Pavlov**: [Microdata, opengraph and other semantic features](https://github.com/iissnan/hexo-theme-next/pull/276)
+- **Gary**: [FastClick](https://github.com/iissnan/hexo-theme-next/pull/324)
+- **Octavian**: [Baidu site vertification](https://github.com/iissnan/hexo-theme-next/pull/367)
+- **Henry Chang**: [Facebook SDK](https://github.com/iissnan/hexo-theme-next/pull/410)
+- **XiaMo**: [LeanCloud visitors](https://github.com/iissnan/hexo-theme-next/pull/439)
+- **iblogc**: [Fix UA in Duoshuo](https://github.com/iissnan/hexo-theme-next/pull/489)
+- **Vincent**: [Automatic headline ID's](https://github.com/iissnan/hexo-theme-next/pull/588)
+- **cissoid**: [Tencent analytics](https://github.com/iissnan/hexo-theme-next/pull/603)
+- **CosmoX**: [AddThis](https://github.com/iissnan/hexo-theme-next/pull/660)
+- **Jason Guo**: [Reward for post](https://github.com/iissnan/hexo-theme-next/pull/687)
+- **Jerry Bendy**: [CNZZ counter](https://github.com/iissnan/hexo-theme-next/pull/712)
+- **Hui Wang**: [Wechat subscriber](https://github.com/iissnan/hexo-theme-next/pull/788)
+- **PoonChiTim**: [Busuanzi counter](https://github.com/iissnan/hexo-theme-next/pull/809)
+- **hydai**: [Facebook comments](https://github.com/iissnan/hexo-theme-next/pull/925)
+- **OAwan**: [`canonical` option](https://github.com/iissnan/hexo-theme-next/pull/931)
+- **Jim Zenn**: [Google Calendar](https://github.com/iissnan/hexo-theme-next/pull/1167)
+- **Abner Chou**: [Disqus improvements](https://github.com/iissnan/hexo-theme-next/pull/1173)
+- **Igor Fesenko**: [Application Insights](https://github.com/iissnan/hexo-theme-next/pull/1257)
+- **jinfang**: [Youyan comments](https://github.com/iissnan/hexo-theme-next/pull/1324)
+- **AlynxZhou**: [`canvas_nest` option](https://github.com/iissnan/hexo-theme-next/pull/1327)
+- **aleon**: [Tencent MTA](https://github.com/iissnan/hexo-theme-next/pull/1408)
+- **asmoker**: [LiveRe comments](https://github.com/iissnan/hexo-theme-next/pull/1415)
+- **Jacksgong**: [Copyright on posts](https://github.com/iissnan/hexo-theme-next/pull/1497)
+- **zhaiqianfeng**: [Changyan comments](https://github.com/iissnan/hexo-theme-next/pull/1514)
+- **zproo**: [`canvas_ribbon` option](https://github.com/iissnan/hexo-theme-next/pull/1565)
+- **jjandxa**: [`three_waves`](https://github.com/iissnan/hexo-theme-next/pull/1534),
+ [`canvas_lines` and `canvas_sphere`](https://github.com/iissnan/hexo-theme-next/pull/1595) options
+- **shenzekun**: [Load bar at the top](https://github.com/iissnan/hexo-theme-next/pull/1689)
+- **elkan1788**: [Upgrade jiathis share](https://github.com/iissnan/hexo-theme-next/pull/1796)
+- **xCss**: [Valine comment system support](https://github.com/iissnan/hexo-theme-next/pull/1811)
+- **Julian Xhokaxhiu**: [`override` option](https://github.com/iissnan/hexo-theme-next/pull/1861)
+- **LEAFERx**: [NeedMoreShare2](https://github.com/iissnan/hexo-theme-next/pull/1913)
+- **aimingoo & LEAFERx**: [Gitment supported with Mint](https://github.com/iissnan/hexo-theme-next/pull/1919)
+- **LeviDing**: [Fix the bug of Gitment](https://github.com/iissnan/hexo-theme-next/pull/1944)
+- **maple3142**: [Firestore visitor counter](https://github.com/iissnan/hexo-theme-next/pull/1978)
+
+It lives on as an open source project with many contributors, a self updating list is [here](https://github.com/theme-next/hexo-theme-next/graphs/contributors).
+
+P.S. If you was do some useful pulls/commits in original repository and you are not in list, let me know and you will be added here.
diff --git a/docs/DATA-FILES.md b/docs/DATA-FILES.md
new file mode 100644
index 000000000..bdf8ab002
--- /dev/null
+++ b/docs/DATA-FILES.md
@@ -0,0 +1,61 @@
+Data Files
+
+Currently, it is not smooth to update NexT theme from pulling or downloading new releases. It is quite often running into conflict status when updating NexT theme via `git pull`, or need to merge configurations manually when upgrading to new releases.
+
+ At present, NexT encourages users to store some options in site's `_config.yml` and other options in theme's `_config.yml`. This approach is applicable, but has some drawbacks:
+1. Configurations are splitted into two pieces
+2. Users may be confused which place should be for options
+
+In order to resolve this issue, NexT will take advantage of Hexo [Data files](https://hexo.io/docs/data-files.html). Because Data files is introduced in Hexo 3, so you need upgrade Hexo to 3.0 (or above) to use this feature.
+
+If you prefer Hexo 2.x, you can still use the old approach for configurations. NexT is still compatible with Hexo 2.x (but errors are possible).
+
+Option 1: Hexo-Way
+
+With this way, all your configurations locate in main hexo config file (`hexo/_config.yml`), you don't need to touch `next/_config.yml` or create any new files. But you must preserve double spaces indents within `theme_config` option.
+
+If there are any new options in new releases, you just need to copy those options from `next/_config.yml`, paste into `hexo/_config.yml` and set their values to whatever you want.
+
+### Usage
+
+1. Check for no exists `hexo/source/_data/next.yml` file (delete it if exists).
+2. Copy needed NexT theme options from theme's `next/_config.yml` into `hexo/_config.yml`, then\
+ 2.1. Move all this settings to the right with two spaces (in Visual Studio Code: select all strings, CTRL + ]).\
+ 2.2. Add `theme_config:` parameter above all this settings.
+
+### Useful links
+
+* [Hexo Configuration](https://hexo.io/docs/configuration.html)
+* [Hexo Pull #757](https://github.com/hexojs/hexo/pull/757)
+
+Option 2: NexT-Way
+
+With this way, you can put all your configurations into one place (`source/_data/next.yml`), you don't need to touch `next/_config.yml`.
+But option may not accurately procces all hexo external libraries with their additional options (for example, `hexo-server` module options may be readed only in default hexo config).
+
+If there are any new options in new releases, you just need to copy those options from `next/_config.yml`, paste into `_data/next.yml` and set their values to whatever you want.
+
+### Usage
+
+1. Please ensure you are using Hexo 3 (or above).
+2. Create an file named `next.yml` in site's `hexo/source/_data` directory (create `_data` directory if it did not exists).
+
+And after that steps there are 2 variants, need to choose only one of them and resume next steps.
+
+* **Variant 1: `override: false` (default)**:
+
+ 1. Check your `override` option in default NexT config, it must set on `false`.\
+ In `next.yml` it must not be defined or set on `false` too.
+ 2. Copy needed options from both site's `_config.yml` and theme's `_config.yml` into `hexo/source/_data/next.yml`.
+
+* **Variant 2: `override: true`**:
+
+ 1. In `next.yml` set `override` option on `true`.
+ 2. Copy **all** NexT theme options from theme's `next/_config.yml` into `hexo/source/_data/next.yml`.
+
+3. Then, in main site's `hexo/_config.yml` need to define `theme: next` option (and if needed, `source_dir: source`).
+4. Use standart parameters to start server, generate or deploy (`hexo clean && hexo g -d && hexo s`).
+
+### Useful links
+
+* [NexT Issue #328](https://github.com/iissnan/hexo-theme-next/issues/328)
diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md
new file mode 100644
index 000000000..3f229994d
--- /dev/null
+++ b/docs/INSTALLATION.md
@@ -0,0 +1,120 @@
+Installation
+
+Step 1 → Go to Hexo dir
+
+Change dir to **hexo root** directory. There must be `node_modules`, `source`, `themes` and other directories:
+ ```sh
+ $ cd hexo
+ $ ls
+ _config.yml node_modules package.json public scaffolds source themes
+ ```
+
+Step 2 → Get NexT
+
+Download theme from GitHub.
+There are 3 options to do it, need to choose only one of them.
+
+### Option 1: Download [latest release version][releases-latest-url]
+
+ At most cases **stable**. Recommended for beginners.
+
+ * Install with [curl & tar & wget][curl-tar-wget-url]:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -s https://api.github.com/repos/theme-next/hexo-theme-next/releases/latest | grep tarball_url | cut -d '"' -f 4 | wget -i - -O- | tar -zx -C themes/next --strip-components=1
+ ```
+ This variant will give to you **only latest release version** (without `.git` directory inside).\
+ So, there is impossible to update this version with `git` later.\
+ Instead you always can use separate configuration (e.g. [data-files][docs-data-files-url]) and download new version inside old directory (or create new directory and redefine `theme` in Hexo config), without losing your old configuration.
+
+### Option 2: Download [tagged release version][releases-url]
+
+ In rare cases useful, but not recommended.\
+ You must define version. Replace `v6.0.0` with any version from [tags list][tags-url].
+
+ * Variant 1: Install with [curl & tar][curl-tar-url]:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -L https://api.github.com/repos/theme-next/hexo-theme-next/tarball/v6.0.0 | tar -zxv -C themes/next --strip-components=1
+ ```
+ Same as above under `curl & tar & wget` variant, but will download **only concrete version**.
+
+ * Variant 2: Install with [git][git-url]:
+
+ ```sh
+ $ git clone --branch v6.0.0 https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+ This variant will give to you the **defined release version** (with `.git` directory inside).\
+ And in any time you can switch to any tagged release, but with limit to defined version.
+
+### Option 3: Download [latest master branch][download-latest-url]
+
+ May be **unstable**, but includes latest features. Recommended for advanced users and for developers.
+
+ * Variant 1: Install with [curl & tar][curl-tar-url]:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -L https://api.github.com/repos/theme-next/hexo-theme-next/tarball | tar -zxv -C themes/next --strip-components=1
+ ```
+ Same as above under `curl & tar & wget` variant, but will download **only latest master branch version**.\
+ At some cases useful for developers.
+
+ * Variant 2: Install with [git][git-url]:
+
+ ```sh
+ $ git clone https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+
+ This variant will give to you the **whole repository** (with `.git` directory inside).\
+ And in any time you can [update current version with git][update-with-git-url] and switch to any tagged release or on latest master or any other branch.\
+ At most cases useful as for users and for developers.
+
+ Get tags list:
+
+ ```sh
+ $ cd themes/next
+ $ git tag -l
+ …
+ v6.0.0
+ v6.0.1
+ v6.0.2
+ ```
+
+ For example, you want to switch on `v6.0.1` [tagged release version][tags-url]. Input the following command:
+
+ ```sh
+ $ git checkout tags/v6.0.1
+ Note: checking out 'tags/v6.0.1'.
+ …
+ HEAD is now at da9cdd2... Release v6.0.1
+ ```
+
+ And if you want to switch back on [master branch][commits-url], input this command:
+
+ ```sh
+ $ git checkout master
+ ```
+
+Step 3 → Set it up
+
+Set theme in main **hexo root config** `_config.yml` file:
+
+```yml
+theme: next
+```
+
+[download-latest-url]: https://github.com/theme-next/hexo-theme-next/archive/master.zip
+[releases-latest-url]: https://github.com/theme-next/hexo-theme-next/releases/latest
+[releases-url]: https://github.com/theme-next/hexo-theme-next/releases
+[tags-url]: https://github.com/theme-next/hexo-theme-next/tags
+[commits-url]: https://github.com/theme-next/hexo-theme-next/commits/master
+
+[git-url]: http://lmgtfy.com/?q=linux+git+install
+[curl-tar-url]: http://lmgtfy.com/?q=linux+curl+tar+install
+[curl-tar-wget-url]: http://lmgtfy.com/?q=linux+curl+tar+wget+install
+
+[update-with-git-url]: https://github.com/theme-next/hexo-theme-next/blob/master/README.md#update
+[docs-data-files-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/DATA-FILES.md
diff --git a/docs/LEANCLOUD-COUNTER-SECURITY.md b/docs/LEANCLOUD-COUNTER-SECURITY.md
new file mode 100644
index 000000000..8b260fea6
--- /dev/null
+++ b/docs/LEANCLOUD-COUNTER-SECURITY.md
@@ -0,0 +1,174 @@
+Before you make the config, please upgrade your NexT version to v6.0.6 or greater.
+
+Please note the difference between **site config file** and **theme config file**
+
+---
+
+# Sign up to Leancloud and create an app
+- Go to Leancloud website [leancloud.cn](leancloud.cn) and sign up to Leancloud. Then login.
+- Click `1` to enter the console:
+
+ ![1](https://lc-cqha0xyi.cn-n1.lcfile.com/fc0c048a1e25dc3d10aa.jpg)
+
+- Then click `1` to create an app:
+
+ ![2](https://lc-cqha0xyi.cn-n1.lcfile.com/33a56b754753a5d34b01.jpg)
+
+- Type your app name in `1` in the pop up window(eg. "test"), then choose `2`, which means developer's plan, and then click `3` to create the app:
+
+ ![3](https://lc-cqha0xyi.cn-n1.lcfile.com/649ccfc6f12015d1eefb.jpg)
+
+# Create Counter class and enable plugin in NexT
+- Click `1`(app name) to enter the app manage page:
+
+ ![4](https://lc-cqha0xyi.cn-n1.lcfile.com/d0889df29841661e0b9e.jpg)
+
+- then click `1` to create a class for counter:
+
+ ![5](https://lc-cqha0xyi.cn-n1.lcfile.com/b0fbc81bd6c19fa09a46.jpg)
+
+- Type `Counter` in the pop up window in `1`, check `2`, then click `3`:
+
+ ![6](https://lc-cqha0xyi.cn-n1.lcfile.com/ae6154d6a55f02f11ebf.jpg)
+
+- Click `1` to enter the app setting, then click `2`:
+
+ ![8](https://lc-cqha0xyi.cn-n1.lcfile.com/9501a6372918dd9a8a92.jpg)
+
+- Paste `App ID` and `App Key` to **theme config file**`_config.yml` like this:
+ ```yml
+ leancloud_visitors:
+ enable: true
+ app_id: <>
+ app_key: <>
+ # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security
+ security: true
+ betterPerformance: false
+ ```
+
+- Set domain whitelist: Click`1`, then type your domain into `2`(**protocol, domain and port should be exactly the same**):
+
+ ![9](https://lc-cqha0xyi.cn-n1.lcfile.com/0e537cc4bec2e185201d.jpg)
+
+# Deploy web engine to avoid your data being changed illegally
+- Click `1 -> 2 -> 3` by order
+
+ ![10](https://lc-cqha0xyi.cn-n1.lcfile.com/d7056dfeeef7c5d66318.jpg)
+
+- Click`1`:
+
+ ![11](https://lc-cqha0xyi.cn-n1.lcfile.com/2737841bbc2bdd572ae0.jpg)
+
+- In the pop up window, click `1` to choose type `Hook`, then choose`beforeUpdate` in `2`, choose `Counter` in `3`. Paste code below into `4`, then click `5` to save it:
+ ```javascript
+ var query = new AV.Query("Counter");
+ if (request.object.updatedKeys.indexOf('time') !== -1) {
+ return query.get(request.object.id).then(function (obj) {
+ if (obj.get("time") + 1 !== request.object.get("time")) {
+ throw new AV.Cloud.Error('Invalid update!');
+ }
+ })
+ }
+ ```
+
+ ![12](https://lc-cqha0xyi.cn-n1.lcfile.com/a8e13418ed1d9405315b.jpg)
+
+- Click `1` to deploy after the message in the red rect shows up:
+
+ ![13](https://lc-cqha0xyi.cn-n1.lcfile.com/ca56bf2e5fc2a1343565.jpg)
+
+- Click `1` in the pop up:
+
+ ![14](https://lc-cqha0xyi.cn-n1.lcfile.com/17548c13b3b23c71d845.jpg)
+
+- Click `1` to close the pop up window after the message in the red rect shows up:
+
+ ![15](https://lc-cqha0xyi.cn-n1.lcfile.com/d2f50de6cefea9fd0ed3.jpg)
+
+# Set access control for your database
+- Open **theme config file**`_config.yml`, set `leancloud_visitors: security` to `true`:
+ ```yml
+ leancloud_visitors:
+ enable: true
+ app_id: <>
+ app_key: <>
+ # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security
+ security: true
+ betterPerformance: false
+ ```
+
+ **Explaination for `betterPerformance`:**
+ Because the Leancloud developer's plan has limits in requst thread amount and running time, counter number may be very slow to load in some times. If set `betterPerformance` to true, counter number will be displayed quickly by assuming the request is accepted normally.
+
+- Open cmd then switch to **root path of site**, type commands to install `hexo-leancloud-counter-security` plugin:
+ ```
+ npm install hexo-leancloud-counter-security --save
+ ```
+
+- Open **site config file**`_config.yml`, add those config:
+ ```yml
+ leancloud_counter_security:
+ enable_sync: true
+ app_id: <>
+ app_key: <
+ username:
+ password:
+ ```
+
+- Type command:
+ ```
+ hexo lc-counter register <> <>
+ ```
+ or
+ ```
+ hexo lc-counter r <> <>
+ ```
+
+ Change `<>` and `<>` to your own username and password (no need to be the same as leancloud account). They will be used in the hexo deploying.
+
+ - Open **site config file**`_config.yml`, change `<>` and `<>`to those you set above:
+ ```yml
+ leancloud_counter_security:
+ enable_sync: true
+ app_id: <>
+ app_key: <
+ username: <> # will be asked while deploying if be left blank
+ password: <> # recommend to leave it blank for security, will be asked while deploying if be left blank
+ ```
+
+- Add the deployer in the `deploy` of **site config file**`_config.yml`:
+ ```yml
+ deploy:
+ # other deployer
+ - type: leancloud_counter_security_sync
+ ```
+
+- Return to the Leancloud console. Click `1 -> 2`, check if there is a record added in the _User (the img below is using username "admin" for example):
+
+ ![16](https://lc-cqha0xyi.cn-n1.lcfile.com/99faa5a0e7160e66d506.jpg)
+
+- Click `1 -> 2 -> 3` by order:
+
+ ![17](https://lc-cqha0xyi.cn-n1.lcfile.com/b72a9e64579f5b71749d.jpg)
+
+- Click `1`(add_fields), then choose `2`:Do as below "create" setting(choose the user you create):
+
+ ![18](https://lc-cqha0xyi.cn-n1.lcfile.com/14a8cb37062693d768ad.jpg)
+
+- click `1`(create), then choose `2`, type the username in `3`, then click `4 -> 5`:
+
+ ![19](https://lc-cqha0xyi.cn-n1.lcfile.com/d91714cfd703ef42b94c.jpg)
+
+ Now your page should be similar to this img after finishing the step.
+
+ ![20](https://lc-cqha0xyi.cn-n1.lcfile.com/c05e7ec9218820baf412.jpg)
+
+- Click `1`(delete), then choose `2`:
+
+ ![21](https://lc-cqha0xyi.cn-n1.lcfile.com/c37b6e20726cfb1d3197.jpg)
+
+Now the bug is fixed.
+
+---
+
+See detailed version here: https://leaferx.online/2018/03/16/lc-security-en/
diff --git a/docs/LICENSE b/docs/LICENSE
new file mode 100644
index 000000000..11571dd27
--- /dev/null
+++ b/docs/LICENSE
@@ -0,0 +1,56 @@
+ «NexT» — Elegant and powerful theme for Hexo.
+
+ Copyright © 2017 «NexT» (github.com/theme-next/hexo-theme-next).
+
+ Detail attribution information for «NexT»
+ is contained in the 'docs/AUTHORS.md' file.
+
+ This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License version 3
+as published by the Free Software Foundation with the addition of the
+following permission added to Section 15 as permitted in Section 7(a):
+FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY «NEXT»,
+«NEXT» DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+
+ This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU Affero General Public License for more details.
+You should have received a copy of the GNU Affero General Public License
+along with this program; if not, see: https://www.gnu.org/licenses/agpl.txt
+
+ In accordance with Section 7(b) of the GNU Affero General Public License:
+
+ a) It is not necessary to specify copyright in each source file of
+ this program because GitHub fully save commits of all modified files
+ with their authors and provides to see for this changes publicly.
+
+ b) For any part of the covered work in which the copyright not specified,
+ except of third party libraries ('source/lib/*') and '*custom.*' files,
+ will mean this part owned by «NexT» in accord with terms in this file.
+
+ c) A covered work must retain theme info link to the «NexT» repository
+ (https://github.com/theme-next/hexo-theme-next) in footer section
+ of every website created, modified or manipulated by using «NexT».
+ «NexT» theme configuration must be:
+ ```
+ footer:
+ theme:
+ enable: true
+ ```
+ Collaborators, best contributors and all authors specified in the
+ 'docs/AUTHORS.md' file of «NexT» repository under the
+ 'https://github.com/theme-next' organization can ignore theme info link
+ requirements.
+
+ Anyone can be released from the requirements of the license by purchasing
+a commercial license. Buying such a license is mandatory as soon as you
+develop commercial activities involving the «NexT» software without
+disclosing the source code of your own applications.
+These activities include:
+ 1. Access to private repository with various premium features.
+ 2. Priority support for resolve all possible issues with «NexT».
+ 3. Priority support for implement all possible features to «NexT».
+
+ For more information, please contact «NexT» Organization at this
+address: sales@theme-next.org
diff --git a/docs/MATH.md b/docs/MATH.md
new file mode 100644
index 000000000..0a757dbd5
--- /dev/null
+++ b/docs/MATH.md
@@ -0,0 +1,290 @@
+Math Equations
+
+NexT provides two render engines for displaying Math Equations.
+
+If you choose to use this feature, you don't need to manually import any JS or CSS. You just need to turn on `enable` of `math` and choose a render `engine` for it (located in `next/_config.yml`):
+
+```yml
+math:
+ enable: true
+ ...
+ engine: mathjax
+```
+
+Notice: only turning on `enable` of `math` **cannot let you see the displayed equations correctly**, you need to install the **corresponding Hexo Renderer** to fully support the display of Math Equations. The corresponding Hexo Renderer per engine will be provided below.
+
+Provided Render Engine
+
+For now, NexT provides two Render Engines: [MathJax](https://www.mathjax.org/) and [Katex](https://khan.github.io/KaTeX/) (default is MathJax).
+
+### MathJax (default)
+
+If you use MathJax to render Math Equations, you need to use **only one of them**: [hexo-renderer-pandoc](https://github.com/wzpan/hexo-renderer-pandoc) or [hexo-renderer-kramed](https://github.com/sun11/hexo-renderer-kramed).
+
+Firstly, you need to uninstall the original renderer `hexo-renderer-marked`, and install one of the renderer above:
+
+```sh
+npm un hexo-renderer-marked --save
+npm i hexo-renderer-pandoc --save # or hexo-renderer-kramed
+```
+
+Secondly, in `next/_config.yml`, turn on `enable` of `math` and choose `mathjax` as `engine`.
+
+```yml
+math:
+ enable: true
+ ...
+ engine: mathjax
+ #engine: katex
+```
+
+Finally, run standard Hexo generate, deploy process or start the server:
+
+```sh
+hexo clean && hexo g -d
+# or hexo clean && hexo s
+```
+
+#### Numbering and referring equations in MathJax
+
+In the new version of NexT, we have added feature to automatically number equations and to refer to equations. We briefly describe how to use this feature below.
+
+In general, to make the automatic equation numbering work, you have to wrap your LaTeX equations in `equation` environment. Using the plain old style (i.e., wrap an equation with two dollar signs in each side) will not work. How to refer to an equation? Just give a `\label{}` tag and then in your later text, use `\ref{}` or `\eqref{}` to refer it. Using `\eqref{}` is preferred since if you use `\ref{}`, there are no parentheses around the equation number. Below are some of the common scenarios for equation numbering.
+
+For simple equations, use the following form to give a tag,
+
+```latex
+$$\begin{equation}
+e=mc^2
+\end{equation}\label{eq1}$$
+```
+
+Then, you can refer to this equation in your text easily by using something like
+
+```
+the famous matter-energy equation $\eqref{eq1}$ proposed by Einstein ...
+```
+
+For multi-line equations, inside the `equation` environment, you can use the `aligned` environment to split it into multiple lines:
+
+```latex
+$$\begin{equation}
+\begin{aligned}
+a &= b + c \\
+ &= d + e + f + g \\
+ &= h + i
+\end{aligned}
+\end{equation}\label{eq2}$$
+```
+
+We can use `align` environment to align multiple equations. Each of these equations will get its own numbers.
+
+```
+$$\begin{align}
+a &= b + c \label{eq3} \\
+x &= yz \label{eq4}\\
+l &= m - n \label{eq5}
+\end{align}$$
+```
+
+In the `align` environment, if you do not want to number one or some equations, just [use `\nonumber`](https://tex.stackexchange.com/questions/17528/show-equation-number-only-once-in-align-environment) right behind these equations. Like the following:
+
+```latex
+$$\begin{align}
+-4 + 5x &= 2+y \nonumber \\
+ w+2 &= -1+w \\
+ ab &= cb
+\end{align}$$
+```
+
+Sometimes, you want to use more “exotic” style to refer your equation. You can use `\tag{}` to achieve this. For example:
+
+```latex
+$$x+1\over\sqrt{1-x^2} \tag{i}\label{eq_tag}$$
+```
+
+For more information, you can visit the [official MathJax documentation on equation numbering](http://docs.mathjax.org/en/latest/tex.html#automatic-equation-numbering). You can also visit this [post](https://jdhao.github.io/2018/01/25/hexo-mathjax-equation-number/) for more details.
+
+### Katex
+
+The Katex engine is a **much faster** math render engine compared to MathJax. And it could survive without JavaScript.
+
+But, what Katex supports is not as full as MathJax. You could check it from the Useful Links below.
+
+If you use Katex to render Math Equations, you need to use **only one of those renderer**: [hexo-renderer-markdown-it-plus](https://github.com/CHENXCHEN/hexo-renderer-markdown-it-plus) or [hexo-renderer-markdown-it](https://github.com/hexojs/hexo-renderer-markdown-it).
+
+Firstly, you need to uninstall the original renderer `hexo-renderer-marked`, and **install one of selected above**.
+
+```sh
+npm un hexo-renderer-marked --save
+npm i hexo-renderer-markdown-it-plus --save
+# or hexo-renderer-markdown-it
+```
+
+Secondly, in `next/_config.yml`, turn on `enable` option of `math` and choose `katex` as render `engine`.
+
+```yml
+math:
+ enable: true
+ ...
+ #engine: mathjax
+ engine: katex
+```
+
+Finally, run the standard Hexo generate, deploy process or start the server:
+
+```sh
+hexo clean && hexo g -d
+# or hexo clean && hexo s
+```
+
+#### If you use hexo-renderer-markdown-it
+
+If you use `hexo-renderer-markdown-it`,you also need to add `markdown-it-katex` as its plugin:
+
+```
+npm i markdown-it-katex --save
+```
+
+And then in `hexo/_config.yml` you need to add `markdown-it-katex` as a plugin for `hexo-renderer-markdown-it`:
+
+```yml
+# config of hexo-renderer-markdown-it
+markdown:
+ render:
+ html: true
+ xhtmlOut: false
+ breaks: true
+ linkify: true
+ typographer: true
+ quotes: '“”‘’'
+ plugins:
+ - markdown-it-katex
+```
+
+#### Known Bugs
+
+1. Firstly, please check [Common Issues](https://github.com/Khan/KaTeX#common-issues) of Katex.
+2. Displayed Math (i.e. `$$...$$`) needs to started with new clear line.\
+ In other words: you must not have any characters (except of whitespaces) **before the opening `$$` and after the ending `$$`** ([comment #32](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-357489509)).
+3. Don't support Unicode ([comment #32](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-357489509)).
+4. Inline Math (..`$...$`) must not have white spaces **after the opening `$` and before the ending `$`** ([comment #32](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-357489509)).
+5. If you use math in Heading (i.e. `## Heading`).\
+ Then in corresponding TOC item it will show the related LaTex code 3 times ([comment #32](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-359018694)).
+6. If you use math in your post's title, it will not be rendered ([comment #32](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-359142879)).
+
+We currently use Katex 0.7.1, some of those bugs might be caused by the outdated version of Katex we use.
+
+But, as what is described in the beginning, the render of Math Equations relies on Hexo Renderer. Currently, Katex-related renderers only support Katex version until 0.7.1.
+
+We will continuously monitor the updates of corresponding renderers, if there is a renderer which supports newer version of Katex, we will update the Katex we use.
+
+### Useful Links
+
+* [Speed test between Katex and MathJax](https://www.intmath.com/cg5/katex-mathjax-comparison.php)
+* [Function support by Katex](https://khan.github.io/KaTeX/function-support.html)
+
+Configuration Specifications
+
+ATTENTION! When you edit those configs, **don't change indentation!**
+
+Currently, all NexT config use **2 spaces indents**.
+
+If your content of config is put just directly after the config name, then a space is needed between the colon and the config content (i.e. `enable: true`)
+
+```yml
+# Math Equations Render Support
+math:
+ enable: false
+
+ # Default(true) will load mathjax/katex script on demand
+ # That is it only render those page who has 'mathjax: true' in Front Matter.
+ # If you set it to false, it will load mathjax/katex srcipt EVERY PAGE.
+ per_page: true
+
+ engine: mathjax
+ #engine: katex
+
+ # hexo-rendering-pandoc (or hexo-renderer-kramed) needed to full MathJax support.
+ mathjax:
+ # For newMathJax CDN (cdnjs.cloudflare.com) with fallback to oldMathJax (cdn.mathjax.org).
+ cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+ # For direct link to MathJax.js with CloudFlare CDN (cdnjs.cloudflare.com).
+ #cdn: //cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML
+ # For automatic detect latest version link to MathJax.js and get from Bootcdn.
+ #cdn: //cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML
+
+ # hexo-renderer-markdown-it-plus (or hexo-renderer-markdown-it with markdown-it-katex plugin)
+ # needed to full Katex support.
+ katex:
+ # Use Katex 0.7.1 as default
+ cdn: //cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css
+ # For whose visitors are mostly in China
+ #cdn: //cdn.bootcss.com/KaTeX/0.7.1/katex.min.css
+ # If you want to try the latest version of Katex, use one below instead
+ #cdn: //cdn.jsdelivr.net/katex/latest/katex.min.css
+```
+
+### enable
+
+`true` or `false`, default is `false`.
+
+`true` to turn on render of Math Equations, `false` to turn off it.
+
+### per_page
+
+`true` or `false`, default is `true`.
+
+This option is to control whether to render Math Equations every page.
+
+The behavior of default (`true`) is to render Math Equations **on demand**.
+
+It will only render those posts which have `mathjax: true` in their Front Matter.
+
+For example:
+
+```md
+
+---
+title: 'Will Render Math'
+mathjax: true
+---
+....
+```
+
+```md
+
+---
+title: 'Not Render Math'
+mathjax: false
+---
+....
+```
+
+```md
+
+---
+title: 'Not Render Math Either'
+---
+....
+```
+
+When you set it to `false`, the math will be rendered on **EVERY PAGE**.
+
+### cdn
+
+Both MathJax and Katex provide a config `cdn`, if you don't know what is `cdn`, **do not touch it**.
+
+Firstly, both MathJax and Katex use the [jsDelivr](https://www.jsdelivr.com/) as the default CDN.
+
+The reason that jsDelivr is chosen is because it is fast everywhere, and jsDelivr has the valid ICP license issued by the Chinese government, it can be accessed in China pretty well.
+
+And we also provide other optional CDNs, including the famous [CDNJS](https://cdnjs.com/) and the [Bootcss](http://www.bootcdn.cn/) which has the quite high access speed in China.
+
+For MathJax, we are currently using version 2.7.1.
+
+For Katex, due to the problem described above, we are now using version 0.7.1.
+
+If you want to try the other CDNs not included in the optional list, you must use the corresponding version.
+
+Particularly, if you are a Chinese blogger or most of your visits come from China, please note that **the CDNJS is blocked in some parts of China**, don't use it as your CDN.
diff --git a/docs/UPDATE-FROM-5.1.X.md b/docs/UPDATE-FROM-5.1.X.md
new file mode 100644
index 000000000..93ae14ec0
--- /dev/null
+++ b/docs/UPDATE-FROM-5.1.X.md
@@ -0,0 +1,19 @@
+Update from NexT v5.1.x
+
+There are no hard breaking changes between 5.1.x and 6.0.x versions. It's change major version to 6 because:
+
+1. Main repo was rebased from [iissnan's](https://github.com/iissnan/hexo-theme-next) profile to [theme-next](https://github.com/theme-next) organization.
+2. Most libraries under the `next/source/lib` directory was moved out to [external repos under NexT organization](https://github.com/theme-next).
+3. 3rd-party plugin [`hexo-wordcount`](https://github.com/willin/hexo-wordcount) was replaced by [`hexo-symbols-count-time`](https://github.com/theme-next/hexo-symbols-count-time) because `hexo-symbols-count-time` no have any external nodejs dependencies, no have [language filter](https://github.com/willin/hexo-wordcount/issues/7) which causes better performance on speed at site generation.
+
+So, i suggest to update from version 5 to version 6 in this way:
+
+1. You don't touch old `next` dir and just do some copies of NexT files:\
+ 1.1. `config.yml` or `next.yml` (if you used [data-files](DATA-FILES.md)).\
+ 1.2. Custom CSS styles what placed in `next/source/css/_custom/*` and `next/source/css/_variables/*` directories.\
+ 1.3. Custom layout styles what placed in `next/layout/_custom/*`.\
+ 1.4. Any another possible custom additions which can be finded by compare tools between repos.
+2. Clone new v6.x repo to any another directory instead of `next`. For example, in `next-reloaded` directory: `git clone https://github.com/theme-next/hexo-theme-next themes/next-reloaded`. So, you don't touch your old NexT 5.1.x directory and can work with new `next-reloaded` dir.
+3. Go to Hexo main config and set theme parameter: `theme: next-reloaded`. So, your `next-reloaded` directory must loading with your generation. If you may see any bugs or you simply not like this version, you anytime can switch for 5.1.x version back.
+
+And how to enable 3rd-party libraries see [here](https://github.com/theme-next/hexo-theme-next/blob/master/docs/INSTALLATION.md#plugins).
diff --git a/docs/ru/DATA-FILES.md b/docs/ru/DATA-FILES.md
new file mode 100644
index 000000000..a1788d74a
--- /dev/null
+++ b/docs/ru/DATA-FILES.md
@@ -0,0 +1,61 @@
+Дата Файлы
+
+Обновление темы NexT через пулы проходит не слишком гладко. Часто происходит конфликтная ситуация при обновлении по команде `git pull`, хотя её и можно обойти, если смерджить настройки в файле конфигурации вручную.
+
+ На данный момент, пользователи хранят одни настройки в корневом `_config.yml` (Hexo), а другие настройки в конфиге темы `_config.yml` (NexT). И всё вроде бы ничего, но имеются некоторые недостатки:
+1. Конфигурация разделяется на две части.
+2. Пользователи могут запутаться, в каком файле какие должны быть настройки.
+
+Во избежании проблемы, NexT использует преимущество Hexo [дата-файлов](https://hexo.io/docs/data-files.html). И т.к. дата-файлы были представлены в Hexo 3, необходимо обновиться до Hexo 3.0 (или выше) для использования этой возможности.
+
+Если же Вы предпочитаете Hexo 2.x, то можно использовать старый способ для конфигураций. NexT всё ещё совместим с Hexo 2.x (но возможны ошибки).
+
+Способ 1: Hexo-Путь
+
+Используя этот способ, вся конфигурация будет раположена в корневом конфиге hexo (`hexo/_config.yml`), благодаря чему нет необходимости изменять оригинальный конфиг темы (`next/_config.yml`) или создавать какие-либо новые файлы. Но в этом случае необходимо сохранять двойные отступы внутри `theme_config` параметра.
+
+Если в новых версиях появятся какие-то новые настройки, нужно просто скопировать эти настройки из оригинального `next/_config.yml` в редактируемый `hexo/_config.yml` и настроить по своему усмотрению.
+
+### Использование
+
+1. Проверяем на существование `hexo/source/_data/next.yml` файл (удаляем, если существует).
+2. Копируем необходимые опции из конфига темы NexT `next/_config.yml` в `hexo/_config.yml`, затем\
+ 2.1. Сдвигаем все опции вправо на 2 пробела (в Visual Studio Code: выделяем все строки, CTRL + ]).\
+ 2.2. Добавляем `theme_config:` параметр перед всеми этими настройками.
+
+### Полезные ссылки
+
+* [Конфигурация Hexo](https://hexo.io/ru/docs/configuration.html)
+* [Hexo Pull #757](https://github.com/hexojs/hexo/pull/757)
+
+Способ 2: NexT-Путь
+
+Используя этот способ, вся конфигурация будет храниться в одном файле (`source/_data/next.yml`), благодаря чему нет необходимости изменять оригинальный конфиг темы (`next/_config.yml`).
+Но с этим способом могут не корректно обрабатываться все внешние библиотеки hexo при использовании их дополнительных опций (например, опции модуля `hexo-server` могут быть считаны только из стандартного конфига hexo).
+
+Если в новых версиях появятся какие-то новые настройки, нужно просто скопировать эти настройки из оригинального `next/_config.yml` во внешний `_data/next.yml` и настроить по своему усмотрению.
+
+### Использование
+
+1. Убеждаемся, что Hexo версии 3 (или выше).
+2. Создаём файл под именем `next.yml` в корневой директории сайта — `hexo/source/_data` (создаём директорию `_data`, если отсутствует).
+
+И после этих шагов есть 2 варианта, нужно выбрать только 1 из них и продолжить следующие шаги.
+
+* **Вариант 1: `override: false` (по-умолчанию)**:
+
+ 1. Проверяем опцию `override` в стандартном конфиге NexT'а, должно быть установлено в `false`.\
+ В файле `next.yml` эта опция не должна быть вписана вовсе или вписана и установлена в `false`.
+ 2. Копируем настройки из конфига темы NexT (`_config.yml`) и из корневого конфига сайта (`_config.yml`) в файл `hexo/source/_data/next.yml`.
+
+* **Вариант 2: `override: true`**:
+
+ 1. В файле `next.yml` ставим опцию `override` в `true`.
+ 2. Копируем **все** опции из оригинального конфига NexT'а `next/_config.yml` в `hexo/source/_data/next.yml`.
+
+3. Затем, в корневом конфиге сайта `hexo/_config.yml` необходимо установить опцию `theme: next` (и если требуется, `source_dir: source`).
+4. Используем станадартные параметры для запускаь генерации или развёртывания (`hexo clean && hexo g -d && hexo s`).
+
+### Полезные ссылки
+
+* [NexT Issue #328](https://github.com/iissnan/hexo-theme-next/issues/328)
diff --git a/docs/ru/INSTALLATION.md b/docs/ru/INSTALLATION.md
new file mode 100644
index 000000000..5cf98afd8
--- /dev/null
+++ b/docs/ru/INSTALLATION.md
@@ -0,0 +1,120 @@
+Установка
+
+Шаг 1 → Идём в директорию Hexo
+
+Меняем каталог на **корневой hexo**. Там должны находиться `node_modules`, `source`, `themes` и другие папки:
+ ```sh
+ $ cd hexo
+ $ ls
+ _config.yml node_modules package.json public scaffolds source themes
+ ```
+
+Шаг 2 → Скачиваем NexT
+
+Скачиваем тему с GitHub.
+Имеются 3 способа как зделать это, нужно выбрать только 1 из них.
+
+### Способ 1: Скачиваем [последнюю версию релиза][releases-latest-url]
+
+ В большинстве случаев **стабильна**. Рекомендуется для начинающих пользователей.
+
+ * Установка с помощью [curl & tar & wget][curl-tar-wget-url]:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -s https://api.github.com/repos/theme-next/hexo-theme-next/releases/latest | grep tarball_url | cut -d '"' -f 4 | wget -i - -O- | tar -zx -C themes/next --strip-components=1
+ ```
+ Этим способом Вы скачаете **только последнюю версию релиза** (без директории `.git` внутри).\
+ Поэтому, в дальнейшем будет невозможно обновить эту версию через `git`.\
+ Зато всегда можно использовать отдельную конфигурацию (т.е. [дата-файлы][docs-data-files-url]) и скачивать новую версию перезаписывая старую (или создать новый каталог и переопределить параметр `theme` в конфиге Hexo), без потери старой конфигурации.
+
+### Способ 2: Скачиваем [указанную версию релиза][releases-url]
+
+ В редких случаях полезно, но не рекомендуется.\
+ Необходимо указать версию. Замените `v6.0.0` на любую версию из [списка тэгов][tags-url].
+
+ * Вариант 1: Установка с помощью [curl & tar][curl-tar-url]:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -L https://api.github.com/repos/theme-next/hexo-theme-next/tarball/v6.0.0 | tar -zxv -C themes/next --strip-components=1
+ ```
+ То же, что и описано выше в способе `curl & tar & wget`, но скачает **только конкретную версию**.
+
+ * Вариант 2: Установка с помощью [git][git-url]:
+
+ ```sh
+ $ git clone --branch v6.0.0 https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+ Этот вариант скачает **указанную версию релиза** (включая директорию `.git` внутри).\
+ И в любой момент Вы можете переключиться на любую весию тэга, но с лимитом до указанной версии.
+
+### Способ 3: Скачиваем [последнюю мастер-ветку][download-latest-url]
+
+ Иногда может быть **нестабильна**, но включает самые последние нововведения. Рекомендуется для продвинутых пользователей и для разработчиков.
+
+ * Вариант 1: Установка с помощью [curl & tar][curl-tar-url]:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -L https://api.github.com/repos/theme-next/hexo-theme-next/tarball | tar -zxv -C themes/next --strip-components=1
+ ```
+ То же, что и описано выше в варианте `curl & tar & wget`, но скачает **только последнюю мастер-ветку**.\
+ В некоторых случаях полезно для разработчиков.
+
+ * Вариант 2: Установка с помощью [git][git-url]:
+
+ ```sh
+ $ git clone https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+
+ Этот вариант скачает **весь репозиторий** (включая директорию `.git` внутри).\
+ И в любой момент Вы можете [обновить текущую версию через git][update-with-git-url] и переключиться на любую версию тэга или на последнюю мастер или любую другую ветку.\
+ В большинстве случаев полезно как для пользователей, так и для разработчиков.
+
+ Смотрим список тэгов:
+
+ ```sh
+ $ cd themes/next
+ $ git tag -l
+ …
+ v6.0.0
+ v6.0.1
+ v6.0.2
+ ```
+
+ Например, Вы хотите переключиться на [версию релиза][tags-url] `v6.0.1`. Вводим следующую команду:
+
+ ```sh
+ $ git checkout tags/v6.0.1
+ Note: checking out 'tags/v6.0.1'.
+ …
+ HEAD is now at da9cdd2... Release v6.0.1
+ ```
+
+ И если вы хотите переключиться обратно на [мастер-ветку][commits-url], вводим следующее:
+
+ ```sh
+ $ git checkout master
+ ```
+
+Шаг 3 → Конфигурируем
+
+Устанавливаем параметр темы в конфиге `_config.yml` **корневой директории hexo**:
+
+```yml
+theme: next
+```
+
+[download-latest-url]: https://github.com/theme-next/hexo-theme-next/archive/master.zip
+[releases-latest-url]: https://github.com/theme-next/hexo-theme-next/releases/latest
+[releases-url]: https://github.com/theme-next/hexo-theme-next/releases
+[tags-url]: https://github.com/theme-next/hexo-theme-next/tags
+[commits-url]: https://github.com/theme-next/hexo-theme-next/commits/master
+
+[git-url]: http://lmgtfy.com/?q=linux+git+install
+[curl-tar-url]: http://lmgtfy.com/?q=linux+curl+tar+install
+[curl-tar-wget-url]: http://lmgtfy.com/?q=linux+curl+tar+wget+install
+
+[update-with-git-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/ru/README.md#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0
+[docs-data-files-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/ru/DATA-FILES.md
diff --git a/docs/ru/README.md b/docs/ru/README.md
new file mode 100644
index 000000000..9b11d9628
--- /dev/null
+++ b/docs/ru/README.md
@@ -0,0 +1,121 @@
+
+
+#
+
+«NexT» — элегантная высококачественная тема под Hexo. Сделана с нуля, с любовью.
+
+[![gitter-image]][gitter-url]
+[![riot-image]][riot-url]
+[![t-chat-image]][t-chat-url]
+[![t-news-image]][t-news-url]
+[![lang-image]][lang-url]
+[![travis-image]][travis-url]
+[![rel-image]][releases-url]
+[![hexo-image]][hexo-url]
+[![lic-image]][lic-url]
+
+## Демо
+
+* :heart_decoration: Muse тема: [LEAFERx](https://leaferx.online) | [XiaMo](https://notes.wanghao.work) | [OAwan](https://oawan.me)
+* :six_pointed_star: Mist тема: [Jeff](https://blog.zzbd.org) | [uchuhimo](http://uchuhimo.me) | [xirong](http://www.ixirong.com)
+* :pisces: Pisces тема: [Vi](http://notes.iissnan.com) | [Acris](https://acris.me) | [Rainy](https://rainylog.com)
+* :gemini: Gemini тема: [Ivan.Nginx](https://almostover.ru) | [Raincal](https://raincal.com) | [Dandy](https://dandyxu.me)
+
+Больше примеров «NexT» [здесь](https://github.com/iissnan/hexo-theme-next/issues/119).
+
+## Установка
+
+Простейший вариант установки — склонировать весь репозиторий:
+
+ ```sh
+ $ cd hexo
+ $ git clone https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+
+Или предлагаю почитать [детальные инструкции по установке][docs-installation-url], если вариант выше не устраивает.
+
+## Плагины
+
+В конфиге NexT'а теперь можно найти зависимости на каждый модуль, который был вынесен во внешние репозитории, которые могут быть найдены по [ссылке основной организации](https://github.com/theme-next).
+
+Например, Вы хотите использовать `fancybox` для своего сайта. Открываем конфиг NexT'а и находим:
+
+```yml
+# Fancybox
+# Dependencies: https://github.com/theme-next/theme-next-fancybox
+fancybox: false
+```
+
+Затем включаем параметр `fancybox` и переходим по ссылке «Dependencies» с дальнейшеми инструкциями по установке этого модуля.
+
+## Обновление
+
+Можно обновить до последней мастер-ветки следующей командой:
+
+```sh
+$ cd themes/next
+$ git pull
+```
+
+А если всплывают ошибки во время обновления (что-то наподобии **«Commit your changes or stash them before you can merge»**), рекомендуется ознакомиться с особенностью хранения [дата-файлов в Hexo][docs-data-files-url].\
+Как бы то ни было, можно обойти ошибки при обновлении если «Закомитить», «Стэшнуть» или «Откатить» локальные изменения. Смотрим [здесь](https://stackoverflow.com/a/15745424/5861495) как это сделать.
+
+**Если нужно обновиться с версии v5.1.x на v6.0.x, читаем [здесь][docs-update-5-1-x-url].**
+
+## Известные баги
+
+Для тех, кто столкнулся с ошибкой **«[Error: Cannot find module 'hexo-util'](https://github.com/iissnan/hexo-theme-next/issues/1490)»**, следует проверить версию NPM.
+
+* `> 3`: Всё равно не работает? Удалите директорию `node_modules` и переустановите с помощью `npm install`.
+* `< 3`: Добавьте `hexo-util` принудительно командой `npm install --save-dev hexo-util` к основным пакетам с Hexo.
+
+## Содействие
+
+Приветсвуется любое содействие, не стесняйтесь сообщать «Баги», брать «Форки» и вливать «Пулы».
+
+## Сторонние приложения
+
+* :triangular_flag_on_post: HexoEditor
+
+[browser-image]: https://img.shields.io/badge/browser-%20chrome%20%7C%20firefox%20%7C%20opera%20%7C%20safari%20%7C%20ie%20%3E%3D%209-lightgrey.svg
+[browser-url]: https://www.browserstack.com
+
+[lang-image]: https://d322cqt584bo4o.cloudfront.net/theme-next/localized.svg "Добавить или улучшить перевод за несколько секунд!"
+[lang-url]: https://crwd.in/theme-next
+
+[gitter-image]: https://img.shields.io/badge/gitter-chat-orange.svg "Вступить в нашу комнату Gitter'а"
+[gitter-url]: https://gitter.im/theme-next
+
+[riot-image]: https://img.shields.io/badge/riot-chat-DCAB08.svg "Вступить в нашу комнату Riot'а"
+[riot-url]: https://riot.im/app/#/room/#NexT:matrix.org
+
+[t-chat-image]: https://img.shields.io/badge/telegram-chat-BAB210.svg "Вступить в нашу группу Telegram'а"
+[t-chat-url]: https://t.me/theme_next
+
+[t-news-image]: https://img.shields.io/badge/telegram-news-98B919.svg "Подписаться на канал Telegram'а с новостями"
+[t-news-url]: https://t.me/theme_next_news
+
+[travis-image]: https://travis-ci.org/theme-next/hexo-theme-next.svg?branch=master
+[travis-url]: https://travis-ci.org/theme-next/hexo-theme-next?branch=master "Travis CI [Linux]"
+
+[hexo-image]: https://img.shields.io/badge/hexo-%3E%3D%203.5.0-blue.svg
+[hexo-url]: http://hexo.io
+
+[lic-image]: https://img.shields.io/badge/license-%20AGPL-blue.svg
+[lic-url]: https://github.com/theme-next/hexo-theme-next/blob/master/LICENSE.md
+
+
+[rel-image]: https://badge.fury.io/gh/theme-next%2Fhexo-theme-next.svg
+
+
+[download-latest-url]: https://github.com/theme-next/hexo-theme-next/archive/master.zip
+[releases-latest-url]: https://github.com/theme-next/hexo-theme-next/releases/latest
+[releases-url]: https://github.com/theme-next/hexo-theme-next/releases
+[tags-url]: https://github.com/theme-next/hexo-theme-next/tags
+[commits-url]: https://github.com/theme-next/hexo-theme-next/commits/master
+
+[docs-installation-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/ru/INSTALLATION.md
+[docs-data-files-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/ru/DATA-FILES.md
+[docs-update-5-1-x-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/ru/UPDATE-FROM-5.1.X.md
diff --git a/docs/ru/UPDATE-FROM-5.1.X.md b/docs/ru/UPDATE-FROM-5.1.X.md
new file mode 100644
index 000000000..499302651
--- /dev/null
+++ b/docs/ru/UPDATE-FROM-5.1.X.md
@@ -0,0 +1,19 @@
+Обновление из-под NexT v5.1.x
+
+Между версиями 5.1.x и 6.0.x нет жёстких изменений. Версия сменилась на мажорную 6 по следующим причинам:
+
+1. Основной репозиторий перебазировался из профиля [iissnan'а](https://github.com/iissnan/hexo-theme-next) в [theme-next](https://github.com/theme-next) организацию.
+2. Большинство библиотек в `next/source/lib` директории были вынесены в [отдельные репозитории под организацией NexT](https://github.com/theme-next).
+3. 3rd-party плагин [`hexo-wordcount`](https://github.com/willin/hexo-wordcount) был заменён на [`hexo-symbols-count-time`](https://github.com/theme-next/hexo-symbols-count-time) т.к. `hexo-symbols-count-time` не имеет никаких сторонних nodejs зависимостей, не имеет [языкового фильтра](https://github.com/willin/hexo-wordcount/issues/7) что обеспечивает улучшенную производительность при генерации сайта.
+
+Поэтому, я предлагаю обновиться с версии 5 на версию 6 следующим способом:
+
+1. Вы не трогаете старую директорию `next`, а всего-лишь делаете резервные копии файлов NexT:\
+ 1.1. `config.yml` или `next.yml` (если Вы использовали [дата-файлы](DATA-FILES.md)).\
+ 1.2. Пользовательских CSS-стилей, которые расположены в `next/source/css/_custom/*` и `next/source/css/_variables/*` директориях.\
+ 1.3. Пользовательских layout-стилей, которые расположены в `next/layout/_custom/*`.\
+ 1.4. Любые другие всевозможные пользовательские изменения, которые могут быть найдены любым инструментом для сравнения файлов.
+2. Склонировать новый v6.x репозиторий в любую другую директорию, отличную от `next`. Например, в директорию `next-reloaded`: `git clone https://github.com/theme-next/hexo-theme-next themes/next-reloaded`. Итак, нет необходимости трогать старую NexT 5.1.x директорию и можно работать с новой `next-reloaded`.
+3. Открываем главную Hexo-конфигурацию и устанавливаем параметр темы: `theme: next-reloaded`. Так Ваша директория `next-reloaded` должна грузиться при генерации. Если Вы будете наблюдать какие-либо баги или Вам попросту не нравится эта новая версия, в любой момент Вы можете использовать старую 5.1.x.
+
+А как активировать 3rd-party библиотеки, смотрим здесь [здесь](https://github.com/theme-next/hexo-theme-next/blob/master/docs/ru/INSTALLATION.md#%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D1%8B).
diff --git a/docs/zh-CN/ALGOLIA-SEARCH.md b/docs/zh-CN/ALGOLIA-SEARCH.md
new file mode 100644
index 000000000..e32ec4c47
--- /dev/null
+++ b/docs/zh-CN/ALGOLIA-SEARCH.md
@@ -0,0 +1,84 @@
+Algolia 搜索
+
+NexT 内部提供 Algolia 的搜索功能,要使用此功能请确保所使用的 NexT 版本在 `v5.1.0` 之后。需要注意的是,仅仅将 `next/_config.yml` 中 `algolia_search` 的 `enable` 打开**并不能让你使用 Algolia 搜索**,你还需要**使用对应的 Hexo-Algolia 插件** 才能真正在博客页面中使用 Algolia 搜索。按照下面介绍的步骤操作即可完成 Algolia 搜索的安装。
+
+1. 前往 [Algolia 注册页面](https://www.algolia.com/),注册一个新账户。 可以使用 GitHub 或者 Google 账户直接登录,注册后的 14 天内拥有所有功能(包括收费类别的)。之后若未续费会自动降级为免费账户,免费账户 总共有 10,000 条记录,每月有 100,000 的可以操作数。注册完成后,创建一个新的 Index,这个 Index 将在后面使用。
+
+ ![](http://theme-next.iissnan.com/uploads/algolia/algolia-step-2.png)
+
+1. Index 创建完成后,此时这个 Index 里未包含任何数据。接下来需要安装 [Hexo Algolia](https://github.com/oncletom/hexo-algolia) 扩展,这个扩展的功能是搜集站点的内容并通过 API 发送给 Algolia。前往站点根目录,执行命令安装:
+
+ ```
+ $ cd hexo
+ $ npm install --save hexo-algolia
+ ```
+
+1. 在 `API Keys` 页面找到需要使用的一些配置的值,包括 `ApplicationID` 和 `Search-Only API Key`。注意,`Admin API Key` 需要保密保存,不要外泄。
+
+ ![](https://user-images.githubusercontent.com/8521181/35479066-64e35aec-0428-11e8-91f9-1ec3afa45c5c.png)
+
+1. 在 `API Keys` 页面,点击 `ALL API KEYS` 找到新建 INDEX 对应的 key,**编辑权限**,在弹出框中找到 ACL ,**勾选 Add records、 Delete records、List indices、Delete index 权限**,点击 `update` 更新。
+
+ ![](https://user-images.githubusercontent.com/8521181/35479064-611aa0b4-0428-11e8-85a1-cfb449b486ec.png)
+ ![](https://user-images.githubusercontent.com/8521181/35479084-d4f7ac02-0428-11e8-95a6-c4e3b1bef47b.png)
+
+1. 编辑 `站点配置文件`,新增以下配置,除了 `chunkSize` 字段,替换成在 Algolia 获取到的值:
+
+ ```yml
+ algolia:
+ applicationID: 'applicationID'
+ apiKey: 'apiKey'
+ indexName: 'indexName'
+ chunkSize: 5000
+ ```
+
+1. 当配置完成,在站点根目录下执行一下命令来更新上传 Index。请注意观察命令的输出。
+
+ ```
+ $ export HEXO_ALGOLIA_INDEXING_KEY=Search-Only API key # 使用 Git Bash
+ # set HEXO_ALGOLIA_INDEXING_KEY=Search-Only API key # 使用 Windows CMD 命令行
+ $ hexo clean
+ $ hexo algolia
+ ```
+
+ ![](http://theme-next.iissnan.com/uploads/algolia/algolia-step-4.png)
+
+1. 切换到 NexT 目录,并安装 algolia-instant-search 到 `source/lib` 目录。
+
+ ```
+ $ cd themes/next
+ $ git clone https://github.com/theme-next/theme-next-algolia-instant-search source/lib/algolia-instant-search
+ ```
+
+ 如果你想直接使用 CDN 设置 Algolia Search,则需要在`主题配置文件`中添加 vendors 字段:
+
+ ```yml
+ vendors:
+ ...
+ # Internal version: 1
+ # https://www.algolia.com
+ algolia_instant_js: https://cdn.jsdelivr.net/npm/instantsearch.js@2.4.1/dist/instantsearch.js
+ algolia_instant_css: https://cdn.jsdelivr.net/npm/instantsearch.js@2.4.1/dist/instantsearch.min.css
+ ...
+ ```
+
+1. 更改`主题配置文件`,找到 Algolia Search 配置部分,将 `enable` 改为 `true`。同时你需要**关闭**其他搜索插件,如 Local Search 等。你也可以根据需要调整 `labels` 中的文本:
+
+ ```yml
+ # Algolia Search
+ algolia_search:
+ enable: true
+ hits:
+ per_page: 10
+ labels:
+ input_placeholder: Search for Posts
+ hits_empty: "We didn't find any results for the search: ${query}"
+ hits_stats: "${hits} results found in ${time} ms"
+ ```
+
+已知的问题
+
+1. 考虑到 Algolia 免费账户的限制,目前 [Hexo-Algolia](https://github.com/oncletom/hexo-algolia) 插件最新版本去掉了正文索引功能。
+1. [Hexo-Algoliasearch](https://github.com/LouisBarranqueiro/hexo-algoliasearch) 插件提供了正文索引功能,不过需要替换 NEXT 主题中的关键字。对于免费账户,`Record Too Big` 的问题同样存在。
+ - 替换 `source/js/src/algolia-search.js` 中所有的 `applicationID` 为 `appId`
+ - 替换 `layout/_partials/head/head.swig` 中所有的 `applicationID` 为 `appId`
diff --git a/docs/zh-CN/CODE_OF_CONDUCT.md b/docs/zh-CN/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..a3518b6ce
--- /dev/null
+++ b/docs/zh-CN/CODE_OF_CONDUCT.md
@@ -0,0 +1,99 @@
+
+
+#
+
+[NexT](https://github.com/theme-next/hexo-theme-next) 是一个优雅而强大的 [Hexo](https://hexo.io/)主题。在这里,您可以构建一个托管在 [GitHub Pages](https://pages.github.com/) 上的静态博客,分享您的生活,并与新朋友进行交流。
+
+参与者公约用来约束在 [NexT](https://github.com/theme-next/hexo-theme-next) 社区中代码更新、问题交流、请求合并等行为。我们期望所有用户相互尊重,礼貌待人。任何违反这些规则的人都将不会被审核,并会在发现后立即被阻止和驱逐。
+
+## 目录
+
+- [我们的保证](#our-pledge)
+- [我们的责任](#our-responsibilities)
+- [我们的标准](#our-standards)
+- [使用范围](#scope)
+- [强制执行](#enforcement)
+- [联系项目维护者](#contacting-maintainers)
+- [来源](#attribution)
+
+
+## 我们的保证
+
+作为此项目的贡献者和维护者,我们承诺尊重所有做出贡献的用户,这些贡献包括了报告问题、发布功能请求、更新文档、提交合并请求以及其他活动。
+
+为了促进一个开放透明且友好的环境,我们作为贡献者和维护者保证:无论年龄、种族、民族、性别认同和表达(方式)、体型、身体健全与否、经验水平、国籍、个人表现、宗教或性别取向,参与者在我们项目和社区中都免于骚扰。
+
+
+## 我们的责任
+
+项目维护者有责任为「可接受的行为」标准做出诠释,有权利及责任去删除、编辑、拒绝与本行为标准有所违背的评论(comments)、提交(commits)、代码、wiki 编辑、问题(issues)和其他贡献,以及项目维护者可暂时或永久性的禁止任何他们认为有不适当、威胁、冒犯、有害行为的贡献者。
+
+
+## 我们的标准
+
+作为 GitHub 上的一个项目,本项目受到 [GitHub 社区准则](https://help.github.com/articles/github-community-guidelines/)的约束。 此外,作为 npm 托管的项目,[npm 公司的行为准则](https://www.npmjs.com/policies/conduct)也涵盖了本项目。
+
+有助于创造正面环境的行为包括但不限于:
+
+* 使用友好和包容性语言
+* 尊重不同的观点和经历
+* 耐心地接受建设性批评
+* 关注对社区最有利的事情
+* 友善对待其他社区成员
+
+身为参与者不能接受的行为包括但不限于:
+
+* 使用与性有关的言语或是图像,以及不受欢迎的性骚扰
+* 捣乱/煽动/造谣的行为或进行侮辱/贬损的评论,人身攻击及政治攻击
+* 公开或私下的骚扰
+* 未经许可地发布他人的个人资料,例如住址或是电子地址
+* 其他可以被合理地认定为不恰当或者违反职业操守的行为
+
+
+## 使用范围
+
+当一个人代表该项目或是其社区时,本行为标准适用于其项目社区和公共社区。
+
+根据某人在本社区范围以外发生的违规情况,项目维护者可以认为其不受欢迎,并采取适当措施来保证所有成员的安全性和舒适性。
+
+
+## 强制执行
+
+如果您看到违反行为准则的行为,请按以下步骤操作:
+
+1. 让这个人知道他所做的并不合适,并要求他停止或编辑他们的提交信息。该人应立即停止行为并纠正问题。
+2. 如果该人没有纠正其行为,或者您不方便与其沟通,请[联系项目维护者](#contacting-maintainers)。上报时,请尽可能多的提供详细信息,链接,截图,上下文或可用于更好地理解和解决情况的其他信息。
+3. 收到上报信息后,项目维护者会查看问题,并采取进一步的措施。
+
+一旦项目维护者参与其中,他们将遵循以下一系列步骤,并尽力保护项目成员的利益。任何维护团队认为有必要且适合的所有投诉都将进行审查及调查,并做出相对应的回应。项目小组有对事件回报者有保密的义务。具体执行的方针近一步细节可能会单独公布。
+
+以下是项目维护者根据需要采取的进一步执法步骤:
+
+1. 再次要求停止违规行为。
+2. 如果违规者还是没有回应,将会受到正式的警告,并收到项目维护者的移除或修改消息。同时,相关的问题或合并请求将会被锁定。
+3. 如果警告后违规行为继续出现,违规者将会被禁言 24 小时。
+4. 如果禁言后违规行为继续出现,违规者将会被处罚长期(6-12个月)禁言。
+
+除此之外,项目维护者可以根据需要删除任何违规的消息,图片,贡献等。如果违规行为被认为是对社区成员的严重或直接威胁,包括任何置社区成员于风险的威胁、身体或言语攻击,项目维护者有充分权利自行决定跳过上述任何步骤。
+
+没有切实地遵守或是执行本行为标准的项目维护人员,可能会因项目领导人或是其他成员的决定,暂时或是永久地取消其参与资格。
+
+
+## 联系项目维护者
+
+您可以通过以下任何方法与维护人员联系
+
+* 电子邮件:
+ * [support@theme-next.org](mailto:support@theme-next.org)
+
+* 即时通信:
+ * [Gitter](https://gitter.im/theme-next)
+ * [Riot](https://riot.im/app/#/room/#NexT:matrix.org)
+ * [Telegram](https://t.me/joinchat/GUNHXA-vZkgSMuimL1VmMw)
+
+
+## 来源
+
+本行为标准改编自[Contributor Covenant](https://www.contributor-covenant.org/) 和 [WeAllJS Code of Conduct](https://wealljs.org/code-of-conduct)。
diff --git a/docs/zh-CN/CONTRIBUTING.md b/docs/zh-CN/CONTRIBUTING.md
new file mode 100644
index 000000000..4025fea89
--- /dev/null
+++ b/docs/zh-CN/CONTRIBUTING.md
@@ -0,0 +1,144 @@
+
+
+#
+
+首先,非常感谢大家抽出宝贵时间来让我们的 NexT 主题越变越好。在这里,我们介绍一下 [NexT 主题及其子模块](https://github.com/theme-next)的开源贡献指南。不过,我们希望大家不要局限于此,更欢迎大家随时进行补充。
+
+## 目录
+
+[如何为 Next 做贡献](#how-can-i-contribute)
+
+ * [你需要了解的](#before-submitting-an-issue)
+ * [反馈 Bug](#reporting-bugs)
+ * [提交功能需求](#suggesting-enhancements)
+ * [提交合并请求](#submitting-a-pull-request)
+ * [发布版本](#creating-releases)
+
+[规范](#guides)
+
+ * [行为规范](#coding-rules)
+ * [编码规范](#coding-standards)
+ * [提交信息规范](#commit-messages-rules)
+
+
+## 如何为 Next 做贡献
+
+目前 Next 主题已经从 [iissnan](https://github.com/iissnan/hexo-theme-next) 的个人仓库移动到了 [Theme-Next](https://github.com/theme-next) 组织仓库中,并升级到 V6 版本。在 V6+ 版本中,`next/source/lib` 目录下的第三方依赖库将独立放置在 [Theme-Next](https://github.com/theme-next) 组织仓库中。在大多数情况下,NexT V5 版本仍然能够正常运行,但是如果你想获得更多的功能和帮助,还是建议您[升级到 NexT V6+ 版本](https://github.com/theme-next/hexo-theme-next/blob/master/docs/UPDATE-FROM-5.1.X.md),并移步 [Theme-Next](https://github.com/theme-next/hexo-theme-next) 仓库。
+
+
+### 你需要了解的
+
+如果你在使用过程中遇到了问题,你可以查阅 FAQs(建设中) 或者 [NexT 帮助文档](https://theme-next.org/docs/)(建设中)。另外,你也可以通过[这里](https://github.com/theme-next/hexo-theme-next/search?q=&type=Issues&utf8=%E2%9C%93)进行大致检索,有些问题已经得到解答,你可以自行解决。对于没有解决的 Issue,你也可以继续提问。
+
+如果你在使用过程中发现了 Bug,请再次确认 Bug 在[最新发布版本](https://github.com/theme-next/hexo-theme-next/releases/latest)中是否重现。如果 Bug 重现,欢迎你到我们的 [Theme-NexT 仓库](https://github.com/theme-next/hexo-theme-next)中[反馈 Bug ](#reporting-bugs) 和[提交功能需求](#suggesting-enhancements),也更期待您[提交合并请求](#submitting-a-pull-request)
+
+
+### 反馈 Bug
+
+反馈 Bug 前,请再次确认您已经查看了[你需要了解的](#before-submitting-an-issue)内容,避免提交重复的 Issue。确定相关仓库后,创建 Issue 并按照[模板](../../.github/ISSUE_TEMPLATE.md)尽可能的详细填写相关信息。
+
+请认真遵守如下指南,这样我们才能更好地理解问题,重现问题和解决问题。
+
+* 在标题中清晰准确地描述你的问题。
+* 参照如下问题尽可能多的提供信息:
+ * Bug 是否能够重现?是一直出现还是偶尔出现?
+ * Bug 是从什么时候开始发生的?
+ * 如果 Bug 突然发生,使用[旧版本主题](https://github.com/theme-next/hexo-theme-next/releases)是否能够重现 Bug?又是从哪个版本开始出现 Bug?
+ * 你所使用 Node,Hexo 以及 Next 的版本号多少?你可以运行 `node -v` 和 `hexo version` 获取版本号,或者查看文件 `package.json` 的内容。
+ * 你使用了哪些插件包?查看文件 `package.json` 的内容即可获取。
+* 一步步详细你是如何重现 Bug 的,做了什么,使用了哪些功能等等。如果你需要展示代码段,请使用 [Markdown 代码块](https://help.github.com/articles/creating-and-highlighting-code-blocks/) 或 [Github 预览链接](https://help.github.com/articles/creating-a-permanent-link-to-a-code-snippet/) 或 [Gist 链接](https://gist.github.com/)。
+* 提供 Bug 的样例,如图像文件、在线演示网址等等。
+* 详细描述通过上述重现过程出现的问题。
+* 详细描述你期待的结果。
+
+
+### 提交功能需求
+
+提交功能需求前,请再次确认您已经查看了[你需要了解的](#before-submitting-an-issue)内容,避免提交重复的 Issue。确定相关仓库后,创建 Issue 并按照[模板](../../.github/ISSUE_TEMPLATE.md)尽可能的详细填写相关信息。
+
+请认真遵守如下指南,这样我们才能更好地理解和开发功能需求:pencil::
+
+* 在标题中清晰准确地描述你的功能需求。
+* 详细描述目前所具有的功能和你所期待的功能,并解释为什么需要该功能。
+* 提供功能需求的样例,如图像文件、在线演示网址等等。
+
+
+### 提交合并请求
+
+提交合并请求前,请再次确认您已经查看了[你需要了解的](#before-submitting-an-issue)内容,避免提交重复的合并请求。确定相关仓库后,创建合并请求。更多详细操作过程可以查看[帮助文档](https://help.github.com/articles/creating-a-pull-request/)。
+
+1. 进入 [hexo-theme-next](https://github.com/theme-next/hexo-theme-next) 源仓库,点击`Fork`。
+2. 进入到已经`Fork`的个人仓库(`https://github.com/username/hexo-theme-next`),点击 **Clone or download** 并复制该仓库地址。选择本地文件夹,并打开 Git Bash ,输入如下命令并回车,即可完成仓库克隆。
+ ```bash
+ $ git clone git@github.com:username/hexo-theme-next.git
+ ```
+3. 进入 `hexo-theme-next` 本地文件夹,并创建分支。
+ ```bash
+ $ cd hexo-theme-next
+ $ git checkout -b patchname
+ ```
+4. 本地修改并测试,推送分支。
+ ```bash
+ $ git add .
+ $ git commit -m "add commit messamge"
+ $ git push origin patchname
+ ```
+5. 进入 `fork` 后的仓库,切换到新提交的 `patchname` 分支,点击 `patchname` 分支右侧的 **New pull request** 。在 PR 对比页面,正确选择你需要发起合并请求的分支,然后点击 **Create pull request** ,建立一个新的合并申请并描述变动。
+
+请认真遵守如下指南,这样我们才能更好地理解你的合并请求:
+
+* 创建合并请求时,请遵守[编码规范](#coding-rules)和[提交信息规范](#commit-messages-rules)。
+* 在标题中清晰准确地描述你的合并请求,不要加入 Issue 编号。
+* 按照[模板](../../.github/PULL_REQUEST_TEMPLATE.md)尽可能的详细填写相关信息。
+* 合并请求需要在所有主题样式中测试通过,并提供所表现功能的样例,如图像文件、在线演示网址等等。
+
+
+### 发布版本
+
+版本发布是将项目发布给用户的一种很好的方式。
+
+1. 进入 GitHub 项目主页,点击 **Releases** 和 **Draft a new release**。
+2. 输入你需要发布的版本号。版本控制是基于 [Git tags](https://git-scm.com/book/en/Git-Basics-Tagging) 工作的,建议按照 [About Major and Minor NexT versions](https://github.com/theme-next/hexo-theme-next/issues/187) 确定版本号。
+3. 确定你需要发布的分支。除非发布测试版本,通常情况下选择 `master` 分支。
+4. 输入发布版本的标题和说明。
+ - 标题为版本号。
+ - 所有内容更改的类型包括了 **Breaking Changes**, **Updates**, **Features** 和 **Bugfixes**。在描述 Breaking Changes 时,使用二级标题分别陈述,描述其他类型时,使用项目列表陈述。
+ - 使用被动语态,省略主语。
+ - 所有的变化都需要记录在版本说明中。对于没有使用 PR 的更改,需要添加相应的 commit 编号。如果使用了 PR 进行合并修改,则直接添加相应的 PR 编号即可。
+5. 如果您希望随版本一起发布二进制文件(如编译的程序),请在上传二进制文件对话框中手动拖放或选择文件。
+6. 如果版本不稳定,请选择 **This is a pre-release**,以通知用户它尚未完全准备好。如果您准备公布您的版本,请点击 **Publish release**。否则,请单击 **Save draft** 以稍后处理。
+
+
+## 规范
+
+
+### 行为规范
+
+为了保证本项目的顺利运作,所有参与人都需要遵守[行为规范](CODE_OF_CONDUCT.md)。
+
+
+### 编码规范
+
+未完待续。
+
+
+### 提交信息规范
+
+我们对项目的 git 提交信息格式进行统一格式约定,每条提交信息由 `type`+`subject` 组成,这将提升项目日志的可读性。
+
+- `type` 用于表述此次提交信息的意义,首写字母大写,包括但不局限于如下类型:
+ * `Build`:基础构建系统或依赖库的变化
+ * `Ci`:CI 构建系统及其脚本变化
+ * `Docs`:文档内容变化
+ * `Feat`:新功能
+ * `Fix`:Bug 修复
+ * `Perf`:性能优化
+ * `Refactor`:重构(即不是新增功能,也不是修改 Bug 的代码变动)
+ * `Style`:格式(不影响代码运行的变动)
+ * `Revert`:代码回滚
+ * `Release`:版本发布
+- `subject` 用于简要描述修改变更的内容,如 `Update code highlighting in readme.md`。
+ * 句尾不要使用符号。
+ * 使用现在时、祈使句语气。
diff --git a/docs/zh-CN/DATA-FILES.md b/docs/zh-CN/DATA-FILES.md
new file mode 100644
index 000000000..624931bb6
--- /dev/null
+++ b/docs/zh-CN/DATA-FILES.md
@@ -0,0 +1,61 @@
+数据文件
+
+目前,通过 pull 或下载新的 release 版本来更新 NexT 主题的体验并不平滑。当用户使用 `git pull` 更新 NexT 主题时经常需要解决冲突问题,而在手动下载 release 版本时也经常需要手动合并配置。
+
+现在来说,NexT 推荐用户存储部分配置在站点的 `_config.yml` 中,而另一部分在主题的 `_config.yml` 中。这一方式固然可用,但也有一些缺点:
+1. 配置项被分裂为两部分;
+2. 用户难以弄清何处存放配置选项。
+
+为了解决这一问题,NexT 将利用 Hexo 的[数据文件](https://hexo.io/docs/data-files.html)特性。因为数据文件是在 Hexo 3 中被引入,所以你需要更新至 Hexo 3.0 以后的版本来使用这一特性。
+
+如果你仍然希望使用 Hexo 2.x,你依旧可以按老的方式进行配置。NexT 仍然兼容 Hexo 2.x(但可能会出现错误)。
+
+选择 1:Hexo 方式
+
+使用这一方式,你的全部配置都将置于 hexo 主要配置文件中(`hexo/_config.yml`),并且不需要修改 `next/_config.yml`,或者创建什么其他的文件。但是所有的主题选项必须放置在 `theme_config` 后,并全部增加两个空格的缩进。
+
+如果在新的 release 中出现了任何新的选项,那么你只需要从 `next/_config.yml` 中将他们复制到 `hexo/_config.yml` 中并设置它们的值为你想要的选项。
+
+### 用法
+
+1. 请确认不存在 `hexo/source/_data/next.yml` 文件(如果已存在,请删除)
+2. 从主题的 `next/_config.yml` 文件中复制你需要的 NexT 配置项到 `hexo/_config.yml` 中,然后\
+ 2.1. 所有这些配置项右移两个空格(在 Visual Studio Code 中:选中这些文字,CTRL + ])。\
+ 2.2. 在这些参数最上方添加一行 `theme_config:`。
+
+### 相关链接
+
+* [Hexo 配置](https://hexo.io/zh-cn/docs/configuration.html)
+* [Hexo Pull #757](https://github.com/hexojs/hexo/pull/757)
+
+选择 2: NexT 方式
+
+使用这一方式,你现在可以将你的全部配置置于同一位置(`source/_data/next.yml`),并且不需要修改 `next/_config.yml`。
+但是可能无法让所有 Hexo 外部库都准确处理它们的附加选项(举个例子,`hexo-server` 模块只会从 Hexo 默认配置文件中读取选项)。
+
+如果在新的 release 中出现了任何新的选项,那么你只需要从 `next/_config.yml` 中将他们复制到 `source/_data/next.yml` 中并设置它们的值为你想要的选项。
+
+### 用法
+
+1. 请确认你的 Hexo 版本为 3.0 或更高。
+2. 在你站点的 `hexo/source/_data` 目录创建一个 `next.yml` 文件(如果 `_data` 目录不存在,请创建之)。
+
+以上步骤之后有 两种选择,请任选其一然后继续后面的步骤。
+
+* **选择 1:`override: false`(默认)**:
+
+ 1. 检查默认 NexT 配置中的 `override` 选项,必须设置为 `false`。\
+ 在 `next.yml` 文件中,也要设置为 `false`,或者不定义此选项。
+ 2. 从站点的 `_config.yml` 与主题的 `_config.yml` 中复制你需要的选项到 `hexo/source/_data/next.yml` 中。
+
+* **选择 2:`override: true`**:
+
+ 1. 在 `next.yml` 中设置 `override` 选项为 `true`。
+ 2. 从 `next/_config.yml` 配置文件中复制**所有**的 NexT 主题选项到 `hexo/source/_data/next.yml` 中。
+
+3. 然后,在站点的 `hexo/_config.yml`中需要定义 `theme: next` 选项(如果需要的话,`source_dir: source`)。
+4. 使用标准参数来启动服务器,生成或部署(`hexo clean && hexo g -d && hexo s`)。
+
+### 相关链接
+
+* [NexT Issue #328](https://github.com/iissnan/hexo-theme-next/issues/328)
diff --git a/docs/zh-CN/INSTALLATION.md b/docs/zh-CN/INSTALLATION.md
new file mode 100644
index 000000000..7ea4b8808
--- /dev/null
+++ b/docs/zh-CN/INSTALLATION.md
@@ -0,0 +1,120 @@
+安装
+
+步骤 1 → 进入 Hexo 目录
+
+进入 **hexo 根**目录。这一目录中应当有 `node_modules`、`source`、`themes` 等若干子目录:
+ ```sh
+ $ cd hexo
+ $ ls
+ _config.yml node_modules package.json public scaffolds source themes
+ ```
+
+步骤 2 → 获取 NexT
+
+从 GitHub 下载主题。
+为了下载这一主题,共有 3 种选项可选。你需要选择其中唯一一个方式。
+
+### 选项 1:下载[最新 release 版本][releases-latest-url]
+
+ 通常情况下请选择 **stable** 版本。推荐不熟悉的用户按此方式进行。
+
+ * 使用 [curl、tar 和 wget][curl-tar-wget-url] 安装:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -s https://api.github.com/repos/theme-next/hexo-theme-next/releases/latest | grep tarball_url | cut -d '"' -f 4 | wget -i - -O- | tar -zx -C themes/next --strip-components=1
+ ```
+ 这种方式将**仅提供最新的 release 版本**(其中不附带 `.git` 目录)。\
+ 因此,将来你将不可能通过 `git` 更新这一方式安装的主题。\
+ 取而代之的,为了能不丢失你的自定义配置,你可以使用独立的配置文件(例如 [数据文件][docs-data-files-url])并下载最新版本到旧版本的目录中(或者下载到新的主题目录中并修改 Hexo 配置中的主题名)。
+
+### 选项 2:下载 [tag 指向的 release 版本][releases-url]
+
+ 在少数情况下将有所帮助,但这并非推荐方式。\
+ 你必须指定一个版本:使用 [tags 列表][tags-url]中的任意 tag 替换 `v6.0.0`。
+
+ * 方式 1:使用 [curl 和 tar][curl-tar-url] 安装:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -L https://api.github.com/repos/theme-next/hexo-theme-next/tarball/v6.0.0 | tar -zxv -C themes/next --strip-components=1
+ ```
+ 和上述的 `curl、tar 和 wget` 方法相同,但只会下载**指定的 release 版本**。
+
+ * 方式 2:使用 [git][git-url] 安装:
+
+ ```sh
+ $ git clone --branch v6.0.0 https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+ 这一方式将为你下载**指定的 release 版本**(其中包含 `.git` 目录)。\
+ 并且,你可以随时切换到任何已定义的版本号所对应的 tag 的版本。
+
+### 选项 3:下载[最新 master 分支][download-latest-url]
+
+ 可能**不稳定**,但包含最新的特性。推荐进阶用户和开发者按此方式进行。
+
+ * 方式 1:使用 [curl 和 tar][curl-tar-url] 安装:
+
+ ```sh
+ $ mkdir themes/next
+ $ curl -L https://api.github.com/repos/theme-next/hexo-theme-next/tarball | tar -zxv -C themes/next --strip-components=1
+ ```
+ 和上述的 `curl、tar 和 wget` 方法相同,但只会下载**最新 master 分支版本**。\
+ 在有些情况对开发者有所帮助。
+
+ * 方式 2:使用 [git][git-url] 安装:
+
+ ```sh
+ $ git clone https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+
+ 这一方式将为你下载**完整仓库**(其中包含 `.git` 目录)。\
+ 你可以随时[使用 git 更新至最新版本][update-with-git-url]并切换至任何有 tag 标记的 release 版本、最新的 master 分支版本、甚至其他分支。\
+ 在绝大多数情况下对用户和开发者友好。
+
+ 获取 tags 列表:
+
+ ```sh
+ $ cd themes/next
+ $ git tag -l
+ …
+ v6.0.0
+ v6.0.1
+ v6.0.2
+ ```
+
+ 例如,假设你想要切换到 `v6.0.1` 这一 [tag 指向的 release 版本][tags-url]。输入如下指令:
+
+ ```sh
+ $ git checkout tags/v6.0.1
+ Note: checking out 'tags/v6.0.1'.
+ …
+ HEAD is now at da9cdd2... Release v6.0.1
+ ```
+
+ 然后,假设你想要切换回 [master 分支][commits-url],输入如下指令即可:
+
+ ```sh
+ $ git checkout master
+ ```
+
+步骤 3 → 完成配置
+
+在 **hexo 根配置**文件 `_config.yml` 中设置你的主题:
+
+```yml
+theme: next
+```
+
+[download-latest-url]: https://github.com/theme-next/hexo-theme-next/archive/master.zip
+[releases-latest-url]: https://github.com/theme-next/hexo-theme-next/releases/latest
+[releases-url]: https://github.com/theme-next/hexo-theme-next/releases
+[tags-url]: https://github.com/theme-next/hexo-theme-next/tags
+[commits-url]: https://github.com/theme-next/hexo-theme-next/commits/master
+
+[git-url]: http://lmgtfy.com/?q=linux+git+install
+[curl-tar-url]: http://lmgtfy.com/?q=linux+curl+tar+install
+[curl-tar-wget-url]: http://lmgtfy.com/?q=linux+curl+tar+wget+install
+
+[update-with-git-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/zh-CN/README.md#update
+[docs-data-files-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/zh-CN/DATA-FILES.md
diff --git a/docs/zh-CN/LEANCLOUD-COUNTER-SECURITY.md b/docs/zh-CN/LEANCLOUD-COUNTER-SECURITY.md
new file mode 100644
index 000000000..a13d4c0b5
--- /dev/null
+++ b/docs/zh-CN/LEANCLOUD-COUNTER-SECURITY.md
@@ -0,0 +1,185 @@
+在配置前,请升级NexT至**v6.0.6**以上。
+
+在配置过程中请注意**博客配置文件**和**主题配置文件**的区别。
+
+---
+
+# 注册Leancloud并创建应用
+- 首先,前往Leancloud官网[leancloud.cn](leancloud.cn)进行注册,并登陆。
+- 然后点击图示`1`处,进入控制台:
+
+ ![1](https://lc-cqha0xyi.cn-n1.lcfile.com/fc0c048a1e25dc3d10aa.jpg)
+
+- 接着,点击图示`1`处,创建应用:
+
+ ![2](https://lc-cqha0xyi.cn-n1.lcfile.com/33a56b754753a5d34b01.jpg)
+
+- 在弹出窗口`1`处输入应用名称(可随意输入,可更改,为演示方便取名为test),并选择`2`处“开发版”,然后点击`3`处创建:
+
+ ![3](https://lc-cqha0xyi.cn-n1.lcfile.com/649ccfc6f12015d1eefb.jpg)
+
+到这里应用创建完成。
+
+# 建立Counter类并在NexT中启用插件
+- 点击`1`处应用名称进入应用管理界面:
+
+ ![4](https://lc-cqha0xyi.cn-n1.lcfile.com/d0889df29841661e0b9e.jpg)
+
+- 如图,点击侧边栏`1`处创建Class:
+
+ ![5](https://lc-cqha0xyi.cn-n1.lcfile.com/b0fbc81bd6c19fa09a46.jpg)
+
+- 在弹出窗口`1`处填入`Counter`,勾选`2`处无限制,并点击`3`处创建Class:
+
+ ![6](https://lc-cqha0xyi.cn-n1.lcfile.com/ae6154d6a55f02f11ebf.jpg)
+
+- 此时类已创建完成。接下来点击图示`1`处进入设置,然后点击`2`处进入应用Key:
+
+ ![8](https://lc-cqha0xyi.cn-n1.lcfile.com/9501a6372918dd9a8a92.jpg)
+
+- 粘贴`App ID`和`App Key`到**NexT主题配置文件**`_config.yml`对应位置。此时配置文件应如下:
+```yml
+leancloud_visitors:
+ enable: true
+ security: true
+ app_id: <>
+ app_key: <>
+```
+
+- 设置Web安全域名确保域名调用安全。点击`1`处进入安全中心,然后在`2`处填写自己博客对应的域名(**注意协议、域名和端口号需严格一致**):
+
+ ![9](https://lc-cqha0xyi.cn-n1.lcfile.com/0e537cc4bec2e185201d.jpg)
+
+到这里内容均与Doublemine的[为NexT主题添加文章阅读量统计功能](https://notes.wanghao.work/2015-10-21-%E4%B8%BANexT%E4%B8%BB%E9%A2%98%E6%B7%BB%E5%8A%A0%E6%96%87%E7%AB%A0%E9%98%85%E8%AF%BB%E9%87%8F%E7%BB%9F%E8%AE%A1%E5%8A%9F%E8%83%BD.html#%E9%85%8D%E7%BD%AELeanCloud)这篇文章相同,只不过截图为新版的Leancloud的界面。
+
+# 部署云引擎以保证访客数量不被随意篡改
+- 点击左侧`1`处云引擎,然后点击`2`处部署,再点击`3`处在线编辑:
+
+ ![10](https://lc-cqha0xyi.cn-n1.lcfile.com/d7056dfeeef7c5d66318.jpg)
+
+- 点击`1`处创建函数:
+
+ ![11](https://lc-cqha0xyi.cn-n1.lcfile.com/2737841bbc2bdd572ae0.jpg)
+
+- 在弹出窗口选择`1`处`Hook`类型,然后`2`处选择`beforeUpdate`,`3`处选择刚才建立的`Counter`类。在`4`中粘贴下方代码后,点`5`处保存。
+ ```javascript
+ var query = new AV.Query("Counter");
+ if (request.object.updatedKeys.indexOf('time') !== -1) {
+ return query.get(request.object.id).then(function (obj) {
+ if (obj.get("time") + 1 !== request.object.get("time")) {
+ throw new AV.Cloud.Error('Invalid update!');
+ }
+ })
+ }
+ ```
+
+ 如图所示:
+
+ ![12](https://lc-cqha0xyi.cn-n1.lcfile.com/a8e13418ed1d9405315b.jpg)
+
+- 点击保存后应出现类似红框处函数。此时点击`1`处部署:
+
+ ![13](https://lc-cqha0xyi.cn-n1.lcfile.com/ca56bf2e5fc2a1343565.jpg)
+
+- 在弹出窗口点击`1`处部署:
+
+ ![14](https://lc-cqha0xyi.cn-n1.lcfile.com/17548c13b3b23c71d845.jpg)
+
+- 等待出现红框处的成功部署信息后,点击`1`处关闭:
+
+ ![15](https://lc-cqha0xyi.cn-n1.lcfile.com/d2f50de6cefea9fd0ed3.jpg)
+
+
+至此云引擎已成功部署,任何非法的访客数量更改请求都将失败。
+
+# 进一步设置权限
+- 打开**NexT主题配置文件**`_config.yml`,将leancloud_visitors下的security设置为true(如没有则新增):
+ ```yml
+ leancloud_visitors:
+ enable: true
+ app_id: <>
+ app_key: <>
+ # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security
+ security: true
+ betterPerformance: false
+ ```
+
+ **对`betterPerformance`选项的说明:**
+ 由于Leancloud免费版的云引擎存在请求线程数和运行时间限制以及休眠机制,很多时候访客数量加载会很慢。如果设置`betterPerformance`为`true`,则网页则会在提交请求之前直接显示访客人数为查询到的人数+1,以增加用户体验。
+
+- 打开cmd并切换至**博客根目录**,键入以下命令以安装`hexo-leancloud-counter-security`插件:
+ ```
+ npm install hexo-leancloud-counter-security --save
+ ```
+
+- 打开**博客配置文件**`_config.yml`,新增以下配置:
+ ```yml
+ leancloud_counter_security:
+ enable_sync: true
+ app_id: <>
+ app_key: <
+ username:
+ password:
+ ```
+
+- 在相同目录键入以下命令:
+ ```
+ hexo lc-counter register <> <>
+ ```
+ 或
+ ```
+ hexo lc-counter r <> <>
+ ```
+
+ 将`<>`和`<>`替换为你自己的用户名和密码(不必与leancloud的账号相同)。此用户名和密码将在hexo部署时使用。
+
+ - 打开**博客配置文件**`_config.yml`,将`<>`和`<>`替换为你刚刚设置的用户名和密码:
+ ```yml
+ leancloud_counter_security:
+ enable_sync: true
+ app_id: <>
+ app_key: <
+ username: <> #如留空则将在部署时询问
+ password: <> #建议留空以保证安全性,如留空则将在部署时询问
+ ```
+
+- 在**博客配置文件**`_config.yml`的`deploy`下添加项:
+ ```yml
+ deploy:
+ # other deployer
+ - type: leancloud_counter_security_sync
+ ```
+
+- 返回Leancloud控制台的应用内。依次点击`1` `2`,检查_User表中是否出现一条记录(图示以用户名为admin为例):
+
+ ![16](https://lc-cqha0xyi.cn-n1.lcfile.com/99faa5a0e7160e66d506.jpg)
+
+- 点击`1`处进入Counter表,依次点击`2` `3`,打开权限设置:
+
+ ![17](https://lc-cqha0xyi.cn-n1.lcfile.com/b72a9e64579f5b71749d.jpg)
+
+- 点击`1`add_fields后选择`2`指定用户, 并将下两栏留空:此处应与下条create设置相同(选择你所创建的用户):
+
+ ![18](https://lc-cqha0xyi.cn-n1.lcfile.com/14a8cb37062693d768ad.jpg)
+
+- 点击`1`create后选择`2`指定用户, 在`3`处键入用户名,点击`4`处后点击`5`处添加:
+
+ ![19](https://lc-cqha0xyi.cn-n1.lcfile.com/d91714cfd703ef42b94c.jpg)
+
+ 完成此步操作后,界面应与图示类似:
+
+ ![20](https://lc-cqha0xyi.cn-n1.lcfile.com/c05e7ec9218820baf412.jpg)
+
+- 点击`1`delete后选择`2`指定用户, 并将下两栏留空:
+
+ ![21](https://lc-cqha0xyi.cn-n1.lcfile.com/c37b6e20726cfb1d3197.jpg)
+
+至此权限已设置完成,数据库记录只能在本地增删。
+
+每次运行`hexo d`部署的时候,插件都会扫描本地`source/_posts`下的文章并与数据库对比,然后在数据库创建没有录入数据库的文章记录。
+
+如果在**博客配置文件**中留空username或password,则在部署过程中程序会要求输入。
+
+---
+
+原文链接:https://leaferx.online/2018/02/11/lc-security/
diff --git a/docs/zh-CN/MATH.md b/docs/zh-CN/MATH.md
new file mode 100644
index 000000000..fcb096e72
--- /dev/null
+++ b/docs/zh-CN/MATH.md
@@ -0,0 +1,297 @@
+数学公式
+
+NexT 内部提供数学公式渲染的引擎,这样你就不需要自己手动在模板中引入 JS 或者 CSS;
+只需要将 `next/_config.yml` 中 `math` 的 `enable` 选项改为 `true`,并选择对应的渲染引擎即可:
+
+
+```yml
+math:
+ enable: true
+ ...
+ engine: mathjax
+```
+
+
+需要注意的是,仅仅将 `math` 的 `enable` 打开**并不能让你看到数学公式**,你还需要**使用对应的 Hexo 渲染器(Renderer)** 才能真正在博客页面中显示出数学公式。引擎对应使用的 Hexo 渲染器会在引擎相关的部分介绍。
+
+提供的渲染引擎
+
+目前,NexT 提供两种数学公式渲染引擎,分别为 [MathJax](https://www.mathjax.org/) 和 [Katex](https://khan.github.io/KaTeX/),默认为 MathJax。
+
+### MathJax(默认)
+
+如果你选择使用 MathJax 进行数学公式渲染,你需要使用 [hexo-renderer-pandoc](https://github.com/wzpan/hexo-renderer-pandoc) 或者 [hexo-renderer-kramed](https://github.com/sun11/hexo-renderer-kramed) 这两个渲染器的其中一个。
+
+首先,卸载原有的渲染器 `hexo-renderer-marked`,并安装这两种渲染器的**其中一个**:
+
+```sh
+npm un hexo-renderer-marked --save
+npm i hexo-renderer-pandoc --save # 或者 hexo-renderer-kramed
+```
+
+
+然后在 `next/_config.yml` 中将 `math` 的 `enable` 打开,并选择 `mathjax` 作为渲染引擎。
+
+```yml
+math:
+ enable: true
+ ...
+ engine: mathjax
+ #engine: katex
+```
+
+执行 Hexo 生成,部署,或者启动服务器:
+
+```sh
+hexo clean && hexo g -d
+# 或者 hexo clean && hexo s
+```
+
+#### 使用 MathJax 给公式编号并引用公式
+
+在新版本的 NexT 主题中,我们加入了公式自动编号和引用功能。下面简要介绍一下如何使用这项功能。
+
+为了使用这项功能,一般来说,你必须把所使用的 LaTeX 公式放在 `equation` 环境里面,采用旧的方法(也就是说,仅仅把公式的每一边用两个 $ 符号包含起来)是无效的。如何引用公式?你只需要在书写公式的时候给公式一个 `\
+label{}` 标记(tag),然后在正文中,可以使用 `\ref{}` 或者 `\eqref{}` 命令来引用对应的公式。使用 `\eqref{}` 是推荐的方式,因为如果你使用 `\ref{}`,公式在文中的引用编号将没有圆括号包围。下面介绍几种常见的公式编号例子。
+
+对于简单的公式,使用下面的方式给公式一个标记,
+
+```latex
+$$\begin{equation}
+e=mc^2
+\end{equation}\label{eq1}$$
+```
+
+然后,在正文中,你可以轻松引用上述公式,一个简单的例子如下:
+
+```
+著名的质能方程 $\eqref{eq1}$ 由爱因斯坦提出 ...
+```
+
+对于多行公式,在 `equation` 环境中,你可以使用 `aligned` 环境把公式分成多行,
+
+```latex
+$$\begin{equation}
+\begin{aligned}
+a &= b + c \\
+ &= d + e + f + g \\
+ &= h + i
+\end{aligned}
+\end{equation}\label{eq2}$$
+```
+
+要对齐多个公式,我们需要使用 `align` 环境。align 环境中的每个公式都有自己的编号:
+
+```
+$$\begin{align}
+a &= b + c \label{eq3} \\
+x &= yz \label{eq4}\\
+l &= m - n \label{eq5}
+\end{align}$$
+```
+
+在 `align` 环境中,如果你不想给某个或某几个公式编号,那么在这些公式后面使用 [`\nonumber`](https://tex.stackexchange.com/questions/17528/show-equation-number-only-once-in-align-environment) 命令即可。例如:
+
+```latex
+$$\begin{align}
+-4 + 5x &= 2+y \nonumber \\
+ w+2 &= -1+w \\
+ ab &= cb
+\end{align}$$
+```
+
+有时,你可能会希望采用更加奇特的方式来标记和引用你的公式,你可以通过使用 `\tag{}` 命令来实现,例如:
+
+```latex
+$$x+1\over\sqrt{1-x^2} \tag{i}\label{eq_tag}$$
+```
+
+如果你想要了解更多信息,请访问 [MathJax 关于公式编号的官方文档](http://docs.mathjax.org/en/latest/tex.html#automatic-equation-numbering)。同时,你也可以访问[这篇博客](https://jdhao.github.io/2018/01/25/hexo-mathjax-equation-number/) 来获取更多细节信息。
+
+### Katex
+
+Katex 渲染引擎相对于 MathJax 来说**大大提高了速度**,而且在关掉 JavaScript 时也能渲染数学公式。
+
+但是 Katex 所支持的东西没有 MathJax 全面,你可以从下面的相关链接中获取更多的信息。
+
+如果你选择使用 Katex 进行数学公式渲染,你需要使用 [hexo-renderer-markdown-it-plus](https://github.com/CHENXCHEN/hexo-renderer-markdown-it-plus) 或者 [hexo-renderer-markdown-it](https://github.com/hexojs/hexo-renderer-markdown-it) 这两种渲染器的其中一个。
+
+首先,卸载原有的渲染器 `hexo-renderer-marked`,并安装这两种渲染器的**其中一个**:
+
+```sh
+npm un hexo-renderer-marked --save
+npm i hexo-renderer-markdown-it-plus --save
+# 或者 hexo-renderer-markdown-it
+```
+
+
+然后在 `next/_config.yml` 中将 `math` 的 `enable` 打开,并选择 `katex` 作为渲染引擎。
+
+```yml
+math:
+ enable: true
+ ...
+ #engine: mathjax
+ engine: katex
+```
+
+执行 Hexo 生成,部署,或者启动服务器:
+
+```sh
+hexo clean && hexo g -d
+# 或者 hexo clean && hexo s
+```
+
+#### 如果你使用 hexo-renderer-markdown-it
+
+如果你使用 `hexo-renderer-markdown-it`,你还需要为其加上 `markdown-it-katex` 作为插件:
+
+```
+npm i markdown-it-katex --save
+```
+
+然后在 `hexo/_config.yml` 中将 `markdown-it-katex` 作为插件写入 `hexo-renderer-markdown-it` 的配置中:
+
+```yml
+markdown:
+ render:
+ html: true
+ xhtmlOut: false
+ breaks: true
+ linkify: true
+ typographer: true
+ quotes: '“”‘’'
+ plugins:
+ - markdown-it-katex
+```
+
+#### 已知的问题
+
+1. 首先请查阅 Katex 的 [Common Issue](https://github.com/Khan/KaTeX#common-issues)
+2. 块级公式(例如 `$$...$$`)必须位于空行。\
+ 即在开头的 `$$` 前和在结尾的 `$$` 后不能有除了空白字符以外的其他字符。([#32comment](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-357489509))
+3. 不支持 Unicode。([#32comment](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-357489509))
+4. 行内公式(例如 `$...$`)在开头的 `$` 后面和结尾的 `$` 前面**不能含有空格**。([#32comment](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-357489509))
+5. 如果你在文章的各级标题中(例如 `## 标题`)使用公式。\
+ 那么文章目录中的这个标题会出现 3 次未渲染的公式代码([#32comment](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-359018694))
+6. 如果你在文章 Title 中使用公式,那么公式将不会被渲染。([#32comment](https://github.com/theme-next/hexo-theme-next/pull/32#issuecomment-359142879))
+
+
+我们目前使用的 Katex 版本为 0.7.1,这里面可能有某些问题是因为 Katex 版本老旧导致的;
+
+但是,就像上面所说的,数学公式的渲染必须依靠渲染器来支持,目前的 Katex 相关的渲染器仅支持到 Katex 0.7.1;
+
+我们会持续关注相关渲染器的更新,如果有渲染器支持更高版本的 Katex,我们会及时更新我们的 Katex 版本。
+
+### 相关链接
+
+* [Katex 与 MathJax 渲染速度对比](https://www.intmath.com/cg5/katex-mathjax-comparison.php)
+* [Katex 支持的功能列表](https://khan.github.io/KaTeX/function-support.html)
+
+相关配置说明
+
+注意,在修改配置选项时,**不要更改配置的缩进**;
+
+目前,NexT 的所有配置都采用**2 空格的缩进**;
+
+如果配置的内容接在冒号后面,那么内容和冒号之间必须有一个空格(例如`enable: true`)
+
+```yml
+
+# Math Equations Render Support
+math:
+ enable: false
+
+ # Default(true) will load mathjax/katex script on demand
+ # That is it only render those page who has 'mathjax: true' in Front Matter.
+ # If you set it to false, it will load mathjax/katex srcipt EVERY PAGE.
+ per_page: true
+
+ engine: mathjax
+ #engine: katex
+
+ # hexo-rendering-pandoc (or hexo-renderer-kramed) needed to full MathJax support.
+ mathjax:
+ # Use 2.7.1 as default, jsdelivr as default CDN, works everywhere even in China
+ cdn: //cdn.jsdelivr.net/npm/mathjax@2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+ # For newMathJax CDN (cdnjs.cloudflare.com) with fallback to oldMathJax (cdn.mathjax.org).
+ #cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+ # For direct link to MathJax.js with CloudFlare CDN (cdnjs.cloudflare.com).
+ #cdn: //cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML
+ # For automatic detect latest version link to MathJax.js and get from Bootcss.
+ #cdn: //cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML
+
+ # hexo-renderer-markdown-it-plus (or hexo-renderer-markdown-it with markdown-it-katex plugin)
+ # needed to full Katex support.
+ katex:
+ # Use 0.7.1 as default, jsdelivr as default CDN, works everywhere even in China
+ cdn: //cdn.jsdelivr.net/npm/katex@0.7.1/dist/katex.min.css
+ # CDNJS, provided by cloudflare, maybe the best CDN, but not works in China
+ #cdn: //cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css
+ # Bootcss, works great in China, but not so well in other region
+ #cdn: //cdn.bootcss.com/KaTeX/0.7.1/katex.min.css
+```
+
+### enable
+
+`true` 或者 `false`,默认为 `false`。
+
+`true` 是打开数学公式渲染,`false` 则是关闭。
+
+### per_page
+
+`true` 或者 `false`,默认为 `true`。
+
+这个选项是控制是否在每篇文章都渲染数学公式;
+
+默认(`true`) 的行为是**只对 Front Matter 中含有 `mathjax: true` 的文章进行数学公式渲染**。
+
+如果 Front Matter 中不含有 `mathjax: true`,或者 `mathjax: false`,那么 NexT 将不会对这些文章进行数学公式渲染。
+
+例如:
+
+```md
+
+---
+title: 'Will Render Math'
+mathjax: true
+---
+....
+```
+
+```md
+
+---
+title: 'Not Render Math'
+mathjax: false
+---
+....
+```
+
+```md
+
+---
+title: 'Not Render Math Either'
+---
+....
+```
+
+当你将它设置为 `false` 时,它就会在每个页面都加载 MathJax 或者 Katex 来进行数学公式渲染。
+
+### cdn
+
+MathJax 和 Katex 都提供了 `cdn` 的配置,如果你不知道什么是 `cdn` ,**请不要修改这个配置**。
+
+首先,MathJax 和 Katex 都使用了 [jsDelivr](https://www.jsdelivr.com/) 作为默认 CDN;
+
+之所以选择 jsDelivr 是因为它在全球各地都有比较不错的速度,而且具有中国官方颁布的 ICP 证书,在中国也能比较好地访问。
+
+同时,我们也提供了其他的 CDN 备选方案,包括著名的 [CDNJS](https://cdnjs.com/) 和在中国地区具有不错访问效果的 [Bootcss](http://www.bootcdn.cn/)。
+
+对于 MathJax 来说,我们目前采用的版本为 2.7.1。
+
+对于 Katex,由于上面提到的版本问题,我们目前采用的版本为 0.7.1。
+
+如果你想尝试我们提供的备选方案以外的 CDN,请注意使用对应的版本。
+
+特别的,对于中国的博客主,或者您的博客访问大部分来源于中国,由于 CDNJS 在部分中国地区被墙,请不要使用 CDNJS 作为 CDN。
diff --git a/docs/zh-CN/README.md b/docs/zh-CN/README.md
new file mode 100644
index 000000000..be209f975
--- /dev/null
+++ b/docs/zh-CN/README.md
@@ -0,0 +1,138 @@
+
+
+#
+
+«NexT» 是一款风格优雅的高质量 Hexo 主题,自点点滴滴中用爱雕琢而成。
+
+[![gitter-image]][gitter-url]
+[![riot-image]][riot-url]
+[![t-chat-image]][t-chat-url]
+[![t-news-image]][t-news-url]
+[![lang-image]][lang-url]
+[![travis-image]][travis-url]
+[![rel-image]][releases-url]
+[![hexo-image]][hexo-url]
+[![lic-image]][lic-url]
+
+## 即时预览
+
+* :heart_decoration: Muse 主题: [LEAFERx](https://leaferx.online) | [XiaMo](https://notes.wanghao.work) | [OAwan](https://oawan.me)
+* :six_pointed_star: Mist 主题: [Jeff](https://blog.zzbd.org) | [uchuhimo](http://uchuhimo.me) | [xirong](http://www.ixirong.com)
+* :pisces: Pisces 主题: [Vi](http://notes.iissnan.com) | [Acris](https://acris.me) | [Rainy](https://rainylog.com)
+* :gemini: Gemini 主题: [Ivan.Nginx](https://almostover.ru) | [Raincal](https://raincal.com) | [Dandy](https://dandyxu.me)
+
+更多 «NexT» 的例子参见[这里](https://github.com/iissnan/hexo-theme-next/issues/119)。
+
+## 安装
+
+最简单的安装方式是直接克隆整个仓库:
+
+ ```sh
+ $ cd hexo
+ $ git clone https://github.com/theme-next/hexo-theme-next themes/next
+ ```
+
+此外,如果你想要使用其他方式,你也可以参见[详细安装步骤][docs-installation-url]。
+
+## 插件
+
+在 NexT 配置中你现在可以找到已经被移至外部仓库的依赖项。你可以在[组织主页](https://github.com/theme-next)中找到它们。
+
+例如,假设你想要在你的站点中使用 `fancybox` 插件,请进入 NexT 配置文件,你会看到如下内容:
+
+```yml
+# Fancybox
+# Dependencies: https://github.com/theme-next/theme-next-fancybox
+fancybox: false
+```
+
+将 `fancybox` 配置项打开,进入它上面的 «Dependencies» 链接以查看它的安装步骤。
+
+### 例外
+
+如果你使用的插件脚本依赖 CDN,那么需要替换你的 CDN 链接:
+
+例如,假如你使用了 `fancybox` 插件并且配置了 CDN 加载链接,进入 Next 配置文件,你会看到如下内容:
+
+```yml
+vendors:
+ # ...
+ # Some contents...
+ # ...
+ fancybox: # Set or update fancybox cdn url.
+ fancybox_css: # Set or update fancybox cdn url.
+```
+
+通过替换 CDN 链接来替换 [插件列表](https://github.com/theme-next) 项目来升级。
+
+## 更新
+
+你可以通过如下命令更新到最新的 master 分支:
+
+```sh
+$ cd themes/next
+$ git pull
+```
+
+如果你在此过程中收到了任何错误报告 (例如 **«Commit your changes or stash them before you can merge»**),我们推荐你使用 [Hexo 数据文件][docs-data-files-url]特性。\
+然而你也可以通过提交(`Commit`)、贮藏(`Stash`)或忽视(`Discard`)本地更改以绕过这种更新错误。具体方法请参考[这里](https://stackoverflow.com/a/15745424/5861495)。
+
+**如果你想要从 v5.1.x 更新到 v6.0.x,阅读[这篇文档][docs-update-5-1-x-url]。**
+
+## 已知问题
+
+对于仍然遇到 **«[Error: Cannot find module 'hexo-util'](https://github.com/iissnan/hexo-theme-next/issues/1490)»** 这一错误的用户,请检查你的 NPM 版本。
+
+* `> 3`:仍然出现错误吗?请删除 `node_modules` 目录并通过 `npm install` 重新安装。
+* `< 3`:请通过 `npm install --save-dev hexo-util` 将 `hexo-util` 依赖手动添加至你的站点依赖包中。
+
+## 贡献你的代码
+
+我们欢迎你贡献出你的一份力量,你可以随时提交 issue 或 fork 本仓库。静候你的 pull request。
+
+## 第三方應用程序
+
+* :triangular_flag_on_post: HexoEditor
+
+[browser-image]: https://img.shields.io/badge/browser-%20chrome%20%7C%20firefox%20%7C%20opera%20%7C%20safari%20%7C%20ie%20%3E%3D%209-lightgrey.svg
+[browser-url]: https://www.browserstack.com
+
+[lang-image]: https://d322cqt584bo4o.cloudfront.net/theme-next/localized.svg "请花几秒钟来添加或修正翻译!"
+[lang-url]: https://crwd.in/theme-next
+
+[gitter-image]: https://img.shields.io/badge/gitter-chat-orange.svg "Join to our Gitter room"
+[gitter-url]: https://gitter.im/theme-next
+
+[riot-image]: https://img.shields.io/badge/riot-chat-DCAB08.svg "Join to our Riot room"
+[riot-url]: https://riot.im/app/#/room/#NexT:matrix.org
+
+[t-chat-image]: https://img.shields.io/badge/telegram-chat-BAB210.svg "Join to our Telegram group"
+[t-chat-url]: https://t.me/theme_next
+
+[t-news-image]: https://img.shields.io/badge/telegram-news-98B919.svg "Join to our Telegram news channel"
+[t-news-url]: https://t.me/theme_next_news
+
+[travis-image]: https://travis-ci.org/theme-next/hexo-theme-next.svg?branch=master
+[travis-url]: https://travis-ci.org/theme-next/hexo-theme-next?branch=master "Travis CI [Linux]"
+
+[hexo-image]: https://img.shields.io/badge/hexo-%3E%3D%203.5.0-blue.svg
+[hexo-url]: http://hexo.io
+
+[lic-image]: https://img.shields.io/badge/license-%20AGPL-blue.svg
+[lic-url]: https://github.com/theme-next/hexo-theme-next/blob/master/LICENSE.md
+
+
+[rel-image]: https://badge.fury.io/gh/theme-next%2Fhexo-theme-next.svg
+
+
+[download-latest-url]: https://github.com/theme-next/hexo-theme-next/archive/master.zip
+[releases-latest-url]: https://github.com/theme-next/hexo-theme-next/releases/latest
+[releases-url]: https://github.com/theme-next/hexo-theme-next/releases
+[tags-url]: https://github.com/theme-next/hexo-theme-next/tags
+[commits-url]: https://github.com/theme-next/hexo-theme-next/commits/master
+
+[docs-installation-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/zh-CN/INSTALLATION.md
+[docs-data-files-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/zh-CN/DATA-FILES.md
+[docs-update-5-1-x-url]: https://github.com/theme-next/hexo-theme-next/blob/master/docs/zh-CN/UPDATE-FROM-5.1.X.md
diff --git a/docs/zh-CN/UPDATE-FROM-5.1.X.md b/docs/zh-CN/UPDATE-FROM-5.1.X.md
new file mode 100644
index 000000000..9a1547aad
--- /dev/null
+++ b/docs/zh-CN/UPDATE-FROM-5.1.X.md
@@ -0,0 +1,29 @@
+从 NexT v5.1.x 更新
+
+在 5.1.x 版本和 6.0.x 版本之间没有很大的革命性改进。主版本号变更至 6 主要是因为:
+
+1. 主仓库已从 [iissnan 名下](https://github.com/iissnan/hexo-theme-next) 迁移至 [theme-next](https://github.com/theme-next) 组织。
+2. `next/source/lib` 目录下的绝大多数库被移出到了 [NexT 组织的外部仓库](https://github.com/theme-next)中。
+3. 第三方插件 [`hexo-wordcount`](https://github.com/willin/hexo-wordcount) 被 [`hexo-symbols-count-time`](https://github.com/theme-next/hexo-symbols-count-time) 所取代,因为 `hexo-symbols-count-time` 没有任何外部 nodejs 依赖、也没有会导致生成站点时的性能问题 [language filter](https://github.com/willin/hexo-wordcount/issues/7)。
+
+推荐通过如下步骤从 v5 升级到 v6:
+
+1. 并不修改原有的 `next` 目录,而只是复制部分 NexT 文件:
+ 1. `config.yml` 或 `next.yml`(如果你使用了[数据文件](DATA-FILES.md))。
+ 2. 自定义的 CSS 配置,它们应在 `next/source/css/_custom/*` 和 `next/source/css/_variables/*` 中。
+ 3. 自定义的排布配置,它们应在 `next/layout/_custom/*` 中。
+ 4. 任何其它可能的附加自定义内容;为了定位它们,你可以通过某些工具在仓库间比较。
+2. 克隆新的 v6.x 仓库到任一异于 `next` 的目录(如 `next-reloaded`):
+ ```sh
+ $ git clone https://github.com/theme-next/hexo-theme-next themes/next-reloaded
+ ```
+ 如此,你可以在不修改原有的 NexT v5.1.x 目录的同时使用 `next-reloaded` 目录中的新版本主题。
+3. 在 Hexo 的主配置文件中设置主题:
+ ```yml
+ ...
+ theme: next-reloaded
+ ...
+ ```
+ 如此,你的 `next-reloaded` 主题将在生成站点时被加载。如果你遇到了任何错误、或只是不喜欢这一新版本,你可以随时切换回旧的 v5.1.x 版本。
+
+关于第三方库的启用,参见[这里](https://github.com/theme-next/hexo-theme-next/blob/master/docs/zh-CN/INSTALLATION.md#插件)。
diff --git a/gulpfile.coffee b/gulpfile.coffee
new file mode 100644
index 000000000..77970d3be
--- /dev/null
+++ b/gulpfile.coffee
@@ -0,0 +1,53 @@
+fs = require('fs')
+path = require('path')
+gulp = require('gulp')
+jshint = require('gulp-jshint')
+stylish = require('jshint-stylish')
+shell = require('gulp-shell')
+yaml = require('js-yaml')
+
+gulp.task 'lint', ->
+ return gulp.src([
+ './source/js/src/utils.js',
+ './source/js/src/motion.js',
+ './source/js/src/algolia-search.js',
+ './source/js/src/bootstrap.js',
+ './source/js/src/post-details.js',
+ './source/js/src/schemes/pisces.js'
+ ]).pipe jshint()
+ .pipe jshint.reporter(stylish)
+
+gulp.task 'lint:stylus', shell.task [
+ '"./node_modules/.bin/stylint" ./source/css/'
+]
+
+gulp.task 'validate:config', (cb) ->
+ themeConfig = fs.readFileSync path.join(__dirname, '_config.yml')
+
+ try
+ yaml.safeLoad(themeConfig)
+ cb()
+ catch error
+ cb new Error(error)
+
+gulp.task 'validate:languages', (cb) ->
+ languagesPath = path.join __dirname, 'languages'
+ languages = fs.readdirSync languagesPath
+ errors = []
+
+ for lang in languages
+ languagePath = path.join languagesPath, lang
+ try
+ yaml.safeLoad fs.readFileSync(languagePath), {
+ filename: path.relative(__dirname, languagePath)
+ }
+ catch error
+ errors.push error
+
+ if errors.length == 0
+ cb()
+ else
+ cb(errors)
+
+
+gulp.task 'default', ['lint', 'validate:config', 'validate:languages']
diff --git a/languages/de.yml b/languages/de.yml
new file mode 100644
index 000000000..5305d66e0
--- /dev/null
+++ b/languages/de.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Archiv
+ category: Kategorie
+ tag: Tag
+ schedule: Schedule
+menu:
+ home: Startseite
+ archives: Archiv
+ categories: Kategorien
+ tags: Tags
+ about: Über
+ search: Suche
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: Übersicht
+ toc: Inhaltsverzeichnis
+post:
+ posted: Veröffentlicht am
+ edited: Edited on
+ created: Post created
+ modified: Updated at
+ edit: Edit this post
+ in: in
+ more: more
+ read_more: Weiterlesen
+ untitled: Unbenannt
+ sticky: Sticky
+ toc_empty: Dieser Artikel hat kein Inhaltsverzeichnis
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: Gesamt
+ tags: tags
+footer:
+ powered: "Erstellt mit %s"
+ theme: Theme
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Keine Tags
+ one: Insgesamt ein Tag
+ other: "Insgesamt %d Tags"
+ categories:
+ zero: Keine Kategorien
+ one: Insgesamt eine Kategorie
+ other: "Insgesamt %d Kategorien"
+ archive_posts:
+ zero: Keine Artikel vorhanden.
+ one: Ein Artikel.
+ other: "Insgesamt %d Artikel."
+state:
+ posts: Artikel
+ pages: Seiten
+ tags: Tags
+ categories: Kategorien
+search:
+ placeholder: Searching...
+cheers:
+ um: Öhm..
+ ok: OK
+ nice: Schön
+ good: Gut
+ great: Wunderbar
+ excellent: Exzellent
+keep_on: Bleib dran.
+symbol:
+ comma: ". "
+ period: ", "
+ colon: ": "
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/default.yml b/languages/default.yml
new file mode 120000
index 000000000..7fcfc3b3a
--- /dev/null
+++ b/languages/default.yml
@@ -0,0 +1 @@
+en.yml
\ No newline at end of file
diff --git a/languages/en.yml b/languages/en.yml
new file mode 100644
index 000000000..ed2555172
--- /dev/null
+++ b/languages/en.yml
@@ -0,0 +1,114 @@
+title:
+ archive: Archive
+ category: Category
+ tag: Tag
+ schedule: Schedule
+
+menu:
+ home: Home
+ archives: Archives
+ categories: Categories
+ tags: Tags
+ about: About
+ search: Search
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+
+sidebar:
+ overview: Overview
+ toc: Table of Contents
+
+post:
+ posted: Posted on
+ edited: Edited on
+ created: Created
+ modified: Modified
+ edit: Edit this post
+ in: In
+ more: more
+ read_more: Read more
+ untitled: Untitled
+ sticky: Sticky
+ toc_empty: This post does not have a Table of Contents
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+
+page:
+ totally: Totally
+ tags: tags
+
+footer:
+ powered: "Powered by %s"
+ theme: Theme
+ total_views: Total Views
+ total_visitors: Total Visitors
+
+counter:
+ tag_cloud:
+ zero: No tags
+ one: 1 tag in total
+ other: "%d tags in total"
+
+ categories:
+ zero: No categories
+ one: 1 category in total
+ other: "%d categories in total"
+
+ archive_posts:
+ zero: No posts.
+ one: 1 post.
+ other: "%d posts in total."
+
+state:
+ posts: posts
+ pages: pages
+ tags: tags
+ categories: categories
+
+search:
+ placeholder: Searching...
+
+cheers:
+ um: Um..
+ ok: OK
+ nice: Nice
+ good: Good
+ great: Great
+ excellent: Excellent
+
+keep_on: Keep on posting.
+
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+
+gitmentbutton: Show comments from Gitment
+
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/fr.yml b/languages/fr.yml
new file mode 100644
index 000000000..896e2049d
--- /dev/null
+++ b/languages/fr.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Archive
+ category: Catégorie
+ tag: Tag
+ schedule: Schedule
+menu:
+ home: Accueil
+ archives: Archives
+ categories: Categories
+ tags: Tags
+ about: A propos
+ search: recherche
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: Ensemble
+ toc: Table Des Matières
+post:
+ posted: Posté le
+ edited: Edited on
+ created: Post created
+ modified: Updated at
+ edit: Edit this post
+ in: In
+ more: more
+ read_more: Lire la suite
+ untitled: Non titré
+ sticky: Sticky
+ toc_empty: This post does not have a Table of Contents
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: Total
+ tags: tags
+footer:
+ powered: "Powered by %s"
+ theme: Thème
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Aucun tags
+ one: 1 tag au total
+ other: "%d tags au total"
+ categories:
+ zero: Aucun categories
+ one: 1 category au total
+ other: "%d categories au total"
+ archive_posts:
+ zero: Aucun article.
+ one: 1 article.
+ other: "%d articles au total."
+state:
+ posts: articles
+ pages: pages
+ tags: tags
+ categories: categories
+search:
+ placeholder: Searching...
+cheers:
+ um: Um..
+ ok: OK
+ nice: Jolie
+ good: Bien
+ great: Super
+ excellent: Excellent
+keep_on: Et ca ne fait que commencer.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/id.yml b/languages/id.yml
new file mode 100644
index 000000000..3eb191310
--- /dev/null
+++ b/languages/id.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Arsip
+ category: Kategori
+ tag: Tag
+ schedule: Schedule
+menu:
+ home: Beranda
+ archives: Arsip
+ categories: Kategori
+ tags: Tags
+ about: Tentang
+ search: Pencarian
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: Ikhtisar
+ toc: Daftar Isi
+post:
+ posted: Diposting di
+ edited: Edited on
+ created: Post created
+ modified: Updated at
+ edit: Edit this post
+ in: Di
+ more: more
+ read_more: Baca lebih
+ untitled: Tidak ada title
+ sticky: Sticky
+ toc_empty: Posting ini tidak memiliki Daftar Isi
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: Total
+ tags: tags
+footer:
+ powered: "Powered by %s"
+ theme: Tema
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Tidak ada tags
+ one: 1 total tag
+ other: "%d total tags"
+ categories:
+ zero: Tidak ada kategori
+ one: 1 total categori
+ other: "%d total kategori"
+ archive_posts:
+ zero: Tidak ada posting.
+ one: 1 posting.
+ other: "%d total posting."
+state:
+ posts: posting
+ pages: halaman
+ tags: tags
+ categories: kategori
+search:
+ placeholder: Searching...
+cheers:
+ um: Um..
+ ok: OK
+ nice: Bagus
+ good: Bagus
+ great: Besar
+ excellent: Baik
+keep_on: Terus Posting.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/it.yml b/languages/it.yml
new file mode 100644
index 000000000..45da05f2c
--- /dev/null
+++ b/languages/it.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Archivio
+ category: Categoria
+ tag: Tag
+ schedule: Programma
+menu:
+ home: Home
+ archives: Archivi
+ categories: Categorie
+ tags: Tags
+ about: Informazioni su
+ search: Cerca
+ schedule: Programma
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: Panoramica
+ toc: Indice
+post:
+ posted: Scritto il
+ edited: Edited on
+ created: Post creato
+ modified: Post modificato
+ edit: Edit this post
+ in: In
+ more: espandi
+ read_more: Leggi di più
+ untitled: Senza titolo
+ sticky: Sticky
+ toc_empty: Questo post non ha un indice
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Autore
+ link: Link
+ license_title: Copyright
+ license_content: "Tutti gli articoli in questo sito sono sotto licenza %s salvo disposizione contraria."
+page:
+ totally: Totale
+ tags: tags
+footer:
+ powered: "Powered by %s"
+ theme: Tema
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Nessun tag
+ one: 1 tag in totale
+ other: "%d tags in totale."
+ categories:
+ zero: Nessuna categoria
+ one: 1 categoria in totale
+ other: "%d categorie in totale."
+ archive_posts:
+ zero: Nessun post.
+ one: 1 post.
+ other: "%d posts in totale."
+state:
+ posts: posts
+ pages: pagine
+ tags: tags
+ categories: categorie
+search:
+ placeholder: Cerca...
+cheers:
+ um: Mh..
+ ok: OK
+ nice: Bello
+ good: Buono
+ great: Ottimo
+ excellent: Eccellente
+keep_on: Continua così.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Dona
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/ja.yml b/languages/ja.yml
new file mode 100644
index 000000000..7935e8ba0
--- /dev/null
+++ b/languages/ja.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: アーカイブ
+ category: カテゴリ
+ tag: タグ
+ schedule: スケジュール
+menu:
+ home: ホーム
+ archives: アーカイブ
+ categories: カテゴリ
+ tags: タグ
+ about: About
+ search: 検索
+ schedule: スケジュール
+ sitemap: サイトマップ
+ commonweal: Commonweal 404
+sidebar:
+ overview: 概要
+ toc: 見出し
+post:
+ posted: 投稿日
+ edited: Edited on
+ created: 作成された時間
+ modified: Updated at
+ edit: Edit this post
+ in: In
+ more: more
+ read_more: 続きを読む
+ untitled: 無題
+ sticky: 固定
+ toc_empty: 見出しがありません
+ views: Views
+ comments_count: コメント
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: 著者
+ link: Post link
+ license_title: 著作権表示
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: 全ページ
+ tags: タグ
+footer:
+ powered: "Powered by %s"
+ theme: テーマ
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: タグなし
+ one: 全 1 タグ
+ other: "全 %d タグ"
+ categories:
+ zero: カテゴリなし
+ one: 全 1 カテゴリ
+ other: "全 %d カテゴリ"
+ archive_posts:
+ zero: ポストなし
+ one: 全 1 ポスト
+ other: "全 %d ポスト"
+state:
+ posts: ポスト
+ pages: ページ
+ tags: タグ
+ categories: カテゴリ
+search:
+ placeholder: 検索…
+cheers:
+ um: うーん
+ ok: はい
+ nice: まあまあ
+ good: いいね
+ great: すごい
+ excellent: 最高
+keep_on: もっと書こう!
+symbol:
+ comma: "、"
+ period: "。"
+ colon: ":"
+reward:
+ donate: Donate
+ wechatpay: WeChat 支払う
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Gitment からのコメントを表示
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/ko.yml b/languages/ko.yml
new file mode 100644
index 000000000..7c2fcd8eb
--- /dev/null
+++ b/languages/ko.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: 아카이브
+ category: 카테고리
+ tag: 태그
+ schedule: Schedule
+menu:
+ home: 홈
+ archives: 아카이브
+ categories: 카테고리
+ tags: 태그
+ about: About
+ search: 검색
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: 흝어보기
+ toc: 목차
+post:
+ posted: 작성일
+ edited: Edited on
+ created: Post created
+ modified: Updated at
+ edit: Edit this post
+ in: In
+ more: more
+ read_more: 더 읽어보기
+ untitled: 제목 없음
+ sticky: 고정
+ toc_empty: 목차 없음
+ views: Views
+ comments_count: 댓글
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: 모두
+ tags: 태그
+footer:
+ powered: "Powered by %s"
+ theme: Theme
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: 태그 없음
+ one: 1개의 태그
+ other: "총 %d개의 태그"
+ categories:
+ zero: 카테고리 없음
+ one: 1개의 카테고리
+ other: "총 %d개의 카테고리"
+ archive_posts:
+ zero: 포스트 없음
+ one: 1개의 포스트
+ other: "총 %d개의 포스트"
+state:
+ posts: 포스트
+ pages: 페이지
+ tags: 태그
+ categories: 카테고리
+search:
+ placeholder: Searching...
+cheers:
+ um: 음..
+ ok: OK
+ nice: 잘했어요
+ good: 좋아요
+ great: 훌륭해요
+ excellent: 완벽해요
+keep_on: 포스트를 마저 작성하세요
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/nl.yml b/languages/nl.yml
new file mode 100644
index 000000000..fa42cc7b5
--- /dev/null
+++ b/languages/nl.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Archief
+ category: Categorie
+ tag: Label
+ schedule: Rooster
+menu:
+ home: Home
+ archives: Archieven
+ categories: Categorieën
+ tags: Labels
+ about: Over
+ search: Zoeken
+ schedule: Rooster
+ sitemap: Sitemap
+ commonweal: Gezond verstand 404
+sidebar:
+ overview: Overzicht
+ toc: Inhoudsopgave
+post:
+ posted: Geplaatst op
+ edited: Edited on
+ created: Post aangemaakt
+ modified: Post aangepast
+ edit: Edit this post
+ in: In
+ more: meer
+ read_more: Lees meer
+ untitled: Naamloos
+ sticky: Sticky
+ toc_empty: Deze post heeft geen inhoudsopgave
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post auteur
+ link: Post link
+ license_title: Copyright melding
+ license_content: "Alle artikelen op deze blog zijn gelicenseerd onder %s, mits niet anders aangegeven."
+page:
+ totally: Totaal
+ tags: labels
+footer:
+ powered: "Mede mogelijk gemaakt door %s"
+ theme: Thema
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Geen labels
+ one: 1 label in totaal
+ other: "%d labels in totaal"
+ categories:
+ zero: Geen categorieën
+ one: 1 categorie in totaal
+ other: "%d categorieën in totaal"
+ archive_posts:
+ zero: Geen posts.
+ one: 1 post.
+ other: "%d posts in totaal."
+state:
+ posts: posts
+ pages: pagina's
+ tags: labels
+ categories: categorieën
+search:
+ placeholder: Zoeken...
+cheers:
+ um: Um..
+ ok: Oké
+ nice: Leuk
+ good: Goed
+ great: Geweldig
+ excellent: Uitstekend
+keep_on: Blijf posten.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Doneer
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/pt-BR.yml b/languages/pt-BR.yml
new file mode 100644
index 000000000..69457f008
--- /dev/null
+++ b/languages/pt-BR.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Arquivo
+ category: Categoria
+ tag: Tag
+ schedule: Schedule
+menu:
+ home: Home
+ archives: Arquivos
+ categories: Categorias
+ tags: Tags
+ about: Sobre
+ search: Pesquisar
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: Visão geral
+ toc: Tabela de conteúdo
+post:
+ posted: Postado em
+ edited: Edited on
+ created: Post created
+ modified: Updated at
+ edit: Edit this post
+ in: Em
+ more: more
+ read_more: Leia mais
+ untitled: Sem título
+ sticky: Sticky
+ toc_empty: Este post não possui tabela de conteúdo
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: Totalmente
+ tags: tags
+footer:
+ powered: "Feito com %s"
+ theme: Tema
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Sem tags
+ one: 1 tag no total de
+ other: "%d tags no total de"
+ categories:
+ zero: Sem categoria
+ one: 1 categoria no total de
+ other: "%d categoria no total de"
+ archive_posts:
+ zero: Sem posts.
+ one: 1 post.
+ other: "%d posts no total."
+state:
+ posts: Posts
+ pages: Páginas
+ tags: Tags
+ categories: Categorias
+search:
+ placeholder: Searching...
+cheers:
+ um: Uhmmmm...
+ ok: OK
+ nice: Bom
+ good: Muito Bom
+ great: Ótimo
+ excellent: Excelente
+keep_on: Continuar no post.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/pt.yml b/languages/pt.yml
new file mode 100644
index 000000000..2a980431d
--- /dev/null
+++ b/languages/pt.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Arquivo
+ category: Categoria
+ tag: Tag
+ schedule: Schedule
+menu:
+ home: Home
+ archives: Arquivos
+ categories: Categorias
+ tags: Tags
+ about: Sobre
+ search: Pesquisa
+ schedule: Schedule
+ sitemap: Sitemap
+ commonweal: Commonweal 404
+sidebar:
+ overview: Visão Geral
+ toc: Tabela de Conteúdo
+post:
+ posted: Postado em
+ edited: Edited on
+ created: Post created
+ modified: Updated at
+ edit: Edit this post
+ in: Em
+ more: more
+ read_more: Ler mais
+ untitled: Sem título
+ sticky: Sticky
+ toc_empty: Esta publicação não possui uma tabela de conteúdo
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Post author
+ link: Post link
+ license_title: Copyright Notice
+ license_content: "All articles in this blog are licensed under %s unless stating additionally."
+page:
+ totally: Totalmente
+ tags: tags
+footer:
+ powered: "Desenvolvido com amor com %s"
+ theme: Tema
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Sem tags
+ one: 1 tag no total
+ other: "%d tags no total"
+ categories:
+ zero: Sem categorias
+ one: 1 categoria no total
+ other: "%d categorias no total"
+ archive_posts:
+ zero: Sem publicações.
+ one: 1 post.
+ other: "%d publicações no total."
+state:
+ posts: publicações
+ pages: páginas
+ tags: tags
+ categories: categorias
+search:
+ placeholder: Searching...
+cheers:
+ um: Um..
+ ok: OK
+ nice: Legal
+ good: Bom
+ great: Grandioso
+ excellent: Excelente
+keep_on: Mantenha-se publicando!
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Donate
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Show comments from Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/ru.yml b/languages/ru.yml
new file mode 100644
index 000000000..c7d8c7988
--- /dev/null
+++ b/languages/ru.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Архив
+ category: Категория
+ tag: Тэг
+ schedule: Календарь
+menu:
+ home: Главная
+ archives: Архив
+ categories: Категории
+ tags: Тэги
+ about: О сайте
+ search: Поиск
+ schedule: Календарь
+ sitemap: Карта сайта
+ commonweal: Страница 404
+sidebar:
+ overview: Обзор
+ toc: Содержание
+post:
+ posted: Размещено
+ edited: Изменено
+ created: Создано
+ modified: Изменено
+ edit: Редактировать запись
+ in: в категории
+ more: more
+ read_more: Читать полностью
+ untitled: Без имени
+ sticky: Ссылка
+ toc_empty: Эта запись без оглавления
+ views: Просмотров
+ comments_count: Комментариев
+ related_posts: Похожие записи
+ copy_button: Скопировать
+ copy_success: Скопировано!
+ copy_failure: Ошибка копирования!
+ copyright:
+ author: Автор записи
+ link: Ссылка на запись
+ license_title: Информация об авторских правах
+ license_content: "Все записи на этом сайте защищены лицензией %s, если не указано дополнительно."
+page:
+ totally: Всего
+ tags: тэги
+footer:
+ powered: "Генератор — %s"
+ theme: Тема
+ total_views: Всего просмотров
+ total_visitors: Всего посетителей
+counter:
+ tag_cloud:
+ zero: Нет тэгов.
+ one: 1 тэг.
+ other: "%d тэгов всего."
+ categories:
+ zero: Нет категорий.
+ one: 1 категория.
+ other: "%d категорий всего."
+ archive_posts:
+ zero: Нет записей.
+ one: 1 запись.
+ other: "%d записей всего."
+state:
+ posts: Архив
+ pages: Страницы
+ tags: Тэги
+ categories: Категории
+search:
+ placeholder: Поиск...
+cheers:
+ um: Эм..
+ ok: OK
+ nice: Неплохо
+ good: Хорошо
+ great: Замечательно
+ excellent: Великолепно
+keep_on: Продолжаю писать.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Донат
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Открыть Gitment комментарии
+accessibility:
+ nav_toggle: Показать/скрыть меню
+ prev_page: Предыдущая страница
+ next_page: Следующая страница
+symbols_count_time:
+ count: Кол-во символов в статье
+ count_total: Общее кол-во символов
+ time: Время чтения
+ time_total: Общее время чтения
+ time_minutes: мин.
diff --git a/languages/tr.yml b/languages/tr.yml
new file mode 100644
index 000000000..899a6d809
--- /dev/null
+++ b/languages/tr.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Arşiv
+ category: Kategori
+ tag: Etiket
+ schedule: Program
+menu:
+ home: Ana Sayfa
+ archives: Arşivler
+ categories: Kategoriler
+ tags: Etiketler
+ about: Hakkımda
+ search: Ara
+ schedule: Program
+ sitemap: Site Haritası
+ commonweal: Hata 404
+sidebar:
+ overview: Genel Bakış
+ toc: İçindekiler
+post:
+ posted: Yayınlandı
+ edited: Düzenlendi
+ created: Oluşturuldu
+ modified: Değiştirildi
+ edit: Bu gönderiyi düzenle
+ in: İçinde
+ more: daha fazla
+ read_more: Daha fazla oku
+ untitled: Başlıksız
+ sticky: Sabit
+ toc_empty: Bu gönderinin içindekiler kısmı yok
+ views: Görünümler
+ comments_count: Yorumlar
+ related_posts: İlgili Gönderiler
+ copy_button: Kopyala
+ copy_success: Kopyalandı
+ copy_failure: Kopyalanamadı
+ copyright:
+ author: Gönderiyi yazan
+ link: Gönderi bağlantısı
+ license_title: Telif Hakkı Bildirimi
+ license_content: "Bu blogdaki tüm makaleler aksi belirtilmediği sürece %s altında lisanslıdır."
+page:
+ totally: Toplamda
+ tags: etiketler
+footer:
+ powered: "%s tarafından desteklenmektedir"
+ theme: Tema
+ total_views: Toplam görüntülenme
+ total_visitors: Toplam Ziyaretçi
+counter:
+ tag_cloud:
+ zero: Etiket yok
+ one: Toplam 1 etiket
+ other: "Toplamda %d etiket"
+ categories:
+ zero: Kategori yok
+ one: Toplamda 1 kategori
+ other: "Toplamda %d kategori"
+ archive_posts:
+ zero: Gönderi yok.
+ one: 1 gönderi.
+ other: "Toplamda %d gönderi."
+state:
+ posts: gönderiler
+ pages: sayfalar
+ tags: etiketler
+ categories: kategoriler
+search:
+ placeholder: Aranıyor...
+cheers:
+ um: Um..
+ ok: Tamam
+ nice: Güzel
+ good: İyi
+ great: Müthiş
+ excellent: Mükemmel
+keep_on: Gönderiye devam.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Bağış
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Gitment'ın yorumlarını göster
+accessibility:
+ nav_toggle: Gezinti çubuğunu değiştir
+ prev_page: Önceki sayfa
+ next_page: Sonraki sayfa
+symbols_count_time:
+ count: Makalede sayılan semboller
+ count_total: Sayılan toplan semboller
+ time: Okuma Süresi
+ time_total: Toplmada Okuma Süresi
+ time_minutes: dk.
diff --git a/languages/vi.yml b/languages/vi.yml
new file mode 100644
index 000000000..9bb900b3b
--- /dev/null
+++ b/languages/vi.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: Lưu Trữ
+ category: Phân Loại
+ tag: Thẻ
+ schedule: Danh Mục
+menu:
+ home: Trang Chủ
+ archives: Lưu Trữ
+ categories: Đầu Mục
+ tags: Thẻ
+ about: Giới Thiệu
+ search: Tìm Kiếm
+ schedule: Danh Mục
+ sitemap: Bản đồ trang
+ commonweal: Commonweal 404
+sidebar:
+ overview: Tổng Quan
+ toc: Mục Lục
+post:
+ posted: Tạo lúc
+ edited: Edited on
+ created: Được tạo
+ modified: Được thay đổi
+ edit: Edit this post
+ in: Trong
+ more: thêm
+ read_more: Đọc tiếp
+ untitled: Không có tiêu đề
+ sticky: Đính
+ toc_empty: Bài viết này không có mục lục
+ views: Views
+ comments_count: Comments
+ related_posts: Related Posts
+ copy_button: Copy
+ copy_success: Copied
+ copy_failure: Copy failed
+ copyright:
+ author: Người viết
+ link: Liên kết bài viết
+ license_title: Chú ý bản quyền
+ license_content: "Tất cả bài viết trong blog này được đăng ký bởi %s trừ khi có thông báo bổ sung."
+page:
+ totally: Toàn bộ
+ tags: thẻ
+footer:
+ powered: "Cung cấp bởi %s"
+ theme: Giao Diện
+ total_views: Total Views
+ total_visitors: Total Visitors
+counter:
+ tag_cloud:
+ zero: Không có thẻ nào
+ one: có 1 thẻ tất cả
+ other: "có %d thẻ tất cả"
+ categories:
+ zero: Không có trong mục nào
+ one: có 1 mục tất cả
+ other: "có %d mục tất cả"
+ archive_posts:
+ zero: Không có bài viết.
+ one: 1 bài viết.
+ other: "tổng số %d bài viết."
+state:
+ posts: bài viết
+ pages: trang
+ tags: thẻ
+ categories: mục
+search:
+ placeholder: Đang tìm...
+cheers:
+ um: Um..
+ ok: Đồng Ý
+ nice: Hay
+ good: Tốt
+ great: Tuyệt vời
+ excellent: Tuyệt cú mèo
+keep_on: Giữ tiến độ nha.
+symbol:
+ comma: ", "
+ period: ". "
+ colon: ": "
+reward:
+ donate: Tài trợ
+ wechatpay: WeChat Pay
+ alipay: Alipay
+ bitcoin: Bitcoin
+gitmentbutton: Hiển thị bình luận từ Gitment
+accessibility:
+ nav_toggle: Toggle navigation bar
+ prev_page: Previous page
+ next_page: Next page
+symbols_count_time:
+ count: Symbols count in article
+ count_total: Symbols count total
+ time: Reading time
+ time_total: Reading time total
+ time_minutes: mins.
diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml
new file mode 100644
index 000000000..0d828c89c
--- /dev/null
+++ b/languages/zh-CN.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: 归档
+ category: 分类
+ tag: 标签
+ schedule: 日程表
+menu:
+ home: 首页
+ archives: 归档
+ categories: 分类
+ tags: 标签
+ about: 关于
+ search: 搜索
+ schedule: 日程表
+ sitemap: 站点地图
+ commonweal: 公益 404
+sidebar:
+ overview: 站点概览
+ toc: 文章目录
+post:
+ posted: 发表于
+ edited: 更新于
+ created: 创建时间
+ modified: 修改时间
+ edit: 编辑
+ in: 分类于
+ more: 更多
+ read_more: 阅读全文
+ untitled: 未命名
+ sticky: 置顶
+ toc_empty: 此文章未包含目录
+ views: 阅读次数
+ comments_count: 评论数
+ related_posts: 相关文章
+ copy_button: 复制
+ copy_success: 复制成功
+ copy_failure: 复制失败
+ copyright:
+ author: 本文作者
+ link: 本文链接
+ license_title: 版权声明
+ license_content: "本博客所有文章除特别声明外,均采用 %s 许可协议。转载请注明出处!"
+page:
+ totally: 共有
+ tags: 标签
+footer:
+ powered: "由 %s 强力驱动"
+ theme: 主题
+ total_views: 总访问量
+ total_visitors: 总访客量
+counter:
+ tag_cloud:
+ zero: 暂无标签
+ one: 目前共计 1 个标签
+ other: "目前共计 %d 个标签"
+ categories:
+ zero: 暂无分类
+ one: 目前共计 1 个分类
+ other: "目前共计 %d 个分类"
+ archive_posts:
+ zero: 暂无日志。
+ one: 目前共计 1 篇日志。
+ other: "目前共计 %d 篇日志。"
+state:
+ posts: 日志
+ pages: 页面
+ tags: 标签
+ categories: 分类
+search:
+ placeholder: 搜索...
+cheers:
+ um: 嗯..
+ ok: 还行
+ nice: 不错
+ good: 很好
+ great: 非常好
+ excellent: 太棒了
+keep_on: 继续努力。
+symbol:
+ comma: ","
+ period: "。"
+ colon: ":"
+reward:
+ donate: 打赏
+ wechatpay: 微信支付
+ alipay: 支付宝
+ bitcoin: 比特币
+gitmentbutton: 显示 Gitment 评论
+accessibility:
+ nav_toggle: 切换导航栏
+ prev_page: 上一页
+ next_page: 下一页
+symbols_count_time:
+ count: 本文字数
+ count_total: 站点总字数
+ time: 阅读时长
+ time_total: 站点阅读时长
+ time_minutes: 分钟
diff --git a/languages/zh-HK.yml b/languages/zh-HK.yml
new file mode 100644
index 000000000..0ef571eb0
--- /dev/null
+++ b/languages/zh-HK.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: 歸檔
+ category: 分類
+ tag: 標籤
+ schedule: 日程表
+menu:
+ home: 首頁
+ archives: 歸檔
+ categories: 分類
+ tags: 標籤
+ about: 關於
+ search: 檢索
+ schedule: 日程表
+ sitemap: 站點地圖
+ commonweal: 公益 404
+sidebar:
+ overview: 本站概覽
+ toc: 文章目錄
+post:
+ posted: 發表於
+ edited: 更新於
+ created: 創建時間
+ modified: 修改時間
+ edit: 編輯
+ in: 分類於
+ more: 更多
+ read_more: 閱讀全文
+ untitled: 未命名
+ sticky: 置頂
+ toc_empty: 此文章未包含目錄
+ views: 閱讀次數
+ comments_count: 評論數
+ related_posts: 相關文章
+ copy_button: 複製
+ copy_success: 複製成功
+ copy_failure: 複製失敗
+ copyright:
+ author: 博主
+ link: 文章連結
+ license_title: 版權聲明
+ license_content: "本網誌所有文章除特別聲明外,均採用 %s 許可協議。轉載請註明出處!"
+page:
+ totally: 共有
+ tags: 標籤
+footer:
+ powered: "由 %s 強力驅動"
+ theme: 主題
+ total_views: 總瀏覽次數
+ total_visitors: 訪客總數
+counter:
+ tag_cloud:
+ zero: 暫無標籤
+ one: 目前共有 1 個標籤
+ other: "目前共有 %d 個標籤"
+ categories:
+ zero: 暫無分類
+ one: 目前共有 1 個分類
+ other: "目前共有 %d 個分類"
+ archive_posts:
+ zero: 暫無文章。
+ one: 目前共有 1 篇文章。
+ other: "目前共有 %d 篇文章。"
+state:
+ posts: 文章
+ pages: 頁面
+ tags: 標籤
+ categories: 分類
+search:
+ placeholder: 搜索...
+cheers:
+ um: 嗯..
+ ok: 還行
+ nice: 好
+ good: 很好
+ great: 非常好
+ excellent: 太棒了
+keep_on: 繼續努力。
+symbol:
+ comma: ","
+ period: "。"
+ colon: ":"
+reward:
+ donate: 打賞
+ wechatpay: 微信支付
+ alipay: 支付寶
+ bitcoin: 比特幣
+gitmentbutton: 顯示 Gitment 評論
+accessibility:
+ nav_toggle: 切換導航欄
+ prev_page: 上一頁
+ next_page: 下一頁
+symbols_count_time:
+ count: 本文字數
+ count_total: 站點總字數
+ time: 閱讀時長
+ time_total: 站點閱讀時長
+ time_minutes: 分鍾
diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml
new file mode 100644
index 000000000..a26e882ee
--- /dev/null
+++ b/languages/zh-TW.yml
@@ -0,0 +1,98 @@
+---
+title:
+ archive: 歸檔
+ category: 分類
+ tag: 標籤
+ schedule: 時間表
+menu:
+ home: 首頁
+ archives: 歸檔
+ categories: 分類
+ tags: 標籤
+ about: 關於
+ search: 搜尋
+ schedule: 時間表
+ sitemap: 網站地圖
+ commonweal: 公益 404
+sidebar:
+ overview: 本站概要
+ toc: 文章目錄
+post:
+ posted: 發表於
+ edited: 更新於
+ created: 創建時間
+ modified: 修改時間
+ edit: 編輯
+ in: 分類於
+ more: 更多
+ read_more: 閱讀全文
+ untitled: 未命名
+ sticky: 置頂
+ toc_empty: 此文章沒有目錄
+ views: 閱讀次數
+ comments_count: 評論數
+ related_posts: 相關文章
+ copy_button: 複製
+ copy_success: 複製成功
+ copy_failure: 複製失敗
+ copyright:
+ author: 作者
+ link: 文章連結
+ license_title: 版權聲明
+ license_content: "本網誌所有文章除特別聲明外,均採用 %s 許可協議。轉載請註明出處!"
+page:
+ totally: 共有
+ tags: 標籤
+footer:
+ powered: "由 %s 強力驅動"
+ theme: 主題
+ total_views: 總瀏覽次數
+ total_visitors: 訪客總數
+counter:
+ tag_cloud:
+ zero: 沒有標籤
+ one: 目前共有 1 個標籤
+ other: "目前共有 %d 個標籤"
+ categories:
+ zero: 沒有分類
+ one: 目前共有 1 個分類
+ other: "目前共有 %d 個分類"
+ archive_posts:
+ zero: 沒有文章。
+ one: 目前共有 1 篇文章。
+ other: "目前共有 %d 篇文章。"
+state:
+ posts: 文章
+ pages: 頁面
+ tags: 標籤
+ categories: 分類
+search:
+ placeholder: 搜尋...
+cheers:
+ um: 嗯..
+ ok: 還行
+ nice: 好
+ good: 很好
+ great: 非常好
+ excellent: 太棒了
+keep_on: 繼續努力。
+symbol:
+ comma: ","
+ period: "。"
+ colon: ":"
+reward:
+ donate: 捐贈
+ wechatpay: 微信支付
+ alipay: 支付寶
+ bitcoin: 比特幣
+gitmentbutton: 顯示 Gitment 評論
+accessibility:
+ nav_toggle: 切換導航欄
+ prev_page: 上一頁
+ next_page: 下一頁
+symbols_count_time:
+ count: 文章字數
+ count_total: 總字數
+ time: 所需閱讀時間
+ time_total: 所需總閱讀時間
+ time_minutes: 分鐘
diff --git a/layout/_custom/head.swig b/layout/_custom/head.swig
new file mode 100644
index 000000000..6aed40d5e
--- /dev/null
+++ b/layout/_custom/head.swig
@@ -0,0 +1,3 @@
+{#
+Custom head.
+#}
diff --git a/layout/_custom/header.swig b/layout/_custom/header.swig
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/layout/_custom/header.swig
@@ -0,0 +1 @@
+
diff --git a/layout/_custom/sidebar.swig b/layout/_custom/sidebar.swig
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/layout/_custom/sidebar.swig
@@ -0,0 +1 @@
+
diff --git a/layout/_layout.swig b/layout/_layout.swig
new file mode 100644
index 000000000..23019f2fa
--- /dev/null
+++ b/layout/_layout.swig
@@ -0,0 +1,110 @@
+
+
+{# NexT version #}
+{% set version = next_env('version') %}
+
+{# Language & Config #}
+{% set title = __('title') !== 'title' && __('title') || config.title %}
+{% set subtitle = __('subtitle') !== 'subtitle' && __('subtitle') || config.subtitle %}
+{% set author = __('author') !== 'author' && __('author') || config.author %}
+{% set description = __('description') !== 'description' && __('description') || config.description %}
+
+{% set html_class = 'theme-next ' + theme.scheme %}
+{% if theme.motion.enable %}
+ {% set html_class = html_class + ' use-motion' %}
+{% endif %}
+
+
+
+ {{ partial('_partials/head/head.swig', {}, {cache: theme.cache.enable}) }}
+ {% include '_partials/head/head-unique.swig' %}
+ {% block title %}{% endblock %}
+ {% include '_third-party/analytics/index.swig' %}
+ {{ partial('_scripts/noscript.swig', {}, {cache: theme.cache.enable}) }}
+
+
+
+
+ {% set container_class = "container " %}
+ {% if theme.sidebar.position %}
+ {% set container_class = container_class + 'sidebar-position-' + theme.sidebar.position %}
+ {% endif %}
+
+
+
+
+
+ {% include '_partials/header/index.swig' %}
+
+
+ {{ partial('_third-party/github-banner.swig', {}, {cache: theme.cache.enable}) }}
+
+
+
+
+ {% if theme.scheme === 'Pisces' || theme.scheme === 'Gemini' %}
+ {% include '_partials/header/sub-menu.swig' %}
+ {% endif %}
+
+ {% block content %}{% endblock %}
+
+ {% include '_partials/comments.swig' %}
+
+ {% if theme.sidebar.display !== 'remove' %}
+ {% block sidebar %}{% endblock %}
+ {% endif %}
+
+
+
+
+
+ {% if not theme.sidebar.b2t %}
+
+
+ {% if theme.sidebar.scrollpercent %}
+ 0%
+ {% endif %}
+
+ {% endif %}
+
+ {% if theme.needmoreshare2.enable and theme.needmoreshare2.float.enable %}
+
+ {% endif %}
+
+
+
+ {% include '_scripts/vendors.swig' %}
+ {% include '_scripts/commons.swig' %}
+
+ {% set scheme_script = '_scripts/schemes/' + theme.scheme | lower + '.swig' %}
+ {% include scheme_script %}
+
+ {% block script_extra %}{% endblock %}
+
+ {% include '_scripts/boostrap.swig' %}
+
+ {% include '_third-party/comments/index.swig' %}
+ {% include '_third-party/search/index.swig' %}
+ {% include '_third-party/analytics/lean-analytics.swig' %}
+ {% include '_third-party/analytics/firestore.swig' %}
+ {% include '_third-party/seo/baidu-push.swig' %}
+ {% include '_third-party/math/index.swig' %}
+ {% include '_third-party/needsharebutton.swig' %}
+ {% include '_third-party/rating.swig' %}
+ {% include '_third-party/pangu.swig' %}
+ {% include '_third-party/scroll-cookie.swig' %}
+ {% include '_third-party/exturl.swig' %}
+ {% include '_third-party/bookmark.swig' %}
+ {% include '_third-party/copy-code.swig' %}
+
+
diff --git a/layout/_macro/menu/menu-badge.swig b/layout/_macro/menu/menu-badge.swig
new file mode 100644
index 000000000..b2dcce135
--- /dev/null
+++ b/layout/_macro/menu/menu-badge.swig
@@ -0,0 +1,14 @@
+{% macro render(name) %}
+
+ {% set badges = {
+ archives: site.posts.length,
+ categories: site.categories.length,
+ tags: site.tags.length }
+ %}
+ {% for menu, count in badges %}
+ {% if name == menu %}
+ {{ count }}
+ {% endif %}
+ {% endfor %}
+
+{% endmacro %}
diff --git a/layout/_macro/menu/menu-item.swig b/layout/_macro/menu/menu-item.swig
new file mode 100644
index 000000000..89879bdfb
--- /dev/null
+++ b/layout/_macro/menu/menu-item.swig
@@ -0,0 +1,20 @@
+{% macro render(name, value) %}
+{% import 'menu-badge.swig' as menu_badge %}
+
+ {% set itemURL = value.split('||')[0] | replace('//', '/', 'g') | trim %}
+
+
+ {%- if theme.menu_settings.icons %}
+
{#
+ #}{% endif %}
+
+ {{- __('menu.' + name ) | replace('menu.', '') -}}
+
+ {%- if theme.menu_settings.badges -%}
+ {{- menu_badge.render(name) | trim -}}
+ {%- endif -%}
+
+
+
+
+{% endmacro %}
diff --git a/layout/_macro/post-collapse.swig b/layout/_macro/post-collapse.swig
new file mode 100644
index 000000000..1894d2466
--- /dev/null
+++ b/layout/_macro/post-collapse.swig
@@ -0,0 +1,34 @@
+{% macro render(post) %}
+
+
+
+
+ <{% if theme.seo %}h3{% else %}h2{% endif %} class="post-title">
+ {% if post.link %}{# Link posts #}
+
+ {{ post.title or post.link }}
+
+
+ {% else %}
+
+ {% if post.type === 'picture' %}
+ {{ post.content }}
+ {% else %}
+ {{ post.title | default(__('post.untitled')) }}
+ {% endif %}
+
+ {% endif %}
+ {% if theme.seo %}h3{% else %}h2{% endif %}>
+
+
+
+
+
+
+{% endmacro %}
diff --git a/layout/_macro/post-copyright.swig b/layout/_macro/post-copyright.swig
new file mode 100644
index 000000000..fd3d9c09a
--- /dev/null
+++ b/layout/_macro/post-copyright.swig
@@ -0,0 +1,14 @@
+
+ -
+ {{ __('post.copyright.link') + __('symbol.colon') }}
+ {{ post.url | default(post.permalink) }}
+
+ -
+ {{ __('post.copyright.license_title') + __('symbol.colon') }} {#
+ #}{{ post.copyright | default(__('post.copyright.license_content', theme.post_copyright.license)) }}{#
+#}
+
diff --git a/layout/_macro/post-related.swig b/layout/_macro/post-related.swig
new file mode 100644
index 000000000..2853b45ac
--- /dev/null
+++ b/layout/_macro/post-related.swig
@@ -0,0 +1,20 @@
+{% set popular_posts = popular_posts_json(theme.related_posts.params, post) %}
+{% if popular_posts.json and popular_posts.json.length > 0 %}
+
+ {{ theme.related_posts.title | default(__('post.related_posts')) }}
+
+ {% for popular_post in popular_posts.json %}
+ -
+ {% if popular_post.date and popular_post.date != '' %}
+ {{ popular_post.date }}
+ {% endif %}
+ {% if popular_post.img && popular_post.img != '' %}
+
+ {% endif %}
+
+ {% if popular_post.excerpt && popular_post.excerpt != '' %}
+
{{ popular_post.excerpt }}
+ {% endif %}
+
+ {% endfor %}
+
+{% endif %}
diff --git a/layout/_macro/post.swig b/layout/_macro/post.swig
new file mode 100644
index 000000000..880a76c21
--- /dev/null
+++ b/layout/_macro/post.swig
@@ -0,0 +1,469 @@
+{% macro render(post, is_index, post_extra_class) %}
+
+ {% set headlessPost = Array.prototype.indexOf.call(['quote', 'picture'], post.type) > -1 %}
+
+ {% set post_class = 'post post-type-' + post.type | default('normal') %}
+ {% if post_extra_class > 0 %}
+ {% set post_class = post_class + ' ' + post_extra_class | default('') %}
+ {% endif %}
+ {% if post.sticky > 0 %}
+ {% set post_class = post_class + ' ' + 'post-sticky' %}
+ {% endif %}
+
+ {% if theme.reading_progress.enable && not is_index %}
+
+ {% endif %}
+
+
+ {##################}
+ {### POST BLOCK ###}
+ {##################}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if not headlessPost %}
+
+
+ {# Not to show title for quote posts that do not have a title #}
+ {% if not (is_index and post.type === 'quote' and not post.title) %}
+ <{% if theme.seo %}h2{% else %}h1{% endif %} class="post-title{% if post.direction && post.direction.toLowerCase() === 'rtl' %} rtl{% endif %}" itemprop="name headline">{#
+ #}{# Link posts #}{#
+ #}{% if post.link %}
+ {% if post.sticky > 0 %}
+ {{ post.sticky }}
+
+
+
+ {% endif %}
+
+ {{ post.title or post.link }}
+
+
+ {% else %}{#
+ #}{% if is_index %}
+ {% if post.sticky > 0 %}
+
+
+
+ {% endif %}
+
+ {{ post.title | default(__('post.untitled'))}}
+
+ {% else -%}
+ {{- post.title -}}
+ {% if theme.post_edit.enable -%}
+
+
+
+ {%- endif %}
+ {% endif %}
+ {% endif %}
+ {% if theme.seo %}h2{% else %}h1{% endif %}>
+ {% endif %}
+
+
+
+ {% endif %}
+
+ {#################}
+ {### POST BODY ###}
+ {#################}
+
+
+ {# Gallery support #}
+ {% if post.photos and post.photos.length %}
+
+ {% set COLUMN_NUMBER = 3 %}
+ {% for photo in post.photos %}
+ {% if loop.index0 % COLUMN_NUMBER === 0 %}{% endif %}
+
+
+
+ {% if loop.index0 % COLUMN_NUMBER === 2 %}{% endif %}
+ {% endfor %}
+
+ {# Append end tag for `post-gallery-row` when (photos size mod COLUMN_NUMBER) is less than COLUMN_NUMBER #}
+ {% if post.photos.length % COLUMN_NUMBER > 0 %}{% endif %}
+
+ {% endif %}
+
+ {% if is_index %}
+ {% if post.description and theme.excerpt_description %}
+ {{ post.description }}
+
+
+
+ {% elif post.excerpt %}
+ {{ post.excerpt }}
+
+
+
+ {% elif theme.auto_excerpt.enable %}
+ {% set content = post.content | striptags %}
+ {{ content.substring(0, theme.auto_excerpt.length) }}
+ {% if content.length > theme.auto_excerpt.length %}...{% endif %}
+
+
+
+ {% else %}
+ {% if post.type === 'picture' %}
+ {{ post.content }}
+ {% else %}
+ {{ post.content }}
+ {% endif %}
+ {% endif %}
+ {% else %}
+ {{ post.content }}
+ {% endif %}
+
+
+ {% if theme.related_posts.enable and (theme.related_posts.display_in_home or not is_index) %}
+ {% include 'post-related.swig' with { post: post } %}
+ {% endif %}
+
+ {#####################}
+ {### END POST BODY ###}
+ {#####################}
+
+ {% if theme.wechat_subscriber.enabled and not is_index %}
+
+ {% include 'wechat-subscriber.swig' %}
+
+ {% endif %}
+
+ {% if (theme.alipay or theme.wechatpay or theme.bitcoin) and not is_index %}
+
+ {% include 'reward.swig' %}
+
+ {% endif %}
+
+ {% if theme.post_copyright.enable and not is_index %}
+
+ {% include 'post-copyright.swig' with { post: post } %}
+
+ {% endif %}
+
+
+
+ {######################}
+ {### END POST BLOCK ###}
+ {######################}
+
+
+{% endmacro %}
diff --git a/layout/_macro/reward.swig b/layout/_macro/reward.swig
new file mode 100644
index 000000000..04c75e250
--- /dev/null
+++ b/layout/_macro/reward.swig
@@ -0,0 +1,30 @@
+
+ {{ theme.reward_comment }}
+
+
+
diff --git a/layout/_macro/sidebar.swig b/layout/_macro/sidebar.swig
new file mode 100644
index 000000000..b71be435a
--- /dev/null
+++ b/layout/_macro/sidebar.swig
@@ -0,0 +1,192 @@
+{% macro render(is_post) %}
+
+
+
+{% endmacro %}
diff --git a/layout/_macro/wechat-subscriber.swig b/layout/_macro/wechat-subscriber.swig
new file mode 100644
index 000000000..aa0fdbc84
--- /dev/null
+++ b/layout/_macro/wechat-subscriber.swig
@@ -0,0 +1,4 @@
+
+
+ {{ theme.wechat_subscriber.description }}
+
diff --git a/layout/_partials/breadcrumb.swig b/layout/_partials/breadcrumb.swig
new file mode 100644
index 000000000..998c50b72
--- /dev/null
+++ b/layout/_partials/breadcrumb.swig
@@ -0,0 +1,23 @@
+{% set paths = page.path.split('/') %}
+{% set count = paths.length %}
+{% if count > 2 %}
+ {% set current = 0 %}
+ {% set link = '' %}
+
+{% endif %}
diff --git a/layout/_partials/comments.swig b/layout/_partials/comments.swig
new file mode 100644
index 000000000..4124b9a86
--- /dev/null
+++ b/layout/_partials/comments.swig
@@ -0,0 +1,63 @@
+{% if page.comments %}
+
+ {% if theme.facebook_sdk.enable and theme.facebook_comments_plugin.enable %}
+
+
+
+
+
+ {% elseif theme.vkontakte_api.enable and theme.vkontakte_api.comments %}
+
+
+
+
+ {% elseif theme.disqus.enable %}
+
+
+
+
+
+
+ {% elseif theme.hypercomments_id %}
+
+
+
+
+ {% elseif theme.youyan_uid %}
+
+
+
+
+ {% elseif theme.livere_uid %}
+
+
+
+
+ {% elseif theme.changyan.enable and theme.changyan.appid and theme.changyan.appkey %}
+
+
+
+
+ {% elseif theme.gitment.enable %}
+
+ {% if theme.gitment.lazy %}
+
+
+ {% elseif theme.valine.enable and theme.valine.appid and theme.valine.appkey %}
+
+
+ {% else %}
+
+ {% endif %}
+
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_partials/footer.swig b/layout/_partials/footer.swig
new file mode 100644
index 000000000..a0ec48ea9
--- /dev/null
+++ b/layout/_partials/footer.swig
@@ -0,0 +1,64 @@
+{#
+#}{% set current = date(Date.now(), "YYYY") %}{#
+#}© {% if theme.footer.since and theme.footer.since != current %}{{ theme.footer.since }} — {% endif %}{#
+#}{{ current }}
+
+
+
+
+
+ {% if config.symbols_count_time.total_symbols %}
+
+
+ {% if theme.symbols_count_time.item_text_total %}
+
+ {% endif %}
+ {#
+ #}{{ symbolsCountTotal(site) }}{#
+ #}
+ {% endif %}
+
+ {% if config.symbols_count_time.total_time %}
+
+
+ {% if theme.symbols_count_time.item_text_total %}
+
+ {% endif %}
+ {#
+ #}{{ symbolsTimeTotal(site, theme.symbols_count_time.awl, theme.symbols_count_time.wpm, __('symbols_count_time.time_minutes')) }}{#
+ #}
+ {% endif %}
+
+
+{% if theme.seo %}
+ {% set nofollow = ' rel="external nofollow"' %}
+{% endif %}
+
+{% if theme.footer.powered.enable %}
+ {#
+ #}{{ __('footer.powered', 'Hexo') }}{% if theme.footer.powered.version %} v{{ hexo_env('version') }}{% endif %}{#
+#}
+{% endif %}
+
+{% if theme.footer.powered.enable and theme.footer.theme.enable %}
+
+{% endif %}
+
+{% if theme.footer.theme.enable %}
+ {#
+ #}{{ __('footer.theme') }} — {#
+ #}{#
+ #}NexT.{{ theme.scheme }}{#
+ #}{% if theme.footer.theme.version %} v{{ version }}{% endif %}{#
+#}
+{% endif %}
+
+{% if theme.footer.custom_text %}
+
+{% endif %}
diff --git a/layout/_partials/head/external-fonts.swig b/layout/_partials/head/external-fonts.swig
new file mode 100644
index 000000000..876e12e7b
--- /dev/null
+++ b/layout/_partials/head/external-fonts.swig
@@ -0,0 +1,51 @@
+{% if theme.font.enable %}
+
+ {% set font_config = theme.font %}
+ {% set font_families = '' %}
+ {% set font_styles = ':300,300italic,400,400italic,700,700italic' %}
+ {% set font_found = false %}
+
+ {% if font_config.global.family and font_config.global.external %}
+ {% set font_families += font_config.global.family + font_styles %}
+ {% set font_found = true %}
+ {% endif %}
+
+ {% if font_config.headings.family and font_config.headings.external %}
+ {% if font_found %}
+ {% set font_families += '|' %}
+ {% endif %}
+
+ {% set font_families += font_config.headings.family + font_styles %}
+ {% endif %}
+
+ {% if font_config.posts.family and font_config.posts.external %}
+ {% if font_found %}
+ {% set font_families += '|' %}
+ {% endif %}
+
+ {% set font_families += font_config.posts.family + font_styles %}
+ {% endif %}
+
+ {% if font_config.logo.family and font_config.logo.external %}
+ {% if font_found %}
+ {% set font_families += '|' %}
+ {% endif %}
+
+ {% set font_families += font_config.logo.family + font_styles %}
+ {% endif %}
+
+ {% if font_config.codes.family and font_config.codes.external %}
+ {% if font_found %}
+ {% set font_families += '|' %}
+ {% endif %}
+
+ {% set font_families += font_config.codes.family + font_styles %}
+ {% endif %}
+
+ {% if font_families !== '' %}
+ {% set font_families += '&subset=latin,latin-ext' %}
+ {% set font_host = font_config.host | default('//fonts.googleapis.com') %}
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_partials/head/head-unique.swig b/layout/_partials/head/head-unique.swig
new file mode 100644
index 000000000..9c1a14828
--- /dev/null
+++ b/layout/_partials/head/head-unique.swig
@@ -0,0 +1,27 @@
+{{
+ open_graph({
+ twitter_id: theme.twitter,
+ google_plus: theme.google_plus,
+ fb_admins: theme.fb_admins,
+ fb_app_id: theme.fb_app_id
+ })
+}}
+
+{% if theme.rss === '' and config.feed and config.feed.path %}
+ {% set theme.rss = config.feed.path %}
+{% endif %}
+{% if theme.rss %}
+
+{% endif %}
+
+{# Canonical, good for google search engine (SEO) : https://support.google.com/webmasters/answer/139066 #}
+{% if theme.canonical %}
+
+{% endif %}
+
+{# Exports some front-matter variables to Front-End #}
+
diff --git a/layout/_partials/head/head.swig b/layout/_partials/head/head.swig
new file mode 100644
index 000000000..17782fd1c
--- /dev/null
+++ b/layout/_partials/head/head.swig
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+{% if theme.needmoreshare2.enable %}
+ {% set needmoreshare2_css = url_for(theme.vendors._internal + '/needsharebutton/needsharebutton.css') %}
+ {% if theme.vendors.needmoreshare2_css %}
+ {% set needmoreshare2_css = theme.vendors.needmoreshare2_css %}
+ {% endif %}
+
+{% endif %}
+
+
+{% if theme.pace %}
+ {% set pace_css_uri = url_for(theme.vendors._internal + '/pace/'+ theme.pace_theme +'.min.css?v=1.0.2') %}
+ {% set pace_js_uri = url_for(theme.vendors._internal + '/pace/pace.min.js?v=1.0.2') %}
+ {% if theme.vendors.pace %}
+ {% set pace_js_uri = theme.vendors.pace %}
+ {% endif %}
+ {% if theme.vendors.pace_css %}
+ {% set pace_css_uri = theme.vendors.pace_css %}
+ {% endif %}
+
+
+{% endif %}
+
+
+{% if theme.han %}
+ {% set Han_uri = url_for(theme.vendors._internal + '/Han/dist/han.min.css?v=3.3') %}
+ {% if theme.vendors.Han %}
+ {% set Han_uri = theme.vendors.Han %}
+ {% endif %}
+
+{% endif %}
+
+
+{# #238, Disable Baidu tranformation #}
+
+
+
+
+{% if theme.google_site_verification %}
+
+{% endif %}
+
+{% if theme.bing_site_verification %}
+
+{% endif %}
+
+{% if theme.yandex_site_verification %}
+
+{% endif %}
+
+
+{% if theme.baidu_site_verification %}
+
+{% endif %}
+
+
+{% if theme.qihu_site_verification %}
+
+{% endif %}
+
+
+{% if theme.fancybox %}
+ {% set fancybox_css_uri = url_for(theme.vendors._internal + '/fancybox/source/jquery.fancybox.css?v=2.1.5') %}
+ {% if theme.vendors.fancybox_css %}
+ {% set fancybox_css_uri = theme.vendors.fancybox_css %}
+ {% endif %}
+
+{% endif %}
+
+{% include "./external-fonts.swig" %}
+
+{% set font_awesome_uri = url_for(theme.vendors._internal + '/font-awesome/css/font-awesome.min.css?v=4.6.2') %}
+{% if theme.vendors.fontawesome %}
+ {% set font_awesome_uri = theme.vendors.fontawesome %}
+{% endif %}
+
+
+
+
+{% if theme.favicon.apple_touch_icon %}
+
+{% endif %}
+{% if theme.favicon.medium %}
+
+{% endif %}
+{% if theme.favicon.small %}
+
+{% endif %}
+{% if theme.favicon.safari_pinned_tab %}
+
+{% endif %}
+{% if theme.favicon.android_manifest %}
+
+{% endif %}
+{% if theme.favicon.ms_browserconfig %}
+
+{% endif %}
+
+
+{% if theme.facebook_sdk.enable and theme.facebook_sdk.webmaster %}
+
+
+{% endif %}
+
+
+{# Export some HEXO Configurations to Front-End #}
+
+
+{% if theme.custom_file_path.head %}
+ {% set custom_head = '../../../../../' + theme.custom_file_path.head %}
+{% else %}
+ {% set custom_head = '../../_custom/head.swig' %}
+{% endif %}
+{% include custom_head %}
diff --git a/layout/_partials/header/brand.swig b/layout/_partials/header/brand.swig
new file mode 100644
index 000000000..3b81f16de
--- /dev/null
+++ b/layout/_partials/header/brand.swig
@@ -0,0 +1,35 @@
+
+
+
+
+
diff --git a/layout/_partials/header/index.swig b/layout/_partials/header/index.swig
new file mode 100644
index 000000000..42a90de29
--- /dev/null
+++ b/layout/_partials/header/index.swig
@@ -0,0 +1,9 @@
+{{ partial('_partials/header/brand.swig', {}, {cache: theme.cache.enable}) }}
+{% include 'menu.swig' %}
+
+{% if theme.custom_file_path.header %}
+ {% set custom_header = '../../../../../' + theme.custom_file_path.header %}
+{% else %}
+ {% set custom_header = '../../_custom/header.swig' %}
+{% endif %}
+{% include custom_header %}
diff --git a/layout/_partials/header/menu.swig b/layout/_partials/header/menu.swig
new file mode 100644
index 000000000..6562fdaeb
--- /dev/null
+++ b/layout/_partials/header/menu.swig
@@ -0,0 +1,52 @@
+{% import '../../_macro/menu/menu-item.swig' as menu_item %}
+
+
diff --git a/layout/_partials/header/sub-menu.swig b/layout/_partials/header/sub-menu.swig
new file mode 100644
index 000000000..cd9bce4ae
--- /dev/null
+++ b/layout/_partials/header/sub-menu.swig
@@ -0,0 +1,92 @@
+{% if not is_home() && not is_post() %}
+ {% if theme.menu %}
+
+ {% import '../../_macro/menu/menu-item.swig' as menu_item %}
+
+ {# Submenu & Submenu-2 #}
+ {% for name, value in theme.menu %}
+ {% set respath = value %}
+ {% if value == '[object Object]' %}
+
+ {# If current URL is value of parent submenu 'default' path #}
+ {% set currentParentUrl = page.path.split('/')[0] | trim %}
+ {% if currentParentUrl == value.default.split('||')[0] | trim | replace('/', '', 'g') %}
+
+ {# Submenu items #}
+
+
+
+ {# End Submenu items #}
+
+ {# Submenu-2 #}
+ {% for name, value in theme.menu %}
+ {% set respath = value %}
+ {% if value == '[object Object]' %}
+
+ {% for subname, subvalue in value %}
+ {% set itemName = subname.toLowerCase() %}
+ {% if itemName == 'default' %}
+ {% set parentValue = subvalue.split('||')[0] | trim %}
+ {% endif %}
+ {% if subvalue == '[object Object]' %}
+
+ {# If current URL is value of parent submenu 'default' path #}
+ {% set paths = page.path.split('/') %}
+ {% for currentSubParentUrl in paths %}
+ {% if currentSubParentUrl == subvalue.default.split('||')[0] | trim | replace('/', '', 'g') %}
+
+ {# Submenu-2 items #}
+
+ {# End Submenu-2 items #}
+
+ {% endif %}
+ {% endfor %}
+ {# End URL & path comparing #}
+
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+ {% endfor %}
+ {# End Submenu-2 #}
+
+ {% endif %}
+ {# End URL & path comparing #}
+
+ {% endif %}
+ {% endfor %}
+ {# End Submenu & Submenu-2 #}
+
+ {% endif %}
+{% endif %}
diff --git a/layout/_partials/page-header.swig b/layout/_partials/page-header.swig
new file mode 100644
index 000000000..8fb71c6b8
--- /dev/null
+++ b/layout/_partials/page-header.swig
@@ -0,0 +1,12 @@
+
+
+<{% if theme.seo %}h2{% else %}h1{% endif %} class="post-title" itemprop="name headline">{{ page.title }}{% if theme.seo %}h2{% else %}h1{% endif %}>
+
+
diff --git a/layout/_partials/pagination.swig b/layout/_partials/pagination.swig
new file mode 100644
index 000000000..1038580b2
--- /dev/null
+++ b/layout/_partials/pagination.swig
@@ -0,0 +1,11 @@
+{% if page.prev or page.next %}
+
+{% endif %}
diff --git a/layout/_partials/search/index.swig b/layout/_partials/search/index.swig
new file mode 100644
index 000000000..9f2bc8b50
--- /dev/null
+++ b/layout/_partials/search/index.swig
@@ -0,0 +1,9 @@
+{% if theme.algolia_search.enable %}
+ {% include '../../_third-party/search/algolia-search/dom.swig' %}
+{% elseif theme.swiftype_key %}
+ {% include 'swiftype.swig' %}
+{% elseif theme.tinysou_Key %}
+ {% include 'tinysou.swig' %}
+{% elseif theme.local_search.enable %}
+ {% include 'localsearch.swig' %}
+{% endif %}
diff --git a/layout/_partials/search/localsearch.swig b/layout/_partials/search/localsearch.swig
new file mode 100644
index 000000000..f106aa06a
--- /dev/null
+++ b/layout/_partials/search/localsearch.swig
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/_partials/search/swiftype.swig b/layout/_partials/search/swiftype.swig
new file mode 100644
index 000000000..732e0c14b
--- /dev/null
+++ b/layout/_partials/search/swiftype.swig
@@ -0,0 +1,12 @@
+
+
+
diff --git a/layout/_partials/search/tinysou.swig b/layout/_partials/search/tinysou.swig
new file mode 100644
index 000000000..2dfa3e317
--- /dev/null
+++ b/layout/_partials/search/tinysou.swig
@@ -0,0 +1,3 @@
+
diff --git a/layout/_partials/share/add-this.swig b/layout/_partials/share/add-this.swig
new file mode 100644
index 000000000..ae0a6b4f5
--- /dev/null
+++ b/layout/_partials/share/add-this.swig
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/layout/_partials/share/baidushare.swig b/layout/_partials/share/baidushare.swig
new file mode 100644
index 000000000..6be489844
--- /dev/null
+++ b/layout/_partials/share/baidushare.swig
@@ -0,0 +1,57 @@
+{% if theme.baidushare.type === "button" %}
+
+
+{% elseif theme.baidushare.type === "slide" %}
+
+{% endif %}
+
diff --git a/layout/_partials/share/duoshuo_share.swig b/layout/_partials/share/duoshuo_share.swig
new file mode 100644
index 000000000..bfa26f465
--- /dev/null
+++ b/layout/_partials/share/duoshuo_share.swig
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/layout/_partials/share/jiathis.swig b/layout/_partials/share/jiathis.swig
new file mode 100644
index 000000000..325135220
--- /dev/null
+++ b/layout/_partials/share/jiathis.swig
@@ -0,0 +1,25 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/layout/_scripts/boostrap.swig b/layout/_scripts/boostrap.swig
new file mode 100644
index 000000000..1bf5ab5b0
--- /dev/null
+++ b/layout/_scripts/boostrap.swig
@@ -0,0 +1,9 @@
+{%
+ set boot_scripts = [
+ 'src/bootstrap.js'
+ ]
+%}
+
+{% for bs in boot_scripts %}
+
+{% endfor %}
diff --git a/layout/_scripts/commons.swig b/layout/_scripts/commons.swig
new file mode 100644
index 000000000..c99e72766
--- /dev/null
+++ b/layout/_scripts/commons.swig
@@ -0,0 +1,10 @@
+{%
+ set js_commons = [
+ 'src/utils.js',
+ 'src/motion.js'
+ ]
+%}
+
+{% for common in js_commons %}
+
+{% endfor %}
diff --git a/layout/_scripts/noscript.swig b/layout/_scripts/noscript.swig
new file mode 100644
index 000000000..6f9140898
--- /dev/null
+++ b/layout/_scripts/noscript.swig
@@ -0,0 +1,26 @@
+
diff --git a/layout/_scripts/pages/post-details.swig b/layout/_scripts/pages/post-details.swig
new file mode 100644
index 000000000..c9f7634fb
--- /dev/null
+++ b/layout/_scripts/pages/post-details.swig
@@ -0,0 +1,2 @@
+
+
diff --git a/layout/_scripts/schemes/gemini.swig b/layout/_scripts/schemes/gemini.swig
new file mode 100644
index 000000000..676db4e12
--- /dev/null
+++ b/layout/_scripts/schemes/gemini.swig
@@ -0,0 +1,10 @@
+{%
+ set scripts = [
+ 'src/affix.js',
+ 'src/schemes/pisces.js'
+ ]
+%}
+
+{% for script in scripts %}
+
+{% endfor %}
diff --git a/layout/_scripts/schemes/mist.swig b/layout/_scripts/schemes/mist.swig
new file mode 100644
index 000000000..e69de29bb
diff --git a/layout/_scripts/schemes/muse.swig b/layout/_scripts/schemes/muse.swig
new file mode 100644
index 000000000..e69de29bb
diff --git a/layout/_scripts/schemes/pisces.swig b/layout/_scripts/schemes/pisces.swig
new file mode 100644
index 000000000..676db4e12
--- /dev/null
+++ b/layout/_scripts/schemes/pisces.swig
@@ -0,0 +1,10 @@
+{%
+ set scripts = [
+ 'src/affix.js',
+ 'src/schemes/pisces.js'
+ ]
+%}
+
+{% for script in scripts %}
+
+{% endfor %}
diff --git a/layout/_scripts/vendors.swig b/layout/_scripts/vendors.swig
new file mode 100644
index 000000000..5e8bf01e4
--- /dev/null
+++ b/layout/_scripts/vendors.swig
@@ -0,0 +1,61 @@
+{# Reset `window.Promise` when it was not a function. #}
+{# IE refers the element whose id is `Promise` as `window.Promise`, this causes Velocity throwing an exception #}
+
+
+{% set js_vendors = {} %}
+{% set js_vendors.jquery = 'jquery/index.js?v=2.1.3' %}
+
+{% if theme.fastclick %}
+ {% set js_vendors.fastclick = 'fastclick/lib/fastclick.min.js?v=1.0.6' %}
+{% endif %}
+
+{% if theme.lazyload %}
+ {% set js_vendors.lazyload = 'jquery_lazyload/jquery.lazyload.js?v=1.9.7' %}
+{% endif %}
+
+{% set js_vendors.velocity = 'velocity/velocity.min.js?v=1.2.1' %}
+{% set js_vendors.velocity_ui = 'velocity/velocity.ui.min.js?v=1.2.1' %}
+
+{% if theme.fancybox %}
+ {% set js_vendors.fancybox = 'fancybox/source/jquery.fancybox.pack.js?v=2.1.5' %}
+{% endif %}
+
+{% if theme.canvas_nest %}
+ {% set js_vendors.canvas_nest = 'canvas-nest/canvas-nest.min.js' %}
+{% endif %}
+
+{% if theme.three_waves %}
+ {% set js_vendors.three = 'three/three.min.js' %}
+ {% set js_vendors.three_waves = 'three/three-waves.min.js' %}
+{% endif %}
+
+{% if theme.canvas_lines %}
+ {% set js_vendors.three = 'three/three.min.js' %}
+ {% set js_vendors.canvas_lines = 'three/canvas_lines.min.js' %}
+{% endif %}
+
+{% if theme.canvas_sphere %}
+ {% set js_vendors.three = 'three/three.min.js' %}
+ {% set js_vendors.canvas_sphere = 'three/canvas_sphere.min.js' %}
+{% endif %}
+
+{% if theme.canvas_ribbon.enable and theme.scheme === 'Pisces'%}
+ {% set js_vendors.canvas_ribbon = 'canvas-ribbon/canvas-ribbon.js' %}
+{% endif %}
+
+{% if theme.reading_progress.enable %}
+ {% set js_vendors.reading_progress = 'reading_progress/reading_progress.js' %}
+{% endif %}
+
+{% for name, internal in js_vendors %}
+ {% set internal_script = url_for(theme.vendors._internal) + '/' + internal %}
+ {% if name == 'canvas_ribbon' %}
+
+ {% else %}
+
+ {% endif %}
+{% endfor %}
diff --git a/layout/_third-party/analytics/analytics-with-widget.swig b/layout/_third-party/analytics/analytics-with-widget.swig
new file mode 100644
index 000000000..f2a40490d
--- /dev/null
+++ b/layout/_third-party/analytics/analytics-with-widget.swig
@@ -0,0 +1,4 @@
+{% include 'busuanzi-counter.swig' %}
+{% include 'tencent-mta.swig' %}
+{% include 'tencent-analytics.swig' %}
+{% include 'cnzz-analytics.swig' %}
\ No newline at end of file
diff --git a/layout/_third-party/analytics/application-insights.swig b/layout/_third-party/analytics/application-insights.swig
new file mode 100644
index 000000000..c0af16fad
--- /dev/null
+++ b/layout/_third-party/analytics/application-insights.swig
@@ -0,0 +1,11 @@
+{% if theme.application_insights %}
+
+{% endif %}
\ No newline at end of file
diff --git a/layout/_third-party/analytics/baidu-analytics.swig b/layout/_third-party/analytics/baidu-analytics.swig
new file mode 100644
index 000000000..9ae1d8349
--- /dev/null
+++ b/layout/_third-party/analytics/baidu-analytics.swig
@@ -0,0 +1,11 @@
+{% if theme.baidu_analytics %}
+
+{% endif %}
diff --git a/layout/_third-party/analytics/busuanzi-counter.swig b/layout/_third-party/analytics/busuanzi-counter.swig
new file mode 100644
index 000000000..880e986cf
--- /dev/null
+++ b/layout/_third-party/analytics/busuanzi-counter.swig
@@ -0,0 +1,20 @@
+{% if theme.busuanzi_count.enable %}
+
+
+
+ {% if theme.busuanzi_count.total_visitors %}
+
+
+
+
+ {% endif %}
+
+ {% if theme.busuanzi_count.total_views %}
+
+
+
+
+ {% endif %}
+
+{% endif %}
+
diff --git a/layout/_third-party/analytics/cnzz-analytics.swig b/layout/_third-party/analytics/cnzz-analytics.swig
new file mode 100644
index 000000000..bffb73cdc
--- /dev/null
+++ b/layout/_third-party/analytics/cnzz-analytics.swig
@@ -0,0 +1,7 @@
+{% if theme.cnzz_siteid %}
+
+
+
+{% endif %}
diff --git a/layout/_third-party/analytics/facebook-sdk.swig b/layout/_third-party/analytics/facebook-sdk.swig
new file mode 100644
index 000000000..7b5a29187
--- /dev/null
+++ b/layout/_third-party/analytics/facebook-sdk.swig
@@ -0,0 +1,19 @@
+{% if theme.facebook_sdk.enable %}
+
+{% endif %}
diff --git a/layout/_third-party/analytics/firestore.swig b/layout/_third-party/analytics/firestore.swig
new file mode 100644
index 000000000..9e5cb7637
--- /dev/null
+++ b/layout/_third-party/analytics/firestore.swig
@@ -0,0 +1,99 @@
+{% if theme.firestore.enable %}
+
+
+ {% if theme.firestore.bluebird %}
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_third-party/analytics/google-analytics.swig b/layout/_third-party/analytics/google-analytics.swig
new file mode 100644
index 000000000..1190babc9
--- /dev/null
+++ b/layout/_third-party/analytics/google-analytics.swig
@@ -0,0 +1,10 @@
+{% if theme.google_analytics %}
+
+
+{% endif %}
diff --git a/layout/_third-party/analytics/index.swig b/layout/_third-party/analytics/index.swig
new file mode 100644
index 000000000..78ae38eec
--- /dev/null
+++ b/layout/_third-party/analytics/index.swig
@@ -0,0 +1,5 @@
+{% include 'facebook-sdk.swig' %}
+{% include 'vkontakte-api.swig' %}
+{% include 'google-analytics.swig' %}
+{% include 'baidu-analytics.swig' %}
+{% include 'application-insights.swig' %}
diff --git a/layout/_third-party/analytics/lean-analytics.swig b/layout/_third-party/analytics/lean-analytics.swig
new file mode 100644
index 000000000..46496471d
--- /dev/null
+++ b/layout/_third-party/analytics/lean-analytics.swig
@@ -0,0 +1,120 @@
+{% if theme.leancloud_visitors.enable %}
+
+ {# custom analytics part create by xiamo; edited by LEAFERx #}
+
+
+
+
+{% endif %}
diff --git a/layout/_third-party/analytics/tencent-analytics.swig b/layout/_third-party/analytics/tencent-analytics.swig
new file mode 100644
index 000000000..c2fab35ec
--- /dev/null
+++ b/layout/_third-party/analytics/tencent-analytics.swig
@@ -0,0 +1,10 @@
+{% if theme.tencent_analytics %}
+
+{% endif %}
diff --git a/layout/_third-party/analytics/tencent-mta.swig b/layout/_third-party/analytics/tencent-mta.swig
new file mode 100644
index 000000000..f4b647015
--- /dev/null
+++ b/layout/_third-party/analytics/tencent-mta.swig
@@ -0,0 +1,14 @@
+{% if theme.tencent_mta %}
+
+{% endif %}
diff --git a/layout/_third-party/analytics/vkontakte-api.swig b/layout/_third-party/analytics/vkontakte-api.swig
new file mode 100644
index 000000000..913a8fc90
--- /dev/null
+++ b/layout/_third-party/analytics/vkontakte-api.swig
@@ -0,0 +1,27 @@
+{% if theme.vkontakte_api.enable %}
+
+
+
+
+{% endif %}
diff --git a/layout/_third-party/bookmark.swig b/layout/_third-party/bookmark.swig
new file mode 100644
index 000000000..f28c12e28
--- /dev/null
+++ b/layout/_third-party/bookmark.swig
@@ -0,0 +1,14 @@
+{% if theme.bookmark and theme.bookmark.enable %}
+ {% set bookmark_uri = url_for(theme.vendors._internal + '/bookmark/bookmark.min.js?v=1.0')%}
+ {% if theme.vendors.bookmark %}
+ {% set bookmark_uri = theme.vendors.bookmark %}
+ {% endif %}
+
+
+{% endif %}
diff --git a/layout/_third-party/comments/changyan.swig b/layout/_third-party/comments/changyan.swig
new file mode 100644
index 000000000..d816b2cba
--- /dev/null
+++ b/layout/_third-party/comments/changyan.swig
@@ -0,0 +1,18 @@
+{% if theme.changyan.enable and theme.changyan.appid and theme.changyan.appkey %}
+ {% if is_home() %}
+
+ {% else %}
+
+
+ {% endif %}
+{% endif %}
diff --git a/layout/_third-party/comments/disqus.swig b/layout/_third-party/comments/disqus.swig
new file mode 100644
index 000000000..7ff74d056
--- /dev/null
+++ b/layout/_third-party/comments/disqus.swig
@@ -0,0 +1,45 @@
+{% if theme.disqus.enable %}
+
+ {% if theme.disqus.count %}
+
+ {% endif %}
+
+ {% if page.comments %}
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_third-party/comments/gitment.swig b/layout/_third-party/comments/gitment.swig
new file mode 100644
index 000000000..edf415f7e
--- /dev/null
+++ b/layout/_third-party/comments/gitment.swig
@@ -0,0 +1,57 @@
+{% if theme.gitment.enable and theme.gitment.client_id %}
+
+ {% if theme.gitment.mint %}
+ {% set CommentsClass = "Gitmint" %}
+
+
+ {% else %}
+ {% set CommentsClass = "Gitment" %}
+
+
+ {% endif %}
+
+
+ {% if theme.gitment.cleanly %}
+
+ {% endif %}
+
+ {% if page.comments %}
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_third-party/comments/hypercomments.swig b/layout/_third-party/comments/hypercomments.swig
new file mode 100644
index 000000000..c90ee1c63
--- /dev/null
+++ b/layout/_third-party/comments/hypercomments.swig
@@ -0,0 +1,27 @@
+{% if not theme.disqus_shortname %}
+
+ {% if theme.hypercomments_id %}
+
+
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_third-party/comments/index.swig b/layout/_third-party/comments/index.swig
new file mode 100644
index 000000000..f9db12d3f
--- /dev/null
+++ b/layout/_third-party/comments/index.swig
@@ -0,0 +1,7 @@
+{% include 'disqus.swig' %}
+{% include 'hypercomments.swig' %}
+{% include 'youyan.swig' %}
+{% include 'livere.swig' %}
+{% include 'changyan.swig' %}
+{% include 'gitment.swig' %}
+{% include 'valine.swig' %}
diff --git a/layout/_third-party/comments/livere.swig b/layout/_third-party/comments/livere.swig
new file mode 100644
index 000000000..99f9b4ed8
--- /dev/null
+++ b/layout/_third-party/comments/livere.swig
@@ -0,0 +1,16 @@
+{% if not (theme.disqus.enable and theme.disqus.shortname) and not theme.hypercomments_id %}
+
+ {% if page.comments and theme.livere_uid %}
+
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_third-party/comments/valine.swig b/layout/_third-party/comments/valine.swig
new file mode 100644
index 000000000..a5d09eec8
--- /dev/null
+++ b/layout/_third-party/comments/valine.swig
@@ -0,0 +1,27 @@
+{% if theme.valine.enable and theme.valine.appid and theme.valine.appkey %}
+
+ {% set valine_uri = '//unpkg.com/valine/dist/Valine.min.js' %}
+ {% if theme.vendors.valine %}
+ {% set valine_uri = theme.vendors.valine %}
+ {% endif %}
+
+
+
+{% endif %}
diff --git a/layout/_third-party/comments/youyan.swig b/layout/_third-party/comments/youyan.swig
new file mode 100644
index 000000000..68dae72f1
--- /dev/null
+++ b/layout/_third-party/comments/youyan.swig
@@ -0,0 +1,14 @@
+{% if not theme.disqus_shortname
+ and not theme.hypercomments_id %}
+
+ {% if theme.youyan_uid %}
+ {% set uid = theme.youyan_uid %}
+
+ {% if page.comments %}
+
+
+
+ {% endif %}
+ {% endif %}
+
+{% endif %}
diff --git a/layout/_third-party/copy-code.swig b/layout/_third-party/copy-code.swig
new file mode 100644
index 000000000..f9831907a
--- /dev/null
+++ b/layout/_third-party/copy-code.swig
@@ -0,0 +1,70 @@
+{% if theme.codeblock.copy_button.enable %}
+
+
+{% endif %}
diff --git a/layout/_third-party/exturl.swig b/layout/_third-party/exturl.swig
new file mode 100644
index 000000000..0a416c36d
--- /dev/null
+++ b/layout/_third-party/exturl.swig
@@ -0,0 +1,3 @@
+{% if theme.exturl %}
+
+{% endif %}
diff --git a/layout/_third-party/github-banner.swig b/layout/_third-party/github-banner.swig
new file mode 100644
index 000000000..3a305a218
--- /dev/null
+++ b/layout/_third-party/github-banner.swig
@@ -0,0 +1,16 @@
+{% if theme.github_banner %}
+ {% set github_banner_bg_color = theme.android_chrome_color %}
+ {% set github_banner_fg_color = "#fff" %}
+ {% set github_title = theme.github_banner.split('||')[1] | trim %}
+ {% if theme.exturl && theme.social_icons.exturl %}
+ {% set github_url = '
+ {% if theme.exturl && theme.social_icons.exturl %}
+
+ {% else %}
+
+ {% endif %}
+{% endif %}
diff --git a/layout/_third-party/math/index.swig b/layout/_third-party/math/index.swig
new file mode 100644
index 000000000..7ef5e3c6b
--- /dev/null
+++ b/layout/_third-party/math/index.swig
@@ -0,0 +1,20 @@
+{% if theme.math.enable %}
+ {% set is_index_has_math = false %}
+
+ {# At home, check if there has `mathjax: true` post #}
+ {% if is_home() %}
+ {% for post in page.posts %}
+ {% if post.mathjax and not is_index_has_math %}
+ {% set is_index_has_math = true %}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+ {% if not theme.math.per_page or (is_index_has_math or page.mathjax) %}
+ {% if theme.math.engine == 'mathjax' %}
+ {% include 'mathjax.swig' %}
+ {% elif theme.math.engine == 'katex' %}
+ {% include 'katex.swig' %}
+ {% endif %}
+ {% endif %}
+{% endif %}
diff --git a/layout/_third-party/math/katex.swig b/layout/_third-party/math/katex.swig
new file mode 100644
index 000000000..9f5c0d5c0
--- /dev/null
+++ b/layout/_third-party/math/katex.swig
@@ -0,0 +1 @@
+
diff --git a/layout/_third-party/math/mathjax.swig b/layout/_third-party/math/mathjax.swig
new file mode 100644
index 000000000..2fce8f2be
--- /dev/null
+++ b/layout/_third-party/math/mathjax.swig
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/layout/_third-party/needsharebutton.swig b/layout/_third-party/needsharebutton.swig
new file mode 100644
index 000000000..9120520c6
--- /dev/null
+++ b/layout/_third-party/needsharebutton.swig
@@ -0,0 +1,24 @@
+{% if theme.needmoreshare2.enable %}
+ {% set needmoreshare2_js = url_for(theme.vendors._internal + '/needsharebutton/needsharebutton.js') %}
+ {% if theme.vendors.needmoreshare2_js %}
+ {% set needmoreshare2_js = theme.vendors.needmoreshare2_js %}
+ {% endif %}
+
+
+
+{% endif %}
\ No newline at end of file
diff --git a/layout/_third-party/pangu.swig b/layout/_third-party/pangu.swig
new file mode 100644
index 000000000..cedb9c369
--- /dev/null
+++ b/layout/_third-party/pangu.swig
@@ -0,0 +1,8 @@
+{% if theme.pangu %}
+ {% set pangu_uri = url_for(theme.vendors._internal + '/pangu/dist/pangu.min.js?v=3.3')%}
+ {% if theme.vendors.pangu %}
+ {% set pangu_uri = theme.vendors.pangu %}
+ {% endif %}
+
+
+{% endif %}
diff --git a/layout/_third-party/rating.swig b/layout/_third-party/rating.swig
new file mode 100644
index 000000000..3b376ce31
--- /dev/null
+++ b/layout/_third-party/rating.swig
@@ -0,0 +1,18 @@
+{% if theme.rating.enable and (not is_home() and is_post()) %}
+
+{% endif %}
diff --git a/layout/_third-party/schedule.swig b/layout/_third-party/schedule.swig
new file mode 100644
index 000000000..6db3a3c46
--- /dev/null
+++ b/layout/_third-party/schedule.swig
@@ -0,0 +1,185 @@
+{% if theme.calendar.enable %}
+{% if page.type == 'schedule' %}
+
+
+
+{% endif %}
+{% endif %}
diff --git a/layout/_third-party/scroll-cookie.swig b/layout/_third-party/scroll-cookie.swig
new file mode 100644
index 000000000..b4d9d07bf
--- /dev/null
+++ b/layout/_third-party/scroll-cookie.swig
@@ -0,0 +1,4 @@
+{% if theme.save_scroll %}
+
+
+{% endif %}
diff --git a/layout/_third-party/search/algolia-search/assets.swig b/layout/_third-party/search/algolia-search/assets.swig
new file mode 100644
index 000000000..07e322217
--- /dev/null
+++ b/layout/_third-party/search/algolia-search/assets.swig
@@ -0,0 +1,18 @@
+{% if theme.algolia_search.enable %}
+
+ {# S: Include Algolia instantsearch.js library #}
+ {% set algolia_instant_css = url_for(theme.vendors._internal + '/algolia-instant-search/instantsearch.min.css') %}
+ {% if theme.vendors.algolia_instant_css %}
+ {% set algolia_instant_css = theme.vendors.algolia_instant_css %}
+ {% endif %}
+
+
+ {% set algolia_instant_js = url_for(theme.vendors._internal + '/algolia-instant-search/instantsearch.min.js') %}
+ {% if theme.vendors.algolia_instant_js %}
+ {% set algolia_instant_js = theme.vendors.algolia_instant_js %}
+ {% endif %}
+
+ {# E: Include Algolia instantsearch.js library #}
+
+
+{% endif %}
diff --git a/layout/_third-party/search/algolia-search/dom.swig b/layout/_third-party/search/algolia-search/dom.swig
new file mode 100644
index 000000000..a733bb179
--- /dev/null
+++ b/layout/_third-party/search/algolia-search/dom.swig
@@ -0,0 +1,20 @@
+{% if theme.algolia_search.enable %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endif %}
diff --git a/layout/_third-party/search/index.swig b/layout/_third-party/search/index.swig
new file mode 100644
index 000000000..0a352bcc8
--- /dev/null
+++ b/layout/_third-party/search/index.swig
@@ -0,0 +1,3 @@
+{% include 'tinysou.swig' %}
+{% include 'localsearch.swig' %}
+{% include 'algolia-search/assets.swig' %}
diff --git a/layout/_third-party/search/localsearch.swig b/layout/_third-party/search/localsearch.swig
new file mode 100644
index 000000000..7ec22de46
--- /dev/null
+++ b/layout/_third-party/search/localsearch.swig
@@ -0,0 +1,336 @@
+{% if theme.local_search.enable %}
+
+{% endif %}
diff --git a/layout/_third-party/search/tinysou.swig b/layout/_third-party/search/tinysou.swig
new file mode 100644
index 000000000..6e186847a
--- /dev/null
+++ b/layout/_third-party/search/tinysou.swig
@@ -0,0 +1,23 @@
+{% if config.tinysou_Key %}
+
+{% endif %}
\ No newline at end of file
diff --git a/layout/_third-party/seo/baidu-push.swig b/layout/_third-party/seo/baidu-push.swig
new file mode 100644
index 000000000..ee6838f3a
--- /dev/null
+++ b/layout/_third-party/seo/baidu-push.swig
@@ -0,0 +1,16 @@
+{% if theme.baidu_push %}
+
+{% endif %}
diff --git a/layout/archive.swig b/layout/archive.swig
new file mode 100644
index 000000000..fc146b6bf
--- /dev/null
+++ b/layout/archive.swig
@@ -0,0 +1,64 @@
+{% extends '_layout.swig' %}
+{% import '_macro/post-collapse.swig' as post_template %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+{% block title %}{{ __('title.archive') }} | {{ title }}{% endblock %}
+
+{% block page_class %}page-archive{% endblock %}
+
+{% block content %}
+
+ {#####################}
+ {### ARCHIVE BLOCK ###}
+ {#####################}
+
+
+
+
+ {% if theme.cheers_enabled %}
+
+ {% set cheers %}
+ {% set posts_length = site.posts.length %}
+ {% if posts_length > 210 %} {% set cheers = 'excellent' %}
+ {% elif posts_length > 130 %} {% set cheers = 'great' %}
+ {% elif posts_length > 80 %} {% set cheers = 'good' %}
+ {% elif posts_length > 50 %} {% set cheers = 'nice' %}
+ {% elif posts_length > 30 %} {% set cheers = 'ok' %}
+ {% else %}
+ {% set cheers = 'um' %}
+ {% endif %}
+ {{ __('cheers.' + cheers) }}! {{ _p("counter.archive_posts", site.posts.length) }} {{ __('keep_on') }}
+
+ {% endif %}
+
+ {% for post in page.posts %}
+
+ {# Show year #}
+ {% set year %}
+ {% set post.year = date(post.date, 'YYYY') %}
+
+ {% if post.year !== year %}
+ {% set year = post.year %}
+
+ <{% if theme.seo %}h2{% else %}h1{% endif %} class="archive-year" id="archive-year-{{ year }}">{{ year }}{% if theme.seo %}h2{% else %}h1{% endif %}>
+
+ {% endif %}
+ {# endshow #}
+
+ {{ post_template.render(post) }}
+
+ {% endfor %}
+
+
+
+ {#########################}
+ {### END ARCHIVE BLOCK ###}
+ {#########################}
+
+ {% include '_partials/pagination.swig' %}
+
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(false) }}
+{% endblock %}
diff --git a/layout/category.swig b/layout/category.swig
new file mode 100644
index 000000000..e28bdbce5
--- /dev/null
+++ b/layout/category.swig
@@ -0,0 +1,38 @@
+{% extends '_layout.swig' %}
+{% import '_macro/post-collapse.swig' as post_template %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+{% block title %}{{ __('title.category') }}: {{ page.category }} | {{ title }}{% endblock %}
+
+{% block content %}
+
+ {######################}
+ {### CATEGORY BLOCK ###}
+ {######################}
+
+
+
+
+ <{% if theme.seo %}h2{% else %}h1{% endif %}>{#
+ #}{{ page.category }}{#
+ #}{{ __('title.category') }}
+ {% if theme.seo %}h2{% else %}h1{% endif %}>
+
+
+ {% for post in page.posts %}
+ {{ post_template.render(post) }}
+ {% endfor %}
+
+
+
+ {##########################}
+ {### END CATEGORY BLOCK ###}
+ {##########################}
+
+ {% include '_partials/pagination.swig' %}
+
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(false) }}
+{% endblock %}
diff --git a/layout/index.swig b/layout/index.swig
new file mode 100644
index 000000000..26ecd8f34
--- /dev/null
+++ b/layout/index.swig
@@ -0,0 +1,23 @@
+{% extends '_layout.swig' %}
+{% import '_macro/post.swig' as post_template %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+{% block title %}{{ title }}{% if theme.index_with_subtitle and subtitle %} — {{ subtitle }}{% endif %}{% endblock %}
+
+{% block page_class %}
+ {% if is_home() %}page-home{% endif -%}
+{% endblock %}
+
+{% block content %}
+
+
+ {% include '_partials/pagination.swig' %}
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(false) }}
+{% endblock %}
diff --git a/layout/page.swig b/layout/page.swig
new file mode 100644
index 000000000..be968fd18
--- /dev/null
+++ b/layout/page.swig
@@ -0,0 +1,83 @@
+{% extends '_layout.swig' %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+ {% block title %}{#
+ #}{% set page_title_suffix = ' | ' + title %}{#
+
+ #}{% if page.type === "categories" and not page.title %}{#
+ #}{{ __('title.category') + page_title_suffix }}{#
+ #}{% elif page.type === "tags" and not page.title %}{#
+ #}{{ __('title.tag') + page_title_suffix }}{#
+ #}{% else %}{#
+ #}{{ page.title + page_title_suffix }}{#
+ #}{% endif %}{#
+#}{% endblock %}
+
+{% block page_class %}page-post-detail{% endblock %}
+
+{% block content %}
+
+
+
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(false) }}
+{% endblock %}
+
+{% block script_extra %}
+ {% include '_scripts/pages/post-details.swig' %}
+{% endblock %}
diff --git a/layout/post.swig b/layout/post.swig
new file mode 100644
index 000000000..ddfdddeab
--- /dev/null
+++ b/layout/post.swig
@@ -0,0 +1,35 @@
+{% extends '_layout.swig' %}
+{% import '_macro/post.swig' as post_template %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+
+{% block title %}{{ page.title }} | {{ title }}{% endblock %}
+
+{% block page_class %}page-post-detail{% endblock %}
+
+
+{% block content %}
+
+
+
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(true) }}
+{% endblock %}
+
+{% block script_extra %}
+ {% include '_scripts/pages/post-details.swig' %}
+{% endblock %}
diff --git a/layout/schedule.swig b/layout/schedule.swig
new file mode 100644
index 000000000..e1d3c04ee
--- /dev/null
+++ b/layout/schedule.swig
@@ -0,0 +1,25 @@
+{% extends '_layout.swig' %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+{% block title %}{{ __('title.schedule') }} | {{ title }}{% endblock %}
+
+{% block page_class %}page-post-detail page-calendar{% endblock %}
+
+{% block content %}
+ {######################}
+ {### SCHEDULE BLOCK ###}
+ {######################}
+
+
+
+
+
+
+ {##########################}
+ {### END SCHEDULE BLOCK ###}
+ {##########################}
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(false) }}
+{% endblock %}
diff --git a/layout/tag.swig b/layout/tag.swig
new file mode 100644
index 000000000..7af5a77c7
--- /dev/null
+++ b/layout/tag.swig
@@ -0,0 +1,37 @@
+{% extends '_layout.swig' %}
+{% import '_macro/post-collapse.swig' as post_template %}
+{% import '_macro/sidebar.swig' as sidebar_template %}
+
+{% block title %}{{ __('title.tag') }}: {{ page.tag }} | {{ title }}{% endblock %}
+
+{% block content %}
+
+ {#################}
+ {### TAG BLOCK ###}
+ {#################}
+
+
+
+
+ <{% if theme.seo %}h2{% else %}h1{% endif %}>{#
+ #}{{ page.tag }}{#
+ #}{{ __('title.tag') }}
+ {% if theme.seo %}h2{% else %}h1{% endif %}>
+
+
+ {% for post in page.posts %}
+ {{ post_template.render(post) }}
+ {% endfor %}
+
+
+
+ {#####################}
+ {### END TAG BLOCK ###}
+ {#####################}
+
+ {% include '_partials/pagination.swig' %}
+{% endblock %}
+
+{% block sidebar %}
+ {{ sidebar_template.render(false) }}
+{% endblock %}
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..dcd68887a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "hexo-theme-next",
+ "version": "6.3.0",
+ "description": "Elegant and powerful theme for Hexo",
+ "main": "index.js",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "test": "gulp"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/theme-next/hexo-theme-next.git"
+ },
+ "keywords": [
+ "hexo",
+ "theme",
+ "next"
+ ],
+ "author": "NexT (https://theme-next.org)",
+ "license": "AGPL",
+ "bugs": {
+ "url": "https://github.com/theme-next/hexo-theme-next/issues"
+ },
+ "homepage": "https://theme-next.org",
+ "devDependencies": {
+ "coffee-script": "^1.10.0",
+ "gulp": "^3.9.0",
+ "gulp-jshint": "^1.12.0",
+ "gulp-shell": "^0.6.1",
+ "js-yaml": "^3.8.1",
+ "jshint-stylish": "^2.1.0",
+ "stylint": "^1.5.9"
+ }
+}
diff --git a/scripts/helpers.js b/scripts/helpers.js
new file mode 100644
index 000000000..03144cd73
--- /dev/null
+++ b/scripts/helpers.js
@@ -0,0 +1,23 @@
+'use strict';
+
+hexo.extend.helper.register('hexo_env', function(type) {
+ return this.env[type];
+});
+
+hexo.extend.helper.register('next_env', function(type) {
+ var env = require('../package.json');
+ return env[type];
+});
+
+hexo.extend.helper.register('item_active', function(path, className) {
+ var canonical = this.page.canonical_path;
+ var current = this.url_for(canonical).replace('index.html', '', 'g');
+ var result = '';
+
+ if (current.indexOf(path) !== -1) {
+ if (path !== '/' || path === current) {
+ result = ' ' + className;
+ }
+ }
+ return result;
+});
diff --git a/scripts/merge-configs.js b/scripts/merge-configs.js
new file mode 100644
index 000000000..2c36f24cc
--- /dev/null
+++ b/scripts/merge-configs.js
@@ -0,0 +1,45 @@
+/* global hexo */
+
+'use strict';
+
+var merge = require('./merge');
+
+hexo.on('generateBefore', function() {
+ if (hexo.locals.get) {
+ var data = hexo.locals.get('data');
+
+ /**
+ * Merge configs from _data/next.yml into hexo.theme.config.
+ * If `override`, configs in next.yml will rewrite configs in hexo.theme.config.
+ * If next.yml not exists, merge all `theme_config.*` into hexo.theme.config.
+ */
+ if (data && data.next) {
+ if (data.next.override) {
+ hexo.theme.config = data.next;
+ } else {
+ merge(hexo.config, data.next);
+ merge(hexo.theme.config, data.next);
+ }
+ } else {
+ merge(hexo.theme.config, hexo.config.theme_config);
+ }
+
+ // Custom languages support. Introduced in NexT v6.3.0.
+ if (data && data.languages) {
+ var lang = this.config.language;
+ var i18n = this.theme.i18n;
+
+ var mergeLang = function(lang) {
+ i18n.set(lang, merge(i18n.get([lang]), data.languages[lang]));
+ };
+
+ if (Array.isArray(lang)) {
+ for (var i = 0; i < lang.length; i++) {
+ mergeLang(lang[i]);
+ }
+ } else {
+ mergeLang(lang);
+ }
+ }
+ }
+});
diff --git a/scripts/merge.js b/scripts/merge.js
new file mode 100644
index 000000000..f964663d5
--- /dev/null
+++ b/scripts/merge.js
@@ -0,0 +1,2225 @@
+/**
+ * lodash (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright jQuery Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
+
+/** Used as the size to enable large array optimizations. */
+var LARGE_ARRAY_SIZE = 200;
+
+/** Used to stand-in for `undefined` hash values. */
+var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+/** Used as references for various `Number` constants. */
+var MAX_SAFE_INTEGER = 9007199254740991;
+
+/** `Object#toString` result references. */
+var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ objectTag = '[object Object]',
+ promiseTag = '[object Promise]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]',
+ weakMapTag = '[object WeakMap]';
+
+var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+/**
+ * Used to match `RegExp`
+ * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
+ */
+var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
+
+/** Used to match `RegExp` flags from their coerced string values. */
+var reFlags = /\w*$/;
+
+/** Used to detect host constructors (Safari). */
+var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+/** Used to detect unsigned integer values. */
+var reIsUint = /^(?:0|[1-9]\d*)$/;
+
+/** Used to identify `toStringTag` values of typed arrays. */
+var typedArrayTags = {};
+typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+ typedArrayTags[uint32Tag] = true;
+typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+ typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
+ typedArrayTags[errorTag] = typedArrayTags[funcTag] =
+ typedArrayTags[mapTag] = typedArrayTags[numberTag] =
+ typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
+ typedArrayTags[setTag] = typedArrayTags[stringTag] =
+ typedArrayTags[weakMapTag] = false;
+
+/** Used to identify `toStringTag` values supported by `_.clone`. */
+var cloneableTags = {};
+cloneableTags[argsTag] = cloneableTags[arrayTag] =
+ cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
+ cloneableTags[boolTag] = cloneableTags[dateTag] =
+ cloneableTags[float32Tag] = cloneableTags[float64Tag] =
+ cloneableTags[int8Tag] = cloneableTags[int16Tag] =
+ cloneableTags[int32Tag] = cloneableTags[mapTag] =
+ cloneableTags[numberTag] = cloneableTags[objectTag] =
+ cloneableTags[regexpTag] = cloneableTags[setTag] =
+ cloneableTags[stringTag] = cloneableTags[symbolTag] =
+ cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+ cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+cloneableTags[errorTag] = cloneableTags[funcTag] =
+ cloneableTags[weakMapTag] = false;
+
+/** Detect free variable `global` from Node.js. */
+var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
+
+/** Detect free variable `self`. */
+var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
+
+/** Used as a reference to the global object. */
+var root = freeGlobal || freeSelf || Function('return this')();
+
+/** Detect free variable `exports`. */
+var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
+
+/** Detect free variable `module`. */
+var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
+
+/** Detect the popular CommonJS extension `module.exports`. */
+var moduleExports = freeModule && freeModule.exports === freeExports;
+
+/** Detect free variable `process` from Node.js. */
+var freeProcess = moduleExports && freeGlobal.process;
+
+/** Used to access faster Node.js helpers. */
+var nodeUtil = (function () {
+ try {
+ return freeProcess && freeProcess.binding('util');
+ } catch (e) {
+ }
+}());
+
+/* Node.js helper references. */
+var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+
+/**
+ * Adds the key-value `pair` to `map`.
+ *
+ * @private
+ * @param {Object} map The map to modify.
+ * @param {Array} pair The key-value pair to add.
+ * @returns {Object} Returns `map`.
+ */
+function addMapEntry(map, pair) {
+ // Don't return `map.set` because it's not chainable in IE 11.
+ map.set(pair[0], pair[1]);
+ return map;
+}
+
+/**
+ * Adds `value` to `set`.
+ *
+ * @private
+ * @param {Object} set The set to modify.
+ * @param {*} value The value to add.
+ * @returns {Object} Returns `set`.
+ */
+function addSetEntry(set, value) {
+ // Don't return `set.add` because it's not chainable in IE 11.
+ set.add(value);
+ return set;
+}
+
+/**
+ * A faster alternative to `Function#apply`, this function invokes `func`
+ * with the `this` binding of `thisArg` and the arguments of `args`.
+ *
+ * @private
+ * @param {Function} func The function to invoke.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} args The arguments to invoke `func` with.
+ * @returns {*} Returns the result of `func`.
+ */
+function apply(func, thisArg, args) {
+ switch (args.length) {
+ case 0:
+ return func.call(thisArg);
+ case 1:
+ return func.call(thisArg, args[0]);
+ case 2:
+ return func.call(thisArg, args[0], args[1]);
+ case 3:
+ return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+}
+
+/**
+ * A specialized version of `_.forEach` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array ? array.length : 0;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+}
+
+/**
+ * Appends the elements of `values` to `array`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to append.
+ * @returns {Array} Returns `array`.
+ */
+function arrayPush(array, values) {
+ var index = -1,
+ length = values.length,
+ offset = array.length;
+
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+}
+
+/**
+ * A specialized version of `_.reduce` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the first element of `array` as
+ * the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1,
+ length = array ? array.length : 0;
+
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+}
+
+/**
+ * The base implementation of `_.times` without support for iteratee shorthands
+ * or max array length checks.
+ *
+ * @private
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ */
+function baseTimes(n, iteratee) {
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+}
+
+/**
+ * The base implementation of `_.unary` without support for storing metadata.
+ *
+ * @private
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new capped function.
+ */
+function baseUnary(func) {
+ return function (value) {
+ return func(value);
+ };
+}
+
+/**
+ * Gets the value at `key` of `object`.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {string} key The key of the property to get.
+ * @returns {*} Returns the property value.
+ */
+function getValue(object, key) {
+ return object == null ? undefined : object[key];
+}
+
+/**
+ * Checks if `value` is a host object in IE < 9.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
+ */
+function isHostObject(value) {
+ // Many host objects are `Object` objects that can coerce to strings
+ // despite having improperly defined `toString` methods.
+ var result = false;
+ if (value != null && typeof value.toString != 'function') {
+ try {
+ result = !!(value + '');
+ } catch (e) {
+ }
+ }
+ return result;
+}
+
+/**
+ * Converts `map` to its key-value pairs.
+ *
+ * @private
+ * @param {Object} map The map to convert.
+ * @returns {Array} Returns the key-value pairs.
+ */
+function mapToArray(map) {
+ var index = -1,
+ result = Array(map.size);
+
+ map.forEach(function (value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+}
+
+/**
+ * Creates a unary function that invokes `func` with its argument transformed.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {Function} transform The argument transform.
+ * @returns {Function} Returns the new function.
+ */
+function overArg(func, transform) {
+ return function (arg) {
+ return func(transform(arg));
+ };
+}
+
+/**
+ * Converts `set` to an array of its values.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the values.
+ */
+function setToArray(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function (value) {
+ result[++index] = value;
+ });
+ return result;
+}
+
+/** Used for built-in method references. */
+var arrayProto = Array.prototype,
+ funcProto = Function.prototype,
+ objectProto = Object.prototype;
+
+/** Used to detect overreaching core-js shims. */
+var coreJsData = root['__core-js_shared__'];
+
+/** Used to detect methods masquerading as native. */
+var maskSrcKey = (function () {
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
+ return uid ? ('Symbol(src)_1.' + uid) : '';
+}());
+
+/** Used to resolve the decompiled source of functions. */
+var funcToString = funcProto.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/** Used to infer the `Object` constructor. */
+var objectCtorString = funcToString.call(Object);
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/** Used to detect if a method is native. */
+var reIsNative = RegExp('^' +
+ funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+);
+
+/** Built-in value references. */
+var Buffer = moduleExports ? root.Buffer : undefined,
+ Symbol = root.Symbol,
+ Uint8Array = root.Uint8Array,
+ getPrototype = overArg(Object.getPrototypeOf, Object),
+ objectCreate = Object.create,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
+ splice = arrayProto.splice;
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeGetSymbols = Object.getOwnPropertySymbols,
+ nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
+ nativeKeys = overArg(Object.keys, Object),
+ nativeMax = Math.max;
+
+/* Built-in method references that are verified to be native. */
+var DataView = getNative(root, 'DataView'),
+ Map = getNative(root, 'Map'),
+ Promise = getNative(root, 'Promise'),
+ Set = getNative(root, 'Set'),
+ WeakMap = getNative(root, 'WeakMap'),
+ nativeCreate = getNative(Object, 'create');
+
+/** Used to detect maps, sets, and weakmaps. */
+var dataViewCtorString = toSource(DataView),
+ mapCtorString = toSource(Map),
+ promiseCtorString = toSource(Promise),
+ setCtorString = toSource(Set),
+ weakMapCtorString = toSource(WeakMap);
+
+/** Used to convert symbols to primitives and strings. */
+var symbolProto = Symbol ? Symbol.prototype : undefined,
+ symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
+
+/**
+ * Creates a hash object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function Hash(entries) {
+ var index = -1,
+ length = entries ? entries.length : 0;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+}
+
+/**
+ * Removes all key-value entries from the hash.
+ *
+ * @private
+ * @name clear
+ * @memberOf Hash
+ */
+function hashClear() {
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
+}
+
+/**
+ * Removes `key` and its value from the hash.
+ *
+ * @private
+ * @name delete
+ * @memberOf Hash
+ * @param {Object} hash The hash to modify.
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function hashDelete(key) {
+ return this.has(key) && delete this.__data__[key];
+}
+
+/**
+ * Gets the hash value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Hash
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function hashGet(key) {
+ var data = this.__data__;
+ if (nativeCreate) {
+ var result = data[key];
+ return result === HASH_UNDEFINED ? undefined : result;
+ }
+ return hasOwnProperty.call(data, key) ? data[key] : undefined;
+}
+
+/**
+ * Checks if a hash value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Hash
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function hashHas(key) {
+ var data = this.__data__;
+ return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
+}
+
+/**
+ * Sets the hash `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Hash
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the hash instance.
+ */
+function hashSet(key, value) {
+ var data = this.__data__;
+ data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
+ return this;
+}
+
+// Add methods to `Hash`.
+Hash.prototype.clear = hashClear;
+Hash.prototype['delete'] = hashDelete;
+Hash.prototype.get = hashGet;
+Hash.prototype.has = hashHas;
+Hash.prototype.set = hashSet;
+
+/**
+ * Creates an list cache object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function ListCache(entries) {
+ var index = -1,
+ length = entries ? entries.length : 0;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+}
+
+/**
+ * Removes all key-value entries from the list cache.
+ *
+ * @private
+ * @name clear
+ * @memberOf ListCache
+ */
+function listCacheClear() {
+ this.__data__ = [];
+}
+
+/**
+ * Removes `key` and its value from the list cache.
+ *
+ * @private
+ * @name delete
+ * @memberOf ListCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function listCacheDelete(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = data.length - 1;
+ if (index == lastIndex) {
+ data.pop();
+ } else {
+ splice.call(data, index, 1);
+ }
+ return true;
+}
+
+/**
+ * Gets the list cache value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf ListCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function listCacheGet(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ return index < 0 ? undefined : data[index][1];
+}
+
+/**
+ * Checks if a list cache value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf ListCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function listCacheHas(key) {
+ return assocIndexOf(this.__data__, key) > -1;
+}
+
+/**
+ * Sets the list cache `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf ListCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the list cache instance.
+ */
+function listCacheSet(key, value) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ data.push([key, value]);
+ } else {
+ data[index][1] = value;
+ }
+ return this;
+}
+
+// Add methods to `ListCache`.
+ListCache.prototype.clear = listCacheClear;
+ListCache.prototype['delete'] = listCacheDelete;
+ListCache.prototype.get = listCacheGet;
+ListCache.prototype.has = listCacheHas;
+ListCache.prototype.set = listCacheSet;
+
+/**
+ * Creates a map cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function MapCache(entries) {
+ var index = -1,
+ length = entries ? entries.length : 0;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+}
+
+/**
+ * Removes all key-value entries from the map.
+ *
+ * @private
+ * @name clear
+ * @memberOf MapCache
+ */
+function mapCacheClear() {
+ this.__data__ = {
+ 'hash': new Hash,
+ 'map': new (Map || ListCache),
+ 'string': new Hash
+ };
+}
+
+/**
+ * Removes `key` and its value from the map.
+ *
+ * @private
+ * @name delete
+ * @memberOf MapCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function mapCacheDelete(key) {
+ return getMapData(this, key)['delete'](key);
+}
+
+/**
+ * Gets the map value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf MapCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function mapCacheGet(key) {
+ return getMapData(this, key).get(key);
+}
+
+/**
+ * Checks if a map value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf MapCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function mapCacheHas(key) {
+ return getMapData(this, key).has(key);
+}
+
+/**
+ * Sets the map `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf MapCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the map cache instance.
+ */
+function mapCacheSet(key, value) {
+ getMapData(this, key).set(key, value);
+ return this;
+}
+
+// Add methods to `MapCache`.
+MapCache.prototype.clear = mapCacheClear;
+MapCache.prototype['delete'] = mapCacheDelete;
+MapCache.prototype.get = mapCacheGet;
+MapCache.prototype.has = mapCacheHas;
+MapCache.prototype.set = mapCacheSet;
+
+/**
+ * Creates a stack cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function Stack(entries) {
+ this.__data__ = new ListCache(entries);
+}
+
+/**
+ * Removes all key-value entries from the stack.
+ *
+ * @private
+ * @name clear
+ * @memberOf Stack
+ */
+function stackClear() {
+ this.__data__ = new ListCache;
+}
+
+/**
+ * Removes `key` and its value from the stack.
+ *
+ * @private
+ * @name delete
+ * @memberOf Stack
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function stackDelete(key) {
+ return this.__data__['delete'](key);
+}
+
+/**
+ * Gets the stack value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Stack
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function stackGet(key) {
+ return this.__data__.get(key);
+}
+
+/**
+ * Checks if a stack value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Stack
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function stackHas(key) {
+ return this.__data__.has(key);
+}
+
+/**
+ * Sets the stack `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Stack
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the stack cache instance.
+ */
+function stackSet(key, value) {
+ var cache = this.__data__;
+ if (cache instanceof ListCache) {
+ var pairs = cache.__data__;
+ if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
+ pairs.push([key, value]);
+ return this;
+ }
+ cache = this.__data__ = new MapCache(pairs);
+ }
+ cache.set(key, value);
+ return this;
+}
+
+// Add methods to `Stack`.
+Stack.prototype.clear = stackClear;
+Stack.prototype['delete'] = stackDelete;
+Stack.prototype.get = stackGet;
+Stack.prototype.has = stackHas;
+Stack.prototype.set = stackSet;
+
+/**
+ * Creates an array of the enumerable property names of the array-like `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @param {boolean} inherited Specify returning inherited property names.
+ * @returns {Array} Returns the array of property names.
+ */
+function arrayLikeKeys(value, inherited) {
+ // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
+ // Safari 9 makes `arguments.length` enumerable in strict mode.
+ var result = (isArray(value) || isArguments(value))
+ ? baseTimes(value.length, String)
+ : [];
+
+ var length = result.length,
+ skipIndexes = !!length;
+
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+/**
+ * This function is like `assignValue` except that it doesn't assign
+ * `undefined` values.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+function assignMergeValue(object, key, value) {
+ if ((value !== undefined && !eq(object[key], value)) ||
+ (typeof key == 'number' && value === undefined && !(key in object))) {
+ object[key] = value;
+ }
+}
+
+/**
+ * Assigns `value` to `key` of `object` if the existing value is not equivalent
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
+ (value === undefined && !(key in object))) {
+ object[key] = value;
+ }
+}
+
+/**
+ * Gets the index at which the `key` is found in `array` of key-value pairs.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} key The key to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+}
+
+/**
+ * The base implementation of `_.assign` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+}
+
+/**
+ * The base implementation of `_.clone` and `_.cloneDeep` which tracks
+ * traversed objects.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @param {boolean} [isFull] Specify a clone including symbols.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The parent object of `value`.
+ * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+function baseClone(value, isDeep, isFull, customizer, key, object, stack) {
+ var result;
+ if (customizer) {
+ result = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result !== undefined) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result);
+ }
+ } else {
+ var tag = getTag(value),
+ isFunc = tag == funcTag || tag == genTag;
+
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ if (isHostObject(value)) {
+ return object ? value : {};
+ }
+ result = initCloneObject(isFunc ? {} : value);
+ if (!isDeep) {
+ return copySymbols(value, baseAssign(result, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result = initCloneByTag(value, tag, baseClone, isDeep);
+ }
+ }
+ // Check for circular references and return its corresponding clone.
+ stack || (stack = new Stack);
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result);
+
+ if (!isArr) {
+ var props = isFull ? getAllKeys(value) : keys(value);
+ }
+ arrayEach(props || value, function (subValue, key) {
+ if (props) {
+ key = subValue;
+ subValue = value[key];
+ }
+ // Recursively populate clone (susceptible to call stack limits).
+ assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack));
+ });
+ return result;
+}
+
+/**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} prototype The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+function baseCreate(proto) {
+ return isObject(proto) ? objectCreate(proto) : {};
+}
+
+/**
+ * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
+ * `keysFunc` and `symbolsFunc` to get the enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @param {Function} symbolsFunc The function to get the symbols of `object`.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+ var result = keysFunc(object);
+ return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
+}
+
+/**
+ * The base implementation of `getTag`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+function baseGetTag(value) {
+ return objectToString.call(value);
+}
+
+/**
+ * The base implementation of `_.isNative` without bad shim checks.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function,
+ * else `false`.
+ */
+function baseIsNative(value) {
+ if (!isObject(value) || isMasked(value)) {
+ return false;
+ }
+ var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
+ return pattern.test(toSource(value));
+}
+
+/**
+ * The base implementation of `_.isTypedArray` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ */
+function baseIsTypedArray(value) {
+ return isObjectLike(value) &&
+ isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
+}
+
+/**
+ * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result = [];
+ for (var key in Object(object)) {
+ if (hasOwnProperty.call(object, key) && key != 'constructor') {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+/**
+ * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function baseKeysIn(object) {
+ if (!isObject(object)) {
+ return nativeKeysIn(object);
+ }
+ var isProto = isPrototype(object),
+ result = [];
+
+ for (var key in object) {
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+/**
+ * The base implementation of `_.merge` without support for multiple sources.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ if (!(isArray(source) || isTypedArray(source))) {
+ var props = baseKeysIn(source);
+ }
+ arrayEach(props || source, function (srcValue, key) {
+ if (props) {
+ key = srcValue;
+ srcValue = source[key];
+ }
+ if (isObject(srcValue)) {
+ stack || (stack = new Stack);
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ }
+ else {
+ var newValue = customizer
+ ? customizer(object[key], srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ if (newValue === undefined) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ });
+}
+
+/**
+ * A specialized version of `baseMerge` for arrays and objects which performs
+ * deep merges and tracks traversed objects enabling objects with circular
+ * references to be merged.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {string} key The key of the value to merge.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} mergeFunc The function to merge values.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = object[key],
+ srcValue = source[key],
+ stacked = stack.get(srcValue);
+
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ var isCommon = newValue === undefined;
+
+ if (isCommon) {
+ newValue = srcValue;
+ if (isArray(srcValue) || isTypedArray(srcValue)) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ }
+ else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ }
+ else {
+ isCommon = false;
+ newValue = baseClone(srcValue, true);
+ }
+ }
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ }
+ else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
+ isCommon = false;
+ newValue = baseClone(srcValue, true);
+ }
+ else {
+ newValue = objValue;
+ }
+ }
+ else {
+ isCommon = false;
+ }
+ }
+ if (isCommon) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ stack.set(srcValue, newValue);
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ stack['delete'](srcValue);
+ }
+ assignMergeValue(object, key, newValue);
+}
+
+/**
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ */
+function baseRest(func, start) {
+ start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
+ return function () {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ array = Array(length);
+
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ index = -1;
+ var otherArgs = Array(start + 1);
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = array;
+ return apply(func, this, otherArgs);
+ };
+}
+
+/**
+ * Creates a clone of `buffer`.
+ *
+ * @private
+ * @param {Buffer} buffer The buffer to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Buffer} Returns the cloned buffer.
+ */
+function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var result = new buffer.constructor(buffer.length);
+ buffer.copy(result);
+ return result;
+}
+
+/**
+ * Creates a clone of `arrayBuffer`.
+ *
+ * @private
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+function cloneArrayBuffer(arrayBuffer) {
+ var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
+ new Uint8Array(result).set(new Uint8Array(arrayBuffer));
+ return result;
+}
+
+/**
+ * Creates a clone of `dataView`.
+ *
+ * @private
+ * @param {Object} dataView The data view to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned data view.
+ */
+function cloneDataView(dataView, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
+ return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
+}
+
+/**
+ * Creates a clone of `map`.
+ *
+ * @private
+ * @param {Object} map The map to clone.
+ * @param {Function} cloneFunc The function to clone values.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned map.
+ */
+function cloneMap(map, isDeep, cloneFunc) {
+ var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);
+ return arrayReduce(array, addMapEntry, new map.constructor);
+}
+
+/**
+ * Creates a clone of `regexp`.
+ *
+ * @private
+ * @param {Object} regexp The regexp to clone.
+ * @returns {Object} Returns the cloned regexp.
+ */
+function cloneRegExp(regexp) {
+ var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
+ result.lastIndex = regexp.lastIndex;
+ return result;
+}
+
+/**
+ * Creates a clone of `set`.
+ *
+ * @private
+ * @param {Object} set The set to clone.
+ * @param {Function} cloneFunc The function to clone values.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned set.
+ */
+function cloneSet(set, isDeep, cloneFunc) {
+ var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);
+ return arrayReduce(array, addSetEntry, new set.constructor);
+}
+
+/**
+ * Creates a clone of the `symbol` object.
+ *
+ * @private
+ * @param {Object} symbol The symbol object to clone.
+ * @returns {Object} Returns the cloned symbol object.
+ */
+function cloneSymbol(symbol) {
+ return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
+}
+
+/**
+ * Creates a clone of `typedArray`.
+ *
+ * @private
+ * @param {Object} typedArray The typed array to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned typed array.
+ */
+function cloneTypedArray(typedArray, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
+}
+
+/**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+function copyArray(source, array) {
+ var index = -1,
+ length = source.length;
+
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+}
+
+/**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property identifiers to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @param {Function} [customizer] The function to customize copied values.
+ * @returns {Object} Returns `object`.
+ */
+function copyObject(source, props, object, customizer) {
+ object || (object = {});
+
+ var index = -1,
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+
+ var newValue = customizer
+ ? customizer(object[key], source[key], key, object, source)
+ : undefined;
+
+ assignValue(object, key, newValue === undefined ? source[key] : newValue);
+ }
+ return object;
+}
+
+/**
+ * Copies own symbol properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+}
+
+/**
+ * Creates a function like `_.assign`.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+function createAssigner(assigner) {
+ return baseRest(function (object, sources) {
+ var index = -1,
+ length = sources.length,
+ customizer = length > 1 ? sources[length - 1] : undefined,
+ guard = length > 2 ? sources[2] : undefined;
+
+ customizer = (assigner.length > 3 && typeof customizer == 'function')
+ ? (length--, customizer)
+ : undefined;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined : customizer;
+ length = 1;
+ }
+ object = Object(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+}
+
+/**
+ * Creates an array of own enumerable property names and symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+function getAllKeys(object) {
+ return baseGetAllKeys(object, keys, getSymbols);
+}
+
+/**
+ * Gets the data for `map`.
+ *
+ * @private
+ * @param {Object} map The map to query.
+ * @param {string} key The reference key.
+ * @returns {*} Returns the map data.
+ */
+function getMapData(map, key) {
+ var data = map.__data__;
+ return isKeyable(key)
+ ? data[typeof key == 'string' ? 'string' : 'hash']
+ : data.map;
+}
+
+/**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+function getNative(object, key) {
+ var value = getValue(object, key);
+ return baseIsNative(value) ? value : undefined;
+}
+
+/**
+ * Creates an array of the own enumerable symbol properties of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;
+
+/**
+ * Gets the `toStringTag` of `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+var getTag = baseGetTag;
+
+// Fallback for data views, maps, sets, and weak maps in IE 11,
+// for data views in Edge < 14, and promises in Node.js.
+if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
+ (Map && getTag(new Map) != mapTag) ||
+ (Promise && getTag(Promise.resolve()) != promiseTag) ||
+ (Set && getTag(new Set) != setTag) ||
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
+ getTag = function (value) {
+ var result = objectToString.call(value),
+ Ctor = result == objectTag ? value.constructor : undefined,
+ ctorString = Ctor ? toSource(Ctor) : undefined;
+
+ if (ctorString) {
+ switch (ctorString) {
+ case dataViewCtorString:
+ return dataViewTag;
+ case mapCtorString:
+ return mapTag;
+ case promiseCtorString:
+ return promiseTag;
+ case setCtorString:
+ return setTag;
+ case weakMapCtorString:
+ return weakMapTag;
+ }
+ }
+ return result;
+ };
+}
+
+/**
+ * Initializes an array clone.
+ *
+ * @private
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
+ */
+function initCloneArray(array) {
+ var length = array.length,
+ result = array.constructor(length);
+
+ // Add properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
+ }
+ return result;
+}
+
+/**
+ * Initializes an object clone.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+function initCloneObject(object) {
+ return (typeof object.constructor == 'function' && !isPrototype(object))
+ ? baseCreate(getPrototype(object))
+ : {};
+}
+
+/**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {Function} cloneFunc The function to clone values.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+function initCloneByTag(object, tag, cloneFunc, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+
+ case dataViewTag:
+ return cloneDataView(object, isDeep);
+
+ case float32Tag:
+ case float64Tag:
+ case int8Tag:
+ case int16Tag:
+ case int32Tag:
+ case uint8Tag:
+ case uint8ClampedTag:
+ case uint16Tag:
+ case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+
+ case mapTag:
+ return cloneMap(object, isDeep, cloneFunc);
+
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ return cloneRegExp(object);
+
+ case setTag:
+ return cloneSet(object, isDeep, cloneFunc);
+
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+}
+
+/**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+function isIndex(value, length) {
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return !!length &&
+ (typeof value == 'number' || reIsUint.test(value)) &&
+ (value > -1 && value % 1 == 0 && value < length);
+}
+
+/**
+ * Checks if the given arguments are from an iteratee call.
+ *
+ * @private
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
+ * else `false`.
+ */
+function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)
+ ) {
+ return eq(object[index], value);
+ }
+ return false;
+}
+
+/**
+ * Checks if `value` is suitable for use as unique object key.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
+ */
+function isKeyable(value) {
+ var type = typeof value;
+ return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
+ ? (value !== '__proto__')
+ : (value === null);
+}
+
+/**
+ * Checks if `func` has its source masked.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` is masked, else `false`.
+ */
+function isMasked(func) {
+ return !!maskSrcKey && (maskSrcKey in func);
+}
+
+/**
+ * Checks if `value` is likely a prototype object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
+ */
+function isPrototype(value) {
+ var Ctor = value && value.constructor,
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+
+ return value === proto;
+}
+
+/**
+ * This function is like
+ * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * except that it includes inherited enumerable properties.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function nativeKeysIn(object) {
+ var result = [];
+ if (object != null) {
+ for (var key in Object(object)) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+/**
+ * Converts `func` to its source code.
+ *
+ * @private
+ * @param {Function} func The function to process.
+ * @returns {string} Returns the source code.
+ */
+function toSource(func) {
+ if (func != null) {
+ try {
+ return funcToString.call(func);
+ } catch (e) {
+ }
+ try {
+ return (func + '');
+ } catch (e) {
+ }
+ }
+ return '';
+}
+
+/**
+ * Performs a
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * comparison between two values to determine if they are equivalent.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ * var other = { 'a': 1 };
+ *
+ * _.eq(object, object);
+ * // => true
+ *
+ * _.eq(object, other);
+ * // => false
+ *
+ * _.eq('a', 'a');
+ * // => true
+ *
+ * _.eq('a', Object('a'));
+ * // => false
+ *
+ * _.eq(NaN, NaN);
+ * // => true
+ */
+function eq(value, other) {
+ return value === other || (value !== value && other !== other);
+}
+
+/**
+ * Checks if `value` is likely an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ * else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+function isArguments(value) {
+ // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
+ return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
+ (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
+}
+
+/**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+var isArray = Array.isArray;
+
+/**
+ * Checks if `value` is array-like. A value is considered array-like if it's
+ * not a function and has a `value.length` that's an integer greater than or
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * @example
+ *
+ * _.isArrayLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLike(document.body.children);
+ * // => true
+ *
+ * _.isArrayLike('abc');
+ * // => true
+ *
+ * _.isArrayLike(_.noop);
+ * // => false
+ */
+function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+}
+
+/**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
+ * else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+}
+
+/**
+ * Checks if `value` is a buffer.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
+ * @example
+ *
+ * _.isBuffer(new Buffer(2));
+ * // => true
+ *
+ * _.isBuffer(new Uint8Array(2));
+ * // => false
+ */
+var isBuffer = nativeIsBuffer || stubFalse;
+
+/**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in Safari 8-9 which returns 'object' for typed array and other constructors.
+ var tag = isObject(value) ? objectToString.call(value) : '';
+ return tag == funcTag || tag == genTag;
+}
+
+/**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @example
+ *
+ * _.isLength(3);
+ * // => true
+ *
+ * _.isLength(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isLength(Infinity);
+ * // => false
+ *
+ * _.isLength('3');
+ * // => false
+ */
+function isLength(value) {
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+}
+
+/**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+function isObject(value) {
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.8.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+function isPlainObject(value) {
+ if (!isObjectLike(value) ||
+ objectToString.call(value) != objectTag || isHostObject(value)) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
+ return (typeof Ctor == 'function' &&
+ Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
+}
+
+/**
+ * Checks if `value` is classified as a typed array.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ * @example
+ *
+ * _.isTypedArray(new Uint8Array);
+ * // => true
+ *
+ * _.isTypedArray([]);
+ * // => false
+ */
+var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+
+/**
+ * Converts `value` to a plain object flattening inherited enumerable string
+ * keyed properties of `value` to own properties of the plain object.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
+ *
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
+ */
+function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+}
+
+/**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+}
+
+/**
+ * Creates an array of the own and inherited enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+ */
+function keysIn(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+}
+
+/**
+ * This method is like `_.assign` except that it recursively merges own and
+ * inherited enumerable string keyed properties of source objects into the
+ * destination object. Source properties that resolve to `undefined` are
+ * skipped if a destination value exists. Array and plain object properties
+ * are merged recursively. Other objects and value types are overridden by
+ * assignment. Source objects are applied from left to right. Subsequent
+ * sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {
+ * 'a': [{ 'b': 2 }, { 'd': 4 }]
+ * };
+ *
+ * var other = {
+ * 'a': [{ 'c': 3 }, { 'e': 5 }]
+ * };
+ *
+ * _.merge(object, other);
+ * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
+ */
+var merge = createAssigner(function (object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+});
+
+/**
+ * This method returns a new empty array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {Array} Returns the new empty array.
+ * @example
+ *
+ * var arrays = _.times(2, _.stubArray);
+ *
+ * console.log(arrays);
+ * // => [[], []]
+ *
+ * console.log(arrays[0] === arrays[1]);
+ * // => false
+ */
+function stubArray() {
+ return [];
+}
+
+/**
+ * This method returns `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {boolean} Returns `false`.
+ * @example
+ *
+ * _.times(2, _.stubFalse);
+ * // => [false, false]
+ */
+function stubFalse() {
+ return false;
+}
+
+module.exports = merge;
diff --git a/scripts/tags/button.js b/scripts/tags/button.js
new file mode 100644
index 000000000..19821cfe7
--- /dev/null
+++ b/scripts/tags/button.js
@@ -0,0 +1,38 @@
+/**
+ * button.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% button /path/to/url/, text, icon [class], title %}
+ * {% btn /path/to/url/, text, icon [class], title %}
+ */
+
+'use strict';
+
+function postButton(args) {
+ args = args.join(' ').split(',');
+ var url = args[0];
+ var text = args[1] || '';
+ var icon = args[2] || '';
+ var title = args[3] || '';
+
+ if (!url) {
+ hexo.log.warn('URL can NOT be empty');
+ }
+
+ text = text.trim();
+ icon = icon.trim();
+ title = title.trim();
+
+ var result = [' 0 && result.push(' title="' + title + '"');
+ result.push('>');
+ icon.length > 0 && result.push('');
+ text.length > 0 && result.push(text);
+ result.push('');
+
+ return result.join('');
+}
+
+hexo.extend.tag.register('button', postButton, { ends: false });
+hexo.extend.tag.register('btn', postButton, { ends: false });
diff --git a/scripts/tags/center-quote.js b/scripts/tags/center-quote.js
new file mode 100644
index 000000000..f673c6e77
--- /dev/null
+++ b/scripts/tags/center-quote.js
@@ -0,0 +1,19 @@
+/**
+ * center-quote.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% centerquote %}Something{% endcenterquote %}
+ * {% cq %}Something{% endcq %}
+ */
+
+'use strict';
+
+function centerQuote (args, content) {
+ return '' +
+ hexo.render.renderSync({text: content, engine: 'markdown'}) +
+ '
';
+}
+
+hexo.extend.tag.register('centerquote', centerQuote, {ends: true});
+hexo.extend.tag.register('cq', centerQuote, {ends: true});
diff --git a/scripts/tags/exturl.js b/scripts/tags/exturl.js
new file mode 100644
index 000000000..a65385e0c
--- /dev/null
+++ b/scripts/tags/exturl.js
@@ -0,0 +1,67 @@
+/**
+ * exturl.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% exturl text url "title" %}
+ * {% extlink text url "title" %}
+ *
+ * If title not defined, url will be used as title.
+ */
+
+'use strict';
+
+/*jshint camelcase: false */
+var util = require('hexo-util');
+/*jshint camelcase: true */
+var htmlTag = util.htmlTag;
+
+var rUrl = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[.\!\/\\w]*))?)/;
+
+// Create Base64 Object
+var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9+/=]/g,"");while(f>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/rn/g,"n");var t="";for(var n=0;n127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};
+
+function extURL(args, content) {
+ var exturl = 'exturl';
+ var url = '';
+ var text = [''];
+ var title = '';
+ var item = '';
+ var i = 0;
+ var len = args.length;
+
+ // Find link URL and text
+ for (; i < len; i++) {
+ item = args[i];
+
+ if (rUrl.test(item)) {
+ url = Base64.encode(item);
+ break;
+ } else {
+ text.push(item);
+ }
+ }
+
+ // Delete link URL and text from arguments
+ args = args.slice(i + 1);
+
+ // If any arguments exists, collect the last text as the link title,
+ // if not, set title as url.
+ if (args.length) {
+ var shift = args[0];
+ title = args.join(' ');
+ } else {
+ title = item;
+ }
+
+ var attrs = {
+ class: exturl,
+ 'data-url': url,
+ title: title
+ };
+
+ return htmlTag('span', attrs, text.join(' '));
+}
+
+hexo.extend.tag.register('exturl', extURL, {ends: false});
+hexo.extend.tag.register('extlink', extURL, {ends: false});
diff --git a/scripts/tags/full-image.js b/scripts/tags/full-image.js
new file mode 100644
index 000000000..028da9295
--- /dev/null
+++ b/scripts/tags/full-image.js
@@ -0,0 +1,33 @@
+/**
+ * full-image.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% fullimage /path/to/image, alt, title %}
+ * {% fi /path/to/image, alt, title %}
+ */
+
+'use strict';
+
+function fullImage(args) {
+ args = args.join(' ').split(',');
+ var src = args[0];
+ var alt = args[1] || '';
+ var title = args[2] || '';
+
+ if (!src) {
+ hexo.log.warn('Image src can NOT be empty');
+ }
+ alt = alt.trim();
+ title = title.trim();
+
+ var image = [' 0 && image.push('alt="' + alt + '"');
+ title.length > 0 && image.push('title="' + title + '"');
+ image.push('/>');
+
+ return image.join(' ');
+}
+
+hexo.extend.tag.register('fullimage', fullImage, { ends: false });
+hexo.extend.tag.register('fi', fullImage, { ends: false });
diff --git a/scripts/tags/group-pictures.js b/scripts/tags/group-pictures.js
new file mode 100644
index 000000000..8b511ecef
--- /dev/null
+++ b/scripts/tags/group-pictures.js
@@ -0,0 +1,843 @@
+/**
+ * group-pictures.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% grouppicture [group]-[layout] %}{% endgrouppicture %}
+ * {% gp [group]-[layout] %}{% endgp %}
+ *
+ * [group] : Total number of pictures to add in the group.
+ * [layout] : Default picture under the group to show.
+ */
+
+'use strict';
+
+function groupPicture(args, content) {
+ args = args[0].split('-');
+ var group = parseInt(args[0]);
+ var layout = parseInt(args[1]);
+
+ content = hexo.render.renderSync({text: content, engine: 'markdown'});
+
+ var pictures = content.match(//g);
+
+ return '' +
+ templates.dispatch(pictures, group, layout) +
+ '';
+}
+
+var templates = {
+
+ dispatch: function (pictures, group, layout) {
+ var fn = 'group' + group + 'Layout' + layout;
+ fn = templates[fn] || templates.defaults;
+ return fn.call(templates, pictures);
+ },
+
+ /**
+ * 2-1
+ *
+ * □
+ * □
+ *
+ * @param pictures
+ * @returns {string}
+ */
+ group2Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1)
+ ]);
+ },
+
+ /**
+ * 2-2
+ *
+ * □ □
+ *
+ * @param pictures
+ */
+ group2Layout2: function (pictures) {
+ return this.getHTML(pictures);
+ },
+
+ /**
+ * 3-1
+ *
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group3Layout1: function (pictures) {
+ return this.getHTML(pictures);
+ },
+
+ /**
+ * 3-2
+ *
+ * □
+ * □ □
+ *
+ * @param pictures
+ */
+ group3Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1)
+ ]);
+ },
+
+ /**
+ * 3-3
+ *
+ * □ □
+ * □
+ *
+ * @param pictures
+ */
+ group3Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2)
+ ]);
+ },
+
+ /**
+ * 4-1
+ *
+ * □
+ * □ □
+ * □
+ *
+ * @param pictures
+ */
+ group4Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 4-2
+ *
+ * □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group4Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1)
+ ]);
+ },
+
+ /**
+ * 4-3
+ *
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group4Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2)
+ ]);
+ },
+
+ /**
+ * 4-4
+ *
+ * □ □ □
+ * □
+ *
+ * @param pictures
+ */
+ group4Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 5-1
+ *
+ * □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group5Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 5-2
+ *
+ * □ □
+ * □
+ * □ □
+ *
+ * @param pictures
+ */
+ group5Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 5-3
+ *
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group5Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2)
+ ]);
+ },
+
+ /**
+ * 5-4
+ *
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group5Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 6-1
+ *
+ * □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group6Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 6-2
+ *
+ * □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group6Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 4),
+ pictures.slice(4)
+ ]);
+ },
+
+ /**
+ * 6-3
+ *
+ * □ □
+ * □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group6Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 6-4
+ *
+ * □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group6Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 4),
+ pictures.slice(4)
+ ]);
+ },
+
+ /**
+ * 6-5
+ *
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group6Layout5: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3)
+ ]);
+ },
+
+ /**
+ * 7-1
+ *
+ * □
+ * □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group7Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5)
+ ]);
+ },
+
+ /**
+ * 7-2
+ *
+ * □
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group7Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 4),
+ pictures.slice(4)
+ ]);
+ },
+
+ /**
+ * 7-3
+ *
+ * □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group7Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 4),
+ pictures.slice(4)
+ ]);
+ },
+
+ /**
+ * 7-4
+ *
+ * □ □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group7Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 5),
+ pictures.slice(5)
+ ]);
+ },
+
+ /**
+ * 7-5
+ *
+ * □ □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group7Layout5: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5)
+ ]);
+ },
+
+ /**
+ * 8-1
+ *
+ * □
+ * □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group8Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5)
+ ]);
+ },
+
+ /**
+ * 8-2
+ *
+ * □
+ * □ □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group8Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 8-3
+ *
+ * □
+ * □ □ □
+ * □ □
+ * □ □
+ * @param pictures
+ */
+ group8Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 4),
+ pictures.slice(4, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 8-4
+ *
+ * □ □
+ * □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group8Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 4),
+ pictures.slice(4, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 8-5
+ *
+ * □ □
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group8Layout5: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 5),
+ pictures.slice(5)
+ ]);
+ },
+
+ /**
+ * 8-6
+ *
+ * □ □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group8Layout6: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5)
+ ]);
+ },
+
+ /**
+ * 8-7
+ *
+ * □ □ □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group8Layout7: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 9-1
+ *
+ * □
+ * □ □
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group9Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 3),
+ pictures.slice(3, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 9-2
+ *
+ * □
+ * □ □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group9Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 4),
+ pictures.slice(4, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 9-3
+ *
+ * □ □
+ * □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group9Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 4),
+ pictures.slice(4, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 9-4
+ *
+ * □ □
+ * □ □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group9Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 4),
+ pictures.slice(4, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 9-5
+ *
+ * □ □
+ * □ □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group9Layout5: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 5),
+ pictures.slice(5, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 9-6
+ *
+ * □ □ □
+ * □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group9Layout6: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 9-7
+ *
+ * □ □ □
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group9Layout7: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 6),
+ pictures.slice(6)
+ ]);
+ },
+
+ /**
+ * 10-1
+ *
+ * □
+ * □ □ □
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group10Layout1: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 1),
+ pictures.slice(1, 4),
+ pictures.slice(4, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 10-2
+ *
+ * □ □
+ * □ □
+ * □ □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group10Layout2: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 4),
+ pictures.slice(4, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 10-3
+ *
+ * □ □
+ * □ □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group10Layout3: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 5),
+ pictures.slice(5, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 10-4
+ *
+ * □ □
+ * □ □ □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group10Layout4: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 2),
+ pictures.slice(2, 5),
+ pictures.slice(5, 8),
+ pictures.slice(8)
+ ]);
+ },
+
+ /**
+ * 10-5
+ *
+ * □ □ □
+ * □ □
+ * □ □
+ * □ □ □
+ *
+ * @param pictures
+ */
+ group10Layout5: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5, 7),
+ pictures.slice(7)
+ ]);
+ },
+
+ /**
+ * 10-6
+ *
+ * □ □ □
+ * □ □
+ * □ □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group10Layout6: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 5),
+ pictures.slice(5, 8),
+ pictures.slice(8)
+ ]);
+ },
+
+ /**
+ * 10-7
+ *
+ * □ □ □
+ * □ □ □
+ * □ □
+ * □ □
+ *
+ * @param pictures
+ */
+ group10Layout7: function (pictures) {
+ return this.getHTML([
+ pictures.slice(0, 3),
+ pictures.slice(3, 6),
+ pictures.slice(6, 8),
+ pictures.slice(8)
+ ]);
+ },
+
+ /**
+ * Defaults Layout
+ *
+ * □ □ □
+ * □ □ □
+ * ...
+ *
+ * @param pictures
+ */
+ defaults: function (pictures) {
+ var ROW_SIZE = 3;
+ var rows = pictures.length / ROW_SIZE + 1;
+ var pictureArr = [];
+
+ for (var i = 0; i < rows; i++) {
+ pictureArr.push(pictures.slice(i * ROW_SIZE, (i + 1) * ROW_SIZE));
+ }
+
+ return this.getHTML(pictureArr);
+ },
+
+ getHTML: function (rows) {
+ var rowHTML = '';
+
+ for (var i = 0; i < rows.length; i++) {
+ rowHTML += this.getRowHTML(rows[i]);
+ }
+
+ return '' + rowHTML + '';
+ },
+
+ getRowHTML: function (pictures) {
+ return (
+ '' +
+ this.getColumnHTML(pictures) +
+ ''
+ );
+ },
+
+ getColumnHTML: function (pictures) {
+ var columns = [];
+ var columnWidth = 100 / pictures.length;
+ var columnStyle = ' style="width: ' + columnWidth + '%;"';
+
+ for (var i = 0; i < pictures.length; i++) {
+ columns.push('' + pictures[i] + '');
+ }
+ return columns.join('');
+ }
+};
+
+hexo.extend.tag.register('grouppicture', groupPicture, {ends: true});
+hexo.extend.tag.register('gp', groupPicture, {ends: true});
diff --git a/scripts/tags/include-raw.js b/scripts/tags/include-raw.js
new file mode 100644
index 000000000..d1a495c2d
--- /dev/null
+++ b/scripts/tags/include-raw.js
@@ -0,0 +1,36 @@
+/**
+ * include.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% include_raw '_data/path/to/file.html' %}
+ *
+ * Path is relative to your site source directory.
+ */
+
+'use strict';
+
+var pathFn = require('path');
+/*jshint camelcase: false */
+var fs = require('hexo-fs');
+/*jshint camelcase: true */
+
+function include_raw (args) {
+ var path = pathFn.join(hexo.source_dir, args[0]);
+
+ return fs.exists(path).then(function(exist) {
+ if (!exist) {
+ hexo.log.error('Include file not found!');
+ return;
+ }
+ return fs.readFile(path).then(function(contents) {
+ if (!contents) {
+ hexo.log.warn('Include file empty.');
+ return;
+ }
+ return contents;
+ });
+ });
+};
+
+hexo.extend.tag.register('include_raw', include_raw, {ends: false, async: true});
diff --git a/scripts/tags/label.js b/scripts/tags/label.js
new file mode 100644
index 000000000..867096d32
--- /dev/null
+++ b/scripts/tags/label.js
@@ -0,0 +1,25 @@
+/**
+ * label.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% label [class]@Text %}
+ *
+ * [class] : default | primary | success | info | warning | danger.
+ * If not defined, default class will be selected.
+ */
+
+'use strict';
+
+function postLabel (args) {
+ args = args.join(' ').split('@');
+ var classes = args[0] || 'default';
+ var text = args[1] || '';
+
+ classes = classes.trim();
+ !text && hexo.log.warn('Label text must be defined!');
+
+ return '' + text + '';
+}
+
+hexo.extend.tag.register('label', postLabel, { ends: false });
diff --git a/scripts/tags/lazy-image.js b/scripts/tags/lazy-image.js
new file mode 100644
index 000000000..e0fbafe9e
--- /dev/null
+++ b/scripts/tags/lazy-image.js
@@ -0,0 +1,33 @@
+/**
+ * lazy-image.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% lazyimage /path/to/image, alt, title %}
+ * {% li /path/to/image, alt, title %}
+ */
+
+'use strict';
+
+function lazyImage(args) {
+ args = args.join(' ').split(',');
+ var src = args[0];
+ var alt = args[1] || '';
+ var title = args[2] || '';
+
+ if (!src) {
+ hexo.log.warn('Image src can NOT be empty');
+ }
+ alt = alt.trim();
+ title = title.trim();
+
+ var image = [' 0 && image.push('alt="' + alt + '"');
+ title.length > 0 && image.push('title="' + title + '"');
+ image.push('/>');
+
+ return image.join(' ');
+}
+
+hexo.extend.tag.register('lazyimage', lazyImage, { ends: false });
+hexo.extend.tag.register('li', lazyImage, { ends: false });
diff --git a/scripts/tags/note.js b/scripts/tags/note.js
new file mode 100644
index 000000000..542de347f
--- /dev/null
+++ b/scripts/tags/note.js
@@ -0,0 +1,22 @@
+/**
+ * note.js | global hexo script.
+ *
+ * ATTENTION! No need to write this tag in 1 line if u don't want see probally bugs.
+ *
+ * Usage:
+ *
+ * {% note [class] %}
+ * Any content (support inline tags too).
+ * {% endnote %}
+ *
+ * [class] : default | primary | success | info | warning | danger.
+ * May be not defined.
+ */
+
+'use strict';
+
+function bscallOut (args, content) {
+ return '' + hexo.render.renderSync({text: content, engine: 'markdown'}).trim() + '';
+}
+
+hexo.extend.tag.register('note', bscallOut, {ends: true});
diff --git a/scripts/tags/tabs.js b/scripts/tags/tabs.js
new file mode 100644
index 000000000..9af8f6828
--- /dev/null
+++ b/scripts/tags/tabs.js
@@ -0,0 +1,78 @@
+/**
+ * tabs.js | global hexo script.
+ *
+ * Usage:
+ *
+ * {% tabs [Unique name], [index] %}
+ *
+ * Any content (support inline tags too).
+ *
+ * {% endtabs %}
+ *
+ * [Unique name] : Unique name of tabs block tag without comma.
+ * Will be used in #id's as prefix for each tab with their index numbers.
+ * If there are whitespaces in name, for generate #id all whitespaces will replaced by dashes.
+ * Only for current url of post/page must be unique!
+ * [index] : Index number of active tab.
+ * If not defined, first tab (1) will be selected.
+ * If index is -1, no tab will be selected. It's will be something like spoiler.
+ * May be not defined.
+ * [Tab caption] : Caption of current tab.
+ * If not caption specified, unique name with tab index suffix will be used as caption of tab.
+ * If not caption specified, but specified icon, caption will empty.
+ * May be not defined.
+ * [icon] : Font awesome icon.
+ * May be not defined.
+ */
+
+'use strict';
+
+ function postTabs (args, content) {
+ var tabBlock = /\n([\w\W\s\S]*?)/g;
+
+ var args = args.join(' ').split(',');
+ var tabName = args[0];
+ var tabActive = args[1] || '';
+
+ var matches = [];
+ var match;
+ var tabId = 0;
+ var tabNav = '';
+ var tabContent = '';
+
+ !tabName && hexo.log.warn('Tabs block must have unique name!');
+
+ while (match = tabBlock.exec(content)) {
+ matches.push(match[1]);
+ matches.push(match[2]);
+ }
+
+ for (var i = 0; i < matches.length; i += 2) {
+ var tabParameters = matches[i].split('@');
+ var postContent = matches[i + 1];
+ var tabCaption = tabParameters[0] || '';
+ var tabIcon = tabParameters[1] || '';
+ var tabHref = '';
+
+ postContent = hexo.render.renderSync({text: postContent, engine: 'markdown'});
+
+ tabId += 1;
+ tabHref = (tabName + ' ' + tabId).toLowerCase().split(' ').join('-');
+
+ ((tabCaption.length === 0) && (tabIcon.length === 0)) && (tabCaption = tabName + ' ' + tabId);
+
+ var isOnlyicon = (tabIcon.length > 0 && tabCaption.length === 0) ? 'style="text-align: center;' : '';
+ tabIcon.length > 0 && (tabIcon = '');
+
+ var isActive = ((tabActive.length > 0 && tabActive == tabId) || (tabActive.length === 0 && tabId == 1)) ? ' active' : '';
+ tabNav += '' + tabIcon + tabCaption + ' ';
+ tabContent += '' + postContent + '';
+ }
+
+ tabNav = ' ';
+ tabContent = '' + tabContent + '';
+
+ return '' + tabNav + tabContent + '';
+ }
+
+ hexo.extend.tag.register('tabs', postTabs, {ends: true});
diff --git a/source/css/_common/components/back-to-top-sidebar.styl b/source/css/_common/components/back-to-top-sidebar.styl
new file mode 100644
index 000000000..d23d35d57
--- /dev/null
+++ b/source/css/_common/components/back-to-top-sidebar.styl
@@ -0,0 +1,25 @@
+.back-to-top {
+ display: none;
+ margin: 20px -10px -20px;
+ background: $body-bg-color;
+ font-size: $b2t-font-size;
+ opacity: $b2t-opacity;
+ cursor: pointer;
+ text-align: center;
+ -webkit-transform: translateZ(0);
+ the-transition();
+ &:hover { opacity: 0.8; }
+
+ +tablet() {
+ fixbutton() if hexo-config('sidebar.onmobile');
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+ +mobile() {
+ fixbutton() if hexo-config('sidebar.onmobile');
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+
+ &.back-to-top-on {
+ display: block;
+ }
+}
diff --git a/source/css/_common/components/back-to-top.styl b/source/css/_common/components/back-to-top.styl
new file mode 100644
index 000000000..1ae463a7d
--- /dev/null
+++ b/source/css/_common/components/back-to-top.styl
@@ -0,0 +1,31 @@
+.back-to-top {
+ box-sizing: border-box;
+ position: fixed;
+ bottom: $b2t-position-bottom;
+ right: $b2t-position-right;
+ z-index: $zindex-5;
+ padding: 0 6px;
+ width: hexo-config('sidebar.scrollpercent') ? initial : 24px;
+ background: $b2t-bg-color;
+ font-size: $b2t-font-size;
+ opacity: $b2t-opacity;
+ color: $b2t-color;
+ cursor: pointer;
+ text-align: center;
+ -webkit-transform: translateZ(0);
+ transition-property: bottom;
+ the-transition();
+
+ +tablet() {
+ fixbutton() if hexo-config('sidebar.onmobile');
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+ +mobile() {
+ fixbutton() if hexo-config('sidebar.onmobile');
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+
+ &.back-to-top-on {
+ bottom: $b2t-position-bottom-on;
+ }
+}
diff --git a/source/css/_common/components/buttons.styl b/source/css/_common/components/buttons.styl
new file mode 100644
index 000000000..771264651
--- /dev/null
+++ b/source/css/_common/components/buttons.styl
@@ -0,0 +1,38 @@
+.btn {
+ display: inline-block;
+ padding: 0 20px;
+ font-size: $btn-default-font-size;
+ color: $btn-default-color;
+ background: $btn-default-bg;
+ border: $btn-default-border-width solid $btn-default-border-color;
+ text-decoration: none;
+ border-radius: $btn-default-radius;
+ transition-property: background-color;
+ the-transition();
+ line-height: 2;
+
+ &:hover {
+ border-color: $btn-default-hover-border-color;
+ color: $btn-default-hover-color;
+ background: $btn-default-hover-bg;
+ }
+
+ +.btn {
+ margin: 0 0 8px 8px;
+ }
+
+ .fa-fw {
+ width: (18em / 14);
+ text-align: left;
+ }
+}
+
+.btn-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ background: $text-color;
+ border-radius: 1px;
+
+ &+.btn-bar { margin-top: 4px; }
+}
diff --git a/source/css/_common/components/comments.styl b/source/css/_common/components/comments.styl
new file mode 100644
index 000000000..bf3edb945
--- /dev/null
+++ b/source/css/_common/components/comments.styl
@@ -0,0 +1 @@
+.comments { margin: 60px 20px 0; }
diff --git a/source/css/_common/components/components.styl b/source/css/_common/components/components.styl
new file mode 100644
index 000000000..fe4a160d9
--- /dev/null
+++ b/source/css/_common/components/components.styl
@@ -0,0 +1,16 @@
+@import "highlight";
+@import "tags";
+
+@import "buttons";
+@import "pagination";
+@import "comments";
+@import "tag-cloud";
+@import hexo-config('sidebar.b2t') ? "back-to-top-sidebar" : "back-to-top";
+
+@import "header";
+@import "post";
+@import "sidebar";
+@import "footer";
+@import "third-party";
+
+@import "pages";
diff --git a/source/css/_common/components/footer/footer.styl b/source/css/_common/components/footer/footer.styl
new file mode 100644
index 000000000..4c4038800
--- /dev/null
+++ b/source/css/_common/components/footer/footer.styl
@@ -0,0 +1,44 @@
+.footer {
+ font-size: 14px;
+ color: $grey-dark;
+
+ img { border: none; }
+}
+
+.footer-inner { text-align: center; }
+
+@keyframes iconAnimate {
+ 0%,100%{transform:scale(1);}
+ 10%,30%{transform:scale(0.9);}
+ 20%,40%,60%,80%{transform:scale(1.1);}
+ 50%,70%{transform:scale(1.1);}
+}
+
+if hexo-config('footer.icon.animated') {
+ #animate {
+ animation: iconAnimate 1.33s ease-in-out infinite;
+ }
+}
+
+.with-love {
+ display: inline-block;
+ margin: 0 5px;
+ color: unquote(hexo-config('footer.icon.color'));
+}
+
+.powered-by,
+.theme-info { display: inline-block; }
+
+.cc-license {
+ margin-top: 10px;
+ text-align: center;
+
+ .cc-opacity {
+ opacity: 0.7;
+ border-bottom: none;
+
+ &:hover { opacity: 0.9; }
+ }
+
+ img { display: inline-block; }
+}
diff --git a/source/css/_common/components/header/github-banner.styl b/source/css/_common/components/header/github-banner.styl
new file mode 100644
index 000000000..3698413e6
--- /dev/null
+++ b/source/css/_common/components/header/github-banner.styl
@@ -0,0 +1,48 @@
+.github-corner {
+ scheme = hexo-config('scheme');
+ bg_color = unquote(hexo-config('android_chrome_color'));
+ mobile_layout_economy = hexo-config('mobile_layout_economy');
+
+ :hover .octo-arm {
+ animation:octocat-wave 560ms ease-in-out;
+ }
+ @keyframes octocat-wave {
+ 0%,100% {
+ transform:rotate(0);
+ }
+ 20%,60% {
+ transform:rotate(-25deg);
+ }
+ 40%,80% {
+ transform:rotate(10deg);
+ }
+ }
+ +tablet-mobile() {
+ >svg {
+ if (scheme == 'Pisces') || (scheme == 'Gemini') {
+ fill: #fff !important;
+ color: bg_color !important;
+ }
+ }
+ .github-corner:hover .octo-arm {
+ animation:none;
+ }
+ .github-corner .octo-arm {
+ animation:octocat-wave 560ms ease-in-out;
+ }
+ }
+ +mobile() {
+ >svg {
+ if (scheme == 'Mist') {
+ top: inherit !important;
+ margin-top: -50px;
+ if mobile_layout_economy {
+ +mobile-small() {
+ margin-top: initial;
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/source/css/_common/components/header/header.styl b/source/css/_common/components/header/header.styl
new file mode 100644
index 000000000..0240caadf
--- /dev/null
+++ b/source/css/_common/components/header/header.styl
@@ -0,0 +1,9 @@
+.header { background: $head-bg; }
+
+.header-inner { position: relative; }
+
+@import "headerband";
+@import "site-meta";
+@import "site-nav";
+@import "menu";
+@import "github-banner" if hexo-config('github_banner');
diff --git a/source/css/_common/components/header/headerband.styl b/source/css/_common/components/header/headerband.styl
new file mode 100644
index 000000000..382dbd9cd
--- /dev/null
+++ b/source/css/_common/components/header/headerband.styl
@@ -0,0 +1,4 @@
+.headband {
+ height: $headband-height;
+ background: $headband-bg;
+}
diff --git a/source/css/_common/components/header/menu.styl b/source/css/_common/components/header/menu.styl
new file mode 100644
index 000000000..d2b0f055d
--- /dev/null
+++ b/source/css/_common/components/header/menu.styl
@@ -0,0 +1,32 @@
+// Menu
+// --------------------------------------------------
+.menu {
+ margin-top: 20px;
+ padding-left: 0;
+ text-align: center;
+}
+
+.menu .menu-item {
+ display: inline-block;
+ margin: 0 10px;
+ list-style: none;
+
+ @media screen and (max-width: 767px) {
+ margin-top: 10px;
+ }
+
+ a {
+ display: block;
+ font-size: 13px;
+ line-height: inherit;
+ border-bottom: 1px solid $menu-link-border;
+ transition-property: border-color;
+ the-transition();
+
+ &:hover { border-bottom-color: $menu-link-hover-border; }
+ }
+
+ .fa { margin-right: 5px; }
+}
+
+.use-motion .menu-item { opacity: 0; }
diff --git a/source/css/_common/components/header/site-meta.styl b/source/css/_common/components/header/site-meta.styl
new file mode 100644
index 000000000..efe31ec26
--- /dev/null
+++ b/source/css/_common/components/header/site-meta.styl
@@ -0,0 +1,48 @@
+.site-meta {
+ margin: 0;
+ text-align: $site-meta-text-align;
+
+ +mobile() { text-align: center; }
+}
+
+.brand {
+ position: relative;
+ display: inline-block;
+ padding: 0 40px;
+ color: $brand-color;
+ background: $brand-bg;
+ border-bottom: none;
+ &:hover { color: $brand-hover-color; }
+}
+
+.logo {
+ display: inline-block;
+ margin-right: 5px;
+ line-height: 36px;
+ vertical-align: top;
+}
+
+.site-title {
+ display: inline-block;
+ vertical-align: top;
+ line-height: 36px;
+ font-size: $logo-font-size;
+ font-weight: normal;
+ font-family: $font-family-logo;
+}
+
+.site-subtitle {
+ margin-top: 10px;
+ font-size: $subtitle-font-size;
+ color: $subtitle-color;
+}
+
+.use-motion {
+ .brand { opacity: 0; }
+
+ .logo, .site-title, .site-subtitle {
+ opacity: 0;
+ position: relative;
+ top: -10px;
+ }
+}
diff --git a/source/css/_common/components/header/site-nav.styl b/source/css/_common/components/header/site-nav.styl
new file mode 100644
index 000000000..c6446e73f
--- /dev/null
+++ b/source/css/_common/components/header/site-nav.styl
@@ -0,0 +1,28 @@
+.site-nav-toggle {
+ display: none;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ +mobile() {
+ display: block;
+ }
+
+ button {
+ margin-top: 2px;
+ padding: 9px 10px;
+ background: transparent;
+ border: none;
+ }
+}
+
+.site-nav {
+ +mobile() {
+ display: none;
+ margin: 0 -10px;
+ padding: 0 10px;
+ clear: both;
+ border-top: 1px solid $gray-lighter;
+ }
+ +tablet() { display: block !important; }
+ +desktop() { display: block !important; }
+}
diff --git a/source/css/_common/components/highlight/diff.styl b/source/css/_common/components/highlight/diff.styl
new file mode 100644
index 000000000..f77949909
--- /dev/null
+++ b/source/css/_common/components/highlight/diff.styl
@@ -0,0 +1,8 @@
+$highlight_theme = hexo-config("highlight_theme")
+
+if $highlight_theme == "normal"
+ $highlight-deletion = #fdd
+ $highlight-addition = #dfd
+else
+ $highlight-deletion = #008000
+ $highlight-addition = #800000
diff --git a/source/css/_common/components/highlight/highlight.styl b/source/css/_common/components/highlight/highlight.styl
new file mode 100644
index 000000000..9b52eb9f5
--- /dev/null
+++ b/source/css/_common/components/highlight/highlight.styl
@@ -0,0 +1,182 @@
+// https://github.com/chriskempson/tomorrow-theme
+
+@require "theme"
+@require "diff"
+
+// Placeholder: $code-block
+$code-block {
+ overflow: auto;
+ margin: 20px 0;
+ padding: 0;
+ font-size $code-font-size;
+ color: $highlight-foreground;
+ background: $highlight-background;
+ line-height: $line-height-code-block;
+}
+
+pre, code { font-family: $code-font-family; }
+
+code {
+ padding: 2px 4px;
+ word-wrap: break-word;
+ color: $code-foreground;
+ background: $code-background;
+ border-radius: $code-border-radius;
+ font-size: $code-font-size;
+}
+
+pre {
+ @extend $code-block;
+ padding: 10px;
+ code {
+ padding: 0;
+ color: $highlight-foreground;
+ background: none;
+ text-shadow: none;
+ }
+}
+
+.highlight {
+ @extend $code-block;
+ // Read values from NexT config and set they as local variables to use as string variables (in any CSS section).
+ hexo-config('codeblock.border_radius') is a 'unit' ? (cbradius = unit(hexo-config('codeblock.border_radius'), px)) : (cbradius = 1px)
+ border-radius: cbradius;
+
+ pre {
+ border: none;
+ margin: 0;
+ padding: 10px 0;
+ }
+
+ table {
+ margin: 0;
+ width: auto;
+ border: none;
+ }
+
+ td {
+ border: none;
+ padding: 0;
+ }
+
+ figcaption {
+ clearfix();
+ font-size: 1em;
+ color: $highlight-foreground;
+ line-height: 1em;
+ margin-bottom: 1em;
+ margin: 0em;
+ padding: 0.5em;
+ background: $code-background;
+ border-bottom: 1px solid #e9e9e9;
+
+ a {
+ float: right;
+ color: $highlight-foreground;
+
+ &:hover { border-bottom-color: $highlight-foreground; }
+ }
+ }
+
+ .gutter pre {
+ padding-left: 10px
+ padding-right: 10px
+ color: $highlight-gutter.color
+ text-align: right
+ background-color: $highlight-gutter.bg-color
+ }
+
+ .code pre {
+ width: 100%
+ padding-left: 10px
+ padding-right: 10px
+ background-color: $highlight-background
+ }
+
+ .line { height: 20px; }
+}
+
+
+.gutter {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.gist table {
+ width: auto;
+
+ td { border: none; }
+}
+
+// For diff highlight
+pre .deletion { background: $highlight-deletion; }
+pre .addition { background: $highlight-addition; }
+pre .meta { color: $highlight-purple; }
+
+pre {
+
+ .comment { color: $highlight-comment; }
+
+ .variable
+ .attribute
+ .tag
+ .regexp
+ .ruby .constant
+ .xml .tag .title
+ .xml .pi
+ .xml .doctype
+ .html .doctype
+ .css .id
+ .css .class
+ .css .pseudo {
+ color: $highlight-red;
+ }
+
+ .number
+ .preprocessor
+ .built_in
+ .literal
+ .params
+ .constant
+ .command {
+ color: $highlight-orange;
+ }
+
+ .ruby .class .title
+ .css .rules .attribute
+ .string
+ .value
+ .inheritance
+ .header
+ .ruby .symbol
+ .xml .cdata
+ .special
+ .number
+ .formula {
+ color: $highlight-green;
+ }
+
+ .title
+ .css .hexcolor {
+ color: $highlight-aqua;
+ }
+
+ .function
+ .python .decorator
+ .python .title
+ .ruby .function .title
+ .ruby .title .keyword
+ .perl .sub
+ .javascript .title
+ .coffeescript .title {
+ color: $highlight-blue;
+ }
+
+ .keyword
+ .javascript .function {
+ color: $highlight-purple;
+ }
+
+}
diff --git a/source/css/_common/components/highlight/theme.styl b/source/css/_common/components/highlight/theme.styl
new file mode 100644
index 000000000..ff1f4be00
--- /dev/null
+++ b/source/css/_common/components/highlight/theme.styl
@@ -0,0 +1,92 @@
+$highlight_theme = hexo-config("highlight_theme")
+
+
+if $highlight_theme == "normal"
+ $highlight-background = #f7f7f7
+ $highlight-current-line = #efefef
+ $highlight-selection = #d6d6d6
+ $highlight-foreground = #4d4d4c
+ $highlight-comment = #8e908c
+ $highlight-red = #c82829
+ $highlight-orange = #f5871f
+ $highlight-yellow = #eab700
+ $highlight-green = #718c00
+ $highlight-aqua = #3e999f
+ $highlight-blue = #4271ae
+ $highlight-purple = #8959a8
+ $highlight-gutter = {
+ color: #869194,
+ bg-color: #eff2f3
+ }
+
+if $highlight_theme == "night"
+ $highlight-background = #1d1f21
+ $highlight-current-line = #282a2e
+ $highlight-selection = #373b41
+ $highlight-foreground = #c5c8c6
+ $highlight-comment = #969896
+ $highlight-red = #cc6666
+ $highlight-orange = #de935f
+ $highlight-yellow = #f0c674
+ $highlight-green = #b5bd68
+ $highlight-aqua = #8abeb7
+ $highlight-blue = #81a2be
+ $highlight-purple = #b294bb
+ $highlight-gutter = {
+ color: lighten($highlight-background, 50%),
+ bg-color: darken($highlight-background, 100%)
+ }
+
+if $highlight_theme == "night eighties"
+ $highlight-background = #2d2d2d
+ $highlight-current-line = #393939
+ $highlight-selection = #515151
+ $highlight-foreground = #cccccc
+ $highlight-comment = #999999
+ $highlight-red = #f2777a
+ $highlight-orange = #f99157
+ $highlight-yellow = #ffcc66
+ $highlight-green = #99cc99
+ $highlight-aqua = #66cccc
+ $highlight-blue = #6699cc
+ $highlight-purple = #cc99cc
+ $highlight-gutter = {
+ color: $highlight-comment,
+ bg-color: darken($highlight-background, 40%)
+ }
+
+if $highlight_theme == "night blue"
+ $highlight-background = #002451
+ $highlight-current-line = #00346e
+ $highlight-selection = #003f8e
+ $highlight-foreground = #ffffff
+ $highlight-comment = #7285b7
+ $highlight-red = #ff9da4
+ $highlight-orange = #ffc58f
+ $highlight-yellow = #ffeead
+ $highlight-green = #d1f1a9
+ $highlight-aqua = #99ffff
+ $highlight-blue = #bbdaff
+ $highlight-purple = #ebbbff
+ $highlight-gutter = {
+ color: $highlight-comment,
+ bg-color: darken($highlight-background, 60%)
+ }
+
+if $highlight_theme == "night bright"
+ $highlight-background = #000000
+ $highlight-current-line = #2a2a2a
+ $highlight-selection = #424242
+ $highlight-foreground = #eaeaea
+ $highlight-comment = #969896
+ $highlight-red = #d54e53
+ $highlight-orange = #e78c45
+ $highlight-yellow = #e7c547
+ $highlight-green = #b9ca4a
+ $highlight-aqua = #70c0b1
+ $highlight-blue = #7aa6da
+ $highlight-purple = #c397d8
+ $highlight-gutter = {
+ color: lighten($highlight-background, 40%),
+ bg-color: lighten($highlight-background, 16%)
+ }
diff --git a/source/css/_common/components/pages/archive.styl b/source/css/_common/components/pages/archive.styl
new file mode 100644
index 000000000..8a1363d68
--- /dev/null
+++ b/source/css/_common/components/pages/archive.styl
@@ -0,0 +1,29 @@
+.page-archive {
+
+ .archive-page-counter {
+ position: relative;
+ top: 3px;
+ left: 20px;
+
+ +mobile() {
+ top: 5px;
+ }
+ }
+
+ .posts-collapse {
+
+ .archive-move-on {
+ position: absolute;
+ top: 11px;
+ left: 0;
+ margin-left: -6px;
+ width: 10px;
+ height: 10px;
+ opacity: 0.5;
+ background: $black-light;
+ border: 1px solid white;
+
+ circle();
+ }
+ }
+}
diff --git a/source/css/_common/components/pages/breadcrumb.styl b/source/css/_common/components/pages/breadcrumb.styl
new file mode 100644
index 000000000..ea9cd0537
--- /dev/null
+++ b/source/css/_common/components/pages/breadcrumb.styl
@@ -0,0 +1,22 @@
+ul.breadcrumb {
+ list-style: none;
+ margin: 1em 0;
+ padding: 0 2em;
+ text-align: center;
+ font-size: $font-size-small
+
+ & li {
+ display: inline;
+ }
+
+ & li+li:before {
+ padding: 0.5em;
+ font-weight: normal;
+ content: "/\00a0";
+ }
+
+ & li+li:last-child {
+ font-weight: bold;
+ }
+
+}
diff --git a/source/css/_common/components/pages/categories.styl b/source/css/_common/components/pages/categories.styl
new file mode 100644
index 000000000..db3bb10a3
--- /dev/null
+++ b/source/css/_common/components/pages/categories.styl
@@ -0,0 +1,27 @@
+.category-all-page {
+ .category-all-title { text-align: center; }
+
+ .category-all { margin-top: 20px; }
+
+ .category-list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+
+ .category-list-item { margin: 5px 10px; }
+
+ .category-list-count {
+ color: $grey;
+ &:before {
+ display: inline;
+ content: " ("
+ }
+ &:after {
+ display: inline;
+ content: ") "
+ }
+ }
+
+ .category-list-child { padding-left: 10px; }
+}
diff --git a/source/css/_common/components/pages/pages.styl b/source/css/_common/components/pages/pages.styl
new file mode 100644
index 000000000..1cffd0721
--- /dev/null
+++ b/source/css/_common/components/pages/pages.styl
@@ -0,0 +1,7 @@
+// Page specific styles
+
+@import "archive";
+@import "categories";
+@import "schedule";
+@import "post-detail";
+@import "breadcrumb";
diff --git a/source/css/_common/components/pages/post-detail.styl b/source/css/_common/components/pages/post-detail.styl
new file mode 100644
index 000000000..3f26afdb2
--- /dev/null
+++ b/source/css/_common/components/pages/post-detail.styl
@@ -0,0 +1,6 @@
+.page-post-detail {
+
+ .sidebar-toggle-line { background: $sidebar-highlight; }
+
+ .comments { overflow: hidden; }
+}
diff --git a/source/css/_common/components/pages/schedule.styl b/source/css/_common/components/pages/schedule.styl
new file mode 100644
index 000000000..18ec9334a
--- /dev/null
+++ b/source/css/_common/components/pages/schedule.styl
@@ -0,0 +1,101 @@
+@keyframes dot-flash {
+ from {opacity: 1; transform:scale(1.1);}
+ to {opacity: 0; transform:scale(1);}
+}
+
+#schedule {
+ ul#event-list {
+ padding-left: 30px
+ hr {
+ margin: 20px 0 45px 0!important
+ background: #222
+ &:after {
+ display: inline-block
+ content: 'NOW'
+ background: #222
+ color: #FFF
+ font-weight:bold
+ text-align: right
+ padding: 0 5px
+ }
+ }
+ li.event {
+ margin: 20px 0px
+ background: #F9F9F9
+ padding-left: 10px
+ min-height: 40px
+ h2.event-summary {
+ margin: 0
+ padding-bottom: 3px
+ &:before {
+ display: inline-block
+ font-family: FontAwesome
+ font-size: 8px
+ content: '\f111'
+ vertical-align: middle
+ margin-right: 25px
+ color: #bbb
+ }
+ }
+ span.event-relative-time {
+ display: inline-block
+ font-size: 12px
+ font-weight: 400
+ padding-left: 12px
+ color: #bbb
+ }
+ span.event-details {
+ display: block
+ color: #bbb
+ margin-left: 56px
+ padding-top: 3px
+ padding-bottom: 6px
+ text-indent: -24px
+ line-height: 18px
+ &:before {
+ text-indent: 0
+ display: inline-block
+ width: 14px
+ font-family: FontAwesome
+ text-align: center
+ margin-right: 9px
+ color: #bbb
+ }
+ &.event-location:before {
+ content: '\f041'
+ }
+ &.event-duration:before {
+ content: '\f017'
+ }
+ }
+ }
+ li.event-past {
+ background: #FCFCFC
+ & > * {
+ opacity: .6
+ }
+ h2.event-summary {
+ color: #bbb
+ &:before {
+ color: #DFDFDF
+ }
+ }
+ }
+ li.event-now {
+ background: #222
+ color: #FFF
+ padding: 15px 0 15px 10px
+ h2.event-summary {
+ &:before {
+ transform: scale(1.2)
+ color: #FFF
+ animation: dot-flash 1s alternate infinite ease-in-out;
+ }
+ }
+ * {
+ color: #FFF!important
+ }
+ }
+ }
+}
+
diff --git a/source/css/_common/components/pagination.styl b/source/css/_common/components/pagination.styl
new file mode 100644
index 000000000..a054ef009
--- /dev/null
+++ b/source/css/_common/components/pagination.styl
@@ -0,0 +1,56 @@
+.pagination {
+ margin: 120px 0 40px;
+ text-align: center;
+ border-top: 1px solid $pagination-border;
+}
+
+.page-number-basic {
+ display: inline-block;
+ position: relative;
+ top: -1px;
+ margin: 0 10px;
+ padding: 0 11px;
+
+ +mobile() { margin: 0 5px; }
+}
+
+.pagination {
+ .prev, .next, .page-number {
+ @extend .page-number-basic;
+ border-bottom: 0;
+ border-top: 1px solid $pagination-link-border;
+ transition-property: border-color;
+ the-transition();
+
+ &:hover { border-top-color: $pagination-link-hover-border; }
+ }
+
+ .space {
+ @extend .page-number-basic;
+ padding: 0;
+ margin: 0;
+ }
+
+ .prev { margin-left: 0; }
+ .next { margin-right: 0; }
+
+ .page-number.current {
+ color: $pagination-active-color;
+ background: $pagination-active-bg;
+ border-top-color: $pagination-active-border;
+ }
+}
+
+@media (max-width: 767px)
+ .pagination { border-top: none; }
+
+ .pagination {
+ .prev, .next, .page-number {
+ margin-bottom: 10px;
+ border-top: 0;
+ border-bottom: 1px solid $pagination-link-border;
+ padding: 0 10px;
+
+ &:hover { border-bottom-color: $pagination-link-hover-border; }
+ }
+ }
diff --git a/source/css/_common/components/post/post-button.styl b/source/css/_common/components/post/post-button.styl
new file mode 100644
index 000000000..fd0809f81
--- /dev/null
+++ b/source/css/_common/components/post/post-button.styl
@@ -0,0 +1,3 @@
+.post-button {
+ margin-top: 40px;
+}
diff --git a/source/css/_common/components/post/post-collapse.styl b/source/css/_common/components/post/post-collapse.styl
new file mode 100644
index 000000000..6633a450d
--- /dev/null
+++ b/source/css/_common/components/post/post-collapse.styl
@@ -0,0 +1,111 @@
+// TODO: Refactor.
+
+@media (max-width: 767px) {
+ .posts-collapse {
+ margin: 0 20px;
+
+ .post-title, .post-meta {
+ display: block;
+ width: auto;
+ text-align: left;
+ }
+ }
+}
+
+.posts-collapse {
+ position: relative;
+ z-index: $zindex-1;
+
+ &::after {
+ content: " ";
+ position: absolute;
+ top: 20px;
+ left: 0;
+ margin-left: -2px;
+ width: 4px;
+ height: 100%;
+ background: $whitesmoke;
+ z-index: $zindex-bottom;
+ }
+
+ margin-left: $posts-collapse-left;
+ +mobile() { margin: 0 20px; }
+
+ .collection-title {
+ position: relative;
+ margin: 60px 0;
+
+ h1, h2 { margin-left: 20px; }
+
+ small { color: $grey; margin-left: 5px; }
+
+ &::before {
+ content: " ";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ margin-left: -4px;
+ margin-top: -4px;
+ width: 8px;
+ height: 8px;
+ background: $grey;
+ circle();
+ }
+ }
+
+ .post { margin: 30px 0; }
+
+ .post-header {
+ position: relative;
+ the-transition();
+ transition-property: border;
+ border-bottom: 1px dashed $grey-light;
+
+ &::before {
+ content: " ";
+ position: absolute;
+ left: 0;
+ top: 12px;
+ width: 6px;
+ height: 6px;
+ margin-left: -4px;
+ background: $grey;
+ circle();
+ border: 1px solid white;
+ the-transition();
+ transition-property: background;
+ }
+ }
+
+ .post-header:hover {
+ border-bottom-color: $grey-dim;
+
+ &::before { background: $black-deep; }
+ }
+
+ .post-meta {
+ position: absolute;
+ font-size: 12px;
+ left: 20px;
+ top: 5px;
+ }
+
+ .post-comments-count { display: none; }
+
+ .post-title {
+ margin-left: 60px;
+ font-size: 16px;
+ font-weight: normal;
+ line-height: inherit;
+
+ &::after {
+ margin-left: 3px;
+ opacity: 0.6;
+ }
+
+ a {
+ color: $grey-dim;
+ border-bottom: none;
+ }
+ }
+}
diff --git a/source/css/_common/components/post/post-copyright.styl b/source/css/_common/components/post/post-copyright.styl
new file mode 100644
index 000000000..f1cc7cbab
--- /dev/null
+++ b/source/css/_common/components/post/post-copyright.styl
@@ -0,0 +1,7 @@
+.post-copyright {
+ margin: $post-copyright.margin;
+ padding: $post-copyright.padding;
+ border-left: $post-copyright.border.width $post-copyright.border.style $post-copyright.border.color;
+ background-color: $post-copyright.bg;
+ list-style: none;
+}
diff --git a/source/css/_common/components/post/post-eof.styl b/source/css/_common/components/post/post-eof.styl
new file mode 100644
index 000000000..e4303252e
--- /dev/null
+++ b/source/css/_common/components/post/post-eof.styl
@@ -0,0 +1,17 @@
+.posts-expand {
+ .post-eof {
+ display: block;
+ margin: $post-eof-margin-top auto $post-eof-margin-bottom;
+ width: 8%;
+ height: 1px;
+ background: $grey-light;
+ text-align: center;
+ }
+}
+
+
+.post:last-child {
+ .post-eof.post-eof.post-eof {
+ display: none;
+ }
+}
diff --git a/source/css/_common/components/post/post-expand.styl b/source/css/_common/components/post/post-expand.styl
new file mode 100644
index 000000000..622540840
--- /dev/null
+++ b/source/css/_common/components/post/post-expand.styl
@@ -0,0 +1,65 @@
+// TODO: Refactor.
+
+.posts-expand {
+ padding-top: 40px;
+}
+
+@media (max-width: 767px) {
+ .posts-expand {
+ margin: 0 20px;
+ }
+
+ .post-body {
+ pre {
+ .gutter pre {
+ padding-right: 10px;
+ }
+ }
+
+ .highlight {
+ margin-left: 0px;
+ margin-right: 0px;
+ padding: 0;
+ .gutter pre {
+ padding-right: 10px;
+ }
+ }
+ }
+}
+
+.posts-expand .post-body {
+ +desktop() { text-align: justify; }
+
+
+ h2, h3, h4, h5, h6 {
+ padding-top: 10px;
+
+ .header-anchor{
+ float: right;
+ margin-left: 10px;
+ color: $grey-light;
+ border-bottom-style: none;
+ visibility: hidden;
+
+ &:hover{
+ color: inherit;
+ }
+ }
+
+ &:hover .header-anchor{
+ visibility: visible;
+ }
+ }
+
+ ul li { list-style: circle; }
+
+ img {
+ box-sizing: border-box;
+ margin: auto;
+ padding: 3px;
+ border: 1px solid $gray-lighter;
+ }
+}
+
+.posts-expand .post-body .fancybox img { margin: 0 auto 25px; }
+.posts-expand .post-body img { margin: 0 auto 25px; }
\ No newline at end of file
diff --git a/source/css/_common/components/post/post-gallery.styl b/source/css/_common/components/post/post-gallery.styl
new file mode 100644
index 000000000..b2385ae3f
--- /dev/null
+++ b/source/css/_common/components/post/post-gallery.styl
@@ -0,0 +1,23 @@
+.post-gallery {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+ border-collapse: separate;
+}
+
+.post-gallery-row { display: table-row; }
+
+.post-gallery .post-gallery-img {
+ display: table-cell;
+ text-align: center;
+ vertical-align: middle;
+ border: none;
+}
+
+.post-gallery .post-gallery-img img {
+ max-width: 100%;
+ max-height: 100%;
+ border: none;
+}
+
+.fancybox-close, .fancybox-close:hover { border: none; }
diff --git a/source/css/_common/components/post/post-meta.styl b/source/css/_common/components/post/post-meta.styl
new file mode 100644
index 000000000..1dc44a9d5
--- /dev/null
+++ b/source/css/_common/components/post/post-meta.styl
@@ -0,0 +1,50 @@
+.posts-expand .post-meta {
+ margin: 3px 0 60px 0;
+ color: $grey-dark;
+ font-family: $font-family-posts;
+ font-size: 12px;
+ text-align: center;
+
+ .post-category-list {
+ display: inline-block;
+ margin: 0;
+ padding: 3px;
+ }
+ .post-category-list-link { color: $grey-dark; }
+
+ .post-description {
+ font-size: 14px;
+ margin-top: 2px;
+ }
+
+ time {
+ border-bottom: 1px dashed $grey-dark;
+ cursor: help;
+ }
+}
+
+.post-symbolscount {
+ if !hexo-config('symbols_count_time.separated_meta') { display: inline-block; }
+}
+
+.post-meta-divider {
+ margin: 0 .5em;
+}
+
+.post-meta-item-icon {
+ margin-right: 3px;
+ +tablet() {
+ display: inline-block;
+ }
+ +mobile() {
+ display: inline-block;
+ }
+}
+.post-meta-item-text {
+ +tablet() {
+ display: none;
+ }
+ +mobile() {
+ display: none;
+ }
+}
diff --git a/source/css/_common/components/post/post-nav.styl b/source/css/_common/components/post/post-nav.styl
new file mode 100644
index 000000000..fa85838d2
--- /dev/null
+++ b/source/css/_common/components/post/post-nav.styl
@@ -0,0 +1,57 @@
+.post-nav {
+ display: table;
+ margin-top: 15px;
+ width: 100%;
+ border-top: 1px solid $gainsboro;
+}
+
+.post-nav-divider {
+ display: table-cell;
+ width: 10%;
+}
+
+.post-nav-item {
+ display: table-cell;
+ padding: 10px 0 0 0;
+ width: 45%;
+ vertical-align: top;
+
+ a {
+ position: relative;
+ display: block;
+ line-height: 25px;
+ font-size: 14px;
+ color: $link-color;
+ border-bottom: none;
+
+ &:hover {
+ color: $link-hover-color;
+ border-bottom: none;
+ }
+
+ &:active { top: 2px; }
+ }
+
+ .fa {
+ position: absolute;
+ top: 8px;
+ left: 0;
+ font-size: 12px;
+ }
+
+}
+
+.post-nav-next {
+ a { padding-left: 15px; }
+}
+
+.post-nav-prev {
+ text-align: right;
+
+ a { padding-right: 15px; }
+
+ .fa {
+ right: 0;
+ left: auto;
+ }
+}
diff --git a/source/css/_common/components/post/post-reading_progress.styl b/source/css/_common/components/post/post-reading_progress.styl
new file mode 100644
index 000000000..590d96ffc
--- /dev/null
+++ b/source/css/_common/components/post/post-reading_progress.styl
@@ -0,0 +1,10 @@
+.reading-progress-bar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 9999;
+ display: block;
+ width: 0;
+ height: unquote(hexo-config('reading_progress.height'));
+ background: unquote(hexo-config('reading_progress.color'));
+}
diff --git a/source/css/_common/components/post/post-reward.styl b/source/css/_common/components/post/post-reward.styl
new file mode 100644
index 000000000..450a104ea
--- /dev/null
+++ b/source/css/_common/components/post/post-reward.styl
@@ -0,0 +1,64 @@
+#rewardButton {
+ cursor: pointer;
+ border: 0;
+ outline: 0;
+ border-radius: 5px;
+ padding: 0;
+ margin: 0;
+ letter-spacing: normal;
+ text-transform: none;
+ text-indent: 0px;
+ text-shadow: none;
+}
+#rewardButton span {
+ display: inline-block;
+ width: 80px;
+ height: 35px;
+ border-radius: 5px;
+ color: #fff;
+ font-weight: 400;
+ font-style: normal;
+ font-variant: normal;
+ font-stretch: normal;
+ font-size: 18px;
+ font-family: "Microsoft Yahei";
+ background: #F44336;
+}
+#rewardButton span:hover{
+ background: #F7877F;
+}
+#QR{
+ padding-top:20px;
+}
+#QR a{
+ border:0;
+}
+#QR img{
+ width: 180px;
+ max-width: 100%;
+ display: inline-block;
+ margin: 0.8em 2em 0 2em;
+}
+#wechat:hover p{
+ animation: roll 0.1s infinite linear;
+ -webkit-animation: roll 0.1s infinite linear;
+ -moz-animation: roll 0.1s infinite linear;
+}
+#alipay:hover p{
+ animation: roll 0.1s infinite linear;
+ -webkit-animation: roll 0.1s infinite linear;
+ -moz-animation: roll 0.1s infinite linear;
+}
+#bitcoin:hover p {
+ animation: roll 0.1s infinite linear;
+ -webkit-animation: roll 0.1s infinite linear;
+ -moz-animation: roll 0.1s infinite linear;
+}
+@keyframes roll {
+ from {
+ transform(rotateZ(30deg));
+ }
+ to {
+ transform(rotateZ(-30deg));
+ }
+}
diff --git a/source/css/_common/components/post/post-rtl.styl b/source/css/_common/components/post/post-rtl.styl
new file mode 100644
index 000000000..ea048b9f0
--- /dev/null
+++ b/source/css/_common/components/post/post-rtl.styl
@@ -0,0 +1,11 @@
+.rtl {
+ &.post-body {
+ p, a, h1, h2, h3, h4, h5, h6, li, ul, ol {
+ direction: rtl;
+ font-family: UKIJ Ekran;
+ }
+ }
+ &.post-title {
+ font-family: UKIJ Ekran;
+ }
+}
diff --git a/source/css/_common/components/post/post-tags.styl b/source/css/_common/components/post/post-tags.styl
new file mode 100644
index 000000000..8c04ec7f0
--- /dev/null
+++ b/source/css/_common/components/post/post-tags.styl
@@ -0,0 +1,10 @@
+.posts-expand .post-tags {
+ margin-top: 40px;
+ text-align: center;
+
+ a {
+ display: inline-block;
+ margin-right: 10px;
+ font-size: 13px;
+ }
+}
diff --git a/source/css/_common/components/post/post-title.styl b/source/css/_common/components/post/post-title.styl
new file mode 100644
index 000000000..80542dc4d
--- /dev/null
+++ b/source/css/_common/components/post/post-title.styl
@@ -0,0 +1,51 @@
+.posts-expand .post-title {
+ text-align: center;
+ word-break: break-word;
+ font-weight: $posts-expand-title-font-weight;
+
+ if hexo-config('post_edit.enable') {
+ .post-edit-link {
+ color: #bbb;
+ display: inline-block;
+ float: right;
+ border-bottom: none;
+ the-transition-ease-in();
+ margin-left: -1.2em;
+ +mobile-small() {
+ margin-left: initial;
+ }
+ &:hover {
+ color: black;
+ }
+ }
+ }
+}
+
+.posts-expand .post-title-link {
+ display: inline-block;
+ position: relative;
+ color: $black-light;
+ border-bottom: none;
+ line-height: 1.2;
+ vertical-align: top;
+
+ &::before {
+ content: "";
+ position: absolute;
+ width: 100%;
+ height: 2px;
+ bottom: 0;
+ left: 0;
+ background-color: #000;
+ visibility: hidden;
+ transform: scaleX(0);
+ the-transition();
+ }
+
+ &:hover::before {
+ visibility: visible;
+ transform: scaleX(1);
+ }
+
+ .fa { font-size: 16px; }
+}
diff --git a/source/css/_common/components/post/post-type.styl b/source/css/_common/components/post/post-type.styl
new file mode 100644
index 000000000..c3d2510b9
--- /dev/null
+++ b/source/css/_common/components/post/post-type.styl
@@ -0,0 +1,14 @@
+// TODO: Refactor.
+
+.page-home, .page-post-detail {
+ .post-type-quote {
+ .post-header,
+ .post-tags {
+ display: none;
+ }
+
+ blockquote {
+ @extend .blockquote-center
+ }
+ }
+}
diff --git a/source/css/_common/components/post/post-widgets.styl b/source/css/_common/components/post/post-widgets.styl
new file mode 100644
index 000000000..4914c5a15
--- /dev/null
+++ b/source/css/_common/components/post/post-widgets.styl
@@ -0,0 +1,41 @@
+.post-widgets {
+ border-top: 1px solid #eee;
+ padding-top: 9px;
+ margin-top: 45px;
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ align-items: center;
+
+ .post-meta-divider {
+ height: 28px;
+ color: $grey-dark;
+ }
+}
+
+.wp_rating {
+ height: 20px;
+ margin-right: 10px;
+ text-align: center;
+ line-height: 20px;
+ padding-top: 6px;
+}
+
+.social-like {
+ font-size: 14px;
+ text-align: center;
+ display: flex;
+ justify-content: center;
+}
+
+.vk_like {
+ width: 85px;
+ height: 21px;
+ padding-top: 7px;
+ align-self: center;
+}
+
+.fb_like {
+ height: 30px;
+ align-self: center;
+}
diff --git a/source/css/_common/components/post/post.styl b/source/css/_common/components/post/post.styl
new file mode 100644
index 000000000..9ca7c9be2
--- /dev/null
+++ b/source/css/_common/components/post/post.styl
@@ -0,0 +1,61 @@
+.post-body {
+ font-family: $font-family-posts;
+ +mobile() {
+ word-break: break-word;
+ }
+}
+
+.post-body .fancybox img {
+ display: block !important;
+ margin: 0 auto;
+ cursor: pointer;
+ cursor: zoom-in;
+ cursor: -webkit-zoom-in;
+}
+
+.post-body .image-caption {
+ margin: -20px auto 15px;
+ text-align: center;
+ font-size: $font-size-base;
+ color: $grey-dark;
+ font-weight: bold;
+ line-height: 1;
+}
+
+.post-body .figure .caption {
+ @extend .post-body .image-caption;
+}
+
+.post-sticky-flag {
+ display: inline-block;
+ font-size: 16px;
+ -ms-transform: rotate(30deg);
+ transform: rotate(30deg);
+}
+
+.use-motion {
+ if hexo-config('motion.transition.post_block') {
+ .post-block,
+ .pagination,
+ .comments { opacity: 0; }
+ }
+ if hexo-config('motion.transition.post_header') { .post-header { opacity: 0; } }
+ if hexo-config('motion.transition.post_body') { .post-body { opacity: 0; } }
+ if hexo-config('motion.transition.coll_header') { .collection-title { opacity: 0; } }
+}
+
+@import "post-expand";
+@import "post-collapse";
+@import "post-type";
+@import "post-title";
+@import "post-meta";
+@import "post-button";
+@import "post-tags";
+@import "post-nav";
+@import "post-eof";
+@import "post-gallery";
+@import "post-reward" if hexo-config('alipay') or hexo-config('wechatpay') or hexo-config('bitcoin');
+@import "post-copyright" if hexo-config('post_copyright.enable');
+@import "post-widgets" if (hexo-config('facebook_sdk.enable') and hexo-config('facebook_sdk.like_button')) or (hexo-config('vkontakte_api.enable') and hexo-config('vkontakte_api.like')) or hexo-config('rating.enable') or (hexo-config('needmoreshare2.enable') and hexo-config('needmoreshare2.postbottom.enable'));
+@import "post-rtl";
+@import "post-reading_progress" if hexo-config('reading_progress.enable');
diff --git a/source/css/_common/components/sidebar/sidebar-author-links.styl b/source/css/_common/components/sidebar/sidebar-author-links.styl
new file mode 100644
index 000000000..9413de9c9
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-author-links.styl
@@ -0,0 +1,25 @@
+.links-of-author {
+ margin-top: 20px;
+}
+
+.links-of-author a,
+.links-of-author .exturl {
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 10px;
+ margin-bottom: 10px;
+ border-bottom-color: $black-light;
+ font-size: 13px;
+ if hexo-config('social_icons.transition') { the-transition(); }
+
+ &:before {
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 3px;
+ content: " ";
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: rgb(random-color(0, 255) - 50%, random-color(0, 255) - 50%, random-color(0, 255) - 50%);
+ }
+}
diff --git a/source/css/_common/components/sidebar/sidebar-author.styl b/source/css/_common/components/sidebar/sidebar-author.styl
new file mode 100644
index 000000000..2da119c7d
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-author.styl
@@ -0,0 +1,45 @@
+.site-author-image {
+ display: block;
+ margin: 0 auto;
+ padding: $site-author-image-padding;
+ max-width: $site-author-image-width;
+ height: $site-author-image-height;
+ border: $site-author-image-border-width solid $site-author-image-border-color;
+ opacity: hexo-config('avatar.opacity') is a 'unit' ? hexo-config('avatar.opacity') : 1;
+}
+
+if hexo-config('avatar.rounded') {
+.site-author-image {
+ border-radius: 100%;
+}
+}
+
+if hexo-config('avatar.rotated') {
+.site-author-image {
+ -webkit-transition: -webkit-transform 1.0s ease-out;
+ -moz-transition: -moz-transform 1.0s ease-out;
+ -ms-transition: -ms-transform 1.0s ease-out;
+ transition: transform 1.0s ease-out;
+}
+}
+
+img:hover {
+ -webkit-transform: rotateZ(360deg);
+ -moz-transform: rotateZ(360deg);
+ -ms-transform: rotate(360deg);
+ transform: rotateZ(360deg);
+}
+
+.site-author-name {
+ margin: $site-author-name-margin;
+ text-align: $site-author-name-align;
+ color: $site-author-name-color;
+ font-weight: $site-author-name-weight;
+}
+
+.site-description {
+ margin-top: $site-description-margin-top;
+ text-align: $site-description-align;
+ font-size: $site-description-font-size;
+ color: $site-description-color;
+}
diff --git a/source/css/_common/components/sidebar/sidebar-blogroll.styl b/source/css/_common/components/sidebar/sidebar-blogroll.styl
new file mode 100644
index 000000000..b677e6868
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-blogroll.styl
@@ -0,0 +1,25 @@
+.links-of-blogroll { font-size: 13px; }
+
+.links-of-blogroll-title {
+ margin-top: 20px;
+ font-size: 14px;
+ font-weight: $font-weight-bold;
+}
+.links-of-blogroll-list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.links-of-blogroll-item {
+ padding: 2px 10px;
+
+ a {
+ max-width: 280px;
+ box-sizing: border-box;
+ display: inline-block;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+}
diff --git a/source/css/_common/components/sidebar/sidebar-dimmer.styl b/source/css/_common/components/sidebar/sidebar-dimmer.styl
new file mode 100644
index 000000000..b2da3cec2
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-dimmer.styl
@@ -0,0 +1,21 @@
+.sidebar-active #sidebar-dimmer {
+ opacity: .7;
+ -webkit-transform: translateX(-150%);
+ transform: translateX(-150%);
+ transition: opacity .2s;
+}
+
+#sidebar-dimmer {
+ display: none;
+ position: absolute;
+ top: 0;
+ left: 100%;
+ width: 200%;
+ height: 100%;
+ background: #000;
+ opacity: 0;
+ transition: opacity .2s,transform 0s .2s;
+ +mobile() {
+ display: block;
+ }
+}
diff --git a/source/css/_common/components/sidebar/sidebar-feed-link.styl b/source/css/_common/components/sidebar/sidebar-feed-link.styl
new file mode 100644
index 000000000..b3868a858
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-feed-link.styl
@@ -0,0 +1,23 @@
+.feed-link {
+ margin-top: 20px;
+
+ a {
+ display: inline-block;
+ padding: 0 15px;
+ color: rgb(252, 100, 35);
+ border: 1px solid rgb(252, 100, 35);
+ border-radius: 4px;
+
+ i {
+ color: rgb(252, 100, 35);
+ font-size: 14px;
+ }
+
+ &:hover {
+ color:white;
+ background: rgb(252, 100, 35);
+
+ i { color: white; }
+ }
+ }
+}
diff --git a/source/css/_common/components/sidebar/sidebar-nav.styl b/source/css/_common/components/sidebar/sidebar-nav.styl
new file mode 100644
index 000000000..973eda70f
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-nav.styl
@@ -0,0 +1,29 @@
+// Sidebar Navigation
+
+.sidebar-nav {
+ margin: 0 0 20px;
+ padding-left: 0;
+}
+.sidebar-nav li {
+ display: inline-block;
+ cursor: pointer;
+ border-bottom: 1px solid transparent;
+ font-size: 14px;
+ color: $sidebar-nav-color;
+
+ &:hover { color: $sidebar-nav-hover-color; }
+}
+
+.page-post-detail .sidebar-nav-toc { padding: 0 5px; }
+
+.page-post-detail .sidebar-nav-overview { margin-left: 10px; }
+
+.sidebar-nav .sidebar-nav-active {
+ color: $sidebar-highlight;
+ border-bottom-color: $sidebar-highlight;
+
+ &:hover { color: $sidebar-highlight; }
+}
+
+.sidebar-panel { display: none; }
+.sidebar-panel-active { display: block; }
diff --git a/source/css/_common/components/sidebar/sidebar-toc.styl b/source/css/_common/components/sidebar/sidebar-toc.styl
new file mode 100644
index 000000000..b9f0264db
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-toc.styl
@@ -0,0 +1,60 @@
+
+.post-toc-empty {
+ font-size: 14px;
+ color: $grey-dim;
+}
+
+.post-toc-wrap { overflow: hidden; }
+
+.post-toc { overflow: auto; }
+
+.post-toc ol {
+ margin: 0;
+ padding: 0 2px 5px 10px;
+ text-align: left;
+ list-style: none;
+ font-size: 14px;
+
+ & > ol { padding-left: 0; }
+
+ a {
+ the-transition();
+ transition-property: all;
+ color: $toc-link-color;
+ border-bottom-color: $toc-link-border-color;
+
+ &:hover {
+ color: $toc-link-hover-color;
+ border-bottom-color: $toc-link-hover-border-color;
+ }
+ }
+}
+
+.post-toc .nav-item {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ //text-align: justify;
+ white-space: nowrap if !hexo-config('toc.wrap');
+ line-height: 1.8;
+}
+
+.post-toc .nav .nav-child { display: none; }
+
+.post-toc .nav .active > .nav-child { display: block; }
+
+.post-toc .nav .active-current > .nav-child {
+ display: block;
+ & > .nav-item { display: block; }
+}
+
+.post-toc .nav .active > a {
+ color: $toc-link-active-color;
+ border-bottom-color: $toc-link-active-border-color;
+}
+
+.post-toc .nav .active-current > a {
+ color: $toc-link-active-current-color;
+ &:hover {
+ color: $toc-link-active-current-border-color;
+ }
+}
diff --git a/source/css/_common/components/sidebar/sidebar-toggle.styl b/source/css/_common/components/sidebar/sidebar-toggle.styl
new file mode 100644
index 000000000..c4b6a06b1
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar-toggle.styl
@@ -0,0 +1,36 @@
+.sidebar-toggle {
+ position: fixed;
+ right: $b2t-position-right;
+ bottom: 45px;
+ width: 14px;
+ height: 14px;
+ padding: 5px;
+ background: $black-deep;
+ line-height: 0;
+ z-index: $zindex-5;
+ cursor: pointer;
+ -webkit-transform: translateZ(0);
+
+ +tablet() {
+ fixbutton() if hexo-config('sidebar.onmobile');
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+ +mobile() {
+ fixbutton() if hexo-config('sidebar.onmobile');
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+}
+
+
+
+.sidebar-toggle-line {
+ position: relative;
+ display: inline-block;
+ vertical-align: top;
+ height: 2px;
+ width: 100%;
+ background: white;
+ margin-top: 3px;
+
+ &:first-child { margin-top: 0; }
+}
diff --git a/source/css/_common/components/sidebar/sidebar.styl b/source/css/_common/components/sidebar/sidebar.styl
new file mode 100644
index 000000000..555668ad4
--- /dev/null
+++ b/source/css/_common/components/sidebar/sidebar.styl
@@ -0,0 +1,52 @@
+.sidebar {
+ position: fixed;
+ right: 0;
+ top: 0;
+ bottom: 0;
+
+ width: 0;
+ z-index: $zindex-4;
+ box-shadow: inset 0 2px 6px black;
+ background: $black-deep;
+ -webkit-transform: translateZ(0); // http://stackoverflow.com/questions/17079857/position-fixed-broken-in-chrome-with-flash-behind
+
+ a, .exturl {
+ color: $grey-dark;
+ border-bottom-color: $black-light;
+ &:hover { color: $gainsboro; }
+ }
+
+ +tablet() {
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+ +mobile() {
+ hide() if not hexo-config('sidebar.onmobile');
+ }
+
+}
+
+.sidebar-inner {
+ position: relative;
+ padding: 20px 10px;
+ color: $grey-dark;
+ text-align: center;
+}
+
+.site-overview-wrap {
+ overflow: hidden;
+}
+
+.site-overview {
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+@import "sidebar-toggle";
+@import "sidebar-author";
+@import "site-state";
+@import "sidebar-feed-link";
+@import "sidebar-author-links";
+@import "sidebar-blogroll";
+@import "sidebar-nav";
+@import "sidebar-toc";
+@import "sidebar-dimmer" if hexo-config('sidebar.onmobile');
diff --git a/source/css/_common/components/sidebar/site-state.styl b/source/css/_common/components/sidebar/site-state.styl
new file mode 100644
index 000000000..c05b0ea09
--- /dev/null
+++ b/source/css/_common/components/sidebar/site-state.styl
@@ -0,0 +1,28 @@
+.site-state {
+ overflow: hidden;
+ line-height: 1.4;
+ white-space: nowrap;
+ text-align: $site-state-align;
+}
+
+.site-state-item {
+ display: inline-block;
+ padding: 0 15px;
+ border-left: 1px solid $site-state-item-border-color;
+
+ &:first-child { border-left: none; }
+
+ a { border-bottom: none; }
+}
+.site-state-item-count {
+ display: block;
+ text-align: center;
+ color: $site-state-item-count-color;
+ font-weight: $font-weight-bold;
+ font-size: $site-state-item-count-font-size;
+}
+
+.site-state-item-name {
+ font-size: $site-state-item-name-font-size;
+ color: $site-state-item-name-color;
+}
diff --git a/source/css/_common/components/tag-cloud.styl b/source/css/_common/components/tag-cloud.styl
new file mode 100644
index 000000000..30b01c642
--- /dev/null
+++ b/source/css/_common/components/tag-cloud.styl
@@ -0,0 +1,8 @@
+.tag-cloud {
+ text-align: center;
+
+ a {
+ display: inline-block;
+ margin: 10px;
+ }
+}
\ No newline at end of file
diff --git a/source/css/_common/components/tags/blockquote-center.styl b/source/css/_common/components/tags/blockquote-center.styl
new file mode 100644
index 000000000..b0f3bccaa
--- /dev/null
+++ b/source/css/_common/components/tags/blockquote-center.styl
@@ -0,0 +1,33 @@
+// Blockquote with all children centered.
+.blockquote-center {
+ position: relative;
+ margin: 40px 0;
+ padding: 0;
+ border-left: none;
+ text-align: center;
+
+ &::before, &::after {
+ position: absolute;
+ content: ' ';
+ display: block;
+ width: 100%;
+ height: 24px;
+ opacity: 0.2;
+ background-repeat: no-repeat;
+ background-position: 0 -6px;
+ background-size: 22px 22px;
+ }
+ &::before {
+ top: -20px;
+ background-image: url($center-quote-left);
+ border-top: 1px solid $grey-light;
+ }
+ &::after {
+ bottom: -20px;
+ background-image: url($center-quote-right);
+ border-bottom: 1px solid $grey-light;
+ background-position: 100% 8px;
+ }
+
+ p, div { text-align: center; }
+}
diff --git a/source/css/_common/components/tags/exturl.styl b/source/css/_common/components/tags/exturl.styl
new file mode 100644
index 000000000..49a1684f9
--- /dev/null
+++ b/source/css/_common/components/tags/exturl.styl
@@ -0,0 +1,18 @@
+.exturl {
+ // Remove the gray background color from active links in IE 10.
+ background-color: transparent;
+
+ cursor: pointer;
+ border-bottom: 1px solid #999;
+
+ .fa {
+ font-size: 14px;
+ }
+}
+
+// Improve readability when focused and also mouse hovered in all browsers.
+.exturl:active, .exturl:hover {
+ outline: 0;
+ color: $black-deep;
+ border-bottom-color: $black-deep;
+}
diff --git a/source/css/_common/components/tags/full-image.styl b/source/css/_common/components/tags/full-image.styl
new file mode 100644
index 000000000..90426d0e7
--- /dev/null
+++ b/source/css/_common/components/tags/full-image.styl
@@ -0,0 +1,12 @@
+// Expand image to 126% with nagative margin-left/right on Desktop.
+.full-image.full-image.full-image.full-image {
+ border: none;
+ max-width: 100%;
+ width: auto;
+ margin: 20px auto 25px;
+// +desktop() {
+// max-width: none;
+// width: $full-image-width;
+// margin: $full-image-margin-vertical $full-image-margin-horizontal;
+// }
+}
diff --git a/source/css/_common/components/tags/group-pictures.styl b/source/css/_common/components/tags/group-pictures.styl
new file mode 100644
index 000000000..ce1461ddf
--- /dev/null
+++ b/source/css/_common/components/tags/group-pictures.styl
@@ -0,0 +1,35 @@
+.post .post-body .group-picture {
+ img {
+ box-sizing: border-box;
+ padding: 0 3px;
+ border: none;
+ }
+}
+
+.post .group-picture-row {
+ overflow: hidden;
+ margin-top: 6px;
+ &:first-child { margin-top: 0; }
+}
+
+.post .group-picture-column { float: left; }
+
+.page-post-detail .post-body .group-picture-column {
+ float: none;
+ margin-top: 10px;
+ width: auto !important;
+ img { margin: 0 auto; }
+}
+
+.page-archive {
+ .group-picture-container { overflow: hidden; }
+ .group-picture-row {
+ float: left;
+ &:first-child { margin-top: 6px; }
+ }
+
+ .group-picture-column {
+ max-width: 150px;
+ max-height: 150px;
+ }
+}
diff --git a/source/css/_common/components/tags/label.styl b/source/css/_common/components/tags/label.styl
new file mode 100644
index 000000000..541dd2dac
--- /dev/null
+++ b/source/css/_common/components/tags/label.styl
@@ -0,0 +1,12 @@
+.post-body .label {
+ display: inline;
+ padding: 0 2px;
+ white-space: nowrap;
+
+ &.default { background-color: $label-default; }
+ &.primary { background-color: $label-primary; }
+ &.info { background-color: $label-info; }
+ &.success { background-color: $label-success; }
+ &.warning { background-color: $label-warning; }
+ &.danger { background-color: $label-danger; }
+}
diff --git a/source/css/_common/components/tags/note-modern.styl b/source/css/_common/components/tags/note-modern.styl
new file mode 100644
index 000000000..cf7659e7a
--- /dev/null
+++ b/source/css/_common/components/tags/note-modern.styl
@@ -0,0 +1,183 @@
+.post-body .note {
+ note_icons = hexo-config('note.icons');
+
+ position: relative;
+ padding: 15px;
+ margin-bottom: 20px;
+
+ border: 1px solid transparent;
+ background-color: $whitesmoke;
+ border-radius: unit(hexo-config('note.border_radius'), px) if hexo-config('note.border_radius') is a 'unit';
+
+ h2, h3, h4, h5, h6 {
+ if note_icons {
+ margin-top: 3px;
+ } else {
+ margin-top: 0;
+ }
+ margin-bottom: 0;
+ border-bottom: initial;
+ padding-top: 0 !important;
+ }
+
+ p, ul, ol, table, pre, blockquote {
+ &:first-child {
+ margin-top: 0;
+ }
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ if note_icons {
+ &:not(.no-icon) {
+ padding-left: 45px;
+ &:before {
+ position: absolute;
+ font-family: 'FontAwesome';
+ font-size: larger;
+ top: 13px;
+ left: 15px;
+ }
+ }
+ }
+
+ &.default {
+ background-color: $note-modern-default-bg;
+ border-color: $note-modern-default-border;
+ color: $note-modern-default-text;
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-default-icon;
+ }
+ }
+ }
+ a {
+ &:not(.btn) {
+ color: $note-modern-default-text;
+ border-bottom: 1px solid $note-modern-default-text;
+ &:hover {
+ color: $note-modern-default-hover;
+ border-bottom: 1px solid $note-modern-default-hover;
+ }
+ }
+ }
+ }
+
+ &.primary {
+ background-color: $note-modern-primary-bg;
+ border-color: $note-modern-primary-border;
+ color: $note-modern-primary-text;
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-primary-icon;
+ }
+ }
+ }
+ a {
+ &:not(.btn) {
+ color: $note-modern-primary-text;
+ border-bottom: 1px solid $note-modern-primary-text;
+ &:hover {
+ color: $note-modern-primary-hover;
+ border-bottom: 1px solid $note-modern-primary-hover;
+ }
+ }
+ }
+ }
+
+ &.info {
+ background-color: $note-modern-info-bg;
+ border-color: $note-modern-info-border;
+ color: $note-modern-info-text;
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-info-icon;
+ }
+ }
+ }
+ a {
+ &:not(.btn) {
+ color: $note-modern-info-text;
+ border-bottom: 1px solid $note-modern-info-text;
+ &:hover {
+ color: $note-modern-info-hover;
+ border-bottom: 1px solid $note-modern-info-hover;
+ }
+ }
+ }
+ }
+
+ &.success {
+ background-color: $note-modern-success-bg;
+ border-color: $note-modern-success-border;
+ color: $note-modern-success-text;
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-success-icon;
+ }
+ }
+ }
+ a {
+ &:not(.btn) {
+ color: $note-modern-success-text;
+ border-bottom: 1px solid $note-modern-success-text;
+ &:hover {
+ color: $note-modern-success-hover;
+ border-bottom: 1px solid $note-modern-success-hover;
+ }
+ }
+ }
+ }
+
+ &.warning {
+ background-color: $note-modern-warning-bg;
+ border-color: $note-modern-warning-border;
+ color: $note-modern-warning-text;
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-warning-icon;
+ }
+ }
+ }
+ a {
+ &:not(.btn) {
+ color: $note-modern-warning-text;
+ border-bottom: 1px solid $note-modern-warning-text;
+ &:hover {
+ color: $note-modern-warning-hover;
+ border-bottom: 1px solid $note-modern-warning-hover;
+ }
+ }
+ }
+ }
+
+ &.danger {
+ background-color: $note-modern-danger-bg;
+ border-color: $note-modern-danger-border;
+ color: $note-modern-danger-text;
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-danger-icon;
+ }
+ }
+ }
+ a {
+ &:not(.btn) {
+ color: $note-modern-danger-text;
+ border-bottom: 1px solid $note-modern-danger-text;
+ &:hover {
+ color: $note-modern-danger-hover;
+ border-bottom: 1px solid $note-modern-danger-hover;
+ }
+ }
+ }
+ }
+
+}
diff --git a/source/css/_common/components/tags/note.styl b/source/css/_common/components/tags/note.styl
new file mode 100644
index 000000000..4b234b0d3
--- /dev/null
+++ b/source/css/_common/components/tags/note.styl
@@ -0,0 +1,161 @@
+.post-body .note {
+ note_style = hexo-config('note.style');
+ note_icons = hexo-config('note.icons');
+
+ position: relative;
+ padding: 15px;
+ margin-bottom: 20px;
+
+ if note_style == 'simple' {
+ border: 1px solid $gainsboro;
+ border-left-width: 5px;
+ }
+ if note_style == 'flat' {
+ border: initial;
+ border-left: 3px solid $gainsboro;
+ background-color: lighten($gainsboro, 65%);
+ }
+ border-radius: unit(hexo-config('note.border_radius'), px) if hexo-config('note.border_radius') is a 'unit';
+
+ h2, h3, h4, h5, h6 {
+ if note_icons {
+ margin-top: 3px;
+ } else {
+ margin-top: 0;
+ }
+ margin-bottom: 0;
+ border-bottom: initial;
+ padding-top: 0 !important;
+ }
+
+ p, ul, ol, table, pre, blockquote {
+ &:first-child {
+ margin-top: 0;
+ }
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ if note_icons {
+ &:not(.no-icon) {
+ padding-left: 45px;
+ &:before {
+ position: absolute;
+ font-family: 'FontAwesome';
+ font-size: larger;
+ top: 13px;
+ left: 15px;
+ }
+ }
+ }
+
+ &.default {
+ if note_style == 'flat' {
+ background-color: $note-default-bg;
+ }
+ border-left-color: $note-default-border;
+ h2, h3, h4, h5, h6 {
+ color: $note-default-text;
+ }
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-default-icon;
+ color : $note-default-text;
+ }
+ }
+ }
+ }
+
+ &.primary {
+ if note_style == 'flat' {
+ background-color: $note-primary-bg;
+ }
+ border-left-color: $note-primary-border;
+ h2, h3, h4, h5, h6 {
+ color: $note-primary-text;
+ }
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-primary-icon;
+ color : $note-primary-text;
+ }
+ }
+ }
+ }
+
+ &.info {
+ if note_style == 'flat' {
+ background-color: $note-info-bg;
+ }
+ border-left-color: $note-info-border;
+ h2, h3, h4, h5, h6 {
+ color: $note-info-text;
+ }
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-info-icon;
+ color : $note-info-text;
+ }
+ }
+ }
+ }
+
+ &.success {
+ if note_style == 'flat' {
+ background-color: $note-success-bg;
+ }
+ border-left-color: $note-success-border;
+ h2, h3, h4, h5, h6 {
+ color: $note-success-text;
+ }
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-success-icon;
+ color : $note-success-text;
+ }
+ }
+ }
+ }
+
+ &.warning {
+ if note_style == 'flat' {
+ background-color: $note-warning-bg;
+ }
+ border-left-color: $note-warning-border;
+ h2, h3, h4, h5, h6 {
+ color: $note-warning-text;
+ }
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-warning-icon;
+ color : $note-warning-text;
+ }
+ }
+ }
+ }
+
+ &.danger {
+ if note_style == 'flat' {
+ background-color: $note-danger-bg;
+ }
+ border-left-color: $note-danger-border;
+ h2, h3, h4, h5, h6 {
+ color: $note-danger-text;
+ }
+ if note_icons {
+ &:not(.no-icon) {
+ &:before {
+ content: $note-danger-icon;
+ color : $note-danger-text;
+ }
+ }
+ }
+ }
+
+}
diff --git a/source/css/_common/components/tags/tabs.styl b/source/css/_common/components/tags/tabs.styl
new file mode 100644
index 000000000..c3c27c4e9
--- /dev/null
+++ b/source/css/_common/components/tags/tabs.styl
@@ -0,0 +1,99 @@
+.post-body .tabs {
+ position: relative;
+ display: block;
+ margin-bottom: 20px;
+ padding-top: 10px;
+
+ // Read tabs border_radius from NexT config and set in "tbr px" to use it as string variable in this CSS section.
+ hexo-config('tabs.border_radius') is a 'unit' ? (tbr = unit(hexo-config('tabs.border_radius'), px)) : (tbr = 0)
+
+ ul.nav-tabs {
+ margin: 0;
+ padding: 0;
+ display: flex;
+ margin-bottom: -1px;
+
+ +mobile-smallest() {
+ display: block;
+ margin-bottom: 5px;
+ }
+
+ li.tab {
+ list-style-type: none !important;
+ margin: 0 .25em 0 0;
+ border-top: 3px solid transparent;
+ border-left: 1px solid transparent;
+ border-right: 1px solid transparent;
+
+ +mobile-smallest() {
+ margin: initial;
+ border-top: 1px solid transparent;
+ border-left: 3px solid transparent;
+ border-right: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ }
+
+ if tbr > 0 {
+ border-radius: tbr tbr 0 0;
+ +mobile-smallest() { border-radius: tbr; }
+ }
+ if hexo-config('tabs.transition.tabs') { the-transition-ease-out(); }
+
+ & a {
+ outline: 0;
+ border-bottom: initial;
+ display: block;
+ line-height: 1.8em;
+ padding: .25em .75em;
+ & i { width: (18em / 14); }
+ if hexo-config('tabs.transition.labels') { the-transition-ease-out(); }
+ }
+
+ &.active {
+ border-top: 3px solid $orange;
+ border-left: 1px solid $table-border-color;
+ border-right: 1px solid $table-border-color;
+ background-color: #fff;
+
+ +mobile-smallest() {
+ border-top: 1px solid $table-border-color;
+ border-left: 3px solid $orange;
+ border-right: 1px solid $table-border-color;
+ border-bottom: 1px solid $table-border-color;
+ }
+
+ & a {
+ cursor: default;
+ color: $link-color;
+ }
+ }
+ }
+
+ }
+
+ .tab-content {
+ background-color: #fff;
+
+ .tab-pane {
+ border: 1px solid $table-border-color;
+ padding: 20px 20px 0 20px;
+ if tbr > 0 { border-radius: tbr; }
+
+ &:not(.active) {
+ hide();
+ }
+ &.active {
+ show();
+ if tbr > 0 {
+ &:nth-of-type(1) {
+ border-radius: 0 tbr tbr tbr;
+ +mobile-smallest() { border-radius: tbr; }
+ }
+ }
+ }
+
+ }
+
+ }
+
+}
diff --git a/source/css/_common/components/tags/tags.styl b/source/css/_common/components/tags/tags.styl
new file mode 100644
index 000000000..e7e027ad8
--- /dev/null
+++ b/source/css/_common/components/tags/tags.styl
@@ -0,0 +1,8 @@
+@import "full-image";
+@import "blockquote-center";
+@import "group-pictures";
+@import "exturl" if hexo-config('exturl');
+@import "note" if hexo-config('note.style') == 'simple' || hexo-config('note.style') == 'flat';
+@import "note-modern" if hexo-config('note.style') == 'modern';
+@import "label" if hexo-config('label');
+@import "tabs" if hexo-config('tabs.enable');
diff --git a/source/css/_common/components/third-party/algolia-search.styl b/source/css/_common/components/third-party/algolia-search.styl
new file mode 100644
index 000000000..652ba1ac8
--- /dev/null
+++ b/source/css/_common/components/third-party/algolia-search.styl
@@ -0,0 +1,135 @@
+// fix bug using algolia search's CDN
+.ais-search-box--magnifier svg {
+ display: none !important;
+}
+.ais-search-box--reset svg {
+ display: none !important;
+}
+
+.algolia-pop-overlay
+ position: fixed
+ width: 100%
+ height: 100%
+ top: 0
+ left: 0
+ z-index: 2080
+ background-color: rgba(0, 0, 0, 0.3)
+ +mobile()
+ display: none;
+
+.algolia-popup
+ overflow: hidden
+ padding: 0
+ display: none
+ position: fixed
+ top: 10%
+ left: 50%
+ width: 700px
+ height: 80%
+ margin-left: -350px
+ background: #fff
+ color: #333
+ z-index: 9999
+ border-radius: 5px
+ +mobile()
+ padding: 0
+ top: 0
+ left: 0
+ margin: 0
+ width: 100%
+ height: 100%
+ border-radius: 0
+
+ .popup-btn-close
+ position: absolute
+ right: 14px
+ color: #4EBD79
+ font-size: 14px
+ font-weight: bold
+ text-transform: uppercase
+ cursor: pointer
+ padding-left: 15px
+ border-left: 1px solid #eee
+ top: 10px
+ .fa
+ color: $grey-dark
+ font-size: 18px
+ &:hover .fa
+ color: $black-deep
+
+.algolia-search
+ padding: 10px 15px 5px
+ max-height: 50px
+ border-bottom: 1px solid #ccc
+ background: $whitesmoke
+ border-top-left-radius: 5px
+ border-top-right-radius: 5px
+
+.algolia-search-input-icon
+ display: inline-block
+ width: 20px
+ .fa
+ font-size: 18px
+
+.algolia-search-input
+ display: inline-block
+ width: calc(90% - 20px)
+ input
+ padding: 5px 0
+ width: 100%
+ outline: none
+ border: none
+ background: transparent
+
+.algolia-powered
+ float: right
+ img
+ display: inline-block
+ height: 18px
+ vertical-align: middle
+
+.algolia-results
+ position: relative
+ overflow: auto
+ padding: 10px 30px
+ height: calc(100% - 50px)
+
+ hr
+ margin: 10px 0
+
+ .highlight
+ font-style: normal
+ margin: 0
+ padding: 0 2px
+ font-size: inherit
+ color: red
+
+.algolia-hits
+ margin-top: 20px
+
+.algolia-hit-item
+ margin: 15px 0
+
+.algolia-hit-item-link
+ display: block
+ border-bottom: 1px dashed #ccc
+ the-transition()
+
+.algolia-pagination
+ .pagination
+ margin-top: 40px
+ border-top: none
+ padding: 0
+ .pagination-item
+ display: inline-block
+ .page-number
+ border-top: none
+ &:hover
+ border-bottom: 1px solid $black-deep
+
+ .current .page-number
+ @extend .pagination .page-number.current
+
+ .disabled-item
+ visibility: hidden
+
diff --git a/source/css/_common/components/third-party/baidushare.styl b/source/css/_common/components/third-party/baidushare.styl
new file mode 100644
index 000000000..fc42b713d
--- /dev/null
+++ b/source/css/_common/components/third-party/baidushare.styl
@@ -0,0 +1,12 @@
+.post-spread {
+ margin-top: 20px;
+ text-align: center;
+}
+
+.bdshare-slide-button-box a { border: none; }
+
+.bdsharebuttonbox {
+ display: inline-block;
+
+ a { border: none; }
+}
diff --git a/source/css/_common/components/third-party/busuanzi-counter.styl b/source/css/_common/components/third-party/busuanzi-counter.styl
new file mode 100644
index 000000000..960fef686
--- /dev/null
+++ b/source/css/_common/components/third-party/busuanzi-counter.styl
@@ -0,0 +1,30 @@
+if hexo-config("scheme") == Pisces
+ .busuanzi-count {
+ +tablet() {
+ width: auto;
+ }
+ +mobile() {
+ width: auto;
+ }
+ }
+
+.site-uv,
+.site-pv,
+.page-pv {
+ display: inline-block;
+
+ .busuanzi-value {
+ margin: 0 5px;
+ }
+}
+
+if hexo-config("busuanzi_count.site_pv") and hexo-config("busuanzi_count.site_uv")
+ .site-uv
+ {
+ margin-right: 10px;
+
+ &::after {
+ content: "|";
+ padding-left: 10px;
+ }
+ }
diff --git a/source/css/_common/components/third-party/gitment.styl b/source/css/_common/components/third-party/gitment.styl
new file mode 100644
index 000000000..52babf0ba
--- /dev/null
+++ b/source/css/_common/components/third-party/gitment.styl
@@ -0,0 +1,13 @@
+#gitment-display-button{
+ display: inline-block;
+ padding: 0 15px;
+ color: #0a9caf;
+ cursor: pointer;
+ font-size: 14px;
+ border: 1px solid #0a9caf;
+ border-radius: 4px;
+}
+#gitment-display-button:hover{
+ color: #fff;
+ background: #0a9caf;
+}
\ No newline at end of file
diff --git a/source/css/_common/components/third-party/han.styl b/source/css/_common/components/third-party/han.styl
new file mode 100644
index 000000000..d02c9697b
--- /dev/null
+++ b/source/css/_common/components/third-party/han.styl
@@ -0,0 +1,3 @@
+.fa {
+ font-family: FontAwesome!important;
+}
diff --git a/source/css/_common/components/third-party/jiathis.styl b/source/css/_common/components/third-party/jiathis.styl
new file mode 100644
index 000000000..d501fb503
--- /dev/null
+++ b/source/css/_common/components/third-party/jiathis.styl
@@ -0,0 +1,10 @@
+.post-spread {
+ margin-top: 20px;
+ text-align: center;
+}
+
+.jiathis_style {
+ display: inline-block;
+
+ a { border: none; }
+}
\ No newline at end of file
diff --git a/source/css/_common/components/third-party/localsearch.styl b/source/css/_common/components/third-party/localsearch.styl
new file mode 100644
index 000000000..85f43cf9a
--- /dev/null
+++ b/source/css/_common/components/third-party/localsearch.styl
@@ -0,0 +1,102 @@
+.local-search-pop-overlay
+ position: fixed
+ width: 100%
+ height: 100%
+ top: 0
+ left: 0
+ z-index: 2080
+ background-color: rgba(0, 0, 0, 0.3)
+
+.local-search-popup
+ display: none
+ position: fixed
+ top: 10%
+ left: 50%
+ margin-left: -350px
+ width: 700px
+ height: 80%
+ padding: 0
+ background: #fff
+ color: #333
+ z-index: 9999
+ border-radius: 5px
+ +mobile()
+ padding: 0
+ top: 0
+ left: 0
+ margin: 0
+ width: 100%
+ height: 100%
+ border-radius: 0
+
+ ul.search-result-list
+ padding: 0
+ margin: 0 5px
+
+ p.search-result
+ border-bottom: 1px dashed #ccc
+ padding: 5px 0
+
+ a.search-result-title
+ font-weight: bold
+ font-size: 16px
+
+ .search-keyword
+ border-bottom: 1px dashed #f00
+ font-weight: bold
+ color: #f00
+
+ .local-search-header
+ padding: 5px
+ height: 36px
+ background: #f5f5f5
+ border-top-left-radius: 5px
+ border-top-right-radius: 5px
+
+ #local-search-result
+ overflow: auto
+ position: relative
+ padding: 5px 25px
+ height: calc(100% - 55px)
+
+ .local-search-input-wrapper
+ display: inline-block
+ width: calc(100% - 90px)
+ height: 36px
+ line-height: 36px
+ padding: 0 5px
+
+ .local-search-input-wrapper input
+ padding: 8px 0
+ height: 20px
+ display: block
+ width: 100%
+ outline: none
+ border: none
+ background: transparent
+ vertical-align: middle
+
+ .search-icon, .popup-btn-close
+ display: inline-block
+ font-size: 18px
+ color: #999
+ height: 36px
+ width: 18px
+ padding-left: 10px
+ padding-right: 10px
+
+ .search-icon
+ float: left
+
+ .popup-btn-close
+ border-left: 1px solid #eee
+ float: right
+ cursor: pointer
+
+ #no-result
+ position: absolute
+ left: 50%
+ top: 50%
+ -webkit-transform: translate(-50%, -50%)
+ transform: translate(-50%, -50%)
+ color: #ccc
diff --git a/source/css/_common/components/third-party/needsharebutton.styl b/source/css/_common/components/third-party/needsharebutton.styl
new file mode 100644
index 000000000..2caae446f
--- /dev/null
+++ b/source/css/_common/components/third-party/needsharebutton.styl
@@ -0,0 +1,27 @@
+#needsharebutton-postbottom {
+ position: relative;
+ cursor: pointer;
+ height: 26px;
+
+ .btn {
+ display: initial;
+ padding: 1px 4px;
+ border: 1px solid $btn-default-border-color;
+ border-radius: 3px;
+ }
+}
+
+#needsharebutton-float {
+ position: fixed;
+ bottom: 38px;
+ left: -8px;
+ z-index: 9999;
+ cursor: pointer;
+
+ .btn {
+ //display: initial;
+ padding: 0 10px 0 14px
+ border: 1px solid $btn-default-border-color;
+ border-radius: 4px;
+ }
+}
diff --git a/source/css/_common/components/third-party/related-posts.styl b/source/css/_common/components/third-party/related-posts.styl
new file mode 100644
index 000000000..7c1e6c4bd
--- /dev/null
+++ b/source/css/_common/components/third-party/related-posts.styl
@@ -0,0 +1,22 @@
+.popular-posts-header {
+ margin-top: $post-eof-margin-bottom;
+ margin-bottom: 10px;
+ font-size: $font-size-headings-base;
+ border-bottom: 1px solid $gainsboro;
+ display: block;
+}
+
+ul.popular-posts {
+ padding: 0;
+
+ .popular-posts-item {
+ // list-style: none;
+ margin-left: 2em;
+ .popular-posts-title {
+ font-weight: normal;
+ font-size: $font-size-base;
+ margin: 0;
+ line-height: $line-height-base * 1.2;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/css/_common/components/third-party/third-party.styl b/source/css/_common/components/third-party/third-party.styl
new file mode 100644
index 000000000..0896976b1
--- /dev/null
+++ b/source/css/_common/components/third-party/third-party.styl
@@ -0,0 +1,9 @@
+@import "gitment" if hexo-config('gitment.enable');
+@import "jiathis";
+@import "han";
+@import "baidushare";
+@import "localsearch";
+@import "busuanzi-counter";
+@import "algolia-search" if hexo-config('algolia_search.enable');
+@import "needsharebutton" if hexo-config('needmoreshare2.enable');
+@import "related-posts" if hexo-config('related_posts.enable');
diff --git a/source/css/_common/outline/outline.styl b/source/css/_common/outline/outline.styl
new file mode 100644
index 000000000..7337e1823
--- /dev/null
+++ b/source/css/_common/outline/outline.styl
@@ -0,0 +1,58 @@
+//
+// Layout
+// Note: Must name this file "outline" instead of "layout"
+// Or Hexo will use it as template layout.
+// =================================================
+
+
+html, body { height: 100%; }
+
+.container {
+ position: relative;
+ min-height: 100%;
+}
+
+
+// Header Section
+// --------------------------------------------------
+.header-inner {
+ margin: 0 auto;
+ padding: 100px 0 70px;
+ width: $content-desktop;
+
+ +desktop-large() {
+ .container & { width: $content-desktop-large; }
+ }
+}
+
+// Main Section
+// --------------------------------------------------
+.main { padding-bottom: $footer-height + $gap-between-main-and-footer; }
+.main-inner {
+ margin: 0 auto;
+ width: $content-desktop;
+
+ +desktop-large() {
+ .container & { width: $content-desktop-large; }
+ }
+}
+
+
+// Footer Section
+// --------------------------------------------------
+.footer {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ min-height: $footer-height;
+}
+.footer-inner {
+ box-sizing: border-box;
+ margin: 20px auto;
+ width: $content-desktop;
+
+ +desktop-large() {
+ .container & { width: $content-desktop-large; }
+ }
+}
diff --git a/source/css/_common/scaffolding/base.styl b/source/css/_common/scaffolding/base.styl
new file mode 100644
index 000000000..378182618
--- /dev/null
+++ b/source/css/_common/scaffolding/base.styl
@@ -0,0 +1,111 @@
+
+::selection {
+ background: $selection-bg;
+ color: $selection-color;
+}
+
+body {
+ position: relative; // Required by scrollspy
+ font-family: $font-family-base;
+ font-size: $font-size-base;
+ line-height: $line-height-base;
+ color: $text-color;
+ background: $body-bg-color;
+
+ +mobile() { padding-right: 0 !important; }
+ +tablet() { padding-right: 0 !important; }
+ +desktop-large() { font-size: $font-size-large; }
+}
+
+h1, h2, h3, h4, h5, h6 {
+ margin: 0;
+ padding: 0;
+ font-weight: bold;
+ line-height: 1.5;
+ font-family: $font-family-headings;
+}
+
+h1, h2, h3, h4, h5, h6 { margin: 20px 0 15px; }
+
+for headline in (1..6) {
+ h{headline} {
+ font-size: $font-size-headings-base - $font-size-headings-step * headline;
+ }
+
+ +mobile() {
+ h{headline} {
+ font-size: $font-size-headings-base - $font-size-headings-step * headline - 4px;
+ }
+ }
+}
+
+p { margin: 0 0 20px 0; }
+
+a {
+ color: $link-color;
+ text-decoration: none;
+ outline: none;
+ border-bottom: 1px solid $grey-dark;
+ word-wrap: break-word;
+
+ &:hover {
+ color: $link-hover-color;
+ border-bottom-color: $link-decoration-hover-color;
+ }
+}
+
+blockquote {
+ margin: 0;
+ padding: 0;
+}
+
+img {
+ display: block;
+ margin: auto;
+ max-width: 100%;
+ height: auto;
+}
+
+
+hr {
+ margin: 40px 0;
+ height: 3px;
+ border: none;
+ background-color: $gray-lighter;
+ background-image: repeating-linear-gradient(
+ -45deg,
+ white,
+ white 4px,
+ transparent 4px,
+ transparent 8px
+ );
+}
+
+blockquote {
+ padding: 0 15px;
+ color: $grey-dim;
+ border-left: 4px solid $gray-lighter;
+
+ cite::before {
+ content: "-";
+ padding: 0 5px;
+ }
+}
+
+dt { font-weight: $font-weight-bolder; }
+
+dd {
+ margin: 0;
+ padding: 0;
+}
+
+kbd {
+ border: 1px solid $grey-light;
+ border-radius: 0.2em;
+ box-shadow: 0.1em 0.1em 0.2em rgba(0,0,0,0.1);
+ background-color: #f9f9f9;
+ font-family: inherit;
+ background-image: -webkit-linear-gradient(top, #eee, white, #eee);
+ padding: 0.1em 0.3em;
+ white-space: nowrap;
+}
diff --git a/source/css/_common/scaffolding/helpers.styl b/source/css/_common/scaffolding/helpers.styl
new file mode 100644
index 000000000..a00d0bb4f
--- /dev/null
+++ b/source/css/_common/scaffolding/helpers.styl
@@ -0,0 +1,67 @@
+//
+// Helpers
+// =================================================
+
+
+
+// Alignment
+.text-left { text-align: left; }
+.text-center { text-align: center; }
+.text-right { text-align: right; }
+.text-justify { text-align: justify; }
+.text-nowrap { white-space: nowrap; }
+
+
+// Transformation
+.text-lowercase { text-transform: lowercase; }
+.text-uppercase { text-transform: uppercase; }
+.text-capitalize { text-transform: capitalize; }
+
+
+// Center-align a block level element.
+.center-block {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+
+// Clearfix. http://nicolasgallagher.com/micro-clearfix-hack/
+.clearfix {
+ clearfix();
+}
+
+.pullquote {
+ width: 45%;
+
+ &.left {
+ float: left;
+ margin-left: 5px;
+ margin-right: 10px;
+ }
+
+ &.right {
+ float: right;
+ margin-left: 10px;
+ margin-right: 5px;
+ }
+}
+
+.affix.affix.affix { position: fixed; }
+
+.translation {
+ margin-top: -20px;
+ font-size: 14px;
+ color: $grey-dark;
+}
+
+// https://davidwalsh.name/detect-scrollbar-width
+.scrollbar-measure {
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+ position: absolute;
+ top: -9999px;
+}
+
+.use-motion .motion-element { opacity: 0; }
diff --git a/source/css/_common/scaffolding/mobile.styl b/source/css/_common/scaffolding/mobile.styl
new file mode 100644
index 000000000..191fbfdaa
--- /dev/null
+++ b/source/css/_common/scaffolding/mobile.styl
@@ -0,0 +1,121 @@
+/*
+// > 1600px
++desktop-large() {
+
+}
+
+// > 992px
++desktop() {
+
+}
+
+// > 768px & < 991px
++tablet() {
+
+}
+
+
+// < 767px
++mobile() {
+
+}
+*/
+
+// < 567px
++mobile-small() {
+
+ // For Muse & Mist schemes only vertical economy.
+ .header-inner {
+ margin-bottom: initial !important;
+ }
+ .main-inner {
+ margin-top: initial !important;
+ }
+
+ // For Pisces & Gemini schemes only wider width (remove main blocks in Gemini).
+ .content-wrap {
+ padding: initial !important;
+ }
+
+ // For all schemes wider width.
+ .posts-expand {
+ padding-top: $content-mobile-padding !important;
+ // For Muse & Mist & Pisces schemes only wider width.
+ margin: initial !important;
+
+ .post-header {
+ padding: 0 18px;
+ }
+
+ .post-meta {
+ margin: 3px 0 10px 0 !important;
+ }
+
+ }
+
+ .post-block {
+ // Inside posts blocks content padding (default 40px).
+ padding: $content-mobile-padding 0 !important;
+ }
+
+ .post-body {
+ // For headers narrow width.
+ h2, h3, h4, h5, h6 {
+ margin: 10px 18px 8px;
+ }
+ // Rewrite paddings & margins inside tags.
+ .note, .tabs .tab-content .tab-pane {
+ h2, h3, h4, h5, h6 {
+ margin: 0 5px;
+ }
+ }
+
+ // For paragraphs narrow width.
+ p {
+ margin: 0 0 10px 0;
+ padding: 0 18px;
+ }
+
+ // Rewrite paddings & margins inside tags.
+ .note > p, .tabs .tab-content .tab-pane > p {
+ padding: 0 5px;
+ }
+
+ .video-container .fluid-vids {
+ margin-bottom: 10px !important;
+ }
+
+ .note {
+ padding: 10px !important;
+ margin-bottom: 10px !important;
+
+ if hexo-config('note.icons') {
+ &:not(.no-icon) {
+ padding-left: 35px !important;
+ &:before {
+ top: 8px !important;
+ left: 12px !important;
+ }
+ }
+ }
+ }
+
+ .tabs .tab-content .tab-pane {
+ padding: 10px 10px 0 10px !important;
+ }
+ }
+
+ // Need to refactor into flex.
+ .post-nav {
+ padding-bottom: 2px;
+ //padding: 2px 8px;
+ }
+
+}
+
+/*
+// < 413px
++mobile-smallest() {
+
+}
+*/
diff --git a/source/css/_common/scaffolding/normalize.styl b/source/css/_common/scaffolding/normalize.styl
new file mode 100644
index 000000000..81c6f31ea
--- /dev/null
+++ b/source/css/_common/scaffolding/normalize.styl
@@ -0,0 +1,427 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
\ No newline at end of file
diff --git a/source/css/_common/scaffolding/scaffolding.styl b/source/css/_common/scaffolding/scaffolding.styl
new file mode 100644
index 000000000..b5d350025
--- /dev/null
+++ b/source/css/_common/scaffolding/scaffolding.styl
@@ -0,0 +1,9 @@
+//
+// Scaffolding
+// =================================================
+
+@import "normalize";
+@import "base";
+@import "helpers";
+@import "tables";
+@import "mobile" if hexo-config('mobile_layout_economy');
diff --git a/source/css/_common/scaffolding/tables.styl b/source/css/_common/scaffolding/tables.styl
new file mode 100644
index 000000000..03fdd6ec2
--- /dev/null
+++ b/source/css/_common/scaffolding/tables.styl
@@ -0,0 +1,32 @@
+table {
+ margin: 20px 0;
+ width: $table-width;
+ border-collapse: collapse;
+ border-spacing: 0;
+ border: 1px solid $table-border-color;
+ font-size: $table-font-size;
+ word-wrap: break-all;
+}
+table>tbody>tr {
+ &:nth-of-type(odd) { background-color: $table-row-odd-bg-color; }
+ &:hover { background-color: $table-row-hover-bg-color; }
+}
+
+caption, th, td {
+ padding: $table-cell-padding;
+ text-align: $table-content-alignment;
+ vertical-align: $table-content-vertical;
+ font-weight: normal;
+}
+
+th, td {
+ border-bottom: 3px solid $table-cell-border-bottom-color;
+ border-right: 1px solid $table-cell-border-right-color;
+}
+
+th {
+ padding-bottom: 10px;
+ font-weight: $table-th-font-weight;
+}
+
+td { border-bottom-width: 1px; }
diff --git a/source/css/_custom/custom.styl b/source/css/_custom/custom.styl
new file mode 100644
index 000000000..63937f7cf
--- /dev/null
+++ b/source/css/_custom/custom.styl
@@ -0,0 +1 @@
+// Custom styles.
diff --git a/source/css/_mixins/Gemini.styl b/source/css/_mixins/Gemini.styl
new file mode 100644
index 000000000..eb4102ee2
--- /dev/null
+++ b/source/css/_mixins/Gemini.styl
@@ -0,0 +1 @@
+@import "Pisces.styl";
diff --git a/source/css/_mixins/Mist.styl b/source/css/_mixins/Mist.styl
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/css/_mixins/Muse.styl b/source/css/_mixins/Muse.styl
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/css/_mixins/Pisces.styl b/source/css/_mixins/Pisces.styl
new file mode 100644
index 000000000..f44810c2f
--- /dev/null
+++ b/source/css/_mixins/Pisces.styl
@@ -0,0 +1,16 @@
+sidebar-inline-links-item() {
+ margin: 5px 0 0;
+ if !hexo-config('social_icons.icons_only') { width: 50%; }
+
+ & a, .exturl {
+ max-width: 216px;
+ box-sizing: border-box;
+ display: inline-block;
+ margin-right: 0;
+ margin-bottom: 0;
+ padding: 0 5px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+}
diff --git a/source/css/_mixins/base.styl b/source/css/_mixins/base.styl
new file mode 100644
index 000000000..bd5131956
--- /dev/null
+++ b/source/css/_mixins/base.styl
@@ -0,0 +1,98 @@
+the-transition() {
+ transition-duration: 0.2s;
+ transition-timing-function: ease-in-out;
+ transition-delay: 0s;
+}
+
+the-transition-ease-in() {
+ transition-duration: 0.2s;
+ transition-timing-function: ease-in;
+ transition-delay: 0s;
+}
+
+the-transition-ease-out() {
+ transition-duration: 0.2s;
+ transition-timing-function: ease-out;
+ transition-delay: 0s;
+}
+
+mobile-smallest() {
+ @media (max-width: 413px) {
+ {block}
+ }
+}
+
+mobile-small() {
+ @media (max-width: 567px) {
+ {block}
+ }
+}
+
+mobile() {
+ @media (max-width: 767px) {
+ {block}
+ }
+}
+
+tablet-mobile() {
+ @media (max-width: 991px) {
+ {block}
+ }
+}
+
+tablet() {
+ @media (min-width: 768px) and (max-width: 991px) {
+ {block}
+ }
+}
+
+desktop() {
+ @media (min-width: 992px) {
+ {block}
+ }
+}
+
+desktop-large() {
+ @media (min-width: 1600px) {
+ {block}
+ }
+}
+
+circle() {
+ border-radius: 50%;
+}
+
+transform() {
+ -webkit-transform: arguments
+ -moz-transform: arguments
+ -ms-transform: arguments
+ -o-transform: arguments
+ transform: arguments
+}
+
+hide() {
+ display: none !important;
+}
+
+show() {
+ display: block !important;
+}
+
+fixbutton() {
+ right: 20px;
+ opacity: 0.8;
+}
+
+random-color($min, $max) {
+ return floor(math(0, 'random') * ($max - $min + 1) + $min);
+}
+
+// Clearfix. http://nicolasgallagher.com/micro-clearfix-hack/
+clearfix() {
+ &:before,
+ &:after {
+ content: " ";
+ display: table;
+ }
+ &:after { clear: both; }
+}
diff --git a/source/css/_mixins/custom.styl b/source/css/_mixins/custom.styl
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/css/_schemes/Gemini/index.styl b/source/css/_schemes/Gemini/index.styl
new file mode 100644
index 000000000..68e08ace9
--- /dev/null
+++ b/source/css/_schemes/Gemini/index.styl
@@ -0,0 +1,274 @@
+@import "../Pisces/_layout";
+@import "../Pisces/_brand";
+@import "../Pisces/_menu";
+@import "../Pisces/_sub-menu";
+@import "../Pisces/_sidebar";
+// Import _posts if want to justify text-align on mobile.
+//@import "../Pisces/_posts";
+
+// =================================================
+// Rewrite _layout.styl
+// =================================================
+// Sidebar padding used as main desktop content padding for sidebar padding and post blocks padding too.
+
+// In main NexT config set `sidebar: offset: 12` option as main padding.
+// In `source/css/_variables/Gemini.styl` there are variables for other resolutions:
+// $content-tablet-paddin = 10px;
+// $content-mobile-padding = 8px;
+// P.S. If u want to change this paddings u may set this variables into `source/css/_variables/custom.styl`.
+
+// So, it will 12px in Desktop, 10px in Tablets and 8px in Mobiles for all possible paddings.
+// =================================================
+// Read values from NexT config and set they as local variables to use as string variables (in any CSS section).
+hexo-config('sidebar.offset') is a 'unit' ? (sboffset = unit(hexo-config('sidebar.offset'), px)) : (sboffset = 0)
+use_seo = hexo-config('seo');
+
+// Maximum content width.
+// =================================================
+$max-content-width = hexo-config('max_content_width')
+if $max-content-width {
+ .header,
+ .container .main-inner,
+ .footer-inner {
+ max-width: unquote($max-content-width);
+ }
+}
+
+// =================================================
+// Desktop layout styles.
+// =================================================
+// Post blocks.
+.content-wrap {
+ padding: initial;
+ background: initial;
+ box-shadow: initial;
+ border-radius: initial;
+}
+
+// Post & Comments blocks.
+.post-block {
+ padding: $content-desktop-padding;
+ background: white;
+ box-shadow: $box-shadow-inner;
+ border-radius: $border-radius-inner;
+}
+
+// When blocks are siblings (homepage).
+#posts > article + article {
+ .post-block {
+ margin-top: sboffset;
+ // Rewrite shadows & borders because all blocks have offsets.
+ box-shadow: $box-shadow;
+ border-radius: $border-radius;
+ }
+}
+
+// Comments blocks.
+.comments {
+ padding: $content-desktop-padding;
+ margin: initial;
+ margin-top: sboffset;
+ background: white;
+ box-shadow: $box-shadow;
+ border-radius: $border-radius;
+}
+
+// Top main padding from header to posts (default 40px).
+.posts-expand {
+ padding-top: initial;
+}
+
+// Post navigation items.
+.post-nav-divider {
+ width: 4%;
+}
+.post-nav-item {
+ width: 48%;
+}
+
+// Post delimiters.
+.post-eof,
+.post-spread {
+ hide();
+}
+
+// Pagination.
+.pagination {
+ .prev, .next, .page-number {
+ margin-bottom: initial;
+ top: initial;
+ }
+ margin: sboffset 0 0;
+ border-top: initial;
+ background: white;
+ box-shadow: $box-shadow;
+ border-radius: $border-radius;
+ padding: 10px 0 10px;
+}
+
+// Footer alignment.
+.main {
+ padding-bottom: initial;
+}
+.footer {
+ bottom: auto;
+}
+
+// Sub-menu(s).
+.sub-menu {
+ border-bottom: initial !important;
+ box-shadow: $box-shadow-inner;
+ // Adapt submenu(s) with post-blocks.
+ &+ #content > #posts {
+ .post-block {
+ box-shadow: $box-shadow;
+ margin-top: sboffset;
+ +tablet() {
+ margin-top: $content-tablet-padding;
+ }
+ +mobile() {
+ margin-top: $content-mobile-padding;
+ }
+ }
+ }
+}
+
+// =================================================
+// Headers.
+// =================================================
+// No need anymore?
+.post-header {
+ h1, h2 {
+ margin: initial;
+ }
+}
+.posts-expand .post-title-link {
+ line-height: inherit;
+}
+.posts-expand .post-title {
+ font-size: 1.7em;
+}
+.post-body {
+ h1 {
+ font-size: 1.6em;
+ border-bottom: 1px solid $body-bg-color;
+ }
+ h2 {
+ font-size: 1.45em;
+ border-bottom: 1px solid $body-bg-color;
+ }
+ h3 {
+ font-size: 1.3em;
+ if use_seo {
+ border-bottom: 1px solid $body-bg-color;
+ } else {
+ border-bottom: 1px dotted $body-bg-color;
+ }
+ }
+ h4 {
+ font-size: 1.2em;
+ if use_seo {
+ border-bottom: 1px dotted $body-bg-color;
+ }
+ }
+ h5 {
+ font-size: 1.07em;
+ }
+ h6 {
+ font-size: 1.03em;
+ }
+}
+
+// =================================================
+// > 768px & < 991px
+// =================================================
++tablet() {
+
+ // Posts in blocks.
+ .content-wrap {
+ padding: $content-tablet-padding;
+ }
+ .posts-expand {
+ margin: initial;
+
+ // Components inside Posts.
+ .post-button {
+ margin-top: ($content-tablet-padding * 2);
+ }
+ }
+
+ .post-block {
+ // Inside posts blocks content padding (default 40px).
+ padding: ($content-tablet-padding * 2);
+ // Rewrite shadows & borders because all blocks have offsets.
+ box-shadow: $box-shadow;
+ border-radius: $border-radius;
+ }
+
+ // Only if blocks are siblings need bottom margin (homepage).
+ #posts > article + article {
+ .post-block {
+ margin-top: $content-tablet-padding;
+ }
+ }
+
+ .comments {
+ margin-top: $content-tablet-padding;
+ padding: $content-tablet-padding ($content-tablet-padding * 2);
+ //padding: initial;
+ //padding-top: $content-tablet-padding;
+ }
+
+ .pagination {
+ margin: $content-tablet-padding 0 0;
+ }
+
+}
+// =================================================
+// < 767px
+// =================================================
++mobile() {
+
+ // Posts in blocks.
+ .content-wrap {
+ padding: $content-mobile-padding;
+ }
+ .posts-expand {
+ margin: initial;
+
+ // Components inside Posts.
+ .post-button {
+ margin-top: sboffset;
+ //padding-bottom : 15px;
+ }
+ img {
+ padding: initial !important;
+ }
+ }
+
+ .post-block {
+ // Inside posts blocks content padding (default 40px).
+ padding: sboffset;
+ min-height: auto;
+ // Rewrite shadows & borders because all blocks have offsets.
+ box-shadow: $box-shadow;
+ border-radius: $border-radius;
+ }
+
+ // Only if blocks are siblings need bottom margin (homepage).
+ #posts > article + article {
+ .post-block {
+ margin-top: $content-mobile-padding;
+ }
+ }
+
+ .comments {
+ margin-top: $content-mobile-padding;
+ padding: 0 sboffset;
+ }
+
+ .pagination {
+ margin: $content-mobile-padding 0 0;
+ }
+
+}
diff --git a/source/css/_schemes/Mist/_base.styl b/source/css/_schemes/Mist/_base.styl
new file mode 100644
index 000000000..cf2f438fc
--- /dev/null
+++ b/source/css/_schemes/Mist/_base.styl
@@ -0,0 +1,9 @@
+// Tags
+// --------------------------------------------------
+
+a { border-bottom-color: $grey-light; }
+
+hr {
+ margin: 20px 0;
+ height: 2px;
+}
diff --git a/source/css/_schemes/Mist/_header.styl b/source/css/_schemes/Mist/_header.styl
new file mode 100644
index 000000000..a19164907
--- /dev/null
+++ b/source/css/_schemes/Mist/_header.styl
@@ -0,0 +1,63 @@
+// Header
+// --------------------------------------------------
+.header { background: $whitesmoke; }
+.header-inner {
+ padding: 25px 0 20px;
+ clearfix();
+
+ +mobile() {
+ width: auto;
+ margin-bottom: 50px;
+ padding: 10px;
+ }
+}
+
+.site-meta {
+ float: left;
+ margin-left: -20px;
+ line-height: normal;
+
+ +mobile() {
+ margin-left: 10px;
+ }
+
+ .brand {
+ padding: 2px 1px;
+ background: none;
+
+ +mobile() { display: block; }
+ }
+
+ .logo { display: none; }
+
+ .site-title {
+ font-size: 22px;
+ font-weight: bolder;
+
+ +mobile() { line-height: 34px; }
+ }
+}
+
+
+.logo-line-before,
+.logo-line-after {
+ display: block;
+ overflow: hidden;
+ margin: 0 auto;
+ width: 75%;
+
+ +mobile() { display: none; }
+
+ i {
+ position: relative;
+ display: block;
+ height: 2px;
+ background: $black-deep;
+ +mobile() { height: 3px; }
+ }
+}
+
+.use-motion {
+ .logo-line-before i { left: -100%; }
+ .logo-line-after i { right: -100%; }
+}
diff --git a/source/css/_schemes/Mist/_logo.styl b/source/css/_schemes/Mist/_logo.styl
new file mode 100644
index 000000000..571b40707
--- /dev/null
+++ b/source/css/_schemes/Mist/_logo.styl
@@ -0,0 +1 @@
+.site-subtitle { display: none; }
diff --git a/source/css/_schemes/Mist/_menu.styl b/source/css/_schemes/Mist/_menu.styl
new file mode 100644
index 000000000..bdf27a954
--- /dev/null
+++ b/source/css/_schemes/Mist/_menu.styl
@@ -0,0 +1,67 @@
+// Menu
+// --------------------------------------------------
+.site-nav-toggle {
+ position: static;
+ float: right;
+}
+
+.menu {
+ //float: right;
+ margin: 8px 0 0 0;
+
+ +mobile() {
+ margin: 20px 0 0 0;
+ padding: 0;
+ }
+
+ br { display: none; }
+
+ .menu-item {
+ margin: 0;
+ +mobile() { display: block; }
+
+ .badge {
+ display: inline-block;
+ padding: 1px 4px;
+ margin-left: 5px;
+ font-weight: 700;
+ line-height: 1;
+ color: $black-light;
+ text-align: center;
+ white-space: nowrap;
+ background-color: #fff;
+ border-radius: 10px;
+ text-shadow: 1px 1px 0px rgba(0,0,0,0.1);
+ +mobile() {
+ float: right;
+ margin: 0.35em 0 0 0;
+ }
+ }
+
+ }
+
+ .menu-item a {
+ padding: 0 10px;
+ border: none;
+ border-radius: 2px;
+ transition-property: background;
+
+ +mobile() {
+ text-align: left;
+ }
+
+ &:hover { background: #e1e1e1; }
+ }
+
+ a::before {
+ display: none;
+
+ +mobile() { display: block; }
+ }
+
+ +mobile() { float: none; }
+}
+
+.menu-item-active a {
+ @extend .menu .menu-item a:hover;
+}
diff --git a/source/css/_schemes/Mist/_posts-expanded.styl b/source/css/_schemes/Mist/_posts-expanded.styl
new file mode 100644
index 000000000..af35e9631
--- /dev/null
+++ b/source/css/_schemes/Mist/_posts-expanded.styl
@@ -0,0 +1,67 @@
+// Post Expanded
+// --------------------------------------------------
+.posts-expand {
+ padding-top: 0;
+
+ .post-title,
+ .post-meta {
+ text-align: $site-meta-text-align;
+ +mobile() { text-align: center; }
+ }
+ .post-eof { display: none; }
+
+ .post { margin-top: 120px; }
+ .post:first-child { margin-top: 0; }
+
+ .post-meta {
+ margin-top: 5px;
+ margin-bottom: 20px;
+ }
+
+ .post-title {
+ position: relative;
+ font-size: $font-size-headings-base;
+ font-weight: 400;
+ +mobile() { font-size: $font-size-headings-small; }
+ +desktop-large() { font-size: $font-size-headings-large; }
+ }
+ .post-title:hover:before { background: $black-deep; }
+
+ .post-body {
+ +mobile() { font-size: $font-size-base; }
+ }
+
+ .post-body img { margin: 0; }
+
+ .post-tags {
+ text-align: left;
+ a {
+ padding: 1px 5px;
+ background: $whitesmoke;
+ border-bottom: none;
+ }
+ a:hover { background: $grey-light; }
+ }
+ .post-nav { margin-top: 40px; }
+}
+
+.post-button {
+ margin-top: 20px;
+ text-align: left;
+
+ a {
+ padding: 0;
+ font-size: $font-size-base;
+ //color: $grey-dim;
+ background: none;
+ border: none;
+ border-bottom: 2px solid $grey-dim;
+ transition-property: border;
+
+ +mobile() { font-size: $font-size-small; }
+ +desktop-large() { font-size: $font-size-large; }
+
+
+ &:hover { border-bottom-color: $black-deep; }
+ }
+}
diff --git a/source/css/_schemes/Mist/_search.styl b/source/css/_schemes/Mist/_search.styl
new file mode 100644
index 000000000..6cd7b2c96
--- /dev/null
+++ b/source/css/_schemes/Mist/_search.styl
@@ -0,0 +1,5 @@
+// Search
+// --------------------------------------------------
+.site-search form {
+ display: none;
+}
\ No newline at end of file
diff --git a/source/css/_schemes/Mist/index.styl b/source/css/_schemes/Mist/index.styl
new file mode 100644
index 000000000..bb2f4c50a
--- /dev/null
+++ b/source/css/_schemes/Mist/index.styl
@@ -0,0 +1,92 @@
+//
+// Mist scheme
+// =================================================
+
+@import "_base";
+@import "outline/outline";
+@import "_header";
+@import "_logo";
+@import "_menu";
+@import "_search.styl";
+@import "_posts-expanded";
+@import "sidebar/sidebar-blogroll";
+// Import _posts if want to justify text-align on mobile.
+// @import "../Pisces/_posts";
+
+// Components
+// --------------------------------------------------
+.btn {
+ padding: 0 10px;
+ border-width: 2px;
+ border-radius: 0;
+}
+
+.headband { display: none; }
+
+
+// Search
+// --------------------------------------------------
+.site-search {
+ position: relative;
+ float: right;
+ margin-top: 5px;
+ padding-top: 3px;
+
+ +mobile() {
+ float: none;
+ padding: 0 10px;
+ }
+}
+
+
+// Page - Container
+// --------------------------------------------------
+.container .main-inner {
+ +mobile() { width: auto; }
+}
+
+
+// Page - Post details
+// --------------------------------------------------
+.page-post-detail {
+ .post-title,
+ .post-meta { text-align: center; }
+
+ .post-title:before { display: none; }
+
+ .post-meta { margin-bottom: 60px; }
+}
+
+
+// Pagination
+// --------------------------------------------------
+.pagination {
+ margin: 120px 0 0;
+ text-align: left;
+
+ +mobile() {
+ margin: 80px 10px 0;
+ text-align: center;
+ }
+}
+
+// Footer
+// --------------------------------------------------
+.footer {
+ margin-top: 80px;
+ padding: 10px 0;
+ background: $whitesmoke;
+ color: $grey-dim;
+}
+.footer-inner {
+ margin: 0 auto;
+ text-align: left;
+
+ +mobile() {
+ width: auto;
+ text-align: center;
+ }
+}
+
+// Helpers
+// --------------------------------------------------
diff --git a/source/css/_schemes/Mist/outline/outline.styl b/source/css/_schemes/Mist/outline/outline.styl
new file mode 100644
index 000000000..12c0bae25
--- /dev/null
+++ b/source/css/_schemes/Mist/outline/outline.styl
@@ -0,0 +1 @@
+.main-inner { margin-top: 80px; }
diff --git a/source/css/_schemes/Mist/sidebar/sidebar-blogroll.styl b/source/css/_schemes/Mist/sidebar/sidebar-blogroll.styl
new file mode 100644
index 000000000..6db1ed79b
--- /dev/null
+++ b/source/css/_schemes/Mist/sidebar/sidebar-blogroll.styl
@@ -0,0 +1 @@
+.links-of-blogroll-inline .links-of-blogroll-item { display: inline-block; }
diff --git a/source/css/_schemes/Muse/_layout.styl b/source/css/_schemes/Muse/_layout.styl
new file mode 100644
index 000000000..010747229
--- /dev/null
+++ b/source/css/_schemes/Muse/_layout.styl
@@ -0,0 +1,9 @@
+.header-inner, .container .main-inner, .footer-inner {
+ +mobile() { width: auto; }
+}
+
+// embed tag
+embed {
+ display: block;
+ margin: 0px auto 25px auto;
+}
diff --git a/source/css/_schemes/Muse/_logo.styl b/source/css/_schemes/Muse/_logo.styl
new file mode 100644
index 000000000..1d0437aef
--- /dev/null
+++ b/source/css/_schemes/Muse/_logo.styl
@@ -0,0 +1,21 @@
+.custom-logo {
+ .site-meta-headline { text-align: center; }
+
+ .brand { background: none; }
+
+ .site-title {
+ margin: 10px auto 0;
+ font-size: 24px;
+ color: $black-deep;
+ a { border: none; }
+ }
+
+
+}
+
+.custom-logo-image {
+ margin: 0 auto;
+ padding: 5px;
+ max-width: 150px;
+ background: white;
+}
diff --git a/source/css/_schemes/Muse/_menu.styl b/source/css/_schemes/Muse/_menu.styl
new file mode 100644
index 000000000..16dbee194
--- /dev/null
+++ b/source/css/_schemes/Muse/_menu.styl
@@ -0,0 +1,60 @@
+.site-nav {
+ +mobile() {
+ position: absolute;
+ left: 0;
+ top: 52px;
+ margin: 0;
+ width: 100%;
+ padding: 0;
+ background: white;
+ border-bottom: 1px solid $gray-lighter;
+ z-index: $zindex-3;
+ }
+}
+
+.menu {
+ +mobile() { text-align: left; }
+}
+.menu .menu-item {
+ +mobile() {
+ display: block;
+ margin: 0 10px;
+ vertical-align: top;
+ }
+
+ .badge {
+ display: inline-block;
+ padding: 1px 4px;
+ margin-left: 5px;
+ font-weight: 700;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ background-color: $gainsboro;
+ +mobile() {
+ float: right;
+ margin: 0.35em 0 0 0;
+ }
+ }
+
+ br {
+ +mobile() { display: none; }
+ }
+
+ a {
+ +mobile() {
+ padding: 5px 10px;
+ border-bottom-color: white !important;
+ }
+ }
+ .fa { margin-right: 0; }
+}
+
+.menu-item-active a {
+ border-bottom-color: $menu-link-hover-border !important;
+ color: $black-deep;
+
+ +mobile() {
+ border-bottom-color: white !important;
+ }
+}
diff --git a/source/css/_schemes/Muse/_search.styl b/source/css/_schemes/Muse/_search.styl
new file mode 100644
index 000000000..6cd7b2c96
--- /dev/null
+++ b/source/css/_schemes/Muse/_search.styl
@@ -0,0 +1,5 @@
+// Search
+// --------------------------------------------------
+.site-search form {
+ display: none;
+}
\ No newline at end of file
diff --git a/source/css/_schemes/Muse/index.styl b/source/css/_schemes/Muse/index.styl
new file mode 100644
index 000000000..292106497
--- /dev/null
+++ b/source/css/_schemes/Muse/index.styl
@@ -0,0 +1,7 @@
+@import "_layout.styl";
+@import "_logo.styl";
+@import "_menu.styl";
+@import "_search.styl";
+@import "sidebar/sidebar-blogroll";
+// Import _posts if want to justify text-align on mobile.
+// @import "../Pisces/_posts";
diff --git a/source/css/_schemes/Muse/sidebar/sidebar-blogroll.styl b/source/css/_schemes/Muse/sidebar/sidebar-blogroll.styl
new file mode 100644
index 000000000..6db1ed79b
--- /dev/null
+++ b/source/css/_schemes/Muse/sidebar/sidebar-blogroll.styl
@@ -0,0 +1 @@
+.links-of-blogroll-inline .links-of-blogroll-item { display: inline-block; }
diff --git a/source/css/_schemes/Pisces/_brand.styl b/source/css/_schemes/Pisces/_brand.styl
new file mode 100644
index 000000000..c85ee8f50
--- /dev/null
+++ b/source/css/_schemes/Pisces/_brand.styl
@@ -0,0 +1,30 @@
+.site-brand-wrapper {
+ position: relative;
+}
+
+.site-meta {
+ padding: 20px 0;
+ color: white;
+ background: $black-deep;
+
+ +tablet() {
+ box-shadow: 0 0 16px rgba(0,0,0,0.5);
+ }
+ +mobile() {
+ box-shadow: 0 0 16px rgba(0,0,0,0.5);
+ }
+}
+
+.brand {
+ padding: 0;
+ background: none;
+
+ &:hover { color: white; }
+}
+
+.site-subtitle {
+ margin: 10px 10px 0;
+ font-weight: initial;
+}
+
+.site-search form { display: none; }
diff --git a/source/css/_schemes/Pisces/_layout.styl b/source/css/_schemes/Pisces/_layout.styl
new file mode 100644
index 000000000..a3a2b5223
--- /dev/null
+++ b/source/css/_schemes/Pisces/_layout.styl
@@ -0,0 +1,130 @@
+.header {
+ position: relative;
+ margin: 0 auto;
+ width: $main-desktop;
+
+ +tablet() {
+ width: auto;
+ }
+ +mobile() {
+ width: auto;
+ }
+}
+
+.header-inner {
+ position: absolute;
+ top: 0;
+ overflow: hidden;
+ padding: 0;
+ width: $sidebar-desktop;
+ background: white;
+ box-shadow: $box-shadow-inner;
+ border-radius: $border-radius-inner;
+
+ +desktop-large() {
+ .container & { width: $sidebar-desktop; }
+ }
+ +tablet() {
+ position: relative;
+ width: auto;
+ border-radius: initial;
+ }
+ +mobile() {
+ position: relative;
+ width: auto;
+ border-radius: initial;
+ }
+}
+
+.main {
+ clearfix();
+ +tablet() {
+ padding-bottom: 100px;
+ }
+ +mobile() {
+ padding-bottom: 100px;
+ }
+}
+
+.container .main-inner {
+ width: $main-desktop;
+
+ +tablet() {
+ width: auto;
+ }
+ +mobile() {
+ width: auto;
+ }
+}
+
+.content-wrap {
+ float: right;
+ box-sizing: border-box;
+ padding: $content-desktop-padding;
+ width: $content-desktop;
+ background: white;
+ min-height: 700px;
+ box-shadow: $box-shadow-inner;
+ border-radius: $border-radius-inner;
+
+ +tablet() {
+ width: 100%;
+ padding: 20px;
+ border-radius: initial;
+ }
+ +mobile() {
+ width: 100%;
+ padding: 20px;
+ min-height: auto;
+ border-radius: initial;
+ }
+}
+
+.sidebar {
+ position: static;
+ float: left;
+ margin-top: 300px;
+ width: $sidebar-desktop;
+ background: $body-bg-color;
+ box-shadow: none;
+
+ +tablet() {
+ display: none;
+ }
+ +mobile() {
+ display: none;
+ }
+}
+
+.sidebar-toggle { display: none; }
+
+
+.footer-inner {
+ width: $main-desktop;
+ padding-left: 260px;
+
+ +tablet() {
+ width: auto;
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+ }
+ +mobile() {
+ width: auto;
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+ }
+}
+
+
+
+.sidebar-position-right {
+ .header-inner { right: 0; }
+ .content-wrap { float: left; }
+ .sidebar { float: right; }
+
+ .footer-inner {
+ padding-left: 0;
+ padding-right: 260px;
+ }
+}
+
diff --git a/source/css/_schemes/Pisces/_menu.styl b/source/css/_schemes/Pisces/_menu.styl
new file mode 100644
index 000000000..e740c1c3c
--- /dev/null
+++ b/source/css/_schemes/Pisces/_menu.styl
@@ -0,0 +1,87 @@
+.site-nav {
+ border-top: none;
+
+ +tablet() {
+ display: none !important;
+ }
+}
+
+.site-nav-on {
+ +tablet() {
+ display: block !important;
+ }
+}
+
+.menu .menu-item {
+ display: block;
+ margin: 0;
+
+ a {
+ position: relative;
+ box-sizing: border-box;
+ padding: 5px 20px;
+ text-align: left;
+ line-height: inherit;
+ transition-property: background-color;
+ the-transition();
+
+ &:hover {
+ background: #f9f9f9;
+ border-bottom-color: white;
+ }
+ }
+
+ .badge {
+ display: inline-block;
+ padding: 2px 5px;
+ font-weight: 700;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ background-color: $grey-light;
+ border-radius: 10px;
+ float: right;
+ margin: 0.35em 0 0 0;
+ text-shadow: 1px 1px 0px rgba(0,0,0,0.1);
+ }
+
+ br { display: none; }
+}
+
+.menu-item-active a {
+ @extend .menu .menu-item a:hover;
+
+ badges = hexo-config('menu_settings.badges');
+ if not badges {
+ &:after {
+ content: " ";
+ position: absolute;
+ top: 50%;
+ margin-top: -3px;
+ right: 15px;
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background-color: $grey;
+ }
+ }
+
+}
+
+.btn-bar {
+ background-color: white;
+}
+
+.site-nav-toggle {
+ left: 20px;
+ top: 50%;
+
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+
+ +tablet() {
+ display: block;
+ }
+}
diff --git a/source/css/_schemes/Pisces/_posts.styl b/source/css/_schemes/Pisces/_posts.styl
new file mode 100644
index 000000000..498409d9c
--- /dev/null
+++ b/source/css/_schemes/Pisces/_posts.styl
@@ -0,0 +1,5 @@
+.post-body {
+ +mobile() {
+ text-align: justify;
+ }
+}
diff --git a/source/css/_schemes/Pisces/_sidebar.styl b/source/css/_schemes/Pisces/_sidebar.styl
new file mode 100644
index 000000000..9ced48649
--- /dev/null
+++ b/source/css/_schemes/Pisces/_sidebar.styl
@@ -0,0 +1,129 @@
+.use-motion .sidebar .motion-element { opacity: 1; }
+
+.sidebar {
+ margin-left: -100%;
+ right: auto;
+ bottom: auto;
+
+ // Do NOT delete this line
+ // or Affix (position: fixed) will not work in Google Chrome.
+ -webkit-transform: none;
+}
+
+
+.sidebar-inner {
+//padding: 20px 10px 0;
+ box-sizing: border-box;
+ width: $sidebar-desktop;
+ color: $text-color;
+ background: white;
+ box-shadow: $box-shadow;
+ border-radius: $border-radius;
+ if (hexo-config('motion.enable') and hexo-config('motion.transition.sidebar')) { opacity: 0; }
+
+ &.affix {
+ position: fixed;
+ top: $sidebar-offset;
+ }
+
+ &.affix-bottom {
+ position: absolute;
+ }
+
+}
+
+.site-overview {
+ //margin: 0 2px;
+ text-align: left;
+}
+
+.site-author {
+ clearfix();
+}
+
+.sidebar a,
+.sidebar .exturl {
+ color: $black-light;
+
+ &:hover { color: $black-deep; }
+}
+
+.site-state-item {
+ padding: 0 10px;
+}
+
+.links-of-author-item {
+ a:before, .exturl:before { display: none; }
+ a, .exturl {
+ border-bottom: none;
+ text-decoration: underline;
+ }
+}
+
+.feed-link {
+ border-top: 1px dotted $grey-light;
+ border-bottom: 1px dotted $grey-light;
+ text-align: center;
+}
+
+.feed-link a {
+ display: block;
+ color: $orange;
+ border: none;
+
+ &:hover {
+ background: none;
+ color: darken($orange, 20%);
+
+ i { color: darken($orange, 20%); }
+ }
+}
+
+.links-of-author {
+ //clearfix();
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+
+ .exturl {
+ font-size: 13px;
+ }
+}
+.links-of-author-item {
+ sidebar-inline-links-item();
+
+ a, .exturl {
+ display: block;
+ text-decoration: none;
+
+ &:hover {
+ border-radius: 4px;
+ background: $gainsboro;
+ }
+ }
+
+ .fa {
+ margin-right: 2px;
+ font-size: 16px;
+ }
+ .fa-globe { font-size: 15px; }
+}
+
+
+.links-of-blogroll {
+ text-align: center;
+ margin-top: 20px;
+ padding: 3px 0 0;
+ border-top: 1px dotted $grey-light;
+}
+.links-of-blogroll-title { margin-top: 0; }
+.links-of-blogroll-item { padding: 0; }
+.links-of-blogroll-inline {
+ clearfix();
+
+ .links-of-blogroll-item {
+ sidebar-inline-links-item();
+ display: inline-block;
+ if !hexo-config('social_icons.icons_only') { width: unset; }
+ }
+}
diff --git a/source/css/_schemes/Pisces/_sub-menu.styl b/source/css/_schemes/Pisces/_sub-menu.styl
new file mode 100644
index 000000000..5d580f36a
--- /dev/null
+++ b/source/css/_schemes/Pisces/_sub-menu.styl
@@ -0,0 +1,38 @@
+.sub-menu {
+ margin: 0;
+ padding: 6px 0;
+ background: #fff !important;
+ border-bottom: 1px solid $table-border-color;
+}
+
+.sub-menu .menu-item {
+ display: inline-block !important;
+
+ & a {
+ padding: initial !important;
+ margin: 5px 10px;
+ }
+
+ & a:hover {
+ background: initial !important;
+ color: $sidebar-highlight;
+ }
+}
+
+.sub-menu .menu-item-active a {
+ background: #fff !important;
+ color: $sidebar-highlight;
+ border-bottom-color: $sidebar-highlight;
+
+ &:hover {
+ background: #fff !important;
+ border-bottom-color: $sidebar-highlight;
+ }
+
+ badges = hexo-config('menu_settings.badges');
+ if not badges {
+ &:after {
+ content: initial;
+ }
+ }
+}
diff --git a/source/css/_schemes/Pisces/index.styl b/source/css/_schemes/Pisces/index.styl
new file mode 100644
index 000000000..0e3f37d84
--- /dev/null
+++ b/source/css/_schemes/Pisces/index.styl
@@ -0,0 +1,6 @@
+@import "_layout";
+@import "_brand";
+@import "_menu";
+@import "_sub-menu";
+@import "_sidebar";
+@import "_posts";
diff --git a/source/css/_variables/Gemini.styl b/source/css/_variables/Gemini.styl
new file mode 100644
index 000000000..04e14ef75
--- /dev/null
+++ b/source/css/_variables/Gemini.styl
@@ -0,0 +1,22 @@
+// Variables of Gemini scheme
+// =================================================
+
+@import "Pisces.styl";
+
+// Settings for some of the most global styles.
+// --------------------------------------------------
+$body-bg-color = #eee
+$main-desktop = 75%
+$sidebar-width = hexo-config('sidebar_width') is a 'unit' ? hexo-config('sidebar_width') : 240
+$sidebar-desktop = unit($sidebar-width, 'px')
+$content-desktop = 'calc(100% - %s)' % unit($sidebar-width + 12, 'px')
+
+// Borders.
+// --------------------------------------------------
+$box-shadow-inner = 0 2px 2px 0 rgba(0,0,0,.12), 0 3px 1px -2px rgba(0,0,0,.06), 0 1px 5px 0 rgba(0,0,0,.12)
+$box-shadow = 0 2px 2px 0 rgba(0,0,0,.12), 0 3px 1px -2px rgba(0,0,0,.06), 0 1px 5px 0 rgba(0,0,0,.12), 0 -1px .5px 0 rgba(0,0,0,.09)
+
+$border-radius-inner = initial
+$border-radius = initial
+//$border-radius-inner = 0 0 3px 3px;
+//$border-radius = 3px;
diff --git a/source/css/_variables/Mist.styl b/source/css/_variables/Mist.styl
new file mode 100644
index 000000000..8ead36ee0
--- /dev/null
+++ b/source/css/_variables/Mist.styl
@@ -0,0 +1,13 @@
+// Variables of Mist scheme
+// =================================================
+
+$font-size-headings-base = 26px
+
+$brand-color = $black-deep
+$brand-hover-color = $brand-color
+
+$site-meta-text-align = left
+$posts-collapse-left = 0
+
+$btn-default-color = $link-color
+$btn-default-bg = transparent
diff --git a/source/css/_variables/Muse.styl b/source/css/_variables/Muse.styl
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/css/_variables/Pisces.styl b/source/css/_variables/Pisces.styl
new file mode 100644
index 000000000..3abb40938
--- /dev/null
+++ b/source/css/_variables/Pisces.styl
@@ -0,0 +1,77 @@
+// Variables of Pisces scheme
+// =================================================
+
+// Settings for some of the most global styles.
+// --------------------------------------------------
+$body-bg-color = #f5f7f9
+
+
+// Borders
+// --------------------------------------------------
+$box-shadow-inner = initial;
+$box-shadow = initial;
+
+$border-radius-inner = initial;
+$border-radius = initial;
+
+
+// Header
+// --------------------------------------------------
+$subtitle-color = $gray-lighter
+
+// Sidebar
+// --------------------------------------------------
+$sidebar-offset = unit(hexo-config('sidebar.offset'), px) if hexo-config('sidebar.offset') is a 'unit'
+
+$sidebar-nav-hover-color = $orange
+$sidebar-highlight = $orange
+
+$site-author-image-width = 120px
+$site-author-image-border-width = 1px
+$site-author-image-border-color = $gainsboro
+
+$site-author-name-margin = 0
+$site-author-name-color = $black-deep
+$site-author-name-align = center
+$site-author-name-weight = $font-weight-bold
+
+$site-description-font-size = 13px
+$site-description-color = $grey-dark
+$site-description-margin-top = 0
+$site-description-align = center
+
+$site-state-item-count-font-size = 16px
+$site-state-item-name-font-size = 13px
+$site-state-item-name-color = $grey-dark
+$site-state-item-border-color = $gainsboro
+
+$toc-link-color = $grey-dim
+$toc-link-border-color = $grey-light
+$toc-link-hover-color = black
+$toc-link-hover-border-color = black
+$toc-link-active-color = $sidebar-highlight
+$toc-link-active-border-color = $sidebar-highlight
+$toc-link-active-current-color = $sidebar-highlight
+$toc-link-active-current-border-color = $sidebar-highlight
+
+
+// Components
+// --------------------------------------------------
+
+// Button
+$btn-default-radius = 2px
+$btn-default-bg = white
+$btn-default-color = $text-color
+$btn-default-border-color = $text-color
+$btn-default-hover-color = white
+$btn-default-hover-bg = $black-deep
+
+// Full Image Tag
+//$full-image-width = 118%
+//$full-image-margin-horizontal = -9%
+//$full-image-margin-vertical = 0
+
+// Back to top
+$b2t-opacity = .6
+$b2t-position-bottom = -100px
+$b2t-position-bottom-on = 30px
diff --git a/source/css/_variables/base.styl b/source/css/_variables/base.styl
new file mode 100644
index 000000000..0deda9c28
--- /dev/null
+++ b/source/css/_variables/base.styl
@@ -0,0 +1,416 @@
+//
+// Variables
+// =================================================
+
+
+
+// Colors
+// colors for use across theme.
+// --------------------------------------------------
+
+$whitesmoke = #f5f5f5
+$gainsboro = #eee
+$gray-lighter = #ddd
+$grey-light = #ccc
+$grey = #bbb
+$grey-dark = #999
+$grey-dim = #666
+$black-light = #555
+$black-dim = #333
+$black-deep = #222
+$red = #ff2a2a
+$blue-bright = #87daff
+$blue = #0684bd
+$blue-deep = #262a30
+$orange = #fc6423
+
+
+
+// Scaffolding
+// Settings for some of the most global styles.
+// --------------------------------------------------
+
+// Global text color on
+$text-color = $black-light
+
+// Global link color.
+$link-color = $black-light
+$link-hover-color = $black-deep
+$link-decoration-color = $grey-light
+$link-decoration-hover-color = $black-deep
+
+// Global border color.
+$border-color = $grey-light
+
+// Background color for
+$body-bg-color = white
+
+// Selection
+$selection-bg = $blue-deep
+$selection-color = white
+
+
+
+// Typography
+// Font, line-height, and elements colors.
+// --------------------------------------------------
+
+
+get_font_family(config) {
+ custom_family = hexo-config('font.' + config + '.family')
+ return custom_family is a 'string' ? custom_family : null
+}
+
+// Font families.
+$font-family-chinese = "PingFang SC", "Microsoft YaHei"
+
+$font-family-base = $font-family-chinese, sans-serif
+$font-family-base = get_font_family('global'), $font-family-chinese, sans-serif if get_font_family('global')
+
+$font-family-logo = $font-family-base
+$font-family-logo = get_font_family('logo'), $font-family-base if get_font_family('logo')
+
+$font-family-headings = $font-family-base
+$font-family-headings = get_font_family('headings'), $font-family-base if get_font_family('headings')
+
+$font-family-posts = $font-family-base
+$font-family-posts = get_font_family('posts'), $font-family-base if get_font_family('posts')
+
+$font-family-monospace = consolas, Menlo, $font-family-chinese, monospace
+$font-family-monospace = get_font_family('codes'), consolas, Menlo, $font-family-chinese, monospace if get_font_family('codes')
+
+$font-family-icons = 'FontAwesome'
+
+
+// Font Weight
+$font-weight-lighter = 200
+$font-weight-light = 300
+$font-weight-normal = 400
+$font-weight-bold = 600
+$font-weight-bolder = 700
+
+
+// Font size
+$font-size-base = 14px
+$font-size-base = unit(hexo-config('font.global.size'), px) if hexo-config('font.global.size') is a 'unit'
+$font-size-small = $font-size-base - 2px
+$font-size-smaller = $font-size-base - 4px
+$font-size-large = $font-size-base + 2px
+$font-size-larger = $font-size-base + 4px
+
+
+// Headings font size
+$font-size-headings-step = 2px
+$font-size-headings-base = 24px
+$font-size-headings-base = unit(hexo-config('font.headings.size'), px) if hexo-config('font.headings.size') is a 'unit'
+$font-size-headings-small = $font-size-headings-base - $font-size-headings-step
+$font-size-headings-smaller = $font-size-headings-small - $font-size-headings-step
+$font-size-headings-large = $font-size-headings-base + $font-size-headings-step
+$font-size-headings-larger = $font-size-headings-large + $font-size-headings-step
+
+// Global line height
+$line-height-base = 2
+$line-height-code-block = 1.6 // Can't be less than 1.3
+
+
+
+// Z-index master list
+// --------------------------------------------------
+$zindex-bottom = -1
+$zindex-1 = 1010
+$zindex-2 = 1020
+$zindex-3 = 1030
+$zindex-4 = 1040
+$zindex-5 = 1050
+
+
+
+// Table
+// --------------------------------------------------
+$table-width = 100%
+$table-border-color = $gray-lighter
+$table-font-size = 14px
+$table-content-alignment = left
+$table-content-vertical = middle
+$table-th-font-weight = 700
+$table-cell-padding = 8px
+$table-cell-border-right-color = $gainsboro
+$table-cell-border-bottom-color = $gray-lighter
+$table-row-odd-bg-color = #f9f9f9
+$table-row-hover-bg-color = $whitesmoke
+
+
+
+// Code & Code Blocks
+// --------------------------------------------------
+$code-font-family = $font-family-monospace
+$code-font-size = 14px
+$code-font-size = unit(hexo-config('font.codes.size'), px) if hexo-config('font.codes.size') is a 'unit'
+$code-border-radius = 3px
+$code-foreground = $black-light
+$code-background = $gainsboro
+
+
+
+// Buttons
+// --------------------------------------------------
+
+$btn-font-weight = normal
+
+$btn-default-radius = 0
+$btn-default-bg = $black-deep
+$btn-default-color = white
+$btn-default-font-size = 14px
+$btn-default-border-width = 2px
+$btn-default-border-color = $black-deep
+$btn-default-hover-bg = white
+$btn-default-hover-color = $black-deep
+$btn-default-hover-border-color = $black-deep
+
+
+
+// Pagination
+// --------------------------------------------------
+
+$pagination-border = $gainsboro
+
+$pagination-link-bg = transparent
+$pagination-link-color = $link-color
+$pagination-link-border = $gainsboro
+
+$pagination-link-hover-bg = transparent
+$pagination-link-hover-color = $link-color
+$pagination-link-hover-border = $black-deep
+
+$pagination-active-bg = $grey-light
+$pagination-active-color = white
+$pagination-active-border = $grey-light
+
+
+
+// Layout sizes
+// --------------------------------------------------
+
+$main-desktop = 960px
+$main-desktop-large = 1200px
+
+$content-desktop = 700px
+$content-desktop-large = 900px
+
+$content-desktop-padding = 40px
+$content-tablet-padding = 10px
+$content-mobile-padding = 8px
+
+$sidebar-desktop = 240px
+
+$footer-height = 50px
+
+$gap-between-main-and-footer = 100px
+
+
+
+// Headband
+// --------------------------------------------------
+$headband-height = 3px
+$headband-bg = $black-deep
+
+
+
+// Section Header
+// Variables for header section elements.
+// --------------------------------------------------
+
+$head-bg = transparent
+
+// Site Meta
+$site-meta-text-align = center
+$brand-color = white
+$brand-hover-color = white
+$brand-bg = $black-deep
+
+$logo-font-size = 20px
+$logo-font-size = unit(hexo-config('font.logo.size'), px) if hexo-config('font.logo.size') is a 'unit'
+
+$site-subtitle-color = $grey-dark
+$subtitle-font-size = 13px
+$subtitle-color = $grey-dark
+
+// Menu
+$menu-link-border = transparent
+$menu-link-hover-border = $black-deep
+
+
+
+// Posts Expand
+// --------------------------------------------------
+$posts-expand-title-font-weight = $font-weight-normal
+$post-copyright = {
+ margin: 2em 0 0,
+ padding: .5em 1em,
+ bg: #f9f9f9,
+ border: {
+ width: 3px,
+ style: solid,
+ color: #ff1700
+ }
+}
+
+
+// Posts Collpase
+// --------------------------------------------------
+$posts-collapse-left = 55px
+$posts-collapse-left-mobile = 5px
+
+
+// Sidebar
+// Variables for sidebar section elements.
+// --------------------------------------------------
+$sidebar-nav-color = $black-light
+$sidebar-nav-hover-color = $whitesmoke
+$sidebar-highlight = $blue-bright
+
+$site-author-image-padding = 2px
+$site-author-image-width = 96px
+$site-author-image-height = auto
+$site-author-image-border-width = 2px
+$site-author-image-border-color = $black-dim
+
+$site-author-name-margin = 5px 0 0
+$site-author-name-color = $whitesmoke
+$site-author-name-align = center
+$site-author-name-weight = normal
+
+$site-description-font-size = 14px
+$site-description-color = $grey-dark
+$site-description-margin-top = 5px
+$site-description-align = center
+
+$site-state-align = center
+$site-state-item-count-font-size = 18px
+$site-state-item-count-color = inherit
+$site-state-item-name-font-size = 13px
+$site-state-item-name-color = inherit
+$site-state-item-border-color = $black-dim
+
+$toc-link-color = $grey-dark
+$toc-link-border-color = $black-light
+$toc-link-hover-color = $grey-light
+$toc-link-hover-border-color = $grey-light
+$toc-link-active-color = $sidebar-highlight
+$toc-link-active-border-color = $sidebar-highlight
+$toc-link-active-current-color = $sidebar-highlight
+$toc-link-active-current-border-color = $sidebar-highlight
+
+
+// Components
+// --------------------------------------------------
+
+// Back to top
+$b2t-opacity = 1
+$b2t-position-bottom = -100px
+$b2t-position-bottom-on = 19px
+$b2t-position-right = 30px
+$b2t-font-size = 12px
+$b2t-color = white
+$b2t-bg-color = $black-deep
+
+// full-image
+//$full-image-width = 110%
+//$full-image-margin-horizontal = -5%
+//$full-image-margin-vertical = 25px
+
+// .post-expand .post-eof
+// In Muse scheme, margin above and below the post separator
+$post-eof-margin-top = 80px // or 160px for more white space
+$post-eof-margin-bottom = 60px // or 120px for less white space
+
+
+// Iconography
+// Icons SVG Base64
+// --------------------------------------------------
+
+// blockquote-center icon
+$center-quote-left = '../images/quote-l.svg'
+$center-quote-right = '../images/quote-r.svg'
+
+
+// Note colors
+// --------------------------------------------------
+// Read note light_bg_offset from NexT config and set in "lbg%" to use it as string variable.
+hexo-config('note.light_bg_offset') is a 'unit' ? (lbg = unit(hexo-config('note.light_bg_offset'),"%")) : (lbg = 0)
+
+// Default
+$note-default-border = #777
+$note-default-bg = lighten(spin($note-default-border, 0), 94% + lbg)
+$note-default-text = $note-default-border
+$note-default-icon = "\f0a9"
+
+$note-modern-default-border = #e1e1e1
+$note-modern-default-bg = lighten(spin($note-modern-default-border, 10), 60% + (lbg * 4))
+$note-modern-default-text = $grey-dim
+$note-modern-default-hover = darken(spin($note-modern-default-text, -10), 32%)
+
+// Primary
+$note-primary-border = #6f42c1
+$note-primary-bg = lighten(spin($note-primary-border, 10), 92% + lbg)
+$note-primary-text = $note-primary-border
+$note-primary-icon = "\f055"
+
+$note-modern-primary-border = #e1c2ff
+$note-modern-primary-bg = lighten(spin($note-modern-primary-border, 10), 40% + (lbg * 4))
+$note-modern-primary-text = #6f42c1
+$note-modern-primary-hover = darken(spin($note-modern-primary-text, -10), 22%)
+
+// Info
+$note-info-border = #428bca
+$note-info-bg = lighten(spin($note-info-border, -10), 91% + lbg)
+$note-info-text = $note-info-border
+$note-info-icon = "\f05a"
+
+$note-modern-info-border = #b3e5ef
+$note-modern-info-bg = lighten(spin($note-modern-info-border, 10), 50% + (lbg * 4))
+$note-modern-info-text = #31708f
+$note-modern-info-hover = darken(spin($note-modern-info-text, -10), 32%)
+
+// Success
+$note-success-border = #5cb85c
+$note-success-bg = lighten(spin($note-success-border, 10), 90% + lbg)
+$note-success-text = $note-success-border
+$note-success-icon = "\f058"
+
+$note-modern-success-border = #d0e6be
+$note-modern-success-bg = lighten(spin($note-modern-success-border, 10), 40% + (lbg * 4))
+$note-modern-success-text = #3c763d
+$note-modern-success-hover = darken(spin($note-modern-success-text, -10), 27%)
+
+// Warning
+$note-warning-border = #f0ad4e
+$note-warning-bg = lighten(spin($note-warning-border, 10), 88% + lbg)
+$note-warning-text = $note-warning-border
+$note-warning-icon = "\f06a"
+
+$note-modern-warning-border = #fae4cd
+$note-modern-warning-bg = lighten(spin($note-modern-warning-border, 10), 43% + (lbg * 4))
+$note-modern-warning-text = #8a6d3b
+$note-modern-warning-hover = darken(spin($note-modern-warning-text, -10), 18%)
+
+// Danger
+$note-danger-border = #d9534f
+$note-danger-bg = lighten(spin($note-danger-border, -10), 92% + lbg)
+$note-danger-text = $note-danger-border
+$note-danger-icon = "\f056"
+
+$note-modern-danger-border = #ebcdd2
+$note-modern-danger-bg = lighten(spin($note-modern-danger-border, 10), 35% + (lbg * 4))
+$note-modern-danger-text = #a94442
+$note-modern-danger-hover = darken(spin($note-modern-danger-text, -10), 22%)
+
+
+// Label colors
+// --------------------------------------------------
+$label-default = lighten(spin($note-default-border, 0), 89% + lbg)
+$label-primary = lighten(spin($note-primary-border, 10), 87% + lbg)
+$label-info = lighten(spin($note-info-border, -10), 86% + lbg)
+$label-success = lighten(spin($note-success-border, 10), 85% + lbg)
+$label-warning = lighten(spin($note-warning-border, 10), 83% + lbg)
+$label-danger = lighten(spin($note-danger-border, -10), 87% + lbg)
diff --git a/source/css/_variables/custom.styl b/source/css/_variables/custom.styl
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/css/main.styl b/source/css/main.styl
new file mode 100644
index 000000000..fdb13608d
--- /dev/null
+++ b/source/css/main.styl
@@ -0,0 +1,50 @@
+// CSS Style Guide: http://codeguide.co/#css
+
+
+
+$scheme = hexo-config('scheme') ? hexo-config('scheme') : 'Muse';
+
+$custom_styles = hexo-config('custom_file_path.styles') ? "../../../../../" + hexo-config('custom_file_path.styles') : custom;
+$custom_mixins = hexo-config('custom_file_path.mixins') ? "../../../../../" + hexo-config('custom_file_path.mixins') : custom;
+$custom_variables = hexo-config('custom_file_path.variables') ? "../../../../../" + hexo-config('custom_file_path.variables') : custom;
+
+$variables = base $scheme $custom_variables;
+$mixins = base $scheme $custom_mixins;
+
+
+
+// Variables Layer
+// --------------------------------------------------
+for $variable in $variables
+ @import "_variables/" + $variable;
+
+
+// Mixins Layer
+// --------------------------------------------------
+for $mixin in $mixins
+ @import "_mixins/" + $mixin;
+
+
+
+// Common Layer
+// --------------------------------------------------
+
+// Scaffolding
+@import "_common/scaffolding";
+
+// Layout
+@import "_common/outline";
+
+// Components
+@import "_common/components";
+
+
+// Schemes Layer
+// --------------------------------------------------
+@import "_schemes/" + $scheme;
+
+
+
+// Custom Layer
+// --------------------------------------------------
+@import "_custom/" + $custom_styles;
diff --git a/source/fonts/.gitkeep b/source/fonts/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/images/algolia_logo.svg b/source/images/algolia_logo.svg
new file mode 100644
index 000000000..470242341
--- /dev/null
+++ b/source/images/algolia_logo.svg
@@ -0,0 +1,9 @@
+
diff --git a/source/images/apple-touch-icon-next.png b/source/images/apple-touch-icon-next.png
new file mode 100644
index 000000000..86a0d1d33
Binary files /dev/null and b/source/images/apple-touch-icon-next.png differ
diff --git a/source/images/avatar.gif b/source/images/avatar.gif
new file mode 100644
index 000000000..989902574
Binary files /dev/null and b/source/images/avatar.gif differ
diff --git a/source/images/cc-by-nc-nd.svg b/source/images/cc-by-nc-nd.svg
new file mode 100644
index 000000000..79a4f2e0d
--- /dev/null
+++ b/source/images/cc-by-nc-nd.svg
@@ -0,0 +1,121 @@
+
+
+
diff --git a/source/images/cc-by-nc-sa.svg b/source/images/cc-by-nc-sa.svg
new file mode 100644
index 000000000..bf6bc26f5
--- /dev/null
+++ b/source/images/cc-by-nc-sa.svg
@@ -0,0 +1,121 @@
+
+
+
diff --git a/source/images/cc-by-nc.svg b/source/images/cc-by-nc.svg
new file mode 100644
index 000000000..36973490a
--- /dev/null
+++ b/source/images/cc-by-nc.svg
@@ -0,0 +1,121 @@
+
+
+
diff --git a/source/images/cc-by-nd.svg b/source/images/cc-by-nd.svg
new file mode 100644
index 000000000..934c61e15
--- /dev/null
+++ b/source/images/cc-by-nd.svg
@@ -0,0 +1,117 @@
+
+
+
diff --git a/source/images/cc-by-sa.svg b/source/images/cc-by-sa.svg
new file mode 100644
index 000000000..463276a8c
--- /dev/null
+++ b/source/images/cc-by-sa.svg
@@ -0,0 +1,121 @@
+
+
+
diff --git a/source/images/cc-by.svg b/source/images/cc-by.svg
new file mode 100644
index 000000000..4bccd14f6
--- /dev/null
+++ b/source/images/cc-by.svg
@@ -0,0 +1,121 @@
+
+
+
diff --git a/source/images/cc-zero.svg b/source/images/cc-zero.svg
new file mode 100644
index 000000000..0f866392f
--- /dev/null
+++ b/source/images/cc-zero.svg
@@ -0,0 +1,72 @@
+
+
+
+
diff --git a/source/images/favicon-16x16-next.png b/source/images/favicon-16x16-next.png
new file mode 100644
index 000000000..de8c5d3a5
Binary files /dev/null and b/source/images/favicon-16x16-next.png differ
diff --git a/source/images/favicon-32x32-next.png b/source/images/favicon-32x32-next.png
new file mode 100644
index 000000000..e02f5f4d5
Binary files /dev/null and b/source/images/favicon-32x32-next.png differ
diff --git a/source/images/loading.gif b/source/images/loading.gif
new file mode 100644
index 000000000..efb6768db
Binary files /dev/null and b/source/images/loading.gif differ
diff --git a/source/images/logo.svg b/source/images/logo.svg
new file mode 100644
index 000000000..cbb3937ec
--- /dev/null
+++ b/source/images/logo.svg
@@ -0,0 +1,23 @@
+
+
diff --git a/source/images/placeholder.gif b/source/images/placeholder.gif
new file mode 100644
index 000000000..efb6768db
Binary files /dev/null and b/source/images/placeholder.gif differ
diff --git a/source/images/quote-l.svg b/source/images/quote-l.svg
new file mode 100644
index 000000000..6dd94a4a0
--- /dev/null
+++ b/source/images/quote-l.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/source/images/quote-r.svg b/source/images/quote-r.svg
new file mode 100644
index 000000000..312b64d71
--- /dev/null
+++ b/source/images/quote-r.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/source/images/searchicon.png b/source/images/searchicon.png
new file mode 100644
index 000000000..14a16cad3
Binary files /dev/null and b/source/images/searchicon.png differ
diff --git a/source/js/src/affix.js b/source/js/src/affix.js
new file mode 100644
index 000000000..11a3d39a0
--- /dev/null
+++ b/source/js/src/affix.js
@@ -0,0 +1,162 @@
+/* ========================================================================
+ * Bootstrap: affix.js v3.3.5
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // AFFIX CLASS DEFINITION
+ // ======================
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, Affix.DEFAULTS, options)
+
+ this.$target = $(this.options.target)
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
+
+ this.$element = $(element)
+ this.affixed = null
+ this.unpin = null
+ this.pinnedOffset = null
+
+ this.checkPosition()
+ }
+
+ Affix.VERSION = '3.3.5'
+
+ Affix.RESET = 'affix affix-top affix-bottom'
+
+ Affix.DEFAULTS = {
+ offset: 0,
+ target: window
+ }
+
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
+ Affix.prototype.getPinnedOffset = function () {
+ if (this.pinnedOffset) return this.pinnedOffset
+ this.$element.removeClass(Affix.RESET).addClass('affix')
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ return (this.pinnedOffset = position.top - scrollTop)
+ }
+
+ Affix.prototype.checkPositionWithEventLoop = function () {
+ setTimeout($.proxy(this.checkPosition, this), 1)
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var height = this.$element.height()
+ var offset = this.options.offset
+ var offsetTop = offset.top
+ var offsetBottom = offset.bottom
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
+
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
+
+ if (affix == 'bottom') {
+ this.$element.offset({
+ top: scrollHeight - height - offsetBottom
+ })
+ }
+ }
+
+
+ // AFFIX PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.affix')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.affix
+
+ $.fn.affix = Plugin
+ $.fn.affix.Constructor = Affix
+
+
+ // AFFIX NO CONFLICT
+ // =================
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ // AFFIX DATA-API
+ // ==============
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ var data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
+
+ Plugin.call($spy, data)
+ })
+ })
+
+}(jQuery);
diff --git a/source/js/src/algolia-search.js b/source/js/src/algolia-search.js
new file mode 100644
index 000000000..9787e2ac3
--- /dev/null
+++ b/source/js/src/algolia-search.js
@@ -0,0 +1,115 @@
+/* global instantsearch: true */
+/*jshint camelcase: false */
+
+$(document).ready(function () {
+ var algoliaSettings = CONFIG.algolia;
+ var isAlgoliaSettingsValid = algoliaSettings.applicationID &&
+ algoliaSettings.apiKey &&
+ algoliaSettings.indexName;
+
+ if (!isAlgoliaSettingsValid) {
+ window.console.error('Algolia Settings are invalid.');
+ return;
+ }
+
+ var search = instantsearch({
+ appId: algoliaSettings.applicationID,
+ apiKey: algoliaSettings.apiKey,
+ indexName: algoliaSettings.indexName,
+ searchFunction: function (helper) {
+ var searchInput = $('#algolia-search-input').find('input');
+
+ if (searchInput.val()) {
+ helper.search();
+ }
+ }
+ });
+
+ // Registering Widgets
+ [
+ instantsearch.widgets.searchBox({
+ container: '#algolia-search-input',
+ placeholder: algoliaSettings.labels.input_placeholder
+ }),
+
+ instantsearch.widgets.hits({
+ container: '#algolia-hits',
+ hitsPerPage: algoliaSettings.hits.per_page || 10,
+ templates: {
+ item: function (data) {
+ var link = data.permalink ? data.permalink : (CONFIG.root + data.path);
+ return (
+ '' +
+ data._highlightResult.title.value +
+ ''
+ );
+ },
+ empty: function (data) {
+ return (
+ '' +
+ algoliaSettings.labels.hits_empty.replace(/\$\{query}/, data.query) +
+ ''
+ );
+ }
+ },
+ cssClasses: {
+ item: 'algolia-hit-item'
+ }
+ }),
+
+ instantsearch.widgets.stats({
+ container: '#algolia-stats',
+ templates: {
+ body: function (data) {
+ var stats = algoliaSettings.labels.hits_stats
+ .replace(/\$\{hits}/, data.nbHits)
+ .replace(/\$\{time}/, data.processingTimeMS);
+ return (
+ stats +
+ '' +
+ ' ' +
+ '' +
+ '
'
+ );
+ }
+ }
+ }),
+
+ instantsearch.widgets.pagination({
+ container: '#algolia-pagination',
+ scrollTo: false,
+ showFirstLast: false,
+ labels: {
+ first: '',
+ last: '',
+ previous: '',
+ next: ''
+ },
+ cssClasses: {
+ root: 'pagination',
+ item: 'pagination-item',
+ link: 'page-number',
+ active: 'current',
+ disabled: 'disabled-item'
+ }
+ })
+ ].forEach(search.addWidget, search);
+
+ search.start();
+
+ $('.popup-trigger').on('click', function(e) {
+ e.stopPropagation();
+ $('body')
+ .append('')
+ .css('overflow', 'hidden');
+ $('.popup').toggle();
+ $('#algolia-search-input').find('input').focus();
+ });
+
+ $('.popup-btn-close').click(function(){
+ $('.popup').hide();
+ $('.algolia-pop-overlay').remove();
+ $('body').css('overflow', '');
+ });
+
+});
diff --git a/source/js/src/bootstrap.js b/source/js/src/bootstrap.js
new file mode 100644
index 000000000..e71de3504
--- /dev/null
+++ b/source/js/src/bootstrap.js
@@ -0,0 +1,53 @@
+/* global NexT: true */
+
+$(document).ready(function () {
+
+ $(document).trigger('bootstrap:before');
+
+ /**
+ * Register JS handlers by condition option.
+ * Need to add config option in Front-End at 'layout/_partials/head.swig' file.
+ */
+ CONFIG.fastclick && NexT.utils.isMobile() && window.FastClick.attach(document.body);
+ CONFIG.lazyload && NexT.utils.lazyLoadPostsImages();
+
+ NexT.utils.registerESCKeyEvent();
+
+ NexT.utils.registerBackToTop();
+
+ // Mobile top menu bar.
+ $('.site-nav-toggle button').on('click', function () {
+ var $siteNav = $('.site-nav');
+ var ON_CLASS_NAME = 'site-nav-on';
+ var isSiteNavOn = $siteNav.hasClass(ON_CLASS_NAME);
+ var animateAction = isSiteNavOn ? 'slideUp' : 'slideDown';
+ var animateCallback = isSiteNavOn ? 'removeClass' : 'addClass';
+
+ $siteNav.stop()[animateAction]('fast', function () {
+ $siteNav[animateCallback](ON_CLASS_NAME);
+ });
+ });
+
+ /**
+ * Register JS handlers by condition option.
+ * Need to add config option in Front-End at 'layout/_partials/head.swig' file.
+ */
+ CONFIG.fancybox && NexT.utils.wrapImageWithFancyBox();
+ CONFIG.tabs && NexT.utils.registerTabsTag();
+
+ NexT.utils.embeddedVideoTransformer();
+
+ // Define Motion Sequence.
+ NexT.motion.integrator
+ .add(NexT.motion.middleWares.logo)
+ .add(NexT.motion.middleWares.menu)
+ .add(NexT.motion.middleWares.postList)
+ .add(NexT.motion.middleWares.sidebar);
+
+ $(document).trigger('motion:before');
+
+ // Bootstrap Motion.
+ CONFIG.motion.enable && NexT.motion.integrator.bootstrap();
+
+ $(document).trigger('bootstrap:after');
+});
diff --git a/source/js/src/exturl.js b/source/js/src/exturl.js
new file mode 100644
index 000000000..b85062ad4
--- /dev/null
+++ b/source/js/src/exturl.js
@@ -0,0 +1,15 @@
+/* global NexT: true */
+
+$(document).ready(function () {
+
+ // Create Base64 Object
+ var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9+/=]/g,"");while(f>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/rn/g,"n");var t="";for(var n=0;n127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};
+
+ $('.exturl').on('click', function () {
+ var $exturl = $(this).attr('data-url');
+ var $decurl = Base64.decode($exturl);
+ window.open($decurl, '_blank');
+ return false;
+ });
+
+});
diff --git a/source/js/src/js.cookie.js b/source/js/src/js.cookie.js
new file mode 100644
index 000000000..c6c397583
--- /dev/null
+++ b/source/js/src/js.cookie.js
@@ -0,0 +1,165 @@
+/*!
+ * JavaScript Cookie v2.1.4
+ * https://github.com/js-cookie/js-cookie
+ *
+ * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
+ * Released under the MIT license
+ */
+;(function (factory) {
+ var registeredInModuleLoader = false;
+ if (typeof define === 'function' && define.amd) {
+ define(factory);
+ registeredInModuleLoader = true;
+ }
+ if (typeof exports === 'object') {
+ module.exports = factory();
+ registeredInModuleLoader = true;
+ }
+ if (!registeredInModuleLoader) {
+ var OldCookies = window.Cookies;
+ var api = window.Cookies = factory();
+ api.noConflict = function () {
+ window.Cookies = OldCookies;
+ return api;
+ };
+ }
+}(function () {
+ function extend () {
+ var i = 0;
+ var result = {};
+ for (; i < arguments.length; i++) {
+ var attributes = arguments[ i ];
+ for (var key in attributes) {
+ result[key] = attributes[key];
+ }
+ }
+ return result;
+ }
+
+ function init (converter) {
+ function api (key, value, attributes) {
+ var result;
+ if (typeof document === 'undefined') {
+ return;
+ }
+
+ // Write
+
+ if (arguments.length > 1) {
+ attributes = extend({
+ path: '/'
+ }, api.defaults, attributes);
+
+ if (typeof attributes.expires === 'number') {
+ var expires = new Date();
+ expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
+ attributes.expires = expires;
+ }
+
+ // We're using "expires" because "max-age" is not supported by IE
+ attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
+
+ try {
+ result = JSON.stringify(value);
+ if (/^[\{\[]/.test(result)) {
+ value = result;
+ }
+ } catch (e) {}
+
+ if (!converter.write) {
+ value = encodeURIComponent(String(value))
+ .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
+ } else {
+ value = converter.write(value, key);
+ }
+
+ key = encodeURIComponent(String(key));
+ key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
+ key = key.replace(/[\(\)]/g, escape);
+
+ var stringifiedAttributes = '';
+
+ for (var attributeName in attributes) {
+ if (!attributes[attributeName]) {
+ continue;
+ }
+ stringifiedAttributes += '; ' + attributeName;
+ if (attributes[attributeName] === true) {
+ continue;
+ }
+ stringifiedAttributes += '=' + attributes[attributeName];
+ }
+ return (document.cookie = key + '=' + value + stringifiedAttributes);
+ }
+
+ // Read
+
+ if (!key) {
+ result = {};
+ }
+
+ // To prevent the for loop in the first place assign an empty array
+ // in case there are no cookies at all. Also prevents odd result when
+ // calling "get()"
+ var cookies = document.cookie ? document.cookie.split('; ') : [];
+ var rdecode = /(%[0-9A-Z]{2})+/g;
+ var i = 0;
+
+ for (; i < cookies.length; i++) {
+ var parts = cookies[i].split('=');
+ var cookie = parts.slice(1).join('=');
+
+ if (cookie.charAt(0) === '"') {
+ cookie = cookie.slice(1, -1);
+ }
+
+ try {
+ var name = parts[0].replace(rdecode, decodeURIComponent);
+ cookie = converter.read ?
+ converter.read(cookie, name) : converter(cookie, name) ||
+ cookie.replace(rdecode, decodeURIComponent);
+
+ if (this.json) {
+ try {
+ cookie = JSON.parse(cookie);
+ } catch (e) {}
+ }
+
+ if (key === name) {
+ result = cookie;
+ break;
+ }
+
+ if (!key) {
+ result[name] = cookie;
+ }
+ } catch (e) {}
+ }
+
+ return result;
+ }
+
+ api.set = api;
+ api.get = function (key) {
+ return api.call(api, key);
+ };
+ api.getJSON = function () {
+ return api.apply({
+ json: true
+ }, [].slice.call(arguments));
+ };
+ api.defaults = {};
+
+ api.remove = function (key, attributes) {
+ api(key, '', extend(attributes, {
+ expires: -1
+ }));
+ };
+
+ api.withConverter = init;
+
+ return api;
+ }
+
+ return init(function () {});
+}));
diff --git a/source/js/src/motion.js b/source/js/src/motion.js
new file mode 100644
index 000000000..c6b72257f
--- /dev/null
+++ b/source/js/src/motion.js
@@ -0,0 +1,352 @@
+/* global NexT: true */
+
+$(document).ready(function () {
+ NexT.motion = {};
+
+ var sidebarToggleLines = {
+ lines: [],
+ push: function (line) {
+ this.lines.push(line);
+ },
+ init: function () {
+ this.lines.forEach(function (line) {
+ line.init();
+ });
+ },
+ arrow: function () {
+ this.lines.forEach(function (line) {
+ line.arrow();
+ });
+ },
+ close: function () {
+ this.lines.forEach(function (line) {
+ line.close();
+ });
+ }
+ };
+
+ function SidebarToggleLine(settings) {
+ this.el = $(settings.el);
+ this.status = $.extend({}, {
+ init: {
+ width: '100%',
+ opacity: 1,
+ left: 0,
+ rotateZ: 0,
+ top: 0
+ }
+ }, settings.status);
+ }
+
+ SidebarToggleLine.prototype.init = function () {
+ this.transform('init');
+ };
+ SidebarToggleLine.prototype.arrow = function () {
+ this.transform('arrow');
+ };
+ SidebarToggleLine.prototype.close = function () {
+ this.transform('close');
+ };
+ SidebarToggleLine.prototype.transform = function (status) {
+ this.el.velocity('stop').velocity(this.status[status]);
+ };
+
+ var sidebarToggleLine1st = new SidebarToggleLine({
+ el: '.sidebar-toggle-line-first',
+ status: {
+ arrow: {width: '50%', rotateZ: '-45deg', top: '2px'},
+ close: {width: '100%', rotateZ: '-45deg', top: '5px'}
+ }
+ });
+ var sidebarToggleLine2nd = new SidebarToggleLine({
+ el: '.sidebar-toggle-line-middle',
+ status: {
+ arrow: {width: '90%'},
+ close: {opacity: 0}
+ }
+ });
+ var sidebarToggleLine3rd = new SidebarToggleLine({
+ el: '.sidebar-toggle-line-last',
+ status: {
+ arrow: {width: '50%', rotateZ: '45deg', top: '-2px'},
+ close: {width: '100%', rotateZ: '45deg', top: '-5px'}
+ }
+ });
+
+ sidebarToggleLines.push(sidebarToggleLine1st);
+ sidebarToggleLines.push(sidebarToggleLine2nd);
+ sidebarToggleLines.push(sidebarToggleLine3rd);
+
+ var SIDEBAR_WIDTH = '320px';
+ var SIDEBAR_DISPLAY_DURATION = 200;
+ var xPos, yPos;
+
+ var sidebarToggleMotion = {
+ toggleEl: $('.sidebar-toggle'),
+ dimmerEl: $('#sidebar-dimmer'),
+ sidebarEl: $('.sidebar'),
+ isSidebarVisible: false,
+ init: function () {
+ this.toggleEl.on('click', this.clickHandler.bind(this));
+ this.dimmerEl.on('click', this.clickHandler.bind(this));
+ this.toggleEl.on('mouseenter', this.mouseEnterHandler.bind(this));
+ this.toggleEl.on('mouseleave', this.mouseLeaveHandler.bind(this));
+ this.sidebarEl.on('touchstart', this.touchstartHandler.bind(this));
+ this.sidebarEl.on('touchend', this.touchendHandler.bind(this));
+ this.sidebarEl.on('touchmove', function(e){e.preventDefault();});
+
+ $(document)
+ .on('sidebar.isShowing', function () {
+ NexT.utils.isDesktop() && $('body').velocity('stop').velocity(
+ {paddingRight: SIDEBAR_WIDTH},
+ SIDEBAR_DISPLAY_DURATION
+ );
+ })
+ .on('sidebar.isHiding', function () {
+ });
+ },
+ clickHandler: function () {
+ this.isSidebarVisible ? this.hideSidebar() : this.showSidebar();
+ this.isSidebarVisible = !this.isSidebarVisible;
+ },
+ mouseEnterHandler: function () {
+ if (this.isSidebarVisible) {
+ return;
+ }
+ sidebarToggleLines.arrow();
+ },
+ mouseLeaveHandler: function () {
+ if (this.isSidebarVisible) {
+ return;
+ }
+ sidebarToggleLines.init();
+ },
+ touchstartHandler: function(e) {
+ xPos = e.originalEvent.touches[0].clientX;
+ yPos = e.originalEvent.touches[0].clientY;
+ },
+ touchendHandler: function(e) {
+ var _xPos = e.originalEvent.changedTouches[0].clientX;
+ var _yPos = e.originalEvent.changedTouches[0].clientY;
+ if (_xPos-xPos > 30 && Math.abs(_yPos-yPos) < 20) {
+ this.clickHandler();
+ }
+ },
+ showSidebar: function () {
+ var self = this;
+
+ sidebarToggleLines.close();
+
+ this.sidebarEl.velocity('stop').velocity({
+ width: SIDEBAR_WIDTH
+ }, {
+ display: 'block',
+ duration: SIDEBAR_DISPLAY_DURATION,
+ begin: function () {
+ $('.sidebar .motion-element').velocity(
+ 'transition.slideRightIn',
+ {
+ stagger: 50,
+ drag: true,
+ complete: function () {
+ self.sidebarEl.trigger('sidebar.motion.complete');
+ }
+ }
+ );
+ },
+ complete: function () {
+ self.sidebarEl.addClass('sidebar-active');
+ self.sidebarEl.trigger('sidebar.didShow');
+ }
+ }
+ );
+
+ this.sidebarEl.trigger('sidebar.isShowing');
+ },
+ hideSidebar: function () {
+ NexT.utils.isDesktop() && $('body').velocity('stop').velocity({paddingRight: 0});
+ this.sidebarEl.find('.motion-element').velocity('stop').css('display', 'none');
+ this.sidebarEl.velocity('stop').velocity({width: 0}, {display: 'none'});
+
+ sidebarToggleLines.init();
+
+ this.sidebarEl.removeClass('sidebar-active');
+ this.sidebarEl.trigger('sidebar.isHiding');
+
+ // Prevent adding TOC to Overview if Overview was selected when close & open sidebar.
+ if (!!$('.post-toc-wrap')) {
+ if ($('.site-overview-wrap').css('display') === 'block') {
+ $('.post-toc-wrap').removeClass('motion-element');
+ } else {
+ $('.post-toc-wrap').addClass('motion-element');
+ }
+ }
+ }
+ };
+ sidebarToggleMotion.init();
+
+ NexT.motion.integrator = {
+ queue: [],
+ cursor: -1,
+ add: function (fn) {
+ this.queue.push(fn);
+ return this;
+ },
+ next: function () {
+ this.cursor++;
+ var fn = this.queue[this.cursor];
+ $.isFunction(fn) && fn(NexT.motion.integrator);
+ },
+ bootstrap: function () {
+ this.next();
+ }
+ };
+
+ NexT.motion.middleWares = {
+ logo: function (integrator) {
+ var sequence = [];
+ var $brand = $('.brand');
+ var $title = $('.site-title');
+ var $subtitle = $('.site-subtitle');
+ var $logoLineTop = $('.logo-line-before i');
+ var $logoLineBottom = $('.logo-line-after i');
+
+ $brand.length > 0 && sequence.push({
+ e: $brand,
+ p: {opacity: 1},
+ o: {duration: 200}
+ });
+
+ NexT.utils.isMist() && hasElement([$logoLineTop, $logoLineBottom]) &&
+ sequence.push(
+ getMistLineSettings($logoLineTop, '100%'),
+ getMistLineSettings($logoLineBottom, '-100%')
+ );
+
+ hasElement($title) && sequence.push({
+ e: $title,
+ p: {opacity: 1, top: 0},
+ o: { duration: 200 }
+ });
+
+ hasElement($subtitle) && sequence.push({
+ e: $subtitle,
+ p: {opacity: 1, top: 0},
+ o: {duration: 200}
+ });
+
+ if (CONFIG.motion.async) {
+ integrator.next();
+ }
+
+ if (sequence.length > 0) {
+ sequence[sequence.length - 1].o.complete = function () {
+ integrator.next();
+ };
+ $.Velocity.RunSequence(sequence);
+ } else {
+ integrator.next();
+ }
+
+
+ function getMistLineSettings (element, translateX) {
+ return {
+ e: $(element),
+ p: {translateX: translateX},
+ o: {
+ duration: 500,
+ sequenceQueue: false
+ }
+ };
+ }
+
+ /**
+ * Check if $elements exist.
+ * @param {jQuery|Array} $elements
+ * @returns {boolean}
+ */
+ function hasElement ($elements) {
+ $elements = Array.isArray($elements) ? $elements : [$elements];
+ return $elements.every(function ($element) {
+ return $element.length > 0;
+ });
+ }
+ },
+
+ menu: function (integrator) {
+
+ if (CONFIG.motion.async) {
+ integrator.next();
+ }
+
+ $('.menu-item').velocity('transition.slideDownIn', {
+ display: null,
+ duration: 200,
+ complete: function () {
+ integrator.next();
+ }
+ });
+ },
+
+ postList: function (integrator) {
+ //var $post = $('.post');
+ var $postBlock = $('.post-block, .pagination, .comments');
+ var $postBlockTransition = CONFIG.motion.transition.post_block;
+ var $postHeader = $('.post-header');
+ var $postHeaderTransition = CONFIG.motion.transition.post_header;
+ var $postBody = $('.post-body');
+ var $postBodyTransition = CONFIG.motion.transition.post_body;
+ var $collHeader = $('.collection-title, .archive-year');
+ var $collHeaderTransition = CONFIG.motion.transition.coll_header;
+ var $sidebarAffix = $('.sidebar-inner');
+ var $sidebarAffixTransition = CONFIG.motion.transition.sidebar;
+ var hasPost = $postBlock.length > 0;
+
+ hasPost ? postMotion() : integrator.next();
+
+ if (CONFIG.motion.async) {
+ integrator.next();
+ }
+
+ function postMotion () {
+ var postMotionOptions = window.postMotionOptions || {
+ stagger: 100,
+ drag: true
+ };
+ postMotionOptions.complete = function () {
+ // After motion complete need to remove transform from sidebar to let affix work on Pisces | Gemini.
+ if (CONFIG.motion.transition.sidebar && (NexT.utils.isPisces() || NexT.utils.isGemini())) {
+ $sidebarAffix.css({ 'transform': 'initial' });
+ }
+ integrator.next();
+ };
+
+ //$post.velocity('transition.slideDownIn', postMotionOptions);
+ if (CONFIG.motion.transition.post_block) {
+ $postBlock.velocity('transition.' + $postBlockTransition, postMotionOptions);
+ }
+ if (CONFIG.motion.transition.post_header) {
+ $postHeader.velocity('transition.' + $postHeaderTransition, postMotionOptions);
+ }
+ if (CONFIG.motion.transition.post_body) {
+ $postBody.velocity('transition.' + $postBodyTransition, postMotionOptions);
+ }
+ if (CONFIG.motion.transition.coll_header) {
+ $collHeader.velocity('transition.' + $collHeaderTransition, postMotionOptions);
+ }
+ // Only for Pisces | Gemini.
+ if (CONFIG.motion.transition.sidebar && (NexT.utils.isPisces() || NexT.utils.isGemini())) {
+ $sidebarAffix.velocity('transition.' + $sidebarAffixTransition, postMotionOptions);
+ }
+ }
+ },
+
+ sidebar: function (integrator) {
+ if (CONFIG.sidebar.display === 'always') {
+ NexT.utils.displaySidebar();
+ }
+ integrator.next();
+ }
+ };
+
+});
diff --git a/source/js/src/post-details.js b/source/js/src/post-details.js
new file mode 100644
index 000000000..bfb6e6b14
--- /dev/null
+++ b/source/js/src/post-details.js
@@ -0,0 +1,104 @@
+/* global NexT: true */
+
+$(document).ready(function () {
+
+ initScrollSpy();
+
+ function initScrollSpy () {
+ var tocSelector = '.post-toc';
+ var $tocElement = $(tocSelector);
+ var activeCurrentSelector = '.active-current';
+
+ $tocElement
+ .on('activate.bs.scrollspy', function () {
+ var $currentActiveElement = $(tocSelector + ' .active').last();
+
+ removeCurrentActiveClass();
+ $currentActiveElement.addClass('active-current');
+
+ // Scrolling to center active TOC element if TOC content is taller then viewport.
+ $tocElement.scrollTop($currentActiveElement.offset().top - $tocElement.offset().top + $tocElement.scrollTop() - ($tocElement.height() / 2));
+ })
+ .on('clear.bs.scrollspy', removeCurrentActiveClass);
+
+ $('body').scrollspy({ target: tocSelector });
+
+ function removeCurrentActiveClass () {
+ $(tocSelector + ' ' + activeCurrentSelector)
+ .removeClass(activeCurrentSelector.substring(1));
+ }
+ }
+
+});
+
+$(document).ready(function () {
+ var html = $('html');
+ var TAB_ANIMATE_DURATION = 200;
+ var hasVelocity = $.isFunction(html.velocity);
+
+ $('.sidebar-nav li').on('click', function () {
+ var item = $(this);
+ var activeTabClassName = 'sidebar-nav-active';
+ var activePanelClassName = 'sidebar-panel-active';
+ if (item.hasClass(activeTabClassName)) {
+ return;
+ }
+
+ var currentTarget = $('.' + activePanelClassName);
+ var target = $('.' + item.data('target'));
+
+ hasVelocity ?
+ currentTarget.velocity('transition.slideUpOut', TAB_ANIMATE_DURATION, function () {
+ target
+ .velocity('stop')
+ .velocity('transition.slideDownIn', TAB_ANIMATE_DURATION)
+ .addClass(activePanelClassName);
+ }) :
+ currentTarget.animate({ opacity: 0 }, TAB_ANIMATE_DURATION, function () {
+ currentTarget.hide();
+ target
+ .stop()
+ .css({'opacity': 0, 'display': 'block'})
+ .animate({ opacity: 1 }, TAB_ANIMATE_DURATION, function () {
+ currentTarget.removeClass(activePanelClassName);
+ target.addClass(activePanelClassName);
+ });
+ });
+
+ item.siblings().removeClass(activeTabClassName);
+ item.addClass(activeTabClassName);
+ });
+
+ // TOC item animation navigate & prevent #item selector in adress bar.
+ $('.post-toc a').on('click', function (e) {
+ e.preventDefault();
+ var targetSelector = NexT.utils.escapeSelector(this.getAttribute('href'));
+ var offset = $(targetSelector).offset().top;
+
+ hasVelocity ?
+ html.velocity('stop').velocity('scroll', {
+ offset: offset + 'px',
+ mobileHA: false
+ }) :
+ $('html, body').stop().animate({
+ scrollTop: offset
+ }, 500);
+ });
+
+ // Expand sidebar on post detail page by default, when post has a toc.
+ var $tocContent = $('.post-toc-content');
+ var display = CONFIG.page.sidebar;
+ if (typeof display !== 'boolean') {
+ // There's no definition sidebar in the page front-matter
+ var isSidebarCouldDisplay = CONFIG.sidebar.display === 'post' ||
+ CONFIG.sidebar.display === 'always';
+ var hasTOC = $tocContent.length > 0 && $tocContent.html().trim().length > 0;
+ display = isSidebarCouldDisplay && hasTOC;
+ }
+ if (display) {
+ CONFIG.motion.enable ?
+ (NexT.motion.middleWares.sidebar = function () {
+ NexT.utils.displaySidebar();
+ }) : NexT.utils.displaySidebar();
+ }
+});
diff --git a/source/js/src/schemes/pisces.js b/source/js/src/schemes/pisces.js
new file mode 100644
index 000000000..0e6e4267e
--- /dev/null
+++ b/source/js/src/schemes/pisces.js
@@ -0,0 +1,57 @@
+$(document).ready(function () {
+
+ var sidebarInner = $('.sidebar-inner');
+
+ initAffix();
+ resizeListener();
+
+ function initAffix () {
+ var headerOffset = getHeaderOffset(),
+ footerOffset = getFooterOffset(),
+ sidebarHeight = $('#sidebar').height() + NexT.utils.getSidebarb2tHeight(),
+ contentHeight = $('#content').height();
+
+ // Not affix if sidebar taller then content (to prevent bottom jumping).
+ if (headerOffset + sidebarHeight < contentHeight) {
+ sidebarInner.affix({
+ offset: {
+ top: headerOffset - CONFIG.sidebar.offset,
+ bottom: footerOffset
+ }
+ });
+ }
+
+ setSidebarMarginTop(headerOffset).css({ 'margin-left': 'initial' });
+ }
+
+ function resizeListener () {
+ var mql = window.matchMedia('(min-width: 991px)');
+ mql.addListener(function(e){
+ if(e.matches){
+ recalculateAffixPosition();
+ }
+ });
+ }
+
+ function getHeaderOffset () {
+ return $('.header-inner').height() + CONFIG.sidebar.offset;
+ }
+
+ function getFooterOffset () {
+ var footerInner = $('.footer-inner'),
+ footerMargin = footerInner.outerHeight(true) - footerInner.outerHeight(),
+ footerOffset = footerInner.outerHeight(true) + footerMargin;
+ return footerOffset;
+ }
+
+ function setSidebarMarginTop (headerOffset) {
+ return $('#sidebar').css({ 'margin-top': headerOffset });
+ }
+
+ function recalculateAffixPosition () {
+ $(window).off('.affix');
+ sidebarInner.removeData('bs.affix').removeClass('affix affix-top affix-bottom');
+ initAffix();
+ }
+
+});
diff --git a/source/js/src/scroll-cookie.js b/source/js/src/scroll-cookie.js
new file mode 100644
index 000000000..34ff200bd
--- /dev/null
+++ b/source/js/src/scroll-cookie.js
@@ -0,0 +1,23 @@
+$(document).ready(function() {
+
+ // Set relative link path (without domain)
+ var rpath = window.location.href.replace(window.location.origin, "");
+
+ // Write position in cookie
+ var timeout;
+ $(window).on("scroll", function() {
+ clearTimeout(timeout);
+ timeout = setTimeout(function () {
+ Cookies.set("scroll-cookie", ($(window).scrollTop() + "|" + rpath), { expires: 365, path: '' });
+ }, 250);
+ });
+
+ // Read position from cookie
+ if (Cookies.get("scroll-cookie") !== undefined) {
+ var cvalues = Cookies.get("scroll-cookie").split('|');
+ if (cvalues[1] == rpath) {
+ $(window).scrollTop(cvalues[0]);
+ }
+ }
+
+});
diff --git a/source/js/src/scrollspy.js b/source/js/src/scrollspy.js
new file mode 100644
index 000000000..f5c5c6cb8
--- /dev/null
+++ b/source/js/src/scrollspy.js
@@ -0,0 +1,182 @@
+/* ========================================================================
+* Bootstrap: scrollspy.js v3.3.2
+* http://getbootstrap.com/javascript/#scrollspy
+* ========================================================================
+* Copyright 2011-2015 Twitter, Inc.
+* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+* ======================================================================== */
+
+/**
+ * Custom by iissnan
+ *
+ * - Add a `clear.bs.scrollspy` event.
+ * - Esacpe targets selector.
+ */
+
+
++function ($) {
+ 'use strict';
+
+ // SCROLLSPY CLASS DEFINITION
+ // ==========================
+
+ function ScrollSpy(element, options) {
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
+ this.selector = (this.options.target || '') + ' .nav li > a'
+ this.offsets = []
+ this.targets = []
+ this.activeTarget = null
+ this.scrollHeight = 0
+
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.VERSION = '3.3.2'
+
+ ScrollSpy.DEFAULTS = {
+ offset: 10
+ }
+
+ ScrollSpy.prototype.getScrollHeight = function () {
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+ }
+
+ ScrollSpy.prototype.refresh = function () {
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
+
+ if (!$.isWindow(this.$scrollElement[0])) {
+ offsetMethod = 'position'
+ offsetBase = this.$scrollElement.scrollTop()
+ }
+
+ this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ var href = $el.data('target') || $el.attr('href')
+ var $href = /^#./.test(href) && $(NexT.utils.escapeSelector(href)) // Need to escape selector.
+
+ return ($href
+ && $href.length
+ && $href.is(':visible')
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
+ })
+
+
+ }
+
+ ScrollSpy.prototype.process = function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ var scrollHeight = this.getScrollHeight()
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
+ var offsets = this.offsets
+ var targets = this.targets
+ var activeTarget = this.activeTarget
+ var i
+
+ if (this.scrollHeight != scrollHeight) {
+ this.refresh()
+ }
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+ }
+
+ if (activeTarget && scrollTop < offsets[0]) {
+ $(this.selector).trigger('clear.bs.scrollspy') // Add a custom event.
+ this.activeTarget = null
+ return this.clear()
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+ && this.activate(targets[i])
+ }
+ }
+
+ ScrollSpy.prototype.activate = function (target) {
+ this.activeTarget = target
+
+ this.clear()
+
+ var selector = this.selector +
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
+
+ var active = $(selector)
+ .parents('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active
+ .closest('li.dropdown')
+ .addClass('active')
+ }
+
+ active.trigger('activate.bs.scrollspy')
+ }
+
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
+
+ // SCROLLSPY PLUGIN DEFINITION
+ // ===========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.scrollspy')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = Plugin
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+
+ // SCROLLSPY NO CONFLICT
+ // =====================
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ // SCROLLSPY DATA-API
+ // ==================
+
+ $(window).on('load.bs.scrollspy.data-api', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ Plugin.call($spy, $spy.data())
+ })
+ })
+
+}(jQuery);
diff --git a/source/js/src/utils.js b/source/js/src/utils.js
new file mode 100644
index 000000000..c68519f55
--- /dev/null
+++ b/source/js/src/utils.js
@@ -0,0 +1,329 @@
+/* global NexT: true */
+
+NexT.utils = NexT.$u = {
+ /**
+ * Wrap images with fancybox support.
+ */
+ wrapImageWithFancyBox: function () {
+ $('.content img')
+ .not('[hidden]')
+ .not('.group-picture img, .post-gallery img')
+ .each(function () {
+ var $image = $(this);
+ var imageTitle = $image.attr('title');
+ var $imageWrapLink = $image.parent('a');
+
+ if ($imageWrapLink.length < 1) {
+ var imageLink = ($image.attr('data-original')) ? this.getAttribute('data-original') : this.getAttribute('src');
+ $imageWrapLink = $image.wrap('').parent('a');
+ }
+
+ $imageWrapLink.addClass('fancybox fancybox.image');
+ $imageWrapLink.attr('rel', 'group');
+
+ if (imageTitle) {
+ $imageWrapLink.append(' ');
+
+ //make sure img title tag will show correctly in fancybox
+ $imageWrapLink.attr('title', imageTitle);
+ }
+ });
+
+ $('.fancybox').fancybox({
+ helpers: {
+ overlay: {
+ locked: false
+ }
+ }
+ });
+ },
+
+ lazyLoadPostsImages: function () {
+ $('#posts').find('img').lazyload({
+ //placeholder: '/images/loading.gif',
+ effect: 'fadeIn',
+ threshold : 0
+ });
+ },
+
+ /**
+ * Tabs tag listener (without twitter bootstrap).
+ */
+ registerTabsTag: function () {
+ var tNav = '.tabs ul.nav-tabs ';
+
+ // Binding `nav-tabs` & `tab-content` by real time permalink changing.
+ $(function() {
+ $(window).bind('hashchange', function() {
+ var tHash = location.hash;
+ if (tHash !== '') {
+ $(tNav + 'li:has(a[href="' + tHash + '"])').addClass('active').siblings().removeClass('active');
+ $(tHash).addClass('active').siblings().removeClass('active');
+ }
+ }).trigger('hashchange');
+ });
+
+ $(tNav + '.tab').on('click', function (href) {
+ href.preventDefault();
+ // Prevent selected tab to select again.
+ if(!$(this).hasClass('active')){
+
+ // Add & Remove active class on `nav-tabs` & `tab-content`.
+ $(this).addClass('active').siblings().removeClass('active');
+ var tActive = $(this).find('a').attr('href');
+ $(tActive).addClass('active').siblings().removeClass('active');
+
+ // Clear location hash in browser if #permalink exists.
+ if (location.hash !== '') {
+ history.pushState('', document.title, window.location.pathname + window.location.search);
+ }
+ }
+ });
+
+ },
+
+ registerESCKeyEvent: function () {
+ $(document).on('keyup', function (event) {
+ var shouldDismissSearchPopup = event.which === 27 &&
+ $('.search-popup').is(':visible');
+ if (shouldDismissSearchPopup) {
+ $('.search-popup').hide();
+ $('.search-popup-overlay').remove();
+ $('body').css('overflow', '');
+ }
+ });
+ },
+
+ registerBackToTop: function () {
+ var THRESHOLD = 50;
+ var $top = $('.back-to-top');
+
+ $(window).on('scroll', function () {
+ $top.toggleClass('back-to-top-on', window.pageYOffset > THRESHOLD);
+
+ var scrollTop = $(window).scrollTop();
+ var contentVisibilityHeight = NexT.utils.getContentVisibilityHeight();
+ var scrollPercent = (scrollTop) / (contentVisibilityHeight);
+ var scrollPercentRounded = Math.round(scrollPercent*100);
+ var scrollPercentMaxed = (scrollPercentRounded > 100) ? 100 : scrollPercentRounded;
+ $('#scrollpercent>span').html(scrollPercentMaxed);
+ });
+
+ $top.on('click', function () {
+ $('body').velocity('scroll');
+ });
+ },
+
+ /**
+ * Transform embedded video to support responsive layout.
+ * @see http://toddmotto.com/fluid-and-responsive-youtube-and-vimeo-videos-with-fluidvids-js/
+ */
+ embeddedVideoTransformer: function () {
+ var $iframes = $('iframe');
+
+ // Supported Players. Extend this if you need more players.
+ var SUPPORTED_PLAYERS = [
+ 'www.youtube.com',
+ 'player.vimeo.com',
+ 'player.youku.com',
+ 'music.163.com',
+ 'www.tudou.com'
+ ];
+ var pattern = new RegExp( SUPPORTED_PLAYERS.join('|') );
+
+ $iframes.each(function () {
+ var iframe = this;
+ var $iframe = $(this);
+ var oldDimension = getDimension($iframe);
+ var newDimension;
+
+ if (this.src.search(pattern) > 0) {
+
+ // Calculate the video ratio based on the iframe's w/h dimensions
+ var videoRatio = getAspectRadio(oldDimension.width, oldDimension.height);
+
+ // Replace the iframe's dimensions and position the iframe absolute
+ // This is the trick to emulate the video ratio
+ $iframe.width('100%').height('100%')
+ .css({
+ position: 'absolute',
+ top: '0',
+ left: '0'
+ });
+
+
+ // Wrap the iframe in a new which uses a dynamically fetched padding-top property
+ // based on the video's w/h dimensions
+ var wrap = document.createElement('div');
+ wrap.className = 'fluid-vids';
+ wrap.style.position = 'relative';
+ wrap.style.marginBottom = '20px';
+ wrap.style.width = '100%';
+ wrap.style.paddingTop = videoRatio + '%';
+ // Fix for appear inside tabs tag.
+ (wrap.style.paddingTop === '') && (wrap.style.paddingTop = '50%');
+
+ // Add the iframe inside our newly created
+ var iframeParent = iframe.parentNode;
+ iframeParent.insertBefore(wrap, iframe);
+ wrap.appendChild(iframe);
+
+ // Additional adjustments for 163 Music
+ if (this.src.search('music.163.com') > 0) {
+ newDimension = getDimension($iframe);
+ var shouldRecalculateAspect = newDimension.width > oldDimension.width ||
+ newDimension.height < oldDimension.height;
+
+ // 163 Music Player has a fixed height, so we need to reset the aspect radio
+ if (shouldRecalculateAspect) {
+ wrap.style.paddingTop = getAspectRadio(newDimension.width, oldDimension.height) + '%';
+ }
+ }
+ }
+ });
+
+ function getDimension($element) {
+ return {
+ width: $element.width(),
+ height: $element.height()
+ };
+ }
+
+ function getAspectRadio(width, height) {
+ return height / width * 100;
+ }
+ },
+
+ hasMobileUA: function () {
+ var nav = window.navigator;
+ var ua = nav.userAgent;
+ var pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g;
+
+ return pa.test(ua);
+ },
+
+ isTablet: function () {
+ return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA();
+ },
+
+ isMobile: function () {
+ return window.screen.width < 767 && this.hasMobileUA();
+ },
+
+ isDesktop: function () {
+ return !this.isTablet() && !this.isMobile();
+ },
+
+ /**
+ * Escape meta symbols in jQuery selectors.
+ *
+ * @param selector
+ * @returns {string|void|XML|*}
+ */
+ escapeSelector: function (selector) {
+ return selector.replace(/[!"$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&');
+ },
+
+ displaySidebar: function () {
+ if (!this.isDesktop() || this.isPisces() || this.isGemini()) {
+ return;
+ }
+ $('.sidebar-toggle').trigger('click');
+ },
+
+ isMist: function () {
+ return CONFIG.scheme === 'Mist';
+ },
+
+ isPisces: function () {
+ return CONFIG.scheme === 'Pisces';
+ },
+
+ isGemini: function () {
+ return CONFIG.scheme === 'Gemini';
+ },
+
+ getScrollbarWidth: function () {
+ var $div = $('').addClass('scrollbar-measure').prependTo('body');
+ var div = $div[0];
+ var scrollbarWidth = div.offsetWidth - div.clientWidth;
+
+ $div.remove();
+
+ return scrollbarWidth;
+ },
+
+ getContentVisibilityHeight: function () {
+ var docHeight = $('#content').height(),
+ winHeight = $(window).height(),
+ contentVisibilityHeight = (docHeight > winHeight) ? (docHeight - winHeight) : ($(document).height() - winHeight);
+ return contentVisibilityHeight;
+ },
+
+ getSidebarb2tHeight: function () {
+ //var sidebarb2tHeight = (CONFIG.sidebar.b2t) ? document.getElementsByClassName('back-to-top')[0].clientHeight : 0;
+ var sidebarb2tHeight = (CONFIG.sidebar.b2t) ? $('.back-to-top').height() : 0;
+ //var sidebarb2tHeight = (CONFIG.sidebar.b2t) ? 24 : 0;
+ return sidebarb2tHeight;
+ },
+
+ getSidebarSchemePadding: function () {
+ var sidebarNavHeight = ($('.sidebar-nav').css('display') == 'block') ? $('.sidebar-nav').outerHeight(true) : 0,
+ sidebarInner = $('.sidebar-inner'),
+ sidebarPadding = sidebarInner.innerWidth() - sidebarInner.width(),
+ sidebarSchemePadding = this.isPisces() || this.isGemini() ?
+ ((sidebarPadding * 2) + sidebarNavHeight + (CONFIG.sidebar.offset * 2) + this.getSidebarb2tHeight()) :
+ ((sidebarPadding * 2) + (sidebarNavHeight / 2));
+ return sidebarSchemePadding;
+ }
+
+ /**
+ * Affix behaviour for Sidebar.
+ *
+ * @returns {Boolean}
+ */
+// needAffix: function () {
+// return this.isPisces() || this.isGemini();
+// }
+};
+
+$(document).ready(function () {
+
+ initSidebarDimension();
+
+ /**
+ * Init Sidebar & TOC inner dimensions on all pages and for all schemes.
+ * Need for Sidebar/TOC inner scrolling if content taller then viewport.
+ */
+ function initSidebarDimension () {
+ var updateSidebarHeightTimer;
+
+ $(window).on('resize', function () {
+ updateSidebarHeightTimer && clearTimeout(updateSidebarHeightTimer);
+
+ updateSidebarHeightTimer = setTimeout(function () {
+ var sidebarWrapperHeight = document.body.clientHeight - NexT.utils.getSidebarSchemePadding();
+
+ updateSidebarHeight(sidebarWrapperHeight);
+ }, 0);
+ });
+
+ // Initialize Sidebar & TOC Width.
+ var scrollbarWidth = NexT.utils.getScrollbarWidth();
+ if ($('.site-overview-wrap').height() > (document.body.clientHeight - NexT.utils.getSidebarSchemePadding())) {
+ $('.site-overview').css('width', 'calc(100% + ' + scrollbarWidth + 'px)');
+ }
+ if ($('.post-toc-wrap').height() > (document.body.clientHeight - NexT.utils.getSidebarSchemePadding())) {
+ $('.post-toc').css('width', 'calc(100% + ' + scrollbarWidth + 'px)');
+ }
+
+ // Initialize Sidebar & TOC Height.
+ updateSidebarHeight(document.body.clientHeight - NexT.utils.getSidebarSchemePadding());
+ }
+
+ function updateSidebarHeight (height) {
+ height = height || 'auto';
+ $('.site-overview, .post-toc').css('max-height', height);
+ }
+
+});
diff --git a/source/lib/fancybox/.bower.json b/source/lib/fancybox/.bower.json
new file mode 100644
index 000000000..bde1f7413
--- /dev/null
+++ b/source/lib/fancybox/.bower.json
@@ -0,0 +1,24 @@
+{
+ "name": "fancybox",
+ "description": "Touch enabled, responsive and fully customizable jQuery lightbox script",
+ "keywords": [
+ "touch",
+ "responsive",
+ "lightbox",
+ "fancybox",
+ "gallery",
+ "jQuery",
+ "plugin"
+ ],
+ "homepage": "http://fancyapps.com/fancybox/",
+ "license": "GPL-3.0",
+ "moduleType": "globals",
+ "main": [
+ "dist/jquery.fancybox.min.css",
+ "dist/jquery.fancybox.min.js"
+ ],
+ "dependencies": {
+ "jquery": ">=1.9.0"
+ }
+}
+
\ No newline at end of file
diff --git a/source/lib/fancybox/.gitattributes b/source/lib/fancybox/.gitattributes
new file mode 100644
index 000000000..f6bb280a0
--- /dev/null
+++ b/source/lib/fancybox/.gitattributes
@@ -0,0 +1,7 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.gif binary
\ No newline at end of file
diff --git a/source/lib/fancybox/LICENSE b/source/lib/fancybox/LICENSE
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/source/lib/fancybox/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/source/lib/fancybox/README.md b/source/lib/fancybox/README.md
new file mode 100644
index 000000000..78068b93f
--- /dev/null
+++ b/source/lib/fancybox/README.md
@@ -0,0 +1,44 @@
+fancyBox 3 for NexT
+
+If you want fancybox v2, please go to theme-next-fancybox
+
+Installation
+
+Step 0 → Delete fancybox 2 (if you want to upgrade from v2)
+
+```bash
+$ rm -rf themes/next/source/lib/fancybox
+```
+
+Step 1 → Go to NexT dir
+
+Change dir to **NexT** directory. There must be `layout`, `source`, `languages` and other directories:
+
+```sh
+$ cd themes/next
+$ ls
+bower.json _config.yml docs gulpfile.coffee languages layout LICENSE.md package.json README.md scripts source test
+```
+
+Step 2 → Get module
+
+Install module to `source/lib` directory:
+
+```sh
+$ git clone https://github.com/theme-next/theme-next-fancybox3 source/lib/fancybox
+```
+
+Step 3 → Set it up
+
+Enable module in **NexT** `_config.yml` file:
+
+```yml
+fancybox: true
+```
+
+Update
+
+```sh
+$ cd themes/next/source/lib/fancybox
+$ git pull
+```
diff --git a/source/lib/fancybox/source/jquery.fancybox.css b/source/lib/fancybox/source/jquery.fancybox.css
new file mode 100644
index 000000000..924369c37
--- /dev/null
+++ b/source/lib/fancybox/source/jquery.fancybox.css
@@ -0,0 +1,752 @@
+@charset "UTF-8";
+body.fancybox-active {
+ overflow: hidden; }
+
+body.fancybox-iosfix {
+ position: fixed;
+ left: 0;
+ right: 0; }
+
+.fancybox-is-hidden {
+ position: absolute;
+ top: -9999px;
+ left: -9999px;
+ visibility: hidden; }
+
+.fancybox-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 99992;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; }
+
+.fancybox-outer,
+.fancybox-inner,
+.fancybox-bg,
+.fancybox-stage {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0; }
+
+.fancybox-outer {
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch; }
+
+.fancybox-bg {
+ background: #1e1e1e;
+ opacity: 0;
+ transition-duration: inherit;
+ transition-property: opacity;
+ transition-timing-function: cubic-bezier(0.47, 0, 0.74, 0.71); }
+
+.fancybox-is-open .fancybox-bg {
+ opacity: 0.87;
+ transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1); }
+
+.fancybox-infobar,
+.fancybox-toolbar,
+.fancybox-caption-wrap {
+ position: absolute;
+ direction: ltr;
+ z-index: 99997;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity .25s, visibility 0s linear .25s;
+ box-sizing: border-box; }
+
+.fancybox-show-infobar .fancybox-infobar,
+.fancybox-show-toolbar .fancybox-toolbar,
+.fancybox-show-caption .fancybox-caption-wrap {
+ opacity: 1;
+ visibility: visible;
+ transition: opacity .25s, visibility 0s; }
+
+.fancybox-infobar {
+ top: 0;
+ left: 0;
+ font-size: 13px;
+ padding: 0 10px;
+ height: 44px;
+ min-width: 44px;
+ line-height: 44px;
+ color: #ccc;
+ text-align: center;
+ pointer-events: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-touch-callout: none;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-font-smoothing: subpixel-antialiased;
+ mix-blend-mode: exclusion; }
+
+.fancybox-toolbar {
+ top: 0;
+ right: 0;
+ margin: 0;
+ padding: 0; }
+
+.fancybox-stage {
+ overflow: hidden;
+ direction: ltr;
+ z-index: 99994;
+ -webkit-transform: translate3d(0, 0, 0); }
+
+.fancybox-is-closing .fancybox-stage {
+ overflow: visible; }
+
+.fancybox-slide {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow: auto;
+ outline: none;
+ white-space: normal;
+ box-sizing: border-box;
+ text-align: center;
+ z-index: 99994;
+ -webkit-overflow-scrolling: touch;
+ display: none;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ transition-property: opacity, -webkit-transform;
+ transition-property: transform, opacity;
+ transition-property: transform, opacity, -webkit-transform; }
+
+.fancybox-slide::before {
+ content: '';
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
+ width: 0; }
+
+.fancybox-is-sliding .fancybox-slide,
+.fancybox-slide--previous,
+.fancybox-slide--current,
+.fancybox-slide--next {
+ display: block; }
+
+.fancybox-slide--image {
+ overflow: visible; }
+
+.fancybox-slide--image::before {
+ display: none; }
+
+.fancybox-slide--video .fancybox-content,
+.fancybox-slide--video iframe {
+ background: #000; }
+
+.fancybox-slide--map .fancybox-content,
+.fancybox-slide--map iframe {
+ background: #E5E3DF; }
+
+.fancybox-slide--next {
+ z-index: 99995; }
+
+.fancybox-slide > * {
+ display: inline-block;
+ position: relative;
+ padding: 24px;
+ margin: 44px 0 44px;
+ border-width: 0;
+ vertical-align: middle;
+ text-align: left;
+ background-color: #fff;
+ overflow: auto;
+ box-sizing: border-box; }
+
+.fancybox-slide > title,
+.fancybox-slide > style,
+.fancybox-slide > meta,
+.fancybox-slide > link,
+.fancybox-slide > script,
+.fancybox-slide > base {
+ display: none; }
+
+.fancybox-slide .fancybox-image-wrap {
+ position: absolute;
+ top: 0;
+ left: 0;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ z-index: 99995;
+ background: transparent;
+ cursor: default;
+ overflow: visible;
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ transition-property: opacity, -webkit-transform;
+ transition-property: transform, opacity;
+ transition-property: transform, opacity, -webkit-transform; }
+
+.fancybox-can-zoomOut .fancybox-image-wrap {
+ cursor: -webkit-zoom-out;
+ cursor: zoom-out; }
+
+.fancybox-can-zoomIn .fancybox-image-wrap {
+ cursor: -webkit-zoom-in;
+ cursor: zoom-in; }
+
+.fancybox-can-drag .fancybox-image-wrap {
+ cursor: -webkit-grab;
+ cursor: grab; }
+
+.fancybox-is-dragging .fancybox-image-wrap {
+ cursor: -webkit-grabbing;
+ cursor: grabbing; }
+
+.fancybox-image,
+.fancybox-spaceball {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ max-width: none;
+ max-height: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+
+.fancybox-spaceball {
+ z-index: 1; }
+
+.fancybox-slide--iframe .fancybox-content {
+ padding: 0;
+ width: 80%;
+ height: 80%;
+ max-width: calc(100% - 100px);
+ max-height: calc(100% - 88px);
+ overflow: visible;
+ background: #fff; }
+
+.fancybox-iframe {
+ display: block;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 100%;
+ height: 100%;
+ background: #fff; }
+
+.fancybox-error {
+ margin: 0;
+ padding: 40px;
+ width: 100%;
+ max-width: 380px;
+ background: #fff;
+ cursor: default; }
+
+.fancybox-error p {
+ margin: 0;
+ padding: 0;
+ color: #444;
+ font-size: 16px;
+ line-height: 20px; }
+
+/* Buttons */
+.fancybox-button {
+ box-sizing: border-box;
+ display: inline-block;
+ vertical-align: top;
+ width: 44px;
+ height: 44px;
+ margin: 0;
+ padding: 10px;
+ border: 0;
+ border-radius: 0;
+ background: rgba(30, 30, 30, 0.6);
+ transition: color .3s ease;
+ cursor: pointer;
+ outline: none; }
+
+.fancybox-button,
+.fancybox-button:visited,
+.fancybox-button:link {
+ color: #ccc; }
+
+.fancybox-button:focus,
+.fancybox-button:hover {
+ color: #fff; }
+
+.fancybox-button[disabled] {
+ color: #ccc;
+ cursor: default;
+ opacity: 0.6; }
+
+.fancybox-button svg {
+ display: block;
+ position: relative;
+ overflow: visible;
+ shape-rendering: geometricPrecision; }
+
+.fancybox-button svg path {
+ fill: currentColor;
+ stroke: currentColor;
+ stroke-linejoin: round;
+ stroke-width: 3; }
+
+.fancybox-button--share svg path {
+ stroke-width: 1; }
+
+.fancybox-button--play svg path:nth-child(2) {
+ display: none; }
+
+.fancybox-button--pause svg path:nth-child(1) {
+ display: none; }
+
+.fancybox-button--zoom svg path {
+ fill: transparent; }
+
+/* Navigation arrows */
+.fancybox-navigation {
+ display: none; }
+
+.fancybox-show-nav .fancybox-navigation {
+ display: block; }
+
+.fancybox-navigation button {
+ position: absolute;
+ top: 50%;
+ margin: -50px 0 0 0;
+ z-index: 99997;
+ background: transparent;
+ width: 60px;
+ height: 100px;
+ padding: 17px; }
+
+.fancybox-navigation button:before {
+ content: "";
+ position: absolute;
+ top: 30px;
+ right: 10px;
+ width: 40px;
+ height: 40px;
+ background: rgba(30, 30, 30, 0.6); }
+
+.fancybox-navigation .fancybox-button--arrow_left {
+ left: 0; }
+
+.fancybox-navigation .fancybox-button--arrow_right {
+ right: 0; }
+
+/* Close button on the top right corner of html content */
+.fancybox-close-small {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 44px;
+ height: 44px;
+ padding: 0;
+ margin: 0;
+ border: 0;
+ border-radius: 0;
+ background: transparent;
+ z-index: 10;
+ cursor: pointer; }
+
+.fancybox-close-small:after {
+ content: '×';
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ width: 30px;
+ height: 30px;
+ font: 20px/30px Arial,"Helvetica Neue",Helvetica,sans-serif;
+ color: #888;
+ font-weight: 300;
+ text-align: center;
+ border-radius: 50%;
+ border-width: 0;
+ background-color: transparent;
+ transition: background-color .25s;
+ box-sizing: border-box;
+ z-index: 2; }
+
+.fancybox-close-small:focus {
+ outline: none; }
+
+.fancybox-close-small:focus:after {
+ outline: 1px dotted #888; }
+
+.fancybox-close-small:hover:after {
+ color: #555;
+ background: #eee; }
+
+.fancybox-slide--image .fancybox-close-small,
+.fancybox-slide--iframe .fancybox-close-small {
+ top: 0;
+ right: -44px; }
+
+.fancybox-slide--image .fancybox-close-small:after,
+.fancybox-slide--iframe .fancybox-close-small:after {
+ font-size: 35px;
+ color: #aaa; }
+
+.fancybox-slide--image .fancybox-close-small:hover:after,
+.fancybox-slide--iframe .fancybox-close-small:hover:after {
+ color: #fff;
+ background: transparent; }
+
+.fancybox-is-scaling .fancybox-close-small,
+.fancybox-is-zoomable.fancybox-can-drag .fancybox-close-small {
+ display: none; }
+
+/* Caption */
+.fancybox-caption-wrap {
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 60px 2vw 0 2vw;
+ background: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.1) 20%, rgba(0, 0, 0, 0.2) 40%, rgba(0, 0, 0, 0.6) 80%, rgba(0, 0, 0, 0.8) 100%);
+ pointer-events: none; }
+
+.fancybox-caption {
+ padding: 30px 0;
+ border-top: 1px solid rgba(255, 255, 255, 0.4);
+ font-size: 14px;
+ color: #fff;
+ line-height: 20px;
+ -webkit-text-size-adjust: none; }
+
+.fancybox-caption a,
+.fancybox-caption button,
+.fancybox-caption select {
+ pointer-events: all;
+ position: relative;
+ /* Fix IE11 */ }
+
+.fancybox-caption a {
+ color: #fff;
+ text-decoration: underline; }
+
+/* Loading indicator */
+.fancybox-slide > .fancybox-loading {
+ border: 6px solid rgba(100, 100, 100, 0.4);
+ border-top: 6px solid rgba(255, 255, 255, 0.6);
+ border-radius: 100%;
+ height: 50px;
+ width: 50px;
+ -webkit-animation: fancybox-rotate .8s infinite linear;
+ animation: fancybox-rotate .8s infinite linear;
+ background: transparent;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -30px;
+ margin-left: -30px;
+ z-index: 99999; }
+
+@-webkit-keyframes fancybox-rotate {
+ from {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ to {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg); } }
+
+@keyframes fancybox-rotate {
+ from {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ to {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg); } }
+
+/* Transition effects */
+.fancybox-animated {
+ transition-timing-function: cubic-bezier(0, 0, 0.25, 1); }
+
+/* transitionEffect: slide */
+.fancybox-fx-slide.fancybox-slide--previous {
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-slide.fancybox-slide--next {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-slide.fancybox-slide--current {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ opacity: 1; }
+
+/* transitionEffect: fade */
+.fancybox-fx-fade.fancybox-slide--previous,
+.fancybox-fx-fade.fancybox-slide--next {
+ opacity: 0;
+ transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1); }
+
+.fancybox-fx-fade.fancybox-slide--current {
+ opacity: 1; }
+
+/* transitionEffect: zoom-in-out */
+.fancybox-fx-zoom-in-out.fancybox-slide--previous {
+ -webkit-transform: scale3d(1.5, 1.5, 1.5);
+ transform: scale3d(1.5, 1.5, 1.5);
+ opacity: 0; }
+
+.fancybox-fx-zoom-in-out.fancybox-slide--next {
+ -webkit-transform: scale3d(0.5, 0.5, 0.5);
+ transform: scale3d(0.5, 0.5, 0.5);
+ opacity: 0; }
+
+.fancybox-fx-zoom-in-out.fancybox-slide--current {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1);
+ opacity: 1; }
+
+/* transitionEffect: rotate */
+.fancybox-fx-rotate.fancybox-slide--previous {
+ -webkit-transform: rotate(-360deg);
+ -ms-transform: rotate(-360deg);
+ transform: rotate(-360deg);
+ opacity: 0; }
+
+.fancybox-fx-rotate.fancybox-slide--next {
+ -webkit-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ opacity: 0; }
+
+.fancybox-fx-rotate.fancybox-slide--current {
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+/* transitionEffect: circular */
+.fancybox-fx-circular.fancybox-slide--previous {
+ -webkit-transform: scale3d(0, 0, 0) translate3d(-100%, 0, 0);
+ transform: scale3d(0, 0, 0) translate3d(-100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-circular.fancybox-slide--next {
+ -webkit-transform: scale3d(0, 0, 0) translate3d(100%, 0, 0);
+ transform: scale3d(0, 0, 0) translate3d(100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-circular.fancybox-slide--current {
+ -webkit-transform: scale3d(1, 1, 1) translate3d(0, 0, 0);
+ transform: scale3d(1, 1, 1) translate3d(0, 0, 0);
+ opacity: 1; }
+
+/* transitionEffect: tube */
+.fancybox-fx-tube.fancybox-slide--previous {
+ -webkit-transform: translate3d(-100%, 0, 0) scale(0.1) skew(-10deg);
+ transform: translate3d(-100%, 0, 0) scale(0.1) skew(-10deg); }
+
+.fancybox-fx-tube.fancybox-slide--next {
+ -webkit-transform: translate3d(100%, 0, 0) scale(0.1) skew(10deg);
+ transform: translate3d(100%, 0, 0) scale(0.1) skew(10deg); }
+
+.fancybox-fx-tube.fancybox-slide--current {
+ -webkit-transform: translate3d(0, 0, 0) scale(1);
+ transform: translate3d(0, 0, 0) scale(1); }
+
+/* Share */
+.fancybox-share {
+ padding: 30px;
+ border-radius: 3px;
+ background: #f4f4f4;
+ max-width: 90%; }
+
+.fancybox-share h1 {
+ color: #222;
+ margin: 0 0 20px 0;
+ font-size: 33px;
+ font-weight: 700;
+ text-align: center; }
+
+.fancybox-share p {
+ margin: 0;
+ padding: 0;
+ text-align: center; }
+
+.fancybox-share p:first-of-type {
+ margin-right: -10px; }
+
+.fancybox-share_button {
+ display: inline-block;
+ text-decoration: none;
+ margin: 0 10px 10px 0;
+ padding: 10px 20px;
+ border: 0;
+ border-radius: 3px;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16);
+ background: #fff;
+ white-space: nowrap;
+ font-size: 16px;
+ line-height: 23px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ min-width: 140px;
+ color: #707070;
+ transition: all .2s; }
+
+.fancybox-share_button:focus,
+.fancybox-share_button:hover {
+ text-decoration: none;
+ color: #333;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.3); }
+
+.fancybox-share_button svg {
+ margin-right: 5px;
+ width: 20px;
+ height: 20px;
+ vertical-align: text-bottom; }
+
+.fancybox-share input {
+ box-sizing: border-box;
+ width: 100%;
+ margin: 5px 0 0 0;
+ padding: 10px 15px;
+ border: 1px solid #d7d7d7;
+ border-radius: 3px;
+ background: #ebebeb;
+ color: #5d5b5b;
+ font-size: 14px;
+ outline: none; }
+
+/* Thumbs */
+.fancybox-thumbs {
+ display: none;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ width: 212px;
+ margin: 0;
+ padding: 2px 2px 4px 2px;
+ background: #fff;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ box-sizing: border-box;
+ z-index: 99995; }
+
+.fancybox-thumbs-x {
+ overflow-y: hidden;
+ overflow-x: auto; }
+
+.fancybox-show-thumbs .fancybox-thumbs {
+ display: block; }
+
+.fancybox-show-thumbs .fancybox-inner {
+ right: 212px; }
+
+.fancybox-thumbs > ul {
+ list-style: none;
+ position: absolute;
+ position: relative;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+ font-size: 0;
+ white-space: nowrap; }
+
+.fancybox-thumbs-x > ul {
+ overflow: hidden; }
+
+.fancybox-thumbs-y > ul::-webkit-scrollbar {
+ width: 7px; }
+
+.fancybox-thumbs-y > ul::-webkit-scrollbar-track {
+ background: #fff;
+ border-radius: 10px;
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); }
+
+.fancybox-thumbs-y > ul::-webkit-scrollbar-thumb {
+ background: #2a2a2a;
+ border-radius: 10px; }
+
+.fancybox-thumbs > ul > li {
+ float: left;
+ overflow: hidden;
+ padding: 0;
+ margin: 2px;
+ width: 100px;
+ height: 75px;
+ max-width: calc(50% - 4px);
+ max-height: calc(100% - 8px);
+ position: relative;
+ cursor: pointer;
+ outline: none;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ box-sizing: border-box; }
+
+li.fancybox-thumbs-loading {
+ background: rgba(0, 0, 0, 0.1); }
+
+.fancybox-thumbs > ul > li > img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ max-width: none;
+ max-height: none;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+
+.fancybox-thumbs > ul > li:before {
+ content: '';
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ border: 4px solid #4ea7f9;
+ z-index: 99991;
+ opacity: 0;
+ transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94); }
+
+.fancybox-thumbs > ul > li.fancybox-thumbs-active:before {
+ opacity: 1; }
+
+/* Styling for Small-Screen Devices */
+@media all and (max-width: 800px) {
+ .fancybox-thumbs {
+ width: 110px; }
+ .fancybox-show-thumbs .fancybox-inner {
+ right: 110px; }
+ .fancybox-thumbs > ul > li {
+ max-width: calc(100% - 10px); } }
diff --git a/source/lib/fancybox/source/jquery.fancybox.js b/source/lib/fancybox/source/jquery.fancybox.js
new file mode 100644
index 000000000..ac97c2cc9
--- /dev/null
+++ b/source/lib/fancybox/source/jquery.fancybox.js
@@ -0,0 +1,5152 @@
+// ==================================================
+// fancyBox v3.2.5
+//
+// Licensed GPLv3 for open source use
+// or fancyBox Commercial License for commercial use
+//
+// http://fancyapps.com/fancybox/
+// Copyright 2017 fancyApps
+//
+// ==================================================
+;(function (window, document, $, undefined) {
+ 'use strict';
+
+ // If there's no jQuery, fancyBox can't work
+ // =========================================
+
+ if ( !$ ) {
+ return;
+ }
+
+ // Check if fancyBox is already initialized
+ // ========================================
+
+ if ( $.fn.fancybox ) {
+
+ if ( 'console' in window ) {
+ console.log( 'fancyBox already initialized' );
+ }
+
+ return;
+ }
+
+ // Private default settings
+ // ========================
+
+ var defaults = {
+
+ // Enable infinite gallery navigation
+ loop : false,
+
+ // Space around image, ignored if zoomed-in or viewport width is smaller than 800px
+ margin : [44, 0],
+
+ // Horizontal space between slides
+ gutter : 50,
+
+ // Enable keyboard navigation
+ keyboard : true,
+
+ // Should display navigation arrows at the screen edges
+ arrows : true,
+
+ // Should display infobar (counter and arrows at the top)
+ infobar : true,
+
+ // Should display toolbar (buttons at the top)
+ toolbar : true,
+
+ // What buttons should appear in the top right corner.
+ // Buttons will be created using templates from `btnTpl` option
+ // and they will be placed into toolbar (class="fancybox-toolbar"` element)
+ buttons : [
+ 'slideShow',
+ 'fullScreen',
+ 'thumbs',
+ 'share',
+ //'download',
+ //'zoom',
+ 'close'
+ ],
+
+ // Detect "idle" time in seconds
+ idleTime : 3,
+
+ // Should display buttons at top right corner of the content
+ // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
+ // Use template from `btnTpl.smallBtn` for customization
+ smallBtn : 'auto',
+
+ // Disable right-click and use simple image protection for images
+ protect : false,
+
+ // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
+ modal : false,
+
+ image : {
+
+ // Wait for images to load before displaying
+ // Requires predefined image dimensions
+ // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
+ preload : "auto"
+
+ },
+
+ ajax : {
+
+ // Object containing settings for ajax request
+ settings : {
+
+ // This helps to indicate that request comes from the modal
+ // Feel free to change naming
+ data : {
+ fancybox : true
+ }
+ }
+
+ },
+
+ iframe : {
+
+ // Iframe template
+ tpl : '',
+
+ // Preload iframe before displaying it
+ // This allows to calculate iframe content width and height
+ // (note: Due to "Same Origin Policy", you can't get cross domain data).
+ preload : true,
+
+ // Custom CSS styling for iframe wrapping element
+ // You can use this to set custom iframe dimensions
+ css : {},
+
+ // Iframe tag attributes
+ attr : {
+ scrolling : 'auto'
+ }
+
+ },
+
+ // Default content type if cannot be detected automatically
+ defaultType : 'image',
+
+ // Open/close animation type
+ // Possible values:
+ // false - disable
+ // "zoom" - zoom images from/to thumbnail
+ // "fade"
+ // "zoom-in-out"
+ //
+ animationEffect : "zoom",
+
+ // Duration in ms for open/close animation
+ animationDuration : 500,
+
+ // Should image change opacity while zooming
+ // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios
+ zoomOpacity : "auto",
+
+ // Transition effect between slides
+ //
+ // Possible values:
+ // false - disable
+ // "fade'
+ // "slide'
+ // "circular'
+ // "tube'
+ // "zoom-in-out'
+ // "rotate'
+ //
+ transitionEffect : "fade",
+
+ // Duration in ms for transition animation
+ transitionDuration : 366,
+
+ // Custom CSS class for slide element
+ slideClass : '',
+
+ // Custom CSS class for layout
+ baseClass : '',
+
+ // Base template for layout
+ baseTpl :
+ '' +
+ '' +
+ '' +
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '' +
+ ' ' +
+ '',
+
+ // Loading indicator template
+ spinnerTpl : '',
+
+ // Error message template
+ errorTpl : '{{ERROR}}
',
+
+ btnTpl : {
+
+ download : '' +
+ '' +
+ '',
+
+ zoom : '',
+
+ close : '',
+
+ // This small close button will be appended to your html/inline/ajax content by default,
+ // if "smallBtn" option is not set to false
+ smallBtn : '',
+
+ // Arrows
+ arrowLeft : '',
+
+ arrowRight : ''
+ },
+
+ // Container is injected into this element
+ parentEl : 'body',
+
+
+ // Focus handling
+ // ==============
+
+ // Try to focus on the first focusable element after opening
+ autoFocus : false,
+
+ // Put focus back to active element after closing
+ backFocus : true,
+
+ // Do not let user to focus on element outside modal content
+ trapFocus : true,
+
+
+ // Module specific options
+ // =======================
+
+ fullScreen : {
+ autoStart : false,
+ },
+
+ // Set `touch: false` to disable dragging/swiping
+ touch : {
+ vertical : true, // Allow to drag content vertically
+ momentum : true // Continue movement after releasing mouse/touch when panning
+ },
+
+ // Hash value when initializing manually,
+ // set `false` to disable hash change
+ hash : null,
+
+ // Customize or add new media types
+ // Example:
+ /*
+ media : {
+ youtube : {
+ params : {
+ autoplay : 0
+ }
+ }
+ }
+ */
+ media : {},
+
+ slideShow : {
+ autoStart : false,
+ speed : 4000
+ },
+
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true, // Hide thumbnail grid when closing animation starts
+ parentEl : '.fancybox-container', // Container is injected into this element
+ axis : 'y' // Vertical (y) or horizontal (x) scrolling
+ },
+
+ // Callbacks
+ //==========
+
+ // See Documentation/API/Events for more information
+ // Example:
+ /*
+ afterShow: function( instance, current ) {
+ console.info( 'Clicked element:' );
+ console.info( current.opts.$orig );
+ }
+ */
+
+ onInit : $.noop, // When instance has been initialized
+
+ beforeLoad : $.noop, // Before the content of a slide is being loaded
+ afterLoad : $.noop, // When the content of a slide is done loading
+
+ beforeShow : $.noop, // Before open animation starts
+ afterShow : $.noop, // When content is done loading and animating
+
+ beforeClose : $.noop, // Before the instance attempts to close. Return false to cancel the close.
+ afterClose : $.noop, // After instance has been closed
+
+ onActivate : $.noop, // When instance is brought to front
+ onDeactivate : $.noop, // When other instance has been activated
+
+
+ // Interaction
+ // ===========
+
+ // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
+ // each option can be string or method that returns value.
+ //
+ // Possible values:
+ // "close" - close instance
+ // "next" - move to next gallery item
+ // "nextOrClose" - move to next gallery item or close if gallery has only one item
+ // "toggleControls" - show/hide controls
+ // "zoom" - zoom image (if loaded)
+ // false - do nothing
+
+ // Clicked on the content
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+
+ // Clicked on the slide
+ clickSlide : 'close',
+
+ // Clicked on the background (backdrop) element
+ clickOutside : 'close',
+
+ // Same as previous two, but for double click
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false,
+
+
+ // Custom options when mobile device is detected
+ // =============================================
+
+ mobile : {
+ margin : 0,
+
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : false;
+ },
+ clickSlide : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : 'close';
+ },
+ dblclickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+ dblclickSlide : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ }
+ },
+
+
+ // Internationalization
+ // ============
+
+ lang : 'en',
+ i18n : {
+ 'en' : {
+ CLOSE : 'Close',
+ NEXT : 'Next',
+ PREV : 'Previous',
+ ERROR : 'The requested content cannot be loaded.
Please try again later.',
+ PLAY_START : 'Start slideshow',
+ PLAY_STOP : 'Pause slideshow',
+ FULL_SCREEN : 'Full screen',
+ THUMBS : 'Thumbnails',
+ DOWNLOAD : 'Download',
+ SHARE : 'Share',
+ ZOOM : 'Zoom'
+ },
+ 'de' : {
+ CLOSE : 'Schliessen',
+ NEXT : 'Weiter',
+ PREV : 'Zurück',
+ ERROR : 'Die angeforderten Daten konnten nicht geladen werden.
Bitte versuchen Sie es später nochmal.',
+ PLAY_START : 'Diaschau starten',
+ PLAY_STOP : 'Diaschau beenden',
+ FULL_SCREEN : 'Vollbild',
+ THUMBS : 'Vorschaubilder',
+ DOWNLOAD : 'Herunterladen',
+ SHARE : 'Teilen',
+ ZOOM : 'Maßstab'
+ }
+ }
+
+ };
+
+ // Few useful variables and methods
+ // ================================
+
+ var $W = $(window);
+ var $D = $(document);
+
+ var called = 0;
+
+
+ // Check if an object is a jQuery object and not a native JavaScript object
+ // ========================================================================
+
+ var isQuery = function ( obj ) {
+ return obj && obj.hasOwnProperty && obj instanceof $;
+ };
+
+
+ // Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
+ // ===============================================================================
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ // Detect the supported transition-end event property name
+ // =======================================================
+
+ var transitionEnd = (function () {
+ var t, el = document.createElement("fakeelement");
+
+ var transitions = {
+ "transition" : "transitionend",
+ "OTransition" : "oTransitionEnd",
+ "MozTransition" : "transitionend",
+ "WebkitTransition": "webkitTransitionEnd"
+ };
+
+ for (t in transitions) {
+ if (el.style[t] !== undefined){
+ return transitions[t];
+ }
+ }
+
+ return 'transitionend';
+ })();
+
+
+ // Force redraw on an element.
+ // This helps in cases where the browser doesn't redraw an updated element properly.
+ // =================================================================================
+
+ var forceRedraw = function( $el ) {
+ return ( $el && $el.length && $el[0].offsetHeight );
+ };
+
+
+ // Class definition
+ // ================
+
+ var FancyBox = function( content, opts, index ) {
+ var self = this;
+
+ self.opts = $.extend( true, { index : index }, $.fancybox.defaults, opts || {} );
+
+ if ( $.fancybox.isMobile ) {
+ self.opts = $.extend( true, {}, self.opts, self.opts.mobile );
+ }
+
+ // Exclude buttons option from deep merging
+ if ( opts && $.isArray( opts.buttons ) ) {
+ self.opts.buttons = opts.buttons;
+ }
+
+ self.id = self.opts.id || ++called;
+ self.group = [];
+
+ self.currIndex = parseInt( self.opts.index, 10 ) || 0;
+ self.prevIndex = null;
+
+ self.prevPos = null;
+ self.currPos = 0;
+
+ self.firstRun = null;
+
+ // Create group elements from original item collection
+ self.createGroup( content );
+
+ if ( !self.group.length ) {
+ return;
+ }
+
+ // Save last active element and current scroll position
+ self.$lastFocus = $(document.activeElement).blur();
+
+ // Collection of gallery objects
+ self.slides = {};
+
+ self.init();
+ };
+
+ $.extend(FancyBox.prototype, {
+
+ // Create DOM structure
+ // ====================
+
+ init : function() {
+ var self = this,
+ firstItem = self.group[ self.currIndex ],
+ firstItemOpts = firstItem.opts,
+ scrollbarWidth = $.fancybox.scrollbarWidth,
+ $scrollDiv,
+ $container,
+ buttonStr;
+
+ self.scrollTop = $D.scrollTop();
+ self.scrollLeft = $D.scrollLeft();
+
+
+ // Hide scrollbars
+ // ===============
+
+ if ( !$.fancybox.getInstance() ) {
+
+ $( 'body' ).addClass( 'fancybox-active' );
+
+ // iOS hack
+ if ( /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream ) {
+
+ // iOS has problems for input elements inside fixed containers,
+ // the workaround is to apply `position: fixed` to `` element,
+ // unfortunately, this makes it lose the scrollbars and forces address bar to appear.
+
+ if ( firstItem.type !== 'image' ) {
+ $( 'body' ).css( 'top', $( 'body' ).scrollTop() * -1 ).addClass( 'fancybox-iosfix' );
+ }
+
+ } else if ( !$.fancybox.isMobile && document.body.scrollHeight > window.innerHeight ) {
+
+ if ( scrollbarWidth === undefined ) {
+ $scrollDiv = $('').appendTo( 'body' );
+
+ scrollbarWidth = $.fancybox.scrollbarWidth = $scrollDiv[0].offsetWidth - $scrollDiv[0].clientWidth;
+
+ $scrollDiv.remove();
+ }
+
+ $( 'head' ).append( '' );
+ $( 'body' ).addClass( 'compensate-for-scrollbar' );
+ }
+ }
+
+
+ // Build html markup and set references
+ // ====================================
+
+ // Build html code for buttons and insert into main template
+ buttonStr = '';
+
+ $.each( firstItemOpts.buttons, function( index, value ) {
+ buttonStr += ( firstItemOpts.btnTpl[ value ] || '' );
+ });
+
+ // Create markup from base template, it will be initially hidden to
+ // avoid unnecessary work like painting while initializing is not complete
+ $container = $(
+ self.translate( self,
+ firstItemOpts.baseTpl
+ .replace( '\{\{buttons\}\}', buttonStr )
+ .replace( '\{\{arrows\}\}', firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight )
+ )
+ )
+ .attr( 'id', 'fancybox-container-' + self.id )
+ .addClass( 'fancybox-is-hidden' )
+ .addClass( firstItemOpts.baseClass )
+ .data( 'FancyBox', self )
+ .appendTo( firstItemOpts.parentEl );
+
+ // Create object holding references to jQuery wrapped nodes
+ self.$refs = {
+ container : $container
+ };
+
+ [ 'bg', 'inner', 'infobar', 'toolbar', 'stage', 'caption', 'navigation' ].forEach(function(item) {
+ self.$refs[ item ] = $container.find( '.fancybox-' + item );
+ });
+
+ self.trigger( 'onInit' );
+
+ // Enable events, deactive previous instances
+ self.activate();
+
+ // Build slides, load and reveal content
+ self.jumpTo( self.currIndex );
+ },
+
+
+ // Simple i18n support - replaces object keys found in template
+ // with corresponding values
+ // ============================================================
+
+ translate : function( obj, str ) {
+ var arr = obj.opts.i18n[ obj.opts.lang ];
+
+ return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
+ var value = arr[n];
+
+ if ( value === undefined ) {
+ return match;
+ }
+
+ return value;
+ });
+ },
+
+ // Create array of gally item objects
+ // Check if each object has valid type and content
+ // ===============================================
+
+ createGroup : function ( content ) {
+ var self = this;
+ var items = $.makeArray( content );
+
+ $.each(items, function( i, item ) {
+ var obj = {},
+ opts = {},
+ $item,
+ type,
+ src,
+ srcParts;
+
+ // Step 1 - Make sure we have an object
+ // ====================================
+
+ if ( $.isPlainObject( item ) ) {
+
+ // We probably have manual usage here, something like
+ // $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
+
+ obj = item;
+ opts = item.opts || item;
+
+ } else if ( $.type( item ) === 'object' && $( item ).length ) {
+
+ // Here we probably have jQuery collection returned by some selector
+ $item = $( item );
+
+ opts = $item.data();
+ opts = $.extend( {}, opts, opts.options || {} );
+
+ // Here we store clicked element
+ opts.$orig = $item;
+
+ obj.src = opts.src || $item.attr( 'href' );
+
+ // Assume that simple syntax is used, for example:
+ // `$.fancybox.open( $("#test"), {} );`
+ if ( !obj.type && !obj.src ) {
+ obj.type = 'inline';
+ obj.src = item;
+ }
+
+ } else {
+
+ // Assume we have a simple html code, for example:
+ // $.fancybox.open( 'Hi!
' );
+
+ obj = {
+ type : 'html',
+ src : item + ''
+ };
+
+ }
+
+ // Each gallery object has full collection of options
+ obj.opts = $.extend( true, {}, self.opts, opts );
+
+ // Do not merge buttons array
+ if ( $.isArray( opts.buttons ) ) {
+ obj.opts.buttons = opts.buttons;
+ }
+
+
+ // Step 2 - Make sure we have content type, if not - try to guess
+ // ==============================================================
+
+ type = obj.type || obj.opts.type;
+ src = obj.src || '';
+
+ if ( !type && src ) {
+ if ( src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i) ) {
+ type = 'image';
+
+ } else if ( src.match(/\.(pdf)((\?|#).*)?$/i) ) {
+ type = 'pdf';
+
+ } else if ( src.charAt(0) === '#' ) {
+ type = 'inline';
+ }
+ }
+
+ if ( type ) {
+ obj.type = type;
+
+ } else {
+ self.trigger( 'objectNeedsType', obj );
+ }
+
+
+ // Step 3 - Some adjustments
+ // =========================
+
+ obj.index = self.group.length;
+
+ // Check if $orig and $thumb objects exist
+ if ( obj.opts.$orig && !obj.opts.$orig.length ) {
+ delete obj.opts.$orig;
+ }
+
+ if ( !obj.opts.$thumb && obj.opts.$orig ) {
+ obj.opts.$thumb = obj.opts.$orig.find( 'img:first' );
+ }
+
+ if ( obj.opts.$thumb && !obj.opts.$thumb.length ) {
+ delete obj.opts.$thumb;
+ }
+
+ // "caption" is a "special" option, it can be used to customize caption per gallery item ..
+ if ( $.type( obj.opts.caption ) === 'function' ) {
+ obj.opts.caption = obj.opts.caption.apply( item, [ self, obj ] );
+ }
+
+ if ( $.type( self.opts.caption ) === 'function' ) {
+ obj.opts.caption = self.opts.caption.apply( item, [ self, obj ] );
+ }
+
+ // Make sure we have caption as a string or jQuery object
+ if ( !( obj.opts.caption instanceof $ ) ) {
+ obj.opts.caption = obj.opts.caption === undefined ? '' : obj.opts.caption + '';
+ }
+
+ // Check if url contains "filter" used to filter the content
+ // Example: "ajax.html #something"
+ if ( type === 'ajax' ) {
+ srcParts = src.split(/\s+/, 2);
+
+ if ( srcParts.length > 1 ) {
+ obj.src = srcParts.shift();
+
+ obj.opts.filter = srcParts.shift();
+ }
+ }
+
+ if ( obj.opts.smallBtn == 'auto' ) {
+
+ if ( $.inArray( type, ['html', 'inline', 'ajax'] ) > -1 ) {
+ obj.opts.toolbar = false;
+ obj.opts.smallBtn = true;
+
+ } else {
+ obj.opts.smallBtn = false;
+ }
+
+ }
+
+ // If the type is "pdf", then simply load file into iframe
+ if ( type === 'pdf' ) {
+ obj.type = 'iframe';
+
+ obj.opts.iframe.preload = false;
+ }
+
+ // Hide all buttons and disable interactivity for modal items
+ if ( obj.opts.modal ) {
+
+ obj.opts = $.extend(true, obj.opts, {
+ // Remove buttons
+ infobar : 0,
+ toolbar : 0,
+
+ smallBtn : 0,
+
+ // Disable keyboard navigation
+ keyboard : 0,
+
+ // Disable some modules
+ slideShow : 0,
+ fullScreen : 0,
+ thumbs : 0,
+ touch : 0,
+
+ // Disable click event handlers
+ clickContent : false,
+ clickSlide : false,
+ clickOutside : false,
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false
+ });
+
+ }
+
+ // Step 4 - Add processed object to group
+ // ======================================
+
+ self.group.push( obj );
+
+ });
+
+ },
+
+
+ // Attach an event handler functions for:
+ // - navigation buttons
+ // - browser scrolling, resizing;
+ // - focusing
+ // - keyboard
+ // - detect idle
+ // ======================================
+
+ addEvents : function() {
+ var self = this;
+
+ self.removeEvents();
+
+ // Make navigation elements clickable
+ self.$refs.container.on('click.fb-close', '[data-fancybox-close]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.close( e );
+
+ }).on( 'click.fb-prev touchend.fb-prev', '[data-fancybox-prev]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.previous();
+
+ }).on( 'click.fb-next touchend.fb-next', '[data-fancybox-next]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.next();
+
+ }).on( 'click.fb', '[data-fancybox-zoom]', function(e) {
+ // Click handler for zoom button
+ self[ self.isScaledDown() ? 'scaleToActual' : 'scaleToFit' ]();
+ });
+
+
+ // Handle page scrolling and browser resizing
+ $W.on('orientationchange.fb resize.fb', function(e) {
+
+ if ( e && e.originalEvent && e.originalEvent.type === "resize" ) {
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ } else {
+
+ self.$refs.stage.hide();
+
+ setTimeout(function() {
+ self.$refs.stage.show();
+
+ self.update();
+ }, 600);
+
+ }
+
+ });
+
+ // Trap keyboard focus inside of the modal, so the user does not accidentally tab outside of the modal
+ // (a.k.a. "escaping the modal")
+ $D.on('focusin.fb', function(e) {
+ var instance = $.fancybox ? $.fancybox.getInstance() : null;
+
+ if ( instance.isClosing || !instance.current || !instance.current.opts.trapFocus || $( e.target ).hasClass( 'fancybox-container' ) || $( e.target ).is( document ) ) {
+ return;
+ }
+
+ if ( instance && $( e.target ).css( 'position' ) !== 'fixed' && !instance.$refs.container.has( e.target ).length ) {
+ e.stopPropagation();
+
+ instance.focus();
+
+ // Sometimes page gets scrolled, set it back
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+ }
+ });
+
+
+ // Enable keyboard navigation
+ $D.on('keydown.fb', function (e) {
+ var current = self.current,
+ keycode = e.keyCode || e.which;
+
+ if ( !current || !current.opts.keyboard ) {
+ return;
+ }
+
+ if ( $(e.target).is('input') || $(e.target).is('textarea') ) {
+ return;
+ }
+
+ // Backspace and Esc keys
+ if ( keycode === 8 || keycode === 27 ) {
+ e.preventDefault();
+
+ self.close( e );
+
+ return;
+ }
+
+ // Left arrow and Up arrow
+ if ( keycode === 37 || keycode === 38 ) {
+ e.preventDefault();
+
+ self.previous();
+
+ return;
+ }
+
+ // Righ arrow and Down arrow
+ if ( keycode === 39 || keycode === 40 ) {
+ e.preventDefault();
+
+ self.next();
+
+ return;
+ }
+
+ self.trigger('afterKeydown', e, keycode);
+ });
+
+
+ // Hide controls after some inactivity period
+ if ( self.group[ self.currIndex ].opts.idleTime ) {
+ self.idleSecondsCounter = 0;
+
+ $D.on('mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle', function(e) {
+ self.idleSecondsCounter = 0;
+
+ if ( self.isIdle ) {
+ self.showControls();
+ }
+
+ self.isIdle = false;
+ });
+
+ self.idleInterval = window.setInterval(function() {
+ self.idleSecondsCounter++;
+
+ if ( self.idleSecondsCounter >= self.group[ self.currIndex ].opts.idleTime ) {
+ self.isIdle = true;
+ self.idleSecondsCounter = 0;
+
+ self.hideControls();
+ }
+
+ }, 1000);
+ }
+
+ },
+
+
+ // Remove events added by the core
+ // ===============================
+
+ removeEvents : function() {
+ var self = this;
+
+ $W.off( 'orientationchange.fb resize.fb' );
+ $D.off( 'focusin.fb keydown.fb .fb-idle' );
+
+ this.$refs.container.off( '.fb-close .fb-prev .fb-next' );
+
+ if ( self.idleInterval ) {
+ window.clearInterval( self.idleInterval );
+
+ self.idleInterval = null;
+ }
+ },
+
+
+ // Change to previous gallery item
+ // ===============================
+
+ previous : function( duration ) {
+ return this.jumpTo( this.currPos - 1, duration );
+ },
+
+
+ // Change to next gallery item
+ // ===========================
+
+ next : function( duration ) {
+ return this.jumpTo( this.currPos + 1, duration );
+ },
+
+
+ // Switch to selected gallery item
+ // ===============================
+
+ jumpTo : function ( pos, duration, slide ) {
+ var self = this,
+ firstRun,
+ loop,
+ current,
+ previous,
+ canvasWidth,
+ currentPos,
+ transitionProps;
+
+ var groupLen = self.group.length;
+
+ if ( self.isSliding || self.isClosing || ( self.isAnimating && self.firstRun ) ) {
+ return;
+ }
+
+ pos = parseInt( pos, 10 );
+ loop = self.current ? self.current.opts.loop : self.opts.loop;
+
+ if ( !loop && ( pos < 0 || pos >= groupLen ) ) {
+ return false;
+ }
+
+ firstRun = self.firstRun = ( self.firstRun === null );
+
+ if ( groupLen < 2 && !firstRun && !!self.isSliding ) {
+ return;
+ }
+
+ previous = self.current;
+
+ self.prevIndex = self.currIndex;
+ self.prevPos = self.currPos;
+
+ // Create slides
+ current = self.createSlide( pos );
+
+ if ( groupLen > 1 ) {
+ if ( loop || current.index > 0 ) {
+ self.createSlide( pos - 1 );
+ }
+
+ if ( loop || current.index < groupLen - 1 ) {
+ self.createSlide( pos + 1 );
+ }
+ }
+
+ self.current = current;
+ self.currIndex = current.index;
+ self.currPos = current.pos;
+
+ self.trigger( 'beforeShow', firstRun );
+
+ self.updateControls();
+
+ currentPos = $.fancybox.getTranslate( current.$slide );
+
+ current.isMoved = ( currentPos.left !== 0 || currentPos.top !== 0 ) && !current.$slide.hasClass( 'fancybox-animated' );
+ current.forcedDuration = undefined;
+
+ if ( $.isNumeric( duration ) ) {
+ current.forcedDuration = duration;
+ } else {
+ duration = current.opts[ firstRun ? 'animationDuration' : 'transitionDuration' ];
+ }
+
+ duration = parseInt( duration, 10 );
+
+ // Fresh start - reveal container, current slide and start loading content
+ if ( firstRun ) {
+
+ if ( current.opts.animationEffect && duration ) {
+ self.$refs.container.css( 'transition-duration', duration + 'ms' );
+ }
+
+ self.$refs.container.removeClass( 'fancybox-is-hidden' );
+
+ forceRedraw( self.$refs.container );
+
+ self.$refs.container.addClass( 'fancybox-is-open' );
+
+ // Make first slide visible (to display loading icon, if needed)
+ current.$slide.addClass( 'fancybox-slide--current' );
+
+ self.loadSlide( current );
+
+ self.preload();
+
+ return;
+ }
+
+ // Clean up
+ $.each(self.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+ });
+
+ // Make current that slide is visible even if content is still loading
+ current.$slide.removeClass( 'fancybox-slide--next fancybox-slide--previous' ).addClass( 'fancybox-slide--current' );
+
+ // If slides have been dragged, animate them to correct position
+ if ( current.isMoved ) {
+ canvasWidth = Math.round( current.$slide.width() );
+
+ $.each(self.slides, function( index, slide ) {
+ var pos = slide.pos - current.pos;
+
+ $.fancybox.animate( slide.$slide, {
+ top : 0,
+ left : ( pos * canvasWidth ) + ( pos * slide.opts.gutter )
+ }, duration, function() {
+
+ slide.$slide.removeAttr('style').removeClass( 'fancybox-slide--next fancybox-slide--previous' );
+
+ if ( slide.pos === self.currPos ) {
+ current.isMoved = false;
+
+ self.complete();
+ }
+ });
+ });
+
+ } else {
+ self.$refs.stage.children().removeAttr( 'style' );
+ }
+
+ // Start transition that reveals current content
+ // or wait when it will be loaded
+
+ if ( current.isLoaded ) {
+ self.revealContent( current );
+
+ } else {
+ self.loadSlide( current );
+ }
+
+ self.preload();
+
+ if ( previous.pos === current.pos ) {
+ return;
+ }
+
+ // Handle previous slide
+ // =====================
+
+ transitionProps = 'fancybox-slide--' + ( previous.pos > current.pos ? 'next' : 'previous' );
+
+ previous.$slide.removeClass( 'fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous' );
+
+ previous.isComplete = false;
+
+ if ( !duration || ( !current.isMoved && !current.opts.transitionEffect ) ) {
+ return;
+ }
+
+ if ( current.isMoved ) {
+ previous.$slide.addClass( transitionProps );
+
+ } else {
+
+ transitionProps = 'fancybox-animated ' + transitionProps + ' fancybox-fx-' + current.opts.transitionEffect;
+
+ $.fancybox.animate( previous.$slide, transitionProps, duration, function() {
+ previous.$slide.removeClass( transitionProps ).removeAttr( 'style' );
+ });
+
+ }
+
+ },
+
+
+ // Create new "slide" element
+ // These are gallery items that are actually added to DOM
+ // =======================================================
+
+ createSlide : function( pos ) {
+
+ var self = this;
+ var $slide;
+ var index;
+
+ index = pos % self.group.length;
+ index = index < 0 ? self.group.length + index : index;
+
+ if ( !self.slides[ pos ] && self.group[ index ] ) {
+ $slide = $('').appendTo( self.$refs.stage );
+
+ self.slides[ pos ] = $.extend( true, {}, self.group[ index ], {
+ pos : pos,
+ $slide : $slide,
+ isLoaded : false,
+ });
+
+ self.updateSlide( self.slides[ pos ] );
+ }
+
+ return self.slides[ pos ];
+ },
+
+
+ // Scale image to the actual size of the image
+ // ===========================================
+
+ scaleToActual : function( x, y, duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var imgPos, posX, posY, scaleX, scaleY;
+
+ var canvasWidth = parseInt( current.$slide.width(), 10 );
+ var canvasHeight = parseInt( current.$slide.height(), 10 );
+
+ var newImgWidth = current.width;
+ var newImgHeight = current.height;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ x = x === undefined ? canvasWidth * 0.5 : x;
+ y = y === undefined ? canvasHeight * 0.5 : y;
+
+ imgPos = $.fancybox.getTranslate( $what );
+
+ scaleX = newImgWidth / imgPos.width;
+ scaleY = newImgHeight / imgPos.height;
+
+ // Get center position for original image
+ posX = ( canvasWidth * 0.5 - newImgWidth * 0.5 );
+ posY = ( canvasHeight * 0.5 - newImgHeight * 0.5 );
+
+ // Make sure image does not move away from edges
+ if ( newImgWidth > canvasWidth ) {
+ posX = imgPos.left * scaleX - ( ( x * scaleX ) - x );
+
+ if ( posX > 0 ) {
+ posX = 0;
+ }
+
+ if ( posX < canvasWidth - newImgWidth ) {
+ posX = canvasWidth - newImgWidth;
+ }
+ }
+
+ if ( newImgHeight > canvasHeight) {
+ posY = imgPos.top * scaleY - ( ( y * scaleY ) - y );
+
+ if ( posY > 0 ) {
+ posY = 0;
+ }
+
+ if ( posY < canvasHeight - newImgHeight ) {
+ posY = canvasHeight - newImgHeight;
+ }
+ }
+
+ self.updateCursor( newImgWidth, newImgHeight );
+
+ $.fancybox.animate( $what, {
+ top : posY,
+ left : posX,
+ scaleX : scaleX,
+ scaleY : scaleY
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ // Stop slideshow
+ if ( self.SlideShow && self.SlideShow.isActive ) {
+ self.SlideShow.stop();
+ }
+ },
+
+
+ // Scale image to fit inside parent element
+ // ========================================
+
+ scaleToFit : function( duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+ var end;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ end = self.getFitPos( current );
+
+ self.updateCursor( end.width, end.height );
+
+ $.fancybox.animate( $what, {
+ top : end.top,
+ left : end.left,
+ scaleX : end.width / $what.width(),
+ scaleY : end.height / $what.height()
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ },
+
+ // Calculate image size to fit inside viewport
+ // ===========================================
+
+ getFitPos : function( slide ) {
+ var self = this;
+ var $what = slide.$content;
+
+ var imgWidth = slide.width;
+ var imgHeight = slide.height;
+
+ var margin = slide.opts.margin;
+
+ var canvasWidth, canvasHeight, minRatio, width, height;
+
+ if ( !$what || !$what.length || ( !imgWidth && !imgHeight) ) {
+ return false;
+ }
+
+ // Convert "margin to CSS style: [ top, right, bottom, left ]
+ if ( $.type( margin ) === "number" ) {
+ margin = [ margin, margin ];
+ }
+
+ if ( margin.length == 2 ) {
+ margin = [ margin[0], margin[1], margin[0], margin[1] ];
+ }
+
+ // We can not use $slide width here, because it can have different diemensions while in transiton
+ canvasWidth = parseInt( self.$refs.stage.width(), 10 ) - ( margin[ 1 ] + margin[ 3 ] );
+ canvasHeight = parseInt( self.$refs.stage.height(), 10 ) - ( margin[ 0 ] + margin[ 2 ] );
+
+ minRatio = Math.min(1, canvasWidth / imgWidth, canvasHeight / imgHeight );
+
+ width = Math.floor( minRatio * imgWidth );
+ height = Math.floor( minRatio * imgHeight );
+
+ // Use floor rounding to make sure it really fits
+ return {
+ top : Math.floor( ( canvasHeight - height ) * 0.5 ) + margin[ 0 ],
+ left : Math.floor( ( canvasWidth - width ) * 0.5 ) + margin[ 3 ],
+ width : width,
+ height : height
+ };
+
+ },
+
+
+ // Update position and content of all slides
+ // =========================================
+
+ update : function() {
+
+ var self = this;
+
+ $.each( self.slides, function( key, slide ) {
+ self.updateSlide( slide );
+ });
+
+ },
+
+
+ // Update slide position and scale content to fit
+ // ==============================================
+
+ updateSlide : function( slide ) {
+
+ var self = this;
+ var $what = slide.$content;
+
+ if ( $what && ( slide.width || slide.height ) ) {
+ self.isAnimating = false;
+
+ $.fancybox.stop( $what );
+
+ $.fancybox.setTranslate( $what, self.getFitPos( slide ) );
+
+ if ( slide.pos === self.currPos ) {
+ self.updateCursor();
+ }
+ }
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.trigger( 'onUpdate', slide );
+
+ },
+
+ // Update cursor style depending if content can be zoomed
+ // ======================================================
+
+ updateCursor : function( nextWidth, nextHeight ) {
+
+ var self = this;
+ var isScaledDown;
+
+ var $container = self.$refs.container.removeClass( 'fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut' );
+
+ if ( !self.current || self.isClosing ) {
+ return;
+ }
+
+ if ( self.isZoomable() ) {
+
+ $container.addClass( 'fancybox-is-zoomable' );
+
+ if ( nextWidth !== undefined && nextHeight !== undefined ) {
+ isScaledDown = nextWidth < self.current.width && nextHeight < self.current.height;
+
+ } else {
+ isScaledDown = self.isScaledDown();
+ }
+
+ if ( isScaledDown ) {
+
+ // If image is scaled down, then, obviously, it can be zoomed to full size
+ $container.addClass( 'fancybox-can-zoomIn' );
+
+ } else {
+
+ if ( self.current.opts.touch ) {
+
+ // If image size ir largen than available available and touch module is not disable,
+ // then user can do panning
+ $container.addClass( 'fancybox-can-drag' );
+
+ } else {
+ $container.addClass( 'fancybox-can-zoomOut' );
+ }
+
+ }
+
+ } else if ( self.current.opts.touch ) {
+ $container.addClass( 'fancybox-can-drag' );
+ }
+
+ },
+
+
+ // Check if current slide is zoomable
+ // ==================================
+
+ isZoomable : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var fitPos;
+
+ if ( !current || self.isClosing ) {
+ return;
+ }
+
+ // Assume that slide is zoomable if
+ // - image is loaded successfuly
+ // - click action is "zoom"
+ // - actual size of the image is smaller than available area
+ if ( current.type === 'image' && current.isLoaded && !current.hasError &&
+ ( current.opts.clickContent === 'zoom' || ( $.isFunction( current.opts.clickContent ) && current.opts.clickContent( current ) === "zoom" ) )
+ ) {
+
+ fitPos = self.getFitPos( current );
+
+ if ( current.width > fitPos.width || current.height > fitPos.height ) {
+ return true;
+ }
+
+ }
+
+ return false;
+
+ },
+
+
+ // Check if current image dimensions are smaller than actual
+ // =========================================================
+
+ isScaledDown : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = $.fancybox.getTranslate( $what );
+ rez = rez.width < current.width || rez.height < current.height;
+ }
+
+ return rez;
+
+ },
+
+
+ // Check if image dimensions exceed parent element
+ // ===============================================
+
+ canPan : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = self.getFitPos( current );
+ rez = Math.abs( $what.width() - rez.width ) > 1 || Math.abs( $what.height() - rez.height ) > 1;
+
+ }
+
+ return rez;
+
+ },
+
+
+ // Load content into the slide
+ // ===========================
+
+ loadSlide : function( slide ) {
+
+ var self = this, type, $slide;
+ var ajaxLoad;
+
+ if ( slide.isLoading ) {
+ return;
+ }
+
+ if ( slide.isLoaded ) {
+ return;
+ }
+
+ slide.isLoading = true;
+
+ self.trigger( 'beforeLoad', slide );
+
+ type = slide.type;
+ $slide = slide.$slide;
+
+ $slide
+ .off( 'refresh' )
+ .trigger( 'onReset' )
+ .addClass( 'fancybox-slide--' + ( type || 'unknown' ) )
+ .addClass( slide.opts.slideClass );
+
+ // Create content depending on the type
+
+ switch ( type ) {
+
+ case 'image':
+
+ self.setImage( slide );
+
+ break;
+
+ case 'iframe':
+
+ self.setIframe( slide );
+
+ break;
+
+ case 'html':
+
+ self.setContent( slide, slide.src || slide.content );
+
+ break;
+
+ case 'inline':
+
+ if ( $( slide.src ).length ) {
+ self.setContent( slide, $( slide.src ) );
+
+ } else {
+ self.setError( slide );
+ }
+
+ break;
+
+ case 'ajax':
+
+ self.showLoading( slide );
+
+ ajaxLoad = $.ajax( $.extend( {}, slide.opts.ajax.settings, {
+ url : slide.src,
+ success : function ( data, textStatus ) {
+
+ if ( textStatus === 'success' ) {
+ self.setContent( slide, data );
+ }
+
+ },
+ error : function ( jqXHR, textStatus ) {
+
+ if ( jqXHR && textStatus !== 'abort' ) {
+ self.setError( slide );
+ }
+
+ }
+ }));
+
+ $slide.one( 'onReset', function () {
+ ajaxLoad.abort();
+ });
+
+ break;
+
+ default:
+
+ self.setError( slide );
+
+ break;
+
+ }
+
+ return true;
+
+ },
+
+
+ // Use thumbnail image, if possible
+ // ================================
+
+ setImage : function( slide ) {
+
+ var self = this;
+ var srcset = slide.opts.srcset || slide.opts.image.srcset;
+
+ var found, temp, pxRatio, windowWidth;
+
+ // If we have "srcset", then we need to find matching "src" value.
+ // This is necessary, because when you set an src attribute, the browser will preload the image
+ // before any javascript or even CSS is applied.
+ if ( srcset ) {
+ pxRatio = window.devicePixelRatio || 1;
+ windowWidth = window.innerWidth * pxRatio;
+
+ temp = srcset.split(',').map(function ( el ) {
+ var ret = {};
+
+ el.trim().split(/\s+/).forEach(function ( el, i ) {
+ var value = parseInt( el.substring(0, el.length - 1), 10 );
+
+ if ( i === 0 ) {
+ return ( ret.url = el );
+ }
+
+ if ( value ) {
+ ret.value = value;
+ ret.postfix = el[ el.length - 1 ];
+ }
+
+ });
+
+ return ret;
+ });
+
+ // Sort by value
+ temp.sort(function (a, b) {
+ return a.value - b.value;
+ });
+
+ // Ok, now we have an array of all srcset values
+ for ( var j = 0; j < temp.length; j++ ) {
+ var el = temp[ j ];
+
+ if ( ( el.postfix === 'w' && el.value >= windowWidth ) || ( el.postfix === 'x' && el.value >= pxRatio ) ) {
+ found = el;
+ break;
+ }
+ }
+
+ // If not found, take the last one
+ if ( !found && temp.length ) {
+ found = temp[ temp.length - 1 ];
+ }
+
+ if ( found ) {
+ slide.src = found.url;
+
+ // If we have default width/height values, we can calculate height for matching source
+ if ( slide.width && slide.height && found.postfix == 'w' ) {
+ slide.height = ( slide.width / slide.height ) * found.value;
+ slide.width = found.value;
+ }
+ }
+ }
+
+ // This will be wrapper containing both ghost and actual image
+ slide.$content = $('')
+ .addClass( 'fancybox-is-hidden' )
+ .appendTo( slide.$slide );
+
+
+ // If we have a thumbnail, we can display it while actual image is loading
+ // Users will not stare at black screen and actual image will appear gradually
+ if ( slide.opts.preload !== false && slide.opts.width && slide.opts.height && ( slide.opts.thumb || slide.opts.$thumb ) ) {
+
+ slide.width = slide.opts.width;
+ slide.height = slide.opts.height;
+
+ slide.$ghost = $('')
+ .one('error', function() {
+
+ $(this).remove();
+
+ slide.$ghost = null;
+
+ self.setBigImage( slide );
+
+ })
+ .one('load', function() {
+
+ self.afterLoad( slide );
+
+ self.setBigImage( slide );
+
+ })
+ .addClass( 'fancybox-image' )
+ .appendTo( slide.$content )
+ .attr( 'src', slide.opts.thumb || slide.opts.$thumb.attr( 'src' ) );
+
+ } else {
+
+ self.setBigImage( slide );
+
+ }
+
+ },
+
+
+ // Create full-size image
+ // ======================
+
+ setBigImage : function ( slide ) {
+ var self = this;
+ var $img = $('');
+
+ slide.$image = $img
+ .one('error', function() {
+
+ self.setError( slide );
+
+ })
+ .one('load', function() {
+
+ // Clear timeout that checks if loading icon needs to be displayed
+ clearTimeout( slide.timouts );
+
+ slide.timouts = null;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.width = this.naturalWidth;
+ slide.height = this.naturalHeight;
+
+ if ( slide.opts.image.srcset ) {
+ $img.attr( 'sizes', '100vw' ).attr( 'srcset', slide.opts.image.srcset );
+ }
+
+ self.hideLoading( slide );
+
+ if ( slide.$ghost ) {
+
+ slide.timouts = setTimeout(function() {
+ slide.timouts = null;
+
+ slide.$ghost.hide();
+
+ }, Math.min( 300, Math.max( 1000, slide.height / 1600 ) ) );
+
+ } else {
+ self.afterLoad( slide );
+ }
+
+ })
+ .addClass( 'fancybox-image' )
+ .attr('src', slide.src)
+ .appendTo( slide.$content );
+
+ if ( ( $img[0].complete || $img[0].readyState == "complete" ) && $img[0].naturalWidth && $img[0].naturalHeight ) {
+ $img.trigger( 'load' );
+
+ } else if( $img[0].error ) {
+ $img.trigger( 'error' );
+
+ } else {
+
+ slide.timouts = setTimeout(function() {
+ if ( !$img[0].complete && !slide.hasError ) {
+ self.showLoading( slide );
+ }
+
+ }, 100);
+
+ }
+
+ },
+
+
+ // Create iframe wrapper, iframe and bindings
+ // ==========================================
+
+ setIframe : function( slide ) {
+ var self = this,
+ opts = slide.opts.iframe,
+ $slide = slide.$slide,
+ $iframe;
+
+ slide.$content = $('')
+ .css( opts.css )
+ .appendTo( $slide );
+
+ $iframe = $( opts.tpl.replace(/\{rnd\}/g, new Date().getTime()) )
+ .attr( opts.attr )
+ .appendTo( slide.$content );
+
+ if ( opts.preload ) {
+
+ self.showLoading( slide );
+
+ // Unfortunately, it is not always possible to determine if iframe is successfully loaded
+ // (due to browser security policy)
+
+ $iframe.on('load.fb error.fb', function(e) {
+ this.isReady = 1;
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.afterLoad( slide );
+ });
+
+ // Recalculate iframe content size
+ // ===============================
+
+ $slide.on('refresh.fb', function() {
+ var $wrap = slide.$content,
+ frameWidth = opts.css.width,
+ frameHeight = opts.css.height,
+ scrollWidth,
+ $contents,
+ $body;
+
+ if ( $iframe[0].isReady !== 1 ) {
+ return;
+ }
+
+ // Check if content is accessible,
+ // it will fail if frame is not with the same origin
+
+ try {
+ $contents = $iframe.contents();
+ $body = $contents.find('body');
+
+ } catch (ignore) {}
+
+ // Calculate dimensions for the wrapper
+ if ( $body && $body.length ) {
+
+ if ( frameWidth === undefined ) {
+ scrollWidth = $iframe[0].contentWindow.document.documentElement.scrollWidth;
+
+ frameWidth = Math.ceil( $body.outerWidth(true) + ( $wrap.width() - scrollWidth ) );
+ frameWidth += $wrap.outerWidth() - $wrap.innerWidth();
+ }
+
+ if ( frameHeight === undefined ) {
+ frameHeight = Math.ceil( $body.outerHeight(true) );
+ frameHeight += $wrap.outerHeight() - $wrap.innerHeight();
+ }
+
+ // Resize wrapper to fit iframe content
+ if ( frameWidth ) {
+ $wrap.width( frameWidth );
+ }
+
+ if ( frameHeight ) {
+ $wrap.height( frameHeight );
+ }
+ }
+
+ $wrap.removeClass( 'fancybox-is-hidden' );
+
+ });
+
+ } else {
+
+ this.afterLoad( slide );
+
+ }
+
+ $iframe.attr( 'src', slide.src );
+
+ if ( slide.opts.smallBtn === true ) {
+ slide.$content.prepend( self.translate( slide, slide.opts.btnTpl.smallBtn ) );
+ }
+
+ // Remove iframe if closing or changing gallery item
+ $slide.one( 'onReset', function () {
+
+ // This helps IE not to throw errors when closing
+ try {
+
+ $( this ).find( 'iframe' ).hide().attr( 'src', '//about:blank' );
+
+ } catch ( ignore ) {}
+
+ $( this ).empty();
+
+ slide.isLoaded = false;
+
+ });
+
+ },
+
+
+ // Wrap and append content to the slide
+ // ======================================
+
+ setContent : function ( slide, content ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ self.hideLoading( slide );
+
+ slide.$slide.empty();
+
+ if ( isQuery( content ) && content.parent().length ) {
+
+ // If content is a jQuery object, then it will be moved to the slide.
+ // The placeholder is created so we will know where to put it back.
+ // If user is navigating gallery fast, then the content might be already inside fancyBox
+ // =====================================================================================
+
+ // Make sure content is not already moved to fancyBox
+ content.parent( '.fancybox-slide--inline' ).trigger( 'onReset' );
+
+ // Create temporary element marking original place of the content
+ slide.$placeholder = $( '' ).hide().insertAfter( content );
+
+ // Make sure content is visible
+ content.css('display', 'inline-block');
+
+ } else if ( !slide.hasError ) {
+
+ // If content is just a plain text, try to convert it to html
+ if ( $.type( content ) === 'string' ) {
+ content = $('').append( $.trim( content ) ).contents();
+
+ // If we have text node, then add wrapping element to make vertical alignment work
+ if ( content[0].nodeType === 3 ) {
+ content = $('').html( content );
+ }
+ }
+
+ // If "filter" option is provided, then filter content
+ if ( slide.opts.filter ) {
+ content = $('').html( content ).find( slide.opts.filter );
+ }
+
+ }
+
+ slide.$slide.one('onReset', function () {
+
+ // Put content back
+ if ( slide.$placeholder ) {
+ slide.$placeholder.after( content.hide() ).remove();
+
+ slide.$placeholder = null;
+ }
+
+ // Remove custom close button
+ if ( slide.$smallBtn ) {
+ slide.$smallBtn.remove();
+
+ slide.$smallBtn = null;
+ }
+
+ // Remove content and mark slide as not loaded
+ if ( !slide.hasError ) {
+ $(this).empty();
+
+ slide.isLoaded = false;
+ }
+
+ });
+
+ slide.$content = $( content ).appendTo( slide.$slide );
+
+ this.afterLoad( slide );
+ },
+
+ // Display error message
+ // =====================
+
+ setError : function ( slide ) {
+
+ slide.hasError = true;
+
+ slide.$slide.removeClass( 'fancybox-slide--' + slide.type );
+
+ this.setContent( slide, this.translate( slide, slide.opts.errorTpl ) );
+
+ },
+
+
+ // Show loading icon inside the slide
+ // ==================================
+
+ showLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && !slide.$spinner ) {
+ slide.$spinner = $( self.opts.spinnerTpl ).appendTo( slide.$slide );
+ }
+
+ },
+
+ // Remove loading icon from the slide
+ // ==================================
+
+ hideLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && slide.$spinner ) {
+ slide.$spinner.remove();
+
+ delete slide.$spinner;
+ }
+
+ },
+
+
+ // Adjustments after slide content has been loaded
+ // ===============================================
+
+ afterLoad : function( slide ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.isLoading = false;
+ slide.isLoaded = true;
+
+ self.trigger( 'afterLoad', slide );
+
+ self.hideLoading( slide );
+
+ if ( slide.opts.smallBtn && !slide.$smallBtn ) {
+ slide.$smallBtn = $( self.translate( slide, slide.opts.btnTpl.smallBtn ) ).appendTo( slide.$content.filter('div,form').first() );
+ }
+
+ if ( slide.opts.protect && slide.$content && !slide.hasError ) {
+
+ // Disable right click
+ slide.$content.on( 'contextmenu.fb', function( e ) {
+ if ( e.button == 2 ) {
+ e.preventDefault();
+ }
+
+ return true;
+ });
+
+ // Add fake element on top of the image
+ // This makes a bit harder for user to select image
+ if ( slide.type === 'image' ) {
+ $( '' ).appendTo( slide.$content );
+ }
+
+ }
+
+ self.revealContent( slide );
+
+ },
+
+
+ // Make content visible
+ // This method is called right after content has been loaded or
+ // user navigates gallery and transition should start
+ // ============================================================
+
+ revealContent : function( slide ) {
+
+ var self = this;
+ var $slide = slide.$slide;
+
+ var effect, effectClassName, duration, opacity, end, start = false;
+
+ effect = slide.opts[ self.firstRun ? 'animationEffect' : 'transitionEffect' ];
+ duration = slide.opts[ self.firstRun ? 'animationDuration' : 'transitionDuration' ];
+
+ duration = parseInt( slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10 );
+
+ if ( slide.isMoved || slide.pos !== self.currPos || !duration ) {
+ effect = false;
+ }
+
+ // Check if can zoom
+ if ( effect === 'zoom' && !( slide.pos === self.currPos && duration && slide.type === 'image' && !slide.hasError && ( start = self.getThumbPos( slide ) ) ) ) {
+ effect = 'fade';
+ }
+
+ // Zoom animation
+ // ==============
+
+ if ( effect === 'zoom' ) {
+ end = self.getFitPos( slide );
+
+ end.scaleX = end.width / start.width;
+ end.scaleY = end.height / start.height;
+
+ delete end.width;
+ delete end.height;
+
+ // Check if we need to animate opacity
+ opacity = slide.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( slide.width / slide.height - start.width / start.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ start.opacity = 0.1;
+ end.opacity = 1;
+ }
+
+ // Draw image at start position
+ $.fancybox.setTranslate( slide.$content.removeClass( 'fancybox-is-hidden' ), start );
+
+ forceRedraw( slide.$content );
+
+ // Start animation
+ $.fancybox.animate( slide.$content, end, duration, function() {
+ self.complete();
+ });
+
+ return;
+ }
+
+ self.updateSlide( slide );
+
+
+ // Simply show content
+ // ===================
+
+ if ( !effect ) {
+ forceRedraw( $slide );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ return;
+ }
+
+ $.fancybox.stop( $slide );
+
+ effectClassName = 'fancybox-animated fancybox-slide--' + ( slide.pos >= self.prevPos ? 'next' : 'previous' ) + ' fancybox-fx-' + effect;
+
+ $slide.removeAttr( 'style' ).removeClass( 'fancybox-slide--current fancybox-slide--next fancybox-slide--previous' ).addClass( effectClassName );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ //Force reflow for CSS3 transitions
+ forceRedraw( $slide );
+
+ $.fancybox.animate( $slide, 'fancybox-slide--current', duration, function(e) {
+ $slide.removeClass( effectClassName ).removeAttr( 'style' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ }, true);
+
+ },
+
+
+ // Check if we can and have to zoom from thumbnail
+ //================================================
+
+ getThumbPos : function( slide ) {
+
+ var self = this;
+ var rez = false;
+
+ // Check if element is inside the viewport by at least 1 pixel
+ var isElementVisible = function( $el ) {
+ var element = $el[0];
+
+ var elementRect = element.getBoundingClientRect();
+ var parentRects = [];
+
+ var visibleInAllParents;
+
+ while ( element.parentElement !== null ) {
+ if ( $(element.parentElement).css('overflow') === 'hidden' || $(element.parentElement).css('overflow') === 'auto' ) {
+ parentRects.push(element.parentElement.getBoundingClientRect());
+ }
+
+ element = element.parentElement;
+ }
+
+ visibleInAllParents = parentRects.every(function(parentRect){
+ var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
+ var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
+
+ return visiblePixelX > 0 && visiblePixelY > 0;
+ });
+
+ return visibleInAllParents &&
+ elementRect.bottom > 0 && elementRect.right > 0 &&
+ elementRect.left < $(window).width() && elementRect.top < $(window).height();
+ };
+
+ var $thumb = slide.opts.$thumb;
+ var thumbPos = $thumb ? $thumb.offset() : 0;
+ var slidePos;
+
+ if ( thumbPos && $thumb[0].ownerDocument === document && isElementVisible( $thumb ) ) {
+ slidePos = self.$refs.stage.offset();
+
+ rez = {
+ top : thumbPos.top - slidePos.top + parseFloat( $thumb.css( "border-top-width" ) || 0 ),
+ left : thumbPos.left - slidePos.left + parseFloat( $thumb.css( "border-left-width" ) || 0 ),
+ width : $thumb.width(),
+ height : $thumb.height(),
+ scaleX : 1,
+ scaleY : 1
+ };
+ }
+
+ return rez;
+ },
+
+
+ // Final adjustments after current gallery item is moved to position
+ // and it`s content is loaded
+ // ==================================================================
+
+ complete : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var slides = {};
+
+ if ( current.isMoved || !current.isLoaded || current.isComplete ) {
+ return;
+ }
+
+ current.isComplete = true;
+
+ current.$slide.siblings().trigger( 'onReset' );
+
+ // Trigger any CSS3 transiton inside the slide
+ forceRedraw( current.$slide );
+
+ current.$slide.addClass( 'fancybox-slide--complete' );
+
+ // Remove unnecessary slides
+ $.each( self.slides, function( key, slide ) {
+ if ( slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1 ) {
+ slides[ slide.pos ] = slide;
+
+ } else if ( slide ) {
+
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.off().remove();
+ }
+ });
+
+ self.slides = slides;
+
+ self.updateCursor();
+
+ self.trigger( 'afterShow' );
+
+ // Try to focus on the first focusable element
+ if ( $( document.activeElement ).is( '[disabled]' ) || ( current.opts.autoFocus && !( current.type == 'image' || current.type === 'iframe' ) ) ) {
+ self.focus();
+ }
+
+ },
+
+
+ // Preload next and previous slides
+ // ================================
+
+ preload : function() {
+ var self = this;
+ var next, prev;
+
+ if ( self.group.length < 2 ) {
+ return;
+ }
+
+ next = self.slides[ self.currPos + 1 ];
+ prev = self.slides[ self.currPos - 1 ];
+
+ if ( next && next.type === 'image' ) {
+ self.loadSlide( next );
+ }
+
+ if ( prev && prev.type === 'image' ) {
+ self.loadSlide( prev );
+ }
+
+ },
+
+
+ // Try to find and focus on the first focusable element
+ // ====================================================
+
+ focus : function() {
+ var current = this.current;
+ var $el;
+
+ if ( this.isClosing ) {
+ return;
+ }
+
+ if ( current && current.isComplete ) {
+
+ // Look for first input with autofocus attribute
+ $el = current.$slide.find('input[autofocus]:enabled:visible:first');
+
+ if ( !$el.length ) {
+ $el = current.$slide.find('button,:input,[tabindex],a').filter(':enabled:visible:first');
+ }
+ }
+
+ $el = $el && $el.length ? $el : this.$refs.container;
+
+ $el.focus();
+ },
+
+
+ // Activates current instance - brings container to the front and enables keyboard,
+ // notifies other instances about deactivating
+ // =================================================================================
+
+ activate : function () {
+ var self = this;
+
+ // Deactivate all instances
+ $( '.fancybox-container' ).each(function () {
+ var instance = $(this).data( 'FancyBox' );
+
+ // Skip self and closing instances
+ if (instance && instance.id !== self.id && !instance.isClosing) {
+ instance.trigger( 'onDeactivate' );
+
+ instance.removeEvents();
+
+ instance.isVisible = false;
+ }
+
+ });
+
+ self.isVisible = true;
+
+ if ( self.current || self.isIdle ) {
+ self.update();
+
+ self.updateControls();
+ }
+
+ self.trigger( 'onActivate' );
+
+ self.addEvents();
+ },
+
+
+ // Start closing procedure
+ // This will start "zoom-out" animation if needed and clean everything up afterwards
+ // =================================================================================
+
+ close : function( e, d ) {
+
+ var self = this;
+ var current = self.current;
+
+ var effect, duration;
+ var $what, opacity, start, end;
+
+ var done = function() {
+ self.cleanUp( e );
+ };
+
+ if ( self.isClosing ) {
+ return false;
+ }
+
+ self.isClosing = true;
+
+ // If beforeClose callback prevents closing, make sure content is centered
+ if ( self.trigger( 'beforeClose', e ) === false ) {
+ self.isClosing = false;
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ return false;
+ }
+
+ // Remove all events
+ // If there are multiple instances, they will be set again by "activate" method
+ self.removeEvents();
+
+ if ( current.timouts ) {
+ clearTimeout( current.timouts );
+ }
+
+ $what = current.$content;
+ effect = current.opts.animationEffect;
+ duration = $.isNumeric( d ) ? d : ( effect ? current.opts.animationDuration : 0 );
+
+ // Remove other slides
+ current.$slide.off( transitionEnd ).removeClass( 'fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated' );
+
+ current.$slide.siblings().trigger( 'onReset' ).remove();
+
+ // Trigger animations
+ if ( duration ) {
+ self.$refs.container.removeClass( 'fancybox-is-open' ).addClass( 'fancybox-is-closing' );
+ }
+
+ // Clean up
+ self.hideLoading( current );
+
+ self.hideControls();
+
+ self.updateCursor();
+
+ // Check if possible to zoom-out
+ if ( effect === 'zoom' && !( e !== true && $what && duration && current.type === 'image' && !current.hasError && ( end = self.getThumbPos( current ) ) ) ) {
+ effect = 'fade';
+ }
+
+ if ( effect === 'zoom' ) {
+ $.fancybox.stop( $what );
+
+ start = $.fancybox.getTranslate( $what );
+
+ start.width = start.width * start.scaleX;
+ start.height = start.height * start.scaleY;
+
+ // Check if we need to animate opacity
+ opacity = current.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( current.width / current.height - end.width / end.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ end.opacity = 0;
+ }
+
+ start.scaleX = start.width / end.width;
+ start.scaleY = start.height / end.height;
+
+ start.width = end.width;
+ start.height = end.height;
+
+ $.fancybox.setTranslate( current.$content, start );
+
+ forceRedraw( current.$content );
+
+ $.fancybox.animate( current.$content, end, duration, done );
+
+ return true;
+ }
+
+ if ( effect && duration ) {
+
+ // If skip animation
+ if ( e === true ) {
+ setTimeout( done, duration );
+
+ } else {
+ $.fancybox.animate( current.$slide.removeClass( 'fancybox-slide--current' ), 'fancybox-animated fancybox-slide--previous fancybox-fx-' + effect, duration, done );
+ }
+
+ } else {
+ done();
+ }
+
+ return true;
+ },
+
+
+ // Final adjustments after removing the instance
+ // =============================================
+
+ cleanUp : function( e ) {
+ var self = this,
+ $body = $( 'body' ),
+ instance,
+ offset;
+
+ self.current.$slide.trigger( 'onReset' );
+
+ self.$refs.container.empty().remove();
+
+ self.trigger( 'afterClose', e );
+
+ // Place back focus
+ if ( self.$lastFocus && !!self.current.opts.backFocus ) {
+ self.$lastFocus.focus();
+ }
+
+ self.current = null;
+
+ // Check if there are other instances
+ instance = $.fancybox.getInstance();
+
+ if ( instance ) {
+ instance.activate();
+
+ } else {
+
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+
+ $body.removeClass( 'fancybox-active compensate-for-scrollbar' );
+
+ if ( $body.hasClass( 'fancybox-iosfix' ) ) {
+ offset = parseInt(document.body.style.top, 10);
+
+ $body.removeClass( 'fancybox-iosfix' ).css( 'top', '' ).scrollTop( offset * -1 );
+ }
+
+ $( '#fancybox-style-noscroll' ).remove();
+
+ }
+
+ },
+
+
+ // Call callback and trigger an event
+ // ==================================
+
+ trigger : function( name, slide ) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ self = this,
+ obj = slide && slide.opts ? slide : self.current,
+ rez;
+
+ if ( obj ) {
+ args.unshift( obj );
+
+ } else {
+ obj = self;
+ }
+
+ args.unshift( self );
+
+ if ( $.isFunction( obj.opts[ name ] ) ) {
+ rez = obj.opts[ name ].apply( obj, args );
+ }
+
+ if ( rez === false ) {
+ return rez;
+ }
+
+ if ( name === 'afterClose' || !self.$refs ) {
+ $D.trigger( name + '.fb', args );
+
+ } else {
+ self.$refs.container.trigger( name + '.fb', args );
+ }
+
+ },
+
+
+ // Update infobar values, navigation button states and reveal caption
+ // ==================================================================
+
+ updateControls : function ( force ) {
+
+ var self = this;
+
+ var current = self.current,
+ index = current.index,
+ caption = current.opts.caption,
+ $container = self.$refs.container,
+ $caption = self.$refs.caption;
+
+ // Recalculate content dimensions
+ current.$slide.trigger( 'refresh' );
+
+ self.$caption = caption && caption.length ? $caption.html( caption ) : null;
+
+ if ( !self.isHiddenControls && !self.isIdle ) {
+ self.showControls();
+ }
+
+ // Update info and navigation elements
+ $container.find('[data-fancybox-count]').html( self.group.length );
+ $container.find('[data-fancybox-index]').html( index + 1 );
+
+ $container.find('[data-fancybox-prev]').prop( 'disabled', ( !current.opts.loop && index <= 0 ) );
+ $container.find('[data-fancybox-next]').prop( 'disabled', ( !current.opts.loop && index >= self.group.length - 1 ) );
+
+ if ( current.type === 'image' ) {
+
+ // Update download button source
+ $container.find('[data-fancybox-download]').attr( 'href', current.opts.image.src || current.src ).show();
+
+ } else {
+ $container.find('[data-fancybox-download],[data-fancybox-zoom]').hide();
+ }
+ },
+
+ // Hide toolbar and caption
+ // ========================
+
+ hideControls : function () {
+
+ this.isHiddenControls = true;
+
+ this.$refs.container.removeClass( 'fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav' );
+
+ },
+
+ showControls : function() {
+ var self = this;
+ var opts = self.current ? self.current.opts : self.opts;
+ var $container = self.$refs.container;
+
+ self.isHiddenControls = false;
+ self.idleSecondsCounter = 0;
+
+ $container
+ .toggleClass( 'fancybox-show-toolbar', !!( opts.toolbar && opts.buttons ) )
+ .toggleClass( 'fancybox-show-infobar', !!( opts.infobar && self.group.length > 1 ) )
+ .toggleClass( 'fancybox-show-nav', !!( opts.arrows && self.group.length > 1 ) )
+ .toggleClass( 'fancybox-is-modal', !!opts.modal );
+
+ if ( self.$caption ) {
+ $container.addClass( 'fancybox-show-caption ');
+
+ } else {
+ $container.removeClass( 'fancybox-show-caption' );
+ }
+
+ },
+
+
+ // Toggle toolbar and caption
+ // ==========================
+
+ toggleControls : function() {
+ if ( this.isHiddenControls ) {
+ this.showControls();
+
+ } else {
+ this.hideControls();
+ }
+
+ },
+
+
+ });
+
+
+ $.fancybox = {
+
+ version : "3.2.5",
+ defaults : defaults,
+
+
+ // Get current instance and execute a command.
+ //
+ // Examples of usage:
+ //
+ // $instance = $.fancybox.getInstance();
+ // $.fancybox.getInstance().jumpTo( 1 );
+ // $.fancybox.getInstance( 'jumpTo', 1 );
+ // $.fancybox.getInstance( function() {
+ // console.info( this.currIndex );
+ // });
+ // ======================================================
+
+ getInstance : function ( command ) {
+ var instance = $('.fancybox-container:not(".fancybox-is-closing"):last').data( 'FancyBox' );
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ if ( instance instanceof FancyBox ) {
+
+ if ( $.type( command ) === 'string' ) {
+ instance[ command ].apply( instance, args );
+
+ } else if ( $.type( command ) === 'function' ) {
+ command.apply( instance, args );
+ }
+
+ return instance;
+ }
+
+ return false;
+
+ },
+
+
+ // Create new instance
+ // ===================
+
+ open : function ( items, opts, index ) {
+ return new FancyBox( items, opts, index );
+ },
+
+
+ // Close current or all instances
+ // ==============================
+
+ close : function ( all ) {
+ var instance = this.getInstance();
+
+ if ( instance ) {
+ instance.close();
+
+ // Try to find and close next instance
+
+ if ( all === true ) {
+ this.close();
+ }
+ }
+
+ },
+
+ // Close instances and unbind all events
+ // ==============================
+
+ destroy : function() {
+
+ this.close( true );
+
+ $D.off( 'click.fb-start' );
+
+ },
+
+
+ // Try to detect mobile devices
+ // ============================
+
+ isMobile : document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
+
+
+ // Detect if 'translate3d' support is available
+ // ============================================
+
+ use3d : (function() {
+ var div = document.createElement('div');
+
+ return window.getComputedStyle && window.getComputedStyle( div ).getPropertyValue('transform') && !(document.documentMode && document.documentMode < 11);
+ }()),
+
+ // Helper function to get current visual state of an element
+ // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
+ // =====================================================================
+
+ getTranslate : function( $el ) {
+ var matrix;
+
+ if ( !$el || !$el.length ) {
+ return false;
+ }
+
+ matrix = $el.eq( 0 ).css('transform');
+
+ if ( matrix && matrix.indexOf( 'matrix' ) !== -1 ) {
+ matrix = matrix.split('(')[1];
+ matrix = matrix.split(')')[0];
+ matrix = matrix.split(',');
+ } else {
+ matrix = [];
+ }
+
+ if ( matrix.length ) {
+
+ // If IE
+ if ( matrix.length > 10 ) {
+ matrix = [ matrix[13], matrix[12], matrix[0], matrix[5] ];
+
+ } else {
+ matrix = [ matrix[5], matrix[4], matrix[0], matrix[3]];
+ }
+
+ matrix = matrix.map(parseFloat);
+
+ } else {
+ matrix = [ 0, 0, 1, 1 ];
+
+ var transRegex = /\.*translate\((.*)px,(.*)px\)/i;
+ var transRez = transRegex.exec( $el.eq( 0 ).attr('style') );
+
+ if ( transRez ) {
+ matrix[ 0 ] = parseFloat( transRez[2] );
+ matrix[ 1 ] = parseFloat( transRez[1] );
+ }
+ }
+
+ return {
+ top : matrix[ 0 ],
+ left : matrix[ 1 ],
+ scaleX : matrix[ 2 ],
+ scaleY : matrix[ 3 ],
+ opacity : parseFloat( $el.css('opacity') ),
+ width : $el.width(),
+ height : $el.height()
+ };
+
+ },
+
+
+ // Shortcut for setting "translate3d" properties for element
+ // Can set be used to set opacity, too
+ // ========================================================
+
+ setTranslate : function( $el, props ) {
+ var str = '';
+ var css = {};
+
+ if ( !$el || !props ) {
+ return;
+ }
+
+ if ( props.left !== undefined || props.top !== undefined ) {
+ str = ( props.left === undefined ? $el.position().left : props.left ) + 'px, ' + ( props.top === undefined ? $el.position().top : props.top ) + 'px';
+
+ if ( this.use3d ) {
+ str = 'translate3d(' + str + ', 0px)';
+
+ } else {
+ str = 'translate(' + str + ')';
+ }
+ }
+
+ if ( props.scaleX !== undefined && props.scaleY !== undefined ) {
+ str = (str.length ? str + ' ' : '') + 'scale(' + props.scaleX + ', ' + props.scaleY + ')';
+ }
+
+ if ( str.length ) {
+ css.transform = str;
+ }
+
+ if ( props.opacity !== undefined ) {
+ css.opacity = props.opacity;
+ }
+
+ if ( props.width !== undefined ) {
+ css.width = props.width;
+ }
+
+ if ( props.height !== undefined ) {
+ css.height = props.height;
+ }
+
+ return $el.css( css );
+ },
+
+
+ // Simple CSS transition handler
+ // =============================
+
+ animate : function ( $el, to, duration, callback, leaveAnimationName ) {
+ if ( $.isFunction( duration ) ) {
+ callback = duration;
+ duration = null;
+ }
+
+ if ( !$.isPlainObject( to ) ) {
+ $el.removeAttr('style');
+ }
+
+ $el.on( transitionEnd, function(e) {
+
+ // Skip events from child elements and z-index change
+ if ( e && e.originalEvent && ( !$el.is( e.originalEvent.target ) || e.originalEvent.propertyName == 'z-index' ) ) {
+ return;
+ }
+
+ $.fancybox.stop( $el );
+
+ if ( $.isPlainObject( to ) ) {
+
+ if ( to.scaleX !== undefined && to.scaleY !== undefined ) {
+ $el.css( 'transition-duration', '' );
+
+ to.width = Math.round( $el.width() * to.scaleX );
+ to.height = Math.round( $el.height() * to.scaleY );
+
+ to.scaleX = 1;
+ to.scaleY = 1;
+
+ $.fancybox.setTranslate( $el, to );
+ }
+
+ } else if ( leaveAnimationName !== true ) {
+ $el.removeClass( to );
+ }
+
+ if ( $.isFunction( callback ) ) {
+ callback( e );
+ }
+
+ });
+
+ if ( $.isNumeric( duration ) ) {
+ $el.css( 'transition-duration', duration + 'ms' );
+ }
+
+ if ( $.isPlainObject( to ) ) {
+ $.fancybox.setTranslate( $el, to );
+
+ } else {
+ $el.addClass( to );
+ }
+
+ if ( to.scaleX && $el.hasClass( 'fancybox-image-wrap' ) ) {
+ $el.parent().addClass( 'fancybox-is-scaling' );
+ }
+
+ // Make sure that `transitionend` callback gets fired
+ $el.data("timer", setTimeout(function() {
+ $el.trigger( 'transitionend' );
+ }, duration + 16));
+
+ },
+
+ stop : function( $el ) {
+ clearTimeout( $el.data("timer") );
+
+ $el.off( 'transitionend' ).css( 'transition-duration', '' );
+
+ if ( $el.hasClass( 'fancybox-image-wrap' ) ) {
+ $el.parent().removeClass( 'fancybox-is-scaling' );
+ }
+ }
+
+ };
+
+
+ // Default click handler for "fancyboxed" links
+ // ============================================
+
+ function _run( e ) {
+ var $target = $( e.currentTarget ),
+ opts = e.data ? e.data.options : {},
+ value = $target.attr( 'data-fancybox' ) || '',
+ index = 0,
+ items = [];
+
+ // Avoid opening multiple times
+ if ( e.isDefaultPrevented() ) {
+ return;
+ }
+
+ e.preventDefault();
+
+ // Get all related items and find index for clicked one
+ if ( value ) {
+ items = opts.selector ? $( opts.selector ) : ( e.data ? e.data.items : [] );
+ items = items.length ? items.filter( '[data-fancybox="' + value + '"]' ) : $( '[data-fancybox="' + value + '"]' );
+
+ index = items.index( $target );
+
+ // Sometimes current item can not be found
+ // (for example, when slider clones items)
+ if ( index < 0 ) {
+ index = 0;
+ }
+
+ } else {
+ items = [ $target ];
+ }
+
+ $.fancybox.open( items, opts, index );
+ }
+
+
+ // Create a jQuery plugin
+ // ======================
+
+ $.fn.fancybox = function (options) {
+ var selector;
+
+ options = options || {};
+ selector = options.selector || false;
+
+ if ( selector ) {
+
+ $( 'body' ).off( 'click.fb-start', selector ).on( 'click.fb-start', selector, {
+ options : options
+ }, _run );
+
+ } else {
+
+ this.off( 'click.fb-start' ).on( 'click.fb-start', {
+ items : this,
+ options : options
+ }, _run);
+
+ }
+
+ return this;
+ };
+
+
+ // Self initializing plugin
+ // ========================
+
+ $D.on( 'click.fb-start', '[data-fancybox]', _run );
+
+}( window, document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Media
+// Adds additional media type support
+//
+// ==========================================================================
+;(function ($) {
+
+ 'use strict';
+
+ // Formats matching url to final form
+
+ var format = function (url, rez, params) {
+ if ( !url ) {
+ return;
+ }
+
+ params = params || '';
+
+ if ( $.type(params) === "object" ) {
+ params = $.param(params, true);
+ }
+
+ $.each(rez, function (key, value) {
+ url = url.replace('$' + key, value || '');
+ });
+
+ if (params.length) {
+ url += (url.indexOf('?') > 0 ? '&' : '?') + params;
+ }
+
+ return url;
+ };
+
+ // Object containing properties for each media type
+
+ var defaults = {
+ youtube : {
+ matcher : /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
+ params : {
+ autoplay : 1,
+ autohide : 1,
+ fs : 1,
+ rel : 0,
+ hd : 1,
+ wmode : 'transparent',
+ enablejsapi : 1,
+ html5 : 1
+ },
+ paramPlace : 8,
+ type : 'iframe',
+ url : '//www.youtube.com/embed/$4',
+ thumb : '//img.youtube.com/vi/$4/hqdefault.jpg'
+ },
+
+ vimeo : {
+ matcher : /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
+ params : {
+ autoplay : 1,
+ hd : 1,
+ show_title : 1,
+ show_byline : 1,
+ show_portrait : 0,
+ fullscreen : 1,
+ api : 1
+ },
+ paramPlace : 3,
+ type : 'iframe',
+ url : '//player.vimeo.com/video/$2'
+ },
+
+ metacafe : {
+ matcher : /metacafe.com\/watch\/(\d+)\/(.*)?/,
+ type : 'iframe',
+ url : '//www.metacafe.com/embed/$1/?ap=1'
+ },
+
+ dailymotion : {
+ matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
+ params : {
+ additionalInfos : 0,
+ autoStart : 1
+ },
+ type : 'iframe',
+ url : '//www.dailymotion.com/embed/video/$1'
+ },
+
+ vine : {
+ matcher : /vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,
+ type : 'iframe',
+ url : '//vine.co/v/$1/embed/simple'
+ },
+
+ instagram : {
+ matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
+ type : 'image',
+ url : '//$1/p/$2/media/?size=l'
+ },
+
+ // Examples:
+ // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
+ // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
+ // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
+ gmap_place : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/?ll=' + ( rez[9] ? rez[9] + '&z=' + Math.floor( rez[10] ) + ( rez[12] ? rez[12].replace(/^\//, "&") : '' ) : rez[12] ) + '&output=' + ( rez[12] && rez[12].indexOf('layer=c') > 0 ? 'svembed' : 'embed' );
+ }
+ },
+
+ // Examples:
+ // https://www.google.com/maps/search/Empire+State+Building/
+ // https://www.google.com/maps/search/?api=1&query=centurylink+field
+ // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
+ gmap_search : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/maps?q=' + rez[5].replace('query=', 'q=').replace('api=1', '') + '&output=embed';
+ }
+ }
+ };
+
+ $(document).on('objectNeedsType.fb', function (e, instance, item) {
+
+ var url = item.src || '',
+ type = false,
+ media,
+ thumb,
+ rez,
+ params,
+ urlParams,
+ paramObj,
+ provider;
+
+ media = $.extend( true, {}, defaults, item.opts.media );
+
+ // Look for any matching media type
+ $.each(media, function ( providerName, providerOpts ) {
+ rez = url.match( providerOpts.matcher );
+
+ if ( !rez ) {
+ return;
+ }
+
+ type = providerOpts.type;
+ paramObj = {};
+
+ if ( providerOpts.paramPlace && rez[ providerOpts.paramPlace ] ) {
+ urlParams = rez[ providerOpts.paramPlace ];
+
+ if ( urlParams[ 0 ] == '?' ) {
+ urlParams = urlParams.substring(1);
+ }
+
+ urlParams = urlParams.split('&');
+
+ for ( var m = 0; m < urlParams.length; ++m ) {
+ var p = urlParams[ m ].split('=', 2);
+
+ if ( p.length == 2 ) {
+ paramObj[ p[0] ] = decodeURIComponent( p[1].replace(/\+/g, " ") );
+ }
+ }
+ }
+
+ params = $.extend( true, {}, providerOpts.params, item.opts[ providerName ], paramObj );
+
+ url = $.type( providerOpts.url ) === "function" ? providerOpts.url.call( this, rez, params, item ) : format( providerOpts.url, rez, params );
+ thumb = $.type( providerOpts.thumb ) === "function" ? providerOpts.thumb.call( this, rez, params, item ) : format( providerOpts.thumb, rez );
+
+ if ( providerName === 'vimeo' ) {
+ url = url.replace('&%23', '#');
+ }
+
+ return false;
+ });
+
+ // If it is found, then change content type and update the url
+
+ if ( type ) {
+ item.src = url;
+ item.type = type;
+
+ if ( !item.opts.thumb && !( item.opts.$thumb && item.opts.$thumb.length ) ) {
+ item.opts.thumb = thumb;
+ }
+
+ if ( type === 'iframe' ) {
+ $.extend(true, item.opts, {
+ iframe : {
+ preload : false,
+ attr : {
+ scrolling : "no"
+ }
+ }
+ });
+
+ item.contentProvider = provider;
+
+ item.opts.slideClass += ' fancybox-slide--' + ( provider == 'gmap_place' || provider == 'gmap_search' ? 'map' : 'video' );
+ }
+
+ } else if ( url ) {
+ item.type = item.opts.defaultType;
+ }
+
+ });
+
+}( window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Guestures
+// Adds touch guestures, handles click and tap events
+//
+// ==========================================================================
+;(function (window, document, $) {
+ 'use strict';
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ var cancelAFrame = (function () {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.mozCancelAnimationFrame ||
+ window.oCancelAnimationFrame ||
+ function (id) {
+ window.clearTimeout(id);
+ };
+ })();
+
+
+ var pointers = function( e ) {
+ var result = [];
+
+ e = e.originalEvent || e || window.e;
+ e = e.touches && e.touches.length ? e.touches : ( e.changedTouches && e.changedTouches.length ? e.changedTouches : [ e ] );
+
+ for ( var key in e ) {
+
+ if ( e[ key ].pageX ) {
+ result.push( { x : e[ key ].pageX, y : e[ key ].pageY } );
+
+ } else if ( e[ key ].clientX ) {
+ result.push( { x : e[ key ].clientX, y : e[ key ].clientY } );
+ }
+ }
+
+ return result;
+ };
+
+ var distance = function( point2, point1, what ) {
+ if ( !point1 || !point2 ) {
+ return 0;
+ }
+
+ if ( what === 'x' ) {
+ return point2.x - point1.x;
+
+ } else if ( what === 'y' ) {
+ return point2.y - point1.y;
+ }
+
+ return Math.sqrt( Math.pow( point2.x - point1.x, 2 ) + Math.pow( point2.y - point1.y, 2 ) );
+ };
+
+ var isClickable = function( $el ) {
+
+ if ( $el.is('a,area,button,[role="button"],input,label,select,summary,textarea') || $.isFunction( $el.get(0).onclick ) || $el.data('selectable') ) {
+ return true;
+ }
+
+ // Check for attributes like data-fancybox-next or data-fancybox-close
+ for ( var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++ ) {
+ if ( atts[i].nodeName.substr(0, 14) === 'data-fancybox-' ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ var hasScrollbars = function( el ) {
+ var overflowY = window.getComputedStyle( el )['overflow-y'];
+ var overflowX = window.getComputedStyle( el )['overflow-x'];
+
+ var vertical = (overflowY === 'scroll' || overflowY === 'auto') && el.scrollHeight > el.clientHeight;
+ var horizontal = (overflowX === 'scroll' || overflowX === 'auto') && el.scrollWidth > el.clientWidth;
+
+ return vertical || horizontal;
+ };
+
+ var isScrollable = function ( $el ) {
+ var rez = false;
+
+ while ( true ) {
+ rez = hasScrollbars( $el.get(0) );
+
+ if ( rez ) {
+ break;
+ }
+
+ $el = $el.parent();
+
+ if ( !$el.length || $el.hasClass( 'fancybox-stage' ) || $el.is( 'body' ) ) {
+ break;
+ }
+ }
+
+ return rez;
+ };
+
+
+ var Guestures = function ( instance ) {
+ var self = this;
+
+ self.instance = instance;
+
+ self.$bg = instance.$refs.bg;
+ self.$stage = instance.$refs.stage;
+ self.$container = instance.$refs.container;
+
+ self.destroy();
+
+ self.$container.on( 'touchstart.fb.touch mousedown.fb.touch', $.proxy(self, 'ontouchstart') );
+ };
+
+ Guestures.prototype.destroy = function() {
+ this.$container.off( '.fb.touch' );
+ };
+
+ Guestures.prototype.ontouchstart = function( e ) {
+ var self = this;
+
+ var $target = $( e.target );
+ var instance = self.instance;
+ var current = instance.current;
+ var $content = current.$content;
+
+ var isTouchDevice = ( e.type == 'touchstart' );
+
+ // Do not respond to both events
+ if ( isTouchDevice ) {
+ self.$container.off( 'mousedown.fb.touch' );
+ }
+
+ // Ignore clicks while zooming or closing
+ if ( !current || self.instance.isAnimating || self.instance.isClosing ) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ return;
+ }
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Ignore taping on links, buttons, input elements
+ if ( !$target.length || isClickable( $target ) || isClickable( $target.parent() ) ) {
+ return;
+ }
+
+ // Ignore clicks on the scrollbar
+ if ( e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ self.startPoints = pointers( e );
+
+ // Prevent zooming if already swiping
+ if ( !self.startPoints || ( self.startPoints.length > 1 && instance.isSliding ) ) {
+ return;
+ }
+
+ self.$target = $target;
+ self.$content = $content;
+ self.canTap = true;
+ self.opts = current.opts.touch;
+
+ $(document).off( '.fb.touch' );
+
+ $(document).on( isTouchDevice ? 'touchend.fb.touch touchcancel.fb.touch' : 'mouseup.fb.touch mouseleave.fb.touch', $.proxy(self, "ontouchend"));
+ $(document).on( isTouchDevice ? 'touchmove.fb.touch' : 'mousemove.fb.touch', $.proxy(self, "ontouchmove"));
+
+ if ( !(self.opts || instance.canPan() ) || !( $target.is( self.$stage ) || self.$stage.find( $target ).length ) ) {
+
+ // Prevent ghosting
+ if ( $target.is('img') ) {
+ e.preventDefault();
+ }
+
+ return;
+ }
+
+ e.stopPropagation();
+
+ if ( !( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) ) {
+ e.preventDefault();
+ }
+
+ self.canvasWidth = Math.round( current.$slide[0].clientWidth );
+ self.canvasHeight = Math.round( current.$slide[0].clientHeight );
+
+ self.startTime = new Date().getTime();
+ self.distanceX = self.distanceY = self.distance = 0;
+
+ self.isPanning = false;
+ self.isSwiping = false;
+ self.isZooming = false;
+
+ self.sliderStartPos = self.sliderLastPos || { top: 0, left: 0 };
+ self.contentStartPos = $.fancybox.getTranslate( self.$content );
+ self.contentLastPos = null;
+
+ if ( self.startPoints.length === 1 && !self.isZooming ) {
+ self.canTap = !instance.isSliding;
+
+ if ( current.type === 'image' && ( self.contentStartPos.width > self.canvasWidth + 1 || self.contentStartPos.height > self.canvasHeight + 1 ) ) {
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.isPanning = true;
+
+ } else {
+
+ self.isSwiping = true;
+ }
+
+ self.$container.addClass('fancybox-controls--isGrabbing');
+ }
+
+ if ( self.startPoints.length === 2 && !instance.isAnimating && !current.hasError && current.type === 'image' && ( current.isLoaded || current.$ghost ) ) {
+ self.isZooming = true;
+
+ self.isSwiping = false;
+ self.isPanning = false;
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.centerPointStartX = ( ( self.startPoints[0].x + self.startPoints[1].x ) * 0.5 ) - $(window).scrollLeft();
+ self.centerPointStartY = ( ( self.startPoints[0].y + self.startPoints[1].y ) * 0.5 ) - $(window).scrollTop();
+
+ self.percentageOfImageAtPinchPointX = ( self.centerPointStartX - self.contentStartPos.left ) / self.contentStartPos.width;
+ self.percentageOfImageAtPinchPointY = ( self.centerPointStartY - self.contentStartPos.top ) / self.contentStartPos.height;
+
+ self.startDistanceBetweenFingers = distance( self.startPoints[0], self.startPoints[1] );
+ }
+
+ };
+
+ Guestures.prototype.ontouchmove = function( e ) {
+
+ var self = this;
+
+ self.newPoints = pointers( e );
+
+ if ( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) {
+ e.stopPropagation();
+
+ self.canTap = false;
+
+ return;
+ }
+
+ if ( !( self.opts || self.instance.canPan() ) || !self.newPoints || !self.newPoints.length ) {
+ return;
+ }
+
+ self.distanceX = distance( self.newPoints[0], self.startPoints[0], 'x' );
+ self.distanceY = distance( self.newPoints[0], self.startPoints[0], 'y' );
+
+ self.distance = distance( self.newPoints[0], self.startPoints[0] );
+
+ // Skip false ontouchmove events (Chrome)
+ if ( self.distance > 0 ) {
+
+ if ( !( self.$target.is( self.$stage ) || self.$stage.find( self.$target ).length ) ) {
+ return;
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ if ( self.isSwiping ) {
+ self.onSwipe();
+
+ } else if ( self.isPanning ) {
+ self.onPan();
+
+ } else if ( self.isZooming ) {
+ self.onZoom();
+ }
+
+ }
+
+ };
+
+ Guestures.prototype.onSwipe = function() {
+
+ var self = this;
+
+ var swiping = self.isSwiping;
+ var left = self.sliderStartPos.left || 0;
+ var angle;
+
+ if ( swiping === true ) {
+
+ if ( Math.abs( self.distance ) > 10 ) {
+
+ self.canTap = false;
+
+ if ( self.instance.group.length < 2 && self.opts.vertical ) {
+ self.isSwiping = 'y';
+
+ } else if ( self.instance.isSliding || self.opts.vertical === false || ( self.opts.vertical === 'auto' && $( window ).width() > 800 ) ) {
+ self.isSwiping = 'x';
+
+ } else {
+ angle = Math.abs( Math.atan2( self.distanceY, self.distanceX ) * 180 / Math.PI );
+
+ self.isSwiping = ( angle > 45 && angle < 135 ) ? 'y' : 'x';
+ }
+
+ self.instance.isSliding = self.isSwiping;
+
+ // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
+ self.startPoints = self.newPoints;
+
+ $.each(self.instance.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.css( 'transition-duration', '0ms' );
+
+ slide.inTransition = false;
+
+ if ( slide.pos === self.instance.current.pos ) {
+ self.sliderStartPos.left = $.fancybox.getTranslate( slide.$slide ).left;
+ }
+ });
+
+ //self.instance.current.isMoved = true;
+
+ // Stop slideshow
+ if ( self.instance.SlideShow && self.instance.SlideShow.isActive ) {
+ self.instance.SlideShow.stop();
+ }
+ }
+
+ } else {
+
+ if ( swiping == 'x' ) {
+
+ // Sticky edges
+ if ( self.distanceX > 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === 0 && !self.instance.current.opts.loop ) ) ) {
+ left = left + Math.pow( self.distanceX, 0.8 );
+
+ } else if ( self.distanceX < 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop ) ) ) {
+ left = left - Math.pow( -self.distanceX, 0.8 );
+
+ } else {
+ left = left + self.distanceX;
+ }
+
+ }
+
+ self.sliderLastPos = {
+ top : swiping == 'x' ? 0 : self.sliderStartPos.top + self.distanceY,
+ left : left
+ };
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+
+ if ( self.sliderLastPos ) {
+ $.each(self.instance.slides, function( index, slide ) {
+ var pos = slide.pos - self.instance.currPos;
+
+ $.fancybox.setTranslate( slide.$slide, {
+ top : self.sliderLastPos.top,
+ left : self.sliderLastPos.left + ( pos * self.canvasWidth ) + ( pos * slide.opts.gutter )
+ });
+ });
+
+ self.$container.addClass( 'fancybox-is-sliding' );
+ }
+
+ });
+
+ }
+
+ };
+
+ Guestures.prototype.onPan = function() {
+
+ var self = this;
+
+ var newOffsetX, newOffsetY, newPos;
+
+ self.canTap = false;
+
+ if ( self.contentStartPos.width > self.canvasWidth ) {
+ newOffsetX = self.contentStartPos.left + self.distanceX;
+
+ } else {
+ newOffsetX = self.contentStartPos.left;
+ }
+
+ newOffsetY = self.contentStartPos.top + self.distanceY;
+
+ newPos = self.limitMovement( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.scaleX = self.contentStartPos.scaleX;
+ newPos.scaleY = self.contentStartPos.scaleY;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+ };
+
+ // Make panning sticky to the edges
+ Guestures.prototype.limitMovement = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var distanceX = self.distanceX;
+ var distanceY = self.distanceY;
+
+ // Slow down proportionally to traveled distance
+
+ minTranslateX = Math.max(0, canvasWidth * 0.5 - newWidth * 0.5 );
+ minTranslateY = Math.max(0, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ maxTranslateX = Math.min( canvasWidth - newWidth, canvasWidth * 0.5 - newWidth * 0.5 );
+ maxTranslateY = Math.min( canvasHeight - newHeight, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ if ( newWidth > canvasWidth ) {
+
+ // ->
+ if ( distanceX > 0 && newOffsetX > minTranslateX ) {
+ newOffsetX = minTranslateX - 1 + Math.pow( -minTranslateX + currentOffsetX + distanceX, 0.8 ) || 0;
+ }
+
+ // <-
+ if ( distanceX < 0 && newOffsetX < maxTranslateX ) {
+ newOffsetX = maxTranslateX + 1 - Math.pow( maxTranslateX - currentOffsetX - distanceX, 0.8 ) || 0;
+ }
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+
+ // \/
+ if ( distanceY > 0 && newOffsetY > minTranslateY ) {
+ newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8 ) || 0;
+ }
+
+ // /\
+ if ( distanceY < 0 && newOffsetY < maxTranslateY ) {
+ newOffsetY = maxTranslateY + 1 - Math.pow ( maxTranslateY - currentOffsetY - distanceY, 0.8 ) || 0;
+ }
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+
+ Guestures.prototype.limitPosition = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ if ( newWidth > canvasWidth ) {
+ newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
+ newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
+
+ } else {
+
+ // Center horizontally
+ newOffsetX = Math.max( 0, canvasWidth / 2 - newWidth / 2 );
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+ newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
+ newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
+
+ } else {
+
+ // Center vertically
+ newOffsetY = Math.max( 0, canvasHeight / 2 - newHeight / 2 );
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+ Guestures.prototype.onZoom = function() {
+
+ var self = this;
+
+ // Calculate current distance between points to get pinch ratio and new width and height
+
+ var currentWidth = self.contentStartPos.width;
+ var currentHeight = self.contentStartPos.height;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var endDistanceBetweenFingers = distance( self.newPoints[0], self.newPoints[1] );
+
+ var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
+
+ var newWidth = Math.floor( currentWidth * pinchRatio );
+ var newHeight = Math.floor( currentHeight * pinchRatio );
+
+ // This is the translation due to pinch-zooming
+ var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
+ var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
+
+ //Point between the two touches
+
+ var centerPointEndX = ((self.newPoints[0].x + self.newPoints[1].x) / 2) - $(window).scrollLeft();
+ var centerPointEndY = ((self.newPoints[0].y + self.newPoints[1].y) / 2) - $(window).scrollTop();
+
+ // And this is the translation due to translation of the centerpoint
+ // between the two fingers
+
+ var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
+ var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
+
+ // The new offset is the old/current one plus the total translation
+
+ var newOffsetX = currentOffsetX + ( translateFromZoomingX + translateFromTranslatingX );
+ var newOffsetY = currentOffsetY + ( translateFromZoomingY + translateFromTranslatingY );
+
+ var newPos = {
+ top : newOffsetY,
+ left : newOffsetX,
+ scaleX : self.contentStartPos.scaleX * pinchRatio,
+ scaleY : self.contentStartPos.scaleY * pinchRatio
+ };
+
+ self.canTap = false;
+
+ self.newWidth = newWidth;
+ self.newHeight = newHeight;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+
+ };
+
+ Guestures.prototype.ontouchend = function( e ) {
+
+ var self = this;
+ var dMs = Math.max( (new Date().getTime() ) - self.startTime, 1);
+
+ var swiping = self.isSwiping;
+ var panning = self.isPanning;
+ var zooming = self.isZooming;
+
+ self.endPoints = pointers( e );
+
+ self.$container.removeClass( 'fancybox-controls--isGrabbing' );
+
+ $(document).off( '.fb.touch' );
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.isSwiping = false;
+ self.isPanning = false;
+ self.isZooming = false;
+
+ if ( self.canTap ) {
+ return self.onTap( e );
+ }
+
+ self.speed = 366;
+
+ // Speed in px/ms
+ self.velocityX = self.distanceX / dMs * 0.5;
+ self.velocityY = self.distanceY / dMs * 0.5;
+
+ self.speedX = Math.max( self.speed * 0.5, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityX ) ) * self.speed ) );
+
+ if ( panning ) {
+ self.endPanning();
+
+ } else if ( zooming ) {
+ self.endZooming();
+
+ } else {
+ self.endSwiping( swiping );
+ }
+
+ return;
+ };
+
+ Guestures.prototype.endSwiping = function( swiping ) {
+
+ var self = this;
+ var ret = false;
+
+ self.instance.isSliding = false;
+ self.sliderLastPos = null;
+
+ // Close if swiped vertically / navigate if horizontally
+ if ( swiping == 'y' && Math.abs( self.distanceY ) > 50 ) {
+
+ // Continue vertical movement
+ $.fancybox.animate( self.instance.current.$slide, {
+ top : self.sliderStartPos.top + self.distanceY + ( self.velocityY * 150 ),
+ opacity : 0
+ }, 150 );
+
+ ret = self.instance.close( true, 300 );
+
+ } else if ( swiping == 'x' && self.distanceX > 50 && self.instance.group.length > 1 ) {
+ ret = self.instance.previous( self.speedX );
+
+ } else if ( swiping == 'x' && self.distanceX < -50 && self.instance.group.length > 1 ) {
+ ret = self.instance.next( self.speedX );
+ }
+
+ if ( ret === false && ( swiping == 'x' || swiping == 'y' ) ) {
+ self.instance.jumpTo( self.instance.current.index, 150 );
+ }
+
+ self.$container.removeClass( 'fancybox-is-sliding' );
+
+ };
+
+ // Limit panning from edges
+ // ========================
+
+ Guestures.prototype.endPanning = function() {
+
+ var self = this;
+ var newOffsetX, newOffsetY, newPos;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ if ( self.opts.momentum === false ) {
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ } else {
+
+ // Continue movement
+ newOffsetX = self.contentLastPos.left + ( self.velocityX * self.speed );
+ newOffsetY = self.contentLastPos.top + ( self.velocityY * self.speed );
+ }
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.width = self.contentStartPos.width;
+ newPos.height = self.contentStartPos.height;
+
+ $.fancybox.animate( self.$content, newPos, 330 );
+ };
+
+
+ Guestures.prototype.endZooming = function() {
+
+ var self = this;
+
+ var current = self.instance.current;
+
+ var newOffsetX, newOffsetY, newPos, reset;
+
+ var newWidth = self.newWidth;
+ var newHeight = self.newHeight;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ reset = {
+ top : newOffsetY,
+ left : newOffsetX,
+ width : newWidth,
+ height : newHeight,
+ scaleX : 1,
+ scaleY : 1
+ };
+
+ // Reset scalex/scaleY values; this helps for perfomance and does not break animation
+ $.fancybox.setTranslate( self.$content, reset );
+
+ if ( newWidth < self.canvasWidth && newHeight < self.canvasHeight ) {
+ self.instance.scaleToFit( 150 );
+
+ } else if ( newWidth > current.width || newHeight > current.height ) {
+ self.instance.scaleToActual( self.centerPointStartX, self.centerPointStartY, 150 );
+
+ } else {
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, newWidth, newHeight );
+
+ // Switch from scale() to width/height or animation will not work correctly
+ $.fancybox.setTranslate( self.content, $.fancybox.getTranslate( self.$content ) );
+
+ $.fancybox.animate( self.$content, newPos, 150 );
+ }
+
+ };
+
+ Guestures.prototype.onTap = function(e) {
+ var self = this;
+ var $target = $( e.target );
+
+ var instance = self.instance;
+ var current = instance.current;
+
+ var endPoints = ( e && pointers( e ) ) || self.startPoints;
+
+ var tapX = endPoints[0] ? endPoints[0].x - self.$stage.offset().left : 0;
+ var tapY = endPoints[0] ? endPoints[0].y - self.$stage.offset().top : 0;
+
+ var where;
+
+ var process = function ( prefix ) {
+
+ var action = current.opts[ prefix ];
+
+ if ( $.isFunction( action ) ) {
+ action = action.apply( instance, [ current, e ] );
+ }
+
+ if ( !action) {
+ return;
+ }
+
+ switch ( action ) {
+
+ case "close" :
+
+ instance.close( self.startEvent );
+
+ break;
+
+ case "toggleControls" :
+
+ instance.toggleControls( true );
+
+ break;
+
+ case "next" :
+
+ instance.next();
+
+ break;
+
+ case "nextOrClose" :
+
+ if ( instance.group.length > 1 ) {
+ instance.next();
+
+ } else {
+ instance.close( self.startEvent );
+ }
+
+ break;
+
+ case "zoom" :
+
+ if ( current.type == 'image' && ( current.isLoaded || current.$ghost ) ) {
+
+ if ( instance.canPan() ) {
+ instance.scaleToFit();
+
+ } else if ( instance.isScaledDown() ) {
+ instance.scaleToActual( tapX, tapY );
+
+ } else if ( instance.group.length < 2 ) {
+ instance.close( self.startEvent );
+ }
+ }
+
+ break;
+ }
+
+ };
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Skip if current slide is not in the center
+ if ( instance.isSliding ) {
+ return;
+ }
+
+ // Skip if clicked on the scrollbar
+ if ( tapX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ // Check where is clicked
+ if ( $target.is( '.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container' ) ) {
+ where = 'Outside';
+
+ } else if ( $target.is( '.fancybox-slide' ) ) {
+ where = 'Slide';
+
+ } else if ( instance.current.$content && instance.current.$content.has( e.target ).length ) {
+ where = 'Content';
+
+ } else {
+ return;
+ }
+
+ // Check if this is a double tap
+ if ( self.tapped ) {
+
+ // Stop previously created single tap
+ clearTimeout( self.tapped );
+ self.tapped = null;
+
+ // Skip if distance between taps is too big
+ if ( Math.abs( tapX - self.tapX ) > 50 || Math.abs( tapY - self.tapY ) > 50 || instance.isSliding ) {
+ return this;
+ }
+
+ // OK, now we assume that this is a double-tap
+ process( 'dblclick' + where );
+
+ } else {
+
+ // Single tap will be processed if user has not clicked second time within 300ms
+ // or there is no need to wait for double-tap
+ self.tapX = tapX;
+ self.tapY = tapY;
+
+ if ( current.opts[ 'dblclick' + where ] && current.opts[ 'dblclick' + where ] !== current.opts[ 'click' + where ] ) {
+ self.tapped = setTimeout(function() {
+ self.tapped = null;
+
+ process( 'click' + where );
+
+ }, 300);
+
+ } else {
+ process( 'click' + where );
+ }
+
+ }
+
+ return this;
+ };
+
+ $(document).on('onActivate.fb', function (e, instance) {
+ if ( instance && !instance.Guestures ) {
+ instance.Guestures = new Guestures( instance );
+ }
+ });
+
+ $(document).on('beforeClose.fb', function (e, instance) {
+ if ( instance && instance.Guestures ) {
+ instance.Guestures.destroy();
+ }
+ });
+
+
+}( window, document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// SlideShow
+// Enables slideshow functionality
+//
+// Example of usage:
+// $.fancybox.getInstance().SlideShow.start()
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ $.extend(true, $.fancybox.defaults, {
+ btnTpl : {
+ slideShow :
+ ''
+ },
+ slideShow : {
+ autoStart : false,
+ speed : 3000
+ }
+ });
+
+ var SlideShow = function( instance ) {
+ this.instance = instance;
+ this.init();
+ };
+
+ $.extend( SlideShow.prototype, {
+ timer : null,
+ isActive : false,
+ $button : null,
+
+ init : function() {
+ var self = this;
+
+ self.$button = self.instance.$refs.toolbar.find('[data-fancybox-play]').on('click', function() {
+ self.toggle();
+ });
+
+ if ( self.instance.group.length < 2 || !self.instance.group[ self.instance.currIndex ].opts.slideShow ) {
+ self.$button.hide();
+ }
+ },
+
+ set : function( force ) {
+ var self = this;
+
+ // Check if reached last element
+ if ( self.instance && self.instance.current && (force === true || self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
+ self.timer = setTimeout(function() {
+ if ( self.isActive ) {
+ self.instance.jumpTo( (self.instance.currIndex + 1) % self.instance.group.length );
+ }
+
+ }, self.instance.current.opts.slideShow.speed);
+
+ } else {
+ self.stop();
+ self.instance.idleSecondsCounter = 0;
+ self.instance.showControls();
+ }
+ },
+
+ clear : function() {
+ var self = this;
+
+ clearTimeout( self.timer );
+
+ self.timer = null;
+ },
+
+ start : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ if ( current ) {
+ self.isActive = true;
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_STOP )
+ .removeClass( 'fancybox-button--play' )
+ .addClass( 'fancybox-button--pause' );
+
+ self.set( true );
+ }
+ },
+
+ stop : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ self.clear();
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_START )
+ .removeClass( 'fancybox-button--pause' )
+ .addClass( 'fancybox-button--play' );
+
+ self.isActive = false;
+ },
+
+ toggle : function() {
+ var self = this;
+
+ if ( self.isActive ) {
+ self.stop();
+
+ } else {
+ self.start();
+ }
+ }
+
+ });
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ if ( instance && !instance.SlideShow ) {
+ instance.SlideShow = new SlideShow( instance );
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, current, firstRun) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( firstRun ) {
+
+ if ( SlideShow && current.opts.slideShow.autoStart ) {
+ SlideShow.start();
+ }
+
+ } else if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.clear();
+ }
+ },
+
+ 'afterShow.fb' : function(e, instance, current) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.set();
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var SlideShow = instance && instance.SlideShow;
+
+ // "P" or Spacebar
+ if ( SlideShow && current.opts.slideShow && ( keycode === 80 || keycode === 32 ) && !$(document.activeElement).is( 'button,a,input' ) ) {
+ keypress.preventDefault();
+
+ SlideShow.toggle();
+ }
+ },
+
+ 'beforeClose.fb onDeactivate.fb' : function(e, instance) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow ) {
+ SlideShow.stop();
+ }
+ }
+ });
+
+ // Page Visibility API to pause slideshow when window is not active
+ $(document).on("visibilitychange", function() {
+ var instance = $.fancybox.getInstance();
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ if ( document.hidden ) {
+ SlideShow.clear();
+
+ } else {
+ SlideShow.set();
+ }
+ }
+ });
+
+}( document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// FullScreen
+// Adds fullscreen functionality
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ // Collection of methods supported by user browser
+ var fn = (function () {
+
+ var fnMap = [
+ [
+ 'requestFullscreen',
+ 'exitFullscreen',
+ 'fullscreenElement',
+ 'fullscreenEnabled',
+ 'fullscreenchange',
+ 'fullscreenerror'
+ ],
+ // new WebKit
+ [
+ 'webkitRequestFullscreen',
+ 'webkitExitFullscreen',
+ 'webkitFullscreenElement',
+ 'webkitFullscreenEnabled',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ // old WebKit (Safari 5.1)
+ [
+ 'webkitRequestFullScreen',
+ 'webkitCancelFullScreen',
+ 'webkitCurrentFullScreenElement',
+ 'webkitCancelFullScreen',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ [
+ 'mozRequestFullScreen',
+ 'mozCancelFullScreen',
+ 'mozFullScreenElement',
+ 'mozFullScreenEnabled',
+ 'mozfullscreenchange',
+ 'mozfullscreenerror'
+ ],
+ [
+ 'msRequestFullscreen',
+ 'msExitFullscreen',
+ 'msFullscreenElement',
+ 'msFullscreenEnabled',
+ 'MSFullscreenChange',
+ 'MSFullscreenError'
+ ]
+ ];
+
+ var val;
+ var ret = {};
+ var i, j;
+
+ for ( i = 0; i < fnMap.length; i++ ) {
+ val = fnMap[ i ];
+
+ if ( val && val[ 1 ] in document ) {
+ for ( j = 0; j < val.length; j++ ) {
+ ret[ fnMap[ 0 ][ j ] ] = val[ j ];
+ }
+
+ return ret;
+ }
+ }
+
+ return false;
+ })();
+
+ // If browser does not have Full Screen API, then simply unset default button template and stop
+ if ( !fn ) {
+
+ if ( $ && $.fancybox ) {
+ $.fancybox.defaults.btnTpl.fullScreen = false;
+ }
+
+ return;
+ }
+
+ var FullScreen = {
+
+ request : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ elem[ fn.requestFullscreen ]( elem.ALLOW_KEYBOARD_INPUT );
+
+ },
+ exit : function () {
+
+ document[ fn.exitFullscreen ]();
+
+ },
+ toggle : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ if ( this.isFullscreen() ) {
+ this.exit();
+
+ } else {
+ this.request( elem );
+ }
+
+ },
+ isFullscreen : function() {
+
+ return Boolean( document[ fn.fullscreenElement ] );
+
+ },
+ enabled : function() {
+
+ return Boolean( document[ fn.fullscreenEnabled ] );
+
+ }
+ };
+
+ $.extend(true, $.fancybox.defaults, {
+ btnTpl : {
+ fullScreen :
+ ''
+ },
+ fullScreen : {
+ autoStart : false
+ }
+ });
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ var $container;
+
+ if ( instance && instance.group[ instance.currIndex ].opts.fullScreen ) {
+ $container = instance.$refs.container;
+
+ $container.on('click.fb-fullscreen', '[data-fancybox-fullscreen]', function(e) {
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ FullScreen.toggle( $container[ 0 ] );
+
+ });
+
+ if ( instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true ) {
+ FullScreen.request( $container[ 0 ] );
+ }
+
+ // Expose API
+ instance.FullScreen = FullScreen;
+
+ } else if ( instance ) {
+ instance.$refs.toolbar.find('[data-fancybox-fullscreen]').hide();
+ }
+
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+
+ // "P" or Spacebar
+ if ( instance && instance.FullScreen && keycode === 70 ) {
+ keypress.preventDefault();
+
+ instance.FullScreen.toggle( instance.$refs.container[ 0 ] );
+ }
+
+ },
+
+ 'beforeClose.fb' : function( instance ) {
+ if ( instance && instance.FullScreen ) {
+ FullScreen.exit();
+ }
+ }
+ });
+
+ $(document).on(fn.fullscreenchange, function() {
+ var isFullscreen = FullScreen.isFullscreen(),
+ instance = $.fancybox.getInstance();
+
+ if ( instance ) {
+
+ // If image is zooming, then force to stop and reposition properly
+ if ( instance.current && instance.current.type === 'image' && instance.isAnimating ) {
+ instance.current.$content.css( 'transition', 'none' );
+
+ instance.isAnimating = false;
+
+ instance.update( true, true, 0 );
+ }
+
+ instance.trigger( 'onFullscreenChange', isFullscreen );
+
+ instance.$refs.container.toggleClass( 'fancybox-is-fullscreen', isFullscreen );
+ }
+
+ });
+
+}( document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Thumbs
+// Displays thumbnails in a grid
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ // Make sure there are default values
+ $.fancybox.defaults = $.extend(true, {
+ btnTpl : {
+ thumbs :
+ ''
+ },
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true, // Hide thumbnail grid when closing animation starts
+ parentEl : '.fancybox-container', // Container is injected into this element
+ axis : 'y' // Vertical (y) or horizontal (x) scrolling
+ }
+ }, $.fancybox.defaults);
+
+ var FancyThumbs = function( instance ) {
+ this.init( instance );
+ };
+
+ $.extend( FancyThumbs.prototype, {
+
+ $button : null,
+ $grid : null,
+ $list : null,
+ isVisible : false,
+ isActive : false,
+
+ init : function( instance ) {
+ var self = this;
+
+ self.instance = instance;
+
+ instance.Thumbs = self;
+
+ // Enable thumbs if at least two group items have thumbnails
+ var first = instance.group[0],
+ second = instance.group[1];
+
+ self.opts = instance.group[ instance.currIndex ].opts.thumbs;
+
+ self.$button = instance.$refs.toolbar.find( '[data-fancybox-thumbs]' );
+
+ if ( self.opts && first && second && (
+ ( first.type == 'image' || first.opts.thumb || first.opts.$thumb ) &&
+ ( second.type == 'image' || second.opts.thumb || second.opts.$thumb )
+ )) {
+
+ self.$button.show().on('click', function() {
+ self.toggle();
+ });
+
+ self.isActive = true;
+
+ } else {
+ self.$button.hide();
+ }
+ },
+
+ create : function() {
+ var self = this,
+ instance = self.instance,
+ parentEl = self.opts.parentEl,
+ list,
+ src;
+
+ self.$grid = $('').appendTo( instance.$refs.container.find( parentEl ).addBack().filter( parentEl ) );
+
+ // Build list HTML
+ list = '';
+
+ $.each(instance.group, function( i, item ) {
+ src = item.opts.thumb || ( item.opts.$thumb ? item.opts.$thumb.attr( 'src' ) : null );
+
+ if ( !src && item.type === 'image' ) {
+ src = item.src;
+ }
+
+ if ( src && src.length ) {
+ list += '';
+ }
+ });
+
+ list += '
';
+
+ self.$list = $( list ).appendTo( self.$grid ).on('click', 'li', function() {
+ instance.jumpTo( $(this).data('index') );
+ });
+
+ self.$list.find( 'img' ).hide().one('load', function() {
+ var $parent = $(this).parent().removeClass( 'fancybox-thumbs-loading' ),
+ thumbWidth = $parent.outerWidth(),
+ thumbHeight = $parent.outerHeight(),
+ width,
+ height,
+ widthRatio,
+ heightRatio;
+
+ width = this.naturalWidth || this.width;
+ height = this.naturalHeight || this.height;
+
+ // Calculate thumbnail dimensions; center vertically and horizontally
+ widthRatio = width / thumbWidth;
+ heightRatio = height / thumbHeight;
+
+ if (widthRatio >= 1 && heightRatio >= 1) {
+ if (widthRatio > heightRatio) {
+ width = width / heightRatio;
+ height = thumbHeight;
+
+ } else {
+ width = thumbWidth;
+ height = height / widthRatio;
+ }
+ }
+
+ $(this).css({
+ width : Math.floor(width),
+ height : Math.floor(height),
+ 'margin-top' : height > thumbHeight ? ( Math.floor(thumbHeight * 0.3 - height * 0.3 ) ) : Math.floor(thumbHeight * 0.5 - height * 0.5 ),
+ 'margin-left' : Math.floor(thumbWidth * 0.5 - width * 0.5 )
+ }).show();
+
+ })
+ .each(function() {
+ this.src = $( this ).data( 'src' );
+ });
+
+ if ( self.opts.axis === 'x' ) {
+ self.$list.width( parseInt( self.$grid.css("padding-right") ) + ( instance.group.length * self.$list.children().eq(0).outerWidth(true) ) + 'px' );
+ }
+ },
+
+ focus : function( duration ) {
+ var self = this,
+ $list = self.$list,
+ thumb,
+ thumbPos;
+
+ if ( self.instance.current ) {
+ thumb = $list.children()
+ .removeClass( 'fancybox-thumbs-active' )
+ .filter('[data-index="' + self.instance.current.index + '"]')
+ .addClass('fancybox-thumbs-active');
+
+ thumbPos = thumb.position();
+
+ // Check if need to scroll to make current thumb visible
+ if ( self.opts.axis === 'y' && ( thumbPos.top < 0 || thumbPos.top > ( $list.height() - thumb.outerHeight() ) ) ) {
+ $list.stop().animate({ 'scrollTop' : $list.scrollTop() + thumbPos.top }, duration);
+
+ } else if ( self.opts.axis === 'x' && (
+ thumbPos.left < $list.parent().scrollLeft() ||
+ thumbPos.left > ( $list.parent().scrollLeft() + ( $list.parent().width() - thumb.outerWidth() ) )
+ )
+ ) {
+ $list.parent().stop().animate({ 'scrollLeft' : thumbPos.left }, duration);
+ }
+ }
+ },
+
+ update : function() {
+ this.instance.$refs.container.toggleClass( 'fancybox-show-thumbs', this.isVisible );
+
+ if ( this.isVisible ) {
+ if ( !this.$grid ) {
+ this.create();
+ }
+
+ this.instance.trigger( 'onThumbsShow' );
+
+ this.focus( 0 );
+
+ } else if ( this.$grid ) {
+ this.instance.trigger( 'onThumbsHide' );
+ }
+
+ // Update content position
+ this.instance.update();
+ },
+
+ hide : function() {
+ this.isVisible = false;
+ this.update();
+ },
+
+ show : function() {
+ this.isVisible = true;
+ this.update();
+ },
+
+ toggle : function() {
+ this.isVisible = !this.isVisible;
+ this.update();
+ }
+ });
+
+ $(document).on({
+
+ 'onInit.fb' : function(e, instance) {
+ var Thumbs;
+
+ if ( instance && !instance.Thumbs ) {
+ Thumbs = new FancyThumbs( instance );
+
+ if ( Thumbs.isActive && Thumbs.opts.autoStart === true ) {
+ Thumbs.show();
+ }
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, item, firstRun) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( Thumbs && Thumbs.isVisible ) {
+ Thumbs.focus( firstRun ? 0 : 250 );
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var Thumbs = instance && instance.Thumbs;
+
+ // "G"
+ if ( Thumbs && Thumbs.isActive && keycode === 71 ) {
+ keypress.preventDefault();
+
+ Thumbs.toggle();
+ }
+ },
+
+ 'beforeClose.fb' : function( e, instance ) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false ) {
+ Thumbs.$grid.hide();
+ }
+ }
+
+ });
+
+}(document, window.jQuery));
+
+//// ==========================================================================
+//
+// Share
+// Displays simple form for sharing current url
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ $.extend(true, $.fancybox.defaults, {
+ btnTpl : {
+ share :
+ ''
+ },
+ share : {
+ tpl :
+ '' +
+ '{{SHARE}}
' +
+ '' +
+ '' +
+ '' +
+ 'Facebook' +
+ '' +
+ '' +
+ '' +
+ 'Pinterest' +
+ '' +
+ '' +
+ '' +
+ 'Twitter' +
+ '' +
+ '
' +
+ '' +
+ ''
+ }
+ });
+
+ function escapeHtml(string) {
+ var entityMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/',
+ '`': '`',
+ '=': '='
+ };
+
+ return String(string).replace(/[&<>"'`=\/]/g, function (s) {
+ return entityMap[s];
+ });
+ }
+
+ $(document).on('click', '[data-fancybox-share]', function() {
+ var f = $.fancybox.getInstance(),
+ url,
+ tpl;
+
+ if ( f ) {
+ url = f.current.opts.hash === false ? f.current.src : window.location;
+ tpl = f.current.opts.share.tpl
+ .replace( /\{\{src\}\}/g, encodeURIComponent( url ) )
+ .replace( /\{\{src_raw\}\}/g, escapeHtml( url ) )
+ .replace( /\{\{descr\}\}/g, f.$caption ? encodeURIComponent( f.$caption.text() ) : '' );
+
+ $.fancybox.open({
+ src : f.translate( f, tpl ),
+ type : 'html',
+ opts : {
+ animationEffect : "fade",
+ animationDuration : 250
+ }
+ });
+ }
+
+ });
+
+}( document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Hash
+// Enables linking to each modal
+//
+// ==========================================================================
+;(function (document, window, $) {
+ 'use strict';
+
+ // Simple $.escapeSelector polyfill (for jQuery prior v3)
+ if ( !$.escapeSelector ) {
+ $.escapeSelector = function( sel ) {
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
+ var fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ };
+
+ return ( sel + "" ).replace( rcssescape, fcssescape );
+ };
+ }
+
+ // Create new history entry only once
+ var shouldCreateHistory = true;
+
+ // Variable containing last hash value set by fancyBox
+ // It will be used to determine if fancyBox needs to close after hash change is detected
+ var currentHash = null;
+
+ // Throttling the history change
+ var timerID = null;
+
+ // Get info about gallery name and current index from url
+ function parseUrl() {
+ var hash = window.location.hash.substr( 1 );
+ var rez = hash.split( '-' );
+ var index = rez.length > 1 && /^\+?\d+$/.test( rez[ rez.length - 1 ] ) ? parseInt( rez.pop( -1 ), 10 ) || 1 : 1;
+ var gallery = rez.join( '-' );
+
+ // Index is starting from 1
+ if ( index < 1 ) {
+ index = 1;
+ }
+
+ return {
+ hash : hash,
+ index : index,
+ gallery : gallery
+ };
+ }
+
+ // Trigger click evnt on links to open new fancyBox instance
+ function triggerFromUrl( url ) {
+ var $el;
+
+ if ( url.gallery !== '' ) {
+
+ // If we can find element matching 'data-fancybox' atribute, then trigger click event for that ..
+ $el = $( "[data-fancybox='" + $.escapeSelector( url.gallery ) + "']" ).eq( url.index - 1 );
+
+ if ( !$el.length ) {
+ // .. if not, try finding element by ID
+ $el = $( "#" + $.escapeSelector( url.gallery ) + "" );
+ }
+
+ if ( $el.length ) {
+ shouldCreateHistory = false;
+
+ $el.trigger( 'click' );
+ }
+
+ }
+ }
+
+ // Get gallery name from current instance
+ function getGalleryID( instance ) {
+ var opts;
+
+ if ( !instance ) {
+ return false;
+ }
+
+ opts = instance.current ? instance.current.opts : instance.opts;
+
+ return opts.hash || ( opts.$orig ? opts.$orig.data( 'fancybox' ) : '' );
+ }
+
+ // Start when DOM becomes ready
+ $(function() {
+
+ // Check if user has disabled this module
+ if ( $.fancybox.defaults.hash === false ) {
+ return;
+ }
+
+ // Update hash when opening/closing fancyBox
+ $(document).on({
+ 'onInit.fb' : function( e, instance ) {
+ var url, gallery;
+
+ if ( instance.group[ instance.currIndex ].opts.hash === false ) {
+ return;
+ }
+
+ url = parseUrl();
+ gallery = getGalleryID( instance );
+
+ // Make sure gallery start index matches index from hash
+ if ( gallery && url.gallery && gallery == url.gallery ) {
+ instance.currIndex = url.index - 1;
+ }
+ },
+
+ 'beforeShow.fb' : function( e, instance, current ) {
+ var gallery;
+
+ if ( !current || current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGalleryID( instance );
+
+ // Update window hash
+ if ( gallery && gallery !== '' ) {
+
+ if ( window.location.hash.indexOf( gallery ) < 0 ) {
+ instance.opts.origHash = window.location.hash;
+ }
+
+ currentHash = gallery + ( instance.group.length > 1 ? '-' + ( current.index + 1 ) : '' );
+
+ if ( 'replaceState' in window.history ) {
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ timerID = setTimeout(function() {
+ window.history[ shouldCreateHistory ? 'pushState' : 'replaceState' ]( {} , document.title, window.location.pathname + window.location.search + '#' + currentHash );
+
+ timerID = null;
+
+ shouldCreateHistory = false;
+
+ }, 300);
+
+ } else {
+ window.location.hash = currentHash;
+ }
+
+ }
+
+ },
+
+ 'beforeClose.fb' : function( e, instance, current ) {
+ var gallery, origHash;
+
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ if ( current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGalleryID( instance );
+ origHash = instance && instance.opts.origHash ? instance.opts.origHash : '';
+
+ // Remove hash from location bar
+ if ( gallery && gallery !== '' ) {
+
+ if ( 'replaceState' in history ) {
+ window.history.replaceState( {} , document.title, window.location.pathname + window.location.search + origHash );
+
+ } else {
+ window.location.hash = origHash;
+
+ // Keep original scroll position
+ $( window ).scrollTop( instance.scrollTop ).scrollLeft( instance.scrollLeft );
+ }
+ }
+
+ currentHash = null;
+ }
+ });
+
+ // Check if need to close after url has changed
+ $(window).on('hashchange.fb', function() {
+ var url = parseUrl();
+
+ if ( $.fancybox.getInstance() ) {
+ if ( currentHash && currentHash !== url.gallery + '-' + url.index && !( url.index === 1 && currentHash == url.gallery ) ) {
+ currentHash = null;
+
+ $.fancybox.close();
+ }
+
+ } else if ( url.gallery !== '' ) {
+ triggerFromUrl( url );
+ }
+ });
+
+ // Check current hash and trigger click event on matching element to start fancyBox, if needed
+ setTimeout(function() {
+ triggerFromUrl( parseUrl() );
+ }, 50);
+ });
+
+}( document, window, window.jQuery || jQuery ));
diff --git a/source/lib/fancybox/source/jquery.fancybox.min.css b/source/lib/fancybox/source/jquery.fancybox.min.css
new file mode 100644
index 000000000..193567a31
--- /dev/null
+++ b/source/lib/fancybox/source/jquery.fancybox.min.css
@@ -0,0 +1 @@
+@charset "UTF-8";body.fancybox-active{overflow:hidden}body.fancybox-iosfix{position:fixed;left:0;right:0}.fancybox-is-hidden{position:absolute;top:-9999px;left:-9999px;visibility:hidden}.fancybox-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:99992;-webkit-tap-highlight-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-stage{position:absolute;top:0;right:0;bottom:0;left:0}.fancybox-outer{overflow-y:auto;-webkit-overflow-scrolling:touch}.fancybox-bg{background:#1e1e1e;opacity:0;transition-duration:inherit;transition-property:opacity;transition-timing-function:cubic-bezier(.47,0,.74,.71)}.fancybox-is-open .fancybox-bg{opacity:.87;transition-timing-function:cubic-bezier(.22,.61,.36,1)}.fancybox-caption-wrap,.fancybox-infobar,.fancybox-toolbar{position:absolute;direction:ltr;z-index:99997;opacity:0;visibility:hidden;transition:opacity .25s,visibility 0s linear .25s;box-sizing:border-box}.fancybox-show-caption .fancybox-caption-wrap,.fancybox-show-infobar .fancybox-infobar,.fancybox-show-toolbar .fancybox-toolbar{opacity:1;visibility:visible;transition:opacity .25s,visibility 0s}.fancybox-infobar{top:0;left:0;font-size:13px;padding:0 10px;height:44px;min-width:44px;line-height:44px;color:#ccc;text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:subpixel-antialiased;mix-blend-mode:exclusion}.fancybox-toolbar{top:0;right:0;margin:0;padding:0}.fancybox-stage{overflow:hidden;direction:ltr;z-index:99994;-webkit-transform:translateZ(0)}.fancybox-is-closing .fancybox-stage{overflow:visible}.fancybox-slide{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;overflow:auto;outline:none;white-space:normal;box-sizing:border-box;text-align:center;z-index:99994;-webkit-overflow-scrolling:touch;display:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.fancybox-slide:before{content:"";display:inline-block;vertical-align:middle;height:100%;width:0}.fancybox-is-sliding .fancybox-slide,.fancybox-slide--current,.fancybox-slide--next,.fancybox-slide--previous{display:block}.fancybox-slide--image{overflow:visible}.fancybox-slide--image:before{display:none}.fancybox-slide--video .fancybox-content,.fancybox-slide--video iframe{background:#000}.fancybox-slide--map .fancybox-content,.fancybox-slide--map iframe{background:#e5e3df}.fancybox-slide--next{z-index:99995}.fancybox-slide>*{display:inline-block;position:relative;padding:24px;margin:44px 0;border-width:0;vertical-align:middle;text-align:left;background-color:#fff;overflow:auto;box-sizing:border-box}.fancybox-slide>base,.fancybox-slide>link,.fancybox-slide>meta,.fancybox-slide>script,.fancybox-slide>style,.fancybox-slide>title{display:none}.fancybox-slide .fancybox-image-wrap{position:absolute;top:0;left:0;margin:0;padding:0;border:0;z-index:99995;background:transparent;cursor:default;overflow:visible;-webkit-transform-origin:top left;transform-origin:top left;background-size:100% 100%;background-repeat:no-repeat;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.fancybox-can-zoomOut .fancybox-image-wrap{cursor:zoom-out}.fancybox-can-zoomIn .fancybox-image-wrap{cursor:zoom-in}.fancybox-can-drag .fancybox-image-wrap{cursor:-webkit-grab;cursor:grab}.fancybox-is-dragging .fancybox-image-wrap{cursor:-webkit-grabbing;cursor:grabbing}.fancybox-image,.fancybox-spaceball{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;border:0;max-width:none;max-height:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fancybox-spaceball{z-index:1}.fancybox-slide--iframe .fancybox-content{padding:0;width:80%;height:80%;max-width:calc(100% - 100px);max-height:calc(100% - 88px);overflow:visible;background:#fff}.fancybox-iframe{display:block;padding:0;border:0;height:100%}.fancybox-error,.fancybox-iframe{margin:0;width:100%;background:#fff}.fancybox-error{padding:40px;max-width:380px;cursor:default}.fancybox-error p{margin:0;padding:0;color:#444;font-size:16px;line-height:20px}.fancybox-button{box-sizing:border-box;display:inline-block;vertical-align:top;width:44px;height:44px;margin:0;padding:10px;border:0;border-radius:0;background:rgba(30,30,30,.6);transition:color .3s ease;cursor:pointer;outline:none}.fancybox-button,.fancybox-button:link,.fancybox-button:visited{color:#ccc}.fancybox-button:focus,.fancybox-button:hover{color:#fff}.fancybox-button[disabled]{color:#ccc;cursor:default;opacity:.6}.fancybox-button svg{display:block;position:relative;overflow:visible;shape-rendering:geometricPrecision}.fancybox-button svg path{fill:currentColor;stroke:currentColor;stroke-linejoin:round;stroke-width:3}.fancybox-button--share svg path{stroke-width:1}.fancybox-button--pause svg path:nth-child(1),.fancybox-button--play svg path:nth-child(2){display:none}.fancybox-button--zoom svg path{fill:transparent}.fancybox-navigation{display:none}.fancybox-show-nav .fancybox-navigation{display:block}.fancybox-navigation button{position:absolute;top:50%;margin:-50px 0 0;z-index:99997;background:transparent;width:60px;height:100px;padding:17px}.fancybox-navigation button:before{content:"";position:absolute;top:30px;right:10px;width:40px;height:40px;background:rgba(30,30,30,.6)}.fancybox-navigation .fancybox-button--arrow_left{left:0}.fancybox-navigation .fancybox-button--arrow_right{right:0}.fancybox-close-small{position:absolute;top:0;right:0;width:44px;height:44px;padding:0;margin:0;border:0;border-radius:0;background:transparent;z-index:10;cursor:pointer}.fancybox-close-small:after{content:"×";position:absolute;top:5px;right:5px;width:30px;height:30px;font:20px/30px Arial,Helvetica Neue,Helvetica,sans-serif;color:#888;font-weight:300;text-align:center;border-radius:50%;border-width:0;background-color:transparent;transition:background-color .25s;box-sizing:border-box;z-index:2}.fancybox-close-small:focus{outline:none}.fancybox-close-small:focus:after{outline:1px dotted #888}.fancybox-close-small:hover:after{color:#555;background:#eee}.fancybox-slide--iframe .fancybox-close-small,.fancybox-slide--image .fancybox-close-small{top:0;right:-44px}.fancybox-slide--iframe .fancybox-close-small:after,.fancybox-slide--image .fancybox-close-small:after{font-size:35px;color:#aaa}.fancybox-slide--iframe .fancybox-close-small:hover:after,.fancybox-slide--image .fancybox-close-small:hover:after{color:#fff;background:transparent}.fancybox-is-scaling .fancybox-close-small,.fancybox-is-zoomable.fancybox-can-drag .fancybox-close-small{display:none}.fancybox-caption-wrap{bottom:0;left:0;right:0;padding:60px 2vw 0;background:linear-gradient(180deg,transparent 0,rgba(0,0,0,.1) 20%,rgba(0,0,0,.2) 40%,rgba(0,0,0,.6) 80%,rgba(0,0,0,.8));pointer-events:none}.fancybox-caption{padding:30px 0;border-top:1px solid hsla(0,0%,100%,.4);font-size:14px;color:#fff;line-height:20px;-webkit-text-size-adjust:none}.fancybox-caption a,.fancybox-caption button,.fancybox-caption select{pointer-events:all;position:relative}.fancybox-caption a{color:#fff;text-decoration:underline}.fancybox-slide>.fancybox-loading{border:6px solid hsla(0,0%,39%,.4);border-top:6px solid hsla(0,0%,100%,.6);border-radius:100%;height:50px;width:50px;-webkit-animation:a .8s infinite linear;animation:a .8s infinite linear;background:transparent;position:absolute;top:50%;left:50%;margin-top:-30px;margin-left:-30px;z-index:99999}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fancybox-animated{transition-timing-function:cubic-bezier(0,0,.25,1)}.fancybox-fx-slide.fancybox-slide--previous{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.fancybox-fx-slide.fancybox-slide--next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.fancybox-fx-slide.fancybox-slide--current{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}.fancybox-fx-fade.fancybox-slide--next,.fancybox-fx-fade.fancybox-slide--previous{opacity:0;transition-timing-function:cubic-bezier(.19,1,.22,1)}.fancybox-fx-fade.fancybox-slide--current{opacity:1}.fancybox-fx-zoom-in-out.fancybox-slide--previous{-webkit-transform:scale3d(1.5,1.5,1.5);transform:scale3d(1.5,1.5,1.5);opacity:0}.fancybox-fx-zoom-in-out.fancybox-slide--next{-webkit-transform:scale3d(.5,.5,.5);transform:scale3d(.5,.5,.5);opacity:0}.fancybox-fx-zoom-in-out.fancybox-slide--current{-webkit-transform:scaleX(1);transform:scaleX(1);opacity:1}.fancybox-fx-rotate.fancybox-slide--previous{-webkit-transform:rotate(-1turn);transform:rotate(-1turn);opacity:0}.fancybox-fx-rotate.fancybox-slide--next{-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:0}.fancybox-fx-rotate.fancybox-slide--current{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.fancybox-fx-circular.fancybox-slide--previous{-webkit-transform:scale3d(0,0,0) translate3d(-100%,0,0);transform:scale3d(0,0,0) translate3d(-100%,0,0);opacity:0}.fancybox-fx-circular.fancybox-slide--next{-webkit-transform:scale3d(0,0,0) translate3d(100%,0,0);transform:scale3d(0,0,0) translate3d(100%,0,0);opacity:0}.fancybox-fx-circular.fancybox-slide--current{-webkit-transform:scaleX(1) translateZ(0);transform:scaleX(1) translateZ(0);opacity:1}.fancybox-fx-tube.fancybox-slide--previous{-webkit-transform:translate3d(-100%,0,0) scale(.1) skew(-10deg);transform:translate3d(-100%,0,0) scale(.1) skew(-10deg)}.fancybox-fx-tube.fancybox-slide--next{-webkit-transform:translate3d(100%,0,0) scale(.1) skew(10deg);transform:translate3d(100%,0,0) scale(.1) skew(10deg)}.fancybox-fx-tube.fancybox-slide--current{-webkit-transform:translateZ(0) scale(1);transform:translateZ(0) scale(1)}.fancybox-share{padding:30px;border-radius:3px;background:#f4f4f4;max-width:90%}.fancybox-share h1{color:#222;margin:0 0 20px;font-size:33px;font-weight:700;text-align:center}.fancybox-share p{margin:0;padding:0;text-align:center}.fancybox-share p:first-of-type{margin-right:-10px}.fancybox-share_button{display:inline-block;text-decoration:none;margin:0 10px 10px 0;padding:10px 20px;border:0;border-radius:3px;box-shadow:0 2px 2px 0 rgba(0,0,0,.16);background:#fff;white-space:nowrap;font-size:16px;line-height:23px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;min-width:140px;color:#707070;transition:all .2s}.fancybox-share_button:focus,.fancybox-share_button:hover{text-decoration:none;color:#333;box-shadow:0 2px 2px 0 rgba(0,0,0,.3)}.fancybox-share_button svg{margin-right:5px;width:20px;height:20px;vertical-align:text-bottom}.fancybox-share input{box-sizing:border-box;width:100%;margin:5px 0 0;padding:10px 15px;border:1px solid #d7d7d7;border-radius:3px;background:#ebebeb;color:#5d5b5b;font-size:14px;outline:none}.fancybox-thumbs{display:none;position:absolute;top:0;bottom:0;right:0;width:212px;margin:0;padding:2px 2px 4px;background:#fff;-webkit-tap-highlight-color:transparent;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;box-sizing:border-box;z-index:99995}.fancybox-thumbs-x{overflow-y:hidden;overflow-x:auto}.fancybox-show-thumbs .fancybox-thumbs{display:block}.fancybox-show-thumbs .fancybox-inner{right:212px}.fancybox-thumbs>ul{list-style:none;position:absolute;position:relative;width:100%;height:100%;margin:0;padding:0;overflow-x:hidden;overflow-y:auto;font-size:0;white-space:nowrap}.fancybox-thumbs-x>ul{overflow:hidden}.fancybox-thumbs-y>ul::-webkit-scrollbar{width:7px}.fancybox-thumbs-y>ul::-webkit-scrollbar-track{background:#fff;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,.3)}.fancybox-thumbs-y>ul::-webkit-scrollbar-thumb{background:#2a2a2a;border-radius:10px}.fancybox-thumbs>ul>li{float:left;overflow:hidden;padding:0;margin:2px;width:100px;height:75px;max-width:calc(50% - 4px);max-height:calc(100% - 8px);position:relative;cursor:pointer;outline:none;-webkit-tap-highlight-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;box-sizing:border-box}li.fancybox-thumbs-loading{background:rgba(0,0,0,.1)}.fancybox-thumbs>ul>li>img{position:absolute;top:0;left:0;max-width:none;max-height:none;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fancybox-thumbs>ul>li:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border:4px solid #4ea7f9;z-index:99991;opacity:0;transition:all .2s cubic-bezier(.25,.46,.45,.94)}.fancybox-thumbs>ul>li.fancybox-thumbs-active:before{opacity:1}@media (max-width:800px){.fancybox-thumbs{width:110px}.fancybox-show-thumbs .fancybox-inner{right:110px}.fancybox-thumbs>ul>li{max-width:calc(100% - 10px)}}
\ No newline at end of file
diff --git a/source/lib/fancybox/source/jquery.fancybox.min.js b/source/lib/fancybox/source/jquery.fancybox.min.js
new file mode 100644
index 000000000..aa654e17a
--- /dev/null
+++ b/source/lib/fancybox/source/jquery.fancybox.min.js
@@ -0,0 +1,12 @@
+// ==================================================
+// fancyBox v3.2.5
+//
+// Licensed GPLv3 for open source use
+// or fancyBox Commercial License for commercial use
+//
+// http://fancyapps.com/fancybox/
+// Copyright 2017 fancyApps
+//
+// ==================================================
+!function(t,e,n,o){"use strict";function a(t){var e=n(t.currentTarget),o=t.data?t.data.options:{},a=e.attr("data-fancybox")||"",i=0,s=[];t.isDefaultPrevented()||(t.preventDefault(),a?(s=o.selector?n(o.selector):t.data?t.data.items:[],s=s.length?s.filter('[data-fancybox="'+a+'"]'):n('[data-fancybox="'+a+'"]'),i=s.index(e),i<0&&(i=0)):s=[e],n.fancybox.open(s,o,i))}if(n){if(n.fn.fancybox)return void("console"in t&&console.log("fancyBox already initialized"));var i={loop:!1,margin:[44,0],gutter:50,keyboard:!0,arrows:!0,infobar:!0,toolbar:!0,buttons:["slideShow","fullScreen","thumbs","share","close"],idleTime:3,smallBtn:"auto",protect:!1,modal:!1,image:{preload:"auto"},ajax:{settings:{data:{fancybox:!0}}},iframe:{tpl:'',preload:!0,css:{},attr:{scrolling:"auto"}},defaultType:"image",animationEffect:"zoom",animationDuration:500,zoomOpacity:"auto",transitionEffect:"fade",transitionDuration:366,slideClass:"",baseClass:"",baseTpl:'',spinnerTpl:'',errorTpl:'{{ERROR}}
',btnTpl:{download:'',zoom:'',close:'',smallBtn:'',arrowLeft:'',arrowRight:''},parentEl:"body",autoFocus:!1,backFocus:!0,trapFocus:!0,fullScreen:{autoStart:!1},touch:{vertical:!0,momentum:!0},hash:null,media:{},slideShow:{autoStart:!1,speed:4e3},thumbs:{autoStart:!1,hideOnClose:!0,parentEl:".fancybox-container",axis:"y"},onInit:n.noop,beforeLoad:n.noop,afterLoad:n.noop,beforeShow:n.noop,afterShow:n.noop,beforeClose:n.noop,afterClose:n.noop,onActivate:n.noop,onDeactivate:n.noop,clickContent:function(t,e){return"image"===t.type&&"zoom"},clickSlide:"close",clickOutside:"close",dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1,mobile:{margin:0,clickContent:function(t,e){return"image"===t.type&&"toggleControls"},clickSlide:function(t,e){return"image"===t.type?"toggleControls":"close"},dblclickContent:function(t,e){return"image"===t.type&&"zoom"},dblclickSlide:function(t,e){return"image"===t.type&&"zoom"}},lang:"en",i18n:{en:{CLOSE:"Close",NEXT:"Next",PREV:"Previous",ERROR:"The requested content cannot be loaded.
Please try again later.",PLAY_START:"Start slideshow",PLAY_STOP:"Pause slideshow",FULL_SCREEN:"Full screen",THUMBS:"Thumbnails",DOWNLOAD:"Download",SHARE:"Share",ZOOM:"Zoom"},de:{CLOSE:"Schliessen",NEXT:"Weiter",PREV:"Zurück",ERROR:"Die angeforderten Daten konnten nicht geladen werden.
Bitte versuchen Sie es später nochmal.",PLAY_START:"Diaschau starten",PLAY_STOP:"Diaschau beenden",FULL_SCREEN:"Vollbild",THUMBS:"Vorschaubilder",DOWNLOAD:"Herunterladen",SHARE:"Teilen",ZOOM:"Maßstab"}}},s=n(t),r=n(e),c=0,l=function(t){return t&&t.hasOwnProperty&&t instanceof n},u=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),d=function(){var t,n=e.createElement("fakeelement"),a={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in a)if(n.style[t]!==o)return a[t];return"transitionend"}(),f=function(t){return t&&t.length&&t[0].offsetHeight},p=function(t,o,a){var i=this;i.opts=n.extend(!0,{index:a},n.fancybox.defaults,o||{}),n.fancybox.isMobile&&(i.opts=n.extend(!0,{},i.opts,i.opts.mobile)),o&&n.isArray(o.buttons)&&(i.opts.buttons=o.buttons),i.id=i.opts.id||++c,i.group=[],i.currIndex=parseInt(i.opts.index,10)||0,i.prevIndex=null,i.prevPos=null,i.currPos=0,i.firstRun=null,i.createGroup(t),i.group.length&&(i.$lastFocus=n(e.activeElement).blur(),i.slides={},i.init())};n.extend(p.prototype,{init:function(){var a,i,s,c=this,l=c.group[c.currIndex],u=l.opts,d=n.fancybox.scrollbarWidth;c.scrollTop=r.scrollTop(),c.scrollLeft=r.scrollLeft(),n.fancybox.getInstance()||(n("body").addClass("fancybox-active"),/iPad|iPhone|iPod/.test(navigator.userAgent)&&!t.MSStream?"image"!==l.type&&n("body").css("top",n("body").scrollTop()*-1).addClass("fancybox-iosfix"):!n.fancybox.isMobile&&e.body.scrollHeight>t.innerHeight&&(d===o&&(a=n('').appendTo("body"),d=n.fancybox.scrollbarWidth=a[0].offsetWidth-a[0].clientWidth,a.remove()),n("head").append('"),n("body").addClass("compensate-for-scrollbar"))),s="",n.each(u.buttons,function(t,e){s+=u.btnTpl[e]||""}),i=n(c.translate(c,u.baseTpl.replace("{{buttons}}",s).replace("{{arrows}}",u.btnTpl.arrowLeft+u.btnTpl.arrowRight))).attr("id","fancybox-container-"+c.id).addClass("fancybox-is-hidden").addClass(u.baseClass).data("FancyBox",c).appendTo(u.parentEl),c.$refs={container:i},["bg","inner","infobar","toolbar","stage","caption","navigation"].forEach(function(t){c.$refs[t]=i.find(".fancybox-"+t)}),c.trigger("onInit"),c.activate(),c.jumpTo(c.currIndex)},translate:function(t,e){var n=t.opts.i18n[t.opts.lang];return e.replace(/\{\{(\w+)\}\}/g,function(t,e){var a=n[e];return a===o?t:a})},createGroup:function(t){var e=this,a=n.makeArray(t);n.each(a,function(t,a){var i,s,r,c,l={},u={};n.isPlainObject(a)?(l=a,u=a.opts||a):"object"===n.type(a)&&n(a).length?(i=n(a),u=i.data(),u=n.extend({},u,u.options||{}),u.$orig=i,l.src=u.src||i.attr("href"),l.type||l.src||(l.type="inline",l.src=a)):l={type:"html",src:a+""},l.opts=n.extend(!0,{},e.opts,u),n.isArray(u.buttons)&&(l.opts.buttons=u.buttons),s=l.type||l.opts.type,r=l.src||"",!s&&r&&(r.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)?s="image":r.match(/\.(pdf)((\?|#).*)?$/i)?s="pdf":"#"===r.charAt(0)&&(s="inline")),s?l.type=s:e.trigger("objectNeedsType",l),l.index=e.group.length,l.opts.$orig&&!l.opts.$orig.length&&delete l.opts.$orig,!l.opts.$thumb&&l.opts.$orig&&(l.opts.$thumb=l.opts.$orig.find("img:first")),l.opts.$thumb&&!l.opts.$thumb.length&&delete l.opts.$thumb,"function"===n.type(l.opts.caption)&&(l.opts.caption=l.opts.caption.apply(a,[e,l])),"function"===n.type(e.opts.caption)&&(l.opts.caption=e.opts.caption.apply(a,[e,l])),l.opts.caption instanceof n||(l.opts.caption=l.opts.caption===o?"":l.opts.caption+""),"ajax"===s&&(c=r.split(/\s+/,2),c.length>1&&(l.src=c.shift(),l.opts.filter=c.shift())),"auto"==l.opts.smallBtn&&(n.inArray(s,["html","inline","ajax"])>-1?(l.opts.toolbar=!1,l.opts.smallBtn=!0):l.opts.smallBtn=!1),"pdf"===s&&(l.type="iframe",l.opts.iframe.preload=!1),l.opts.modal&&(l.opts=n.extend(!0,l.opts,{infobar:0,toolbar:0,smallBtn:0,keyboard:0,slideShow:0,fullScreen:0,thumbs:0,touch:0,clickContent:!1,clickSlide:!1,clickOutside:!1,dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1})),e.group.push(l)})},addEvents:function(){var o=this;o.removeEvents(),o.$refs.container.on("click.fb-close","[data-fancybox-close]",function(t){t.stopPropagation(),t.preventDefault(),o.close(t)}).on("click.fb-prev touchend.fb-prev","[data-fancybox-prev]",function(t){t.stopPropagation(),t.preventDefault(),o.previous()}).on("click.fb-next touchend.fb-next","[data-fancybox-next]",function(t){t.stopPropagation(),t.preventDefault(),o.next()}).on("click.fb","[data-fancybox-zoom]",function(t){o[o.isScaledDown()?"scaleToActual":"scaleToFit"]()}),s.on("orientationchange.fb resize.fb",function(t){t&&t.originalEvent&&"resize"===t.originalEvent.type?u(function(){o.update()}):(o.$refs.stage.hide(),setTimeout(function(){o.$refs.stage.show(),o.update()},600))}),r.on("focusin.fb",function(t){var a=n.fancybox?n.fancybox.getInstance():null;a.isClosing||!a.current||!a.current.opts.trapFocus||n(t.target).hasClass("fancybox-container")||n(t.target).is(e)||a&&"fixed"!==n(t.target).css("position")&&!a.$refs.container.has(t.target).length&&(t.stopPropagation(),a.focus(),s.scrollTop(o.scrollTop).scrollLeft(o.scrollLeft))}),r.on("keydown.fb",function(t){var e=o.current,a=t.keyCode||t.which;if(e&&e.opts.keyboard&&!n(t.target).is("input")&&!n(t.target).is("textarea"))return 8===a||27===a?(t.preventDefault(),void o.close(t)):37===a||38===a?(t.preventDefault(),void o.previous()):39===a||40===a?(t.preventDefault(),void o.next()):void o.trigger("afterKeydown",t,a)}),o.group[o.currIndex].opts.idleTime&&(o.idleSecondsCounter=0,r.on("mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",function(t){o.idleSecondsCounter=0,o.isIdle&&o.showControls(),o.isIdle=!1}),o.idleInterval=t.setInterval(function(){o.idleSecondsCounter++,o.idleSecondsCounter>=o.group[o.currIndex].opts.idleTime&&(o.isIdle=!0,o.idleSecondsCounter=0,o.hideControls())},1e3))},removeEvents:function(){var e=this;s.off("orientationchange.fb resize.fb"),r.off("focusin.fb keydown.fb .fb-idle"),this.$refs.container.off(".fb-close .fb-prev .fb-next"),e.idleInterval&&(t.clearInterval(e.idleInterval),e.idleInterval=null)},previous:function(t){return this.jumpTo(this.currPos-1,t)},next:function(t){return this.jumpTo(this.currPos+1,t)},jumpTo:function(t,e,a){var i,s,r,c,l,u,d,p=this,h=p.group.length;if(!(p.isSliding||p.isClosing||p.isAnimating&&p.firstRun)){if(t=parseInt(t,10),s=p.current?p.current.opts.loop:p.opts.loop,!s&&(t<0||t>=h))return!1;if(i=p.firstRun=null===p.firstRun,!(h<2&&!i&&p.isSliding)){if(c=p.current,p.prevIndex=p.currIndex,p.prevPos=p.currPos,r=p.createSlide(t),h>1&&((s||r.index>0)&&p.createSlide(t-1),(s||r.indexr.pos?"next":"previous"),c.$slide.removeClass("fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous"),c.isComplete=!1,e&&(r.isMoved||r.opts.transitionEffect)&&(r.isMoved?c.$slide.addClass(d):(d="fancybox-animated "+d+" fancybox-fx-"+r.opts.transitionEffect,n.fancybox.animate(c.$slide,d,e,function(){c.$slide.removeClass(d).removeAttr("style")}))))}}},createSlide:function(t){var e,o,a=this;return o=t%a.group.length,o=o<0?a.group.length+o:o,!a.slides[t]&&a.group[o]&&(e=n('').appendTo(a.$refs.stage),a.slides[t]=n.extend(!0,{},a.group[o],{pos:t,$slide:e,isLoaded:!1}),a.updateSlide(a.slides[t])),a.slides[t]},scaleToActual:function(t,e,a){var i,s,r,c,l,u=this,d=u.current,f=d.$content,p=parseInt(d.$slide.width(),10),h=parseInt(d.$slide.height(),10),g=d.width,b=d.height;"image"!=d.type||d.hasError||!f||u.isAnimating||(n.fancybox.stop(f),u.isAnimating=!0,t=t===o?.5*p:t,e=e===o?.5*h:e,i=n.fancybox.getTranslate(f),c=g/i.width,l=b/i.height,s=.5*p-.5*g,r=.5*h-.5*b,g>p&&(s=i.left*c-(t*c-t),s>0&&(s=0),sh&&(r=i.top*l-(e*l-e),r>0&&(r=0),rt.width||o.height>t.height))},isScaledDown:function(){var t=this,e=t.current,o=e.$content,a=!1;return o&&(a=n.fancybox.getTranslate(o),a=a.width1||Math.abs(n.height()-o.height)>1),o},loadSlide:function(t){var e,o,a,i=this;if(!t.isLoading&&!t.isLoaded){switch(t.isLoading=!0,i.trigger("beforeLoad",t),e=t.type,o=t.$slide,o.off("refresh").trigger("onReset").addClass("fancybox-slide--"+(e||"unknown")).addClass(t.opts.slideClass),e){case"image":i.setImage(t);break;case"iframe":i.setIframe(t);break;case"html":i.setContent(t,t.src||t.content);break;case"inline":n(t.src).length?i.setContent(t,n(t.src)):i.setError(t);break;case"ajax":i.showLoading(t),a=n.ajax(n.extend({},t.opts.ajax.settings,{url:t.src,success:function(e,n){"success"===n&&i.setContent(t,e)},error:function(e,n){e&&"abort"!==n&&i.setError(t)}})),o.one("onReset",function(){a.abort()});break;default:i.setError(t)}return!0}},setImage:function(e){var o,a,i,s,r=this,c=e.opts.srcset||e.opts.image.srcset;if(c){i=t.devicePixelRatio||1,s=t.innerWidth*i,a=c.split(",").map(function(t){var e={};return t.trim().split(/\s+/).forEach(function(t,n){var o=parseInt(t.substring(0,t.length-1),10);return 0===n?e.url=t:void(o&&(e.value=o,e.postfix=t[t.length-1]))}),e}),a.sort(function(t,e){return t.value-e.value});for(var l=0;l=s||"x"===u.postfix&&u.value>=i){o=u;break}}!o&&a.length&&(o=a[a.length-1]),o&&(e.src=o.url,e.width&&e.height&&"w"==o.postfix&&(e.height=e.width/e.height*o.value,e.width=o.value))}e.$content=n('').addClass("fancybox-is-hidden").appendTo(e.$slide),e.opts.preload!==!1&&e.opts.width&&e.opts.height&&(e.opts.thumb||e.opts.$thumb)?(e.width=e.opts.width,e.height=e.opts.height,e.$ghost=n("").one("error",function(){n(this).remove(),e.$ghost=null,r.setBigImage(e)}).one("load",function(){r.afterLoad(e),r.setBigImage(e)}).addClass("fancybox-image").appendTo(e.$content).attr("src",e.opts.thumb||e.opts.$thumb.attr("src"))):r.setBigImage(e)},setBigImage:function(t){var e=this,o=n("");t.$image=o.one("error",function(){e.setError(t)}).one("load",function(){clearTimeout(t.timouts),t.timouts=null,e.isClosing||(t.width=this.naturalWidth,t.height=this.naturalHeight,t.opts.image.srcset&&o.attr("sizes","100vw").attr("srcset",t.opts.image.srcset),e.hideLoading(t),t.$ghost?t.timouts=setTimeout(function(){t.timouts=null,t.$ghost.hide()},Math.min(300,Math.max(1e3,t.height/1600))):e.afterLoad(t))}).addClass("fancybox-image").attr("src",t.src).appendTo(t.$content),(o[0].complete||"complete"==o[0].readyState)&&o[0].naturalWidth&&o[0].naturalHeight?o.trigger("load"):o[0].error?o.trigger("error"):t.timouts=setTimeout(function(){o[0].complete||t.hasError||e.showLoading(t)},100)},setIframe:function(t){var e,a=this,i=t.opts.iframe,s=t.$slide;t.$content=n('').css(i.css).appendTo(s),e=n(i.tpl.replace(/\{rnd\}/g,(new Date).getTime())).attr(i.attr).appendTo(t.$content),i.preload?(a.showLoading(t),e.on("load.fb error.fb",function(e){this.isReady=1,t.$slide.trigger("refresh"),a.afterLoad(t)}),s.on("refresh.fb",function(){var n,a,s,r=t.$content,c=i.css.width,l=i.css.height;if(1===e[0].isReady){try{a=e.contents(),s=a.find("body")}catch(t){}s&&s.length&&(c===o&&(n=e[0].contentWindow.document.documentElement.scrollWidth,c=Math.ceil(s.outerWidth(!0)+(r.width()-n)),c+=r.outerWidth()-r.innerWidth()),l===o&&(l=Math.ceil(s.outerHeight(!0)),l+=r.outerHeight()-r.innerHeight()),c&&r.width(c),l&&r.height(l)),r.removeClass("fancybox-is-hidden")}})):this.afterLoad(t),e.attr("src",t.src),t.opts.smallBtn===!0&&t.$content.prepend(a.translate(t,t.opts.btnTpl.smallBtn)),s.one("onReset",function(){try{n(this).find("iframe").hide().attr("src","//about:blank")}catch(t){}n(this).empty(),t.isLoaded=!1})},setContent:function(t,e){var o=this;o.isClosing||(o.hideLoading(t),t.$slide.empty(),l(e)&&e.parent().length?(e.parent(".fancybox-slide--inline").trigger("onReset"),t.$placeholder=n("").hide().insertAfter(e),e.css("display","inline-block")):t.hasError||("string"===n.type(e)&&(e=n("").append(n.trim(e)).contents(),3===e[0].nodeType&&(e=n("").html(e))),t.opts.filter&&(e=n("").html(e).find(t.opts.filter))),t.$slide.one("onReset",function(){t.$placeholder&&(t.$placeholder.after(e.hide()).remove(),t.$placeholder=null),t.$smallBtn&&(t.$smallBtn.remove(),t.$smallBtn=null),t.hasError||(n(this).empty(),t.isLoaded=!1)}),t.$content=n(e).appendTo(t.$slide),this.afterLoad(t))},setError:function(t){t.hasError=!0,t.$slide.removeClass("fancybox-slide--"+t.type),this.setContent(t,this.translate(t,t.opts.errorTpl))},showLoading:function(t){var e=this;t=t||e.current,t&&!t.$spinner&&(t.$spinner=n(e.opts.spinnerTpl).appendTo(t.$slide))},hideLoading:function(t){var e=this;t=t||e.current,t&&t.$spinner&&(t.$spinner.remove(),delete t.$spinner)},afterLoad:function(t){var e=this;e.isClosing||(t.isLoading=!1,t.isLoaded=!0,e.trigger("afterLoad",t),e.hideLoading(t),t.opts.smallBtn&&!t.$smallBtn&&(t.$smallBtn=n(e.translate(t,t.opts.btnTpl.smallBtn)).appendTo(t.$content.filter("div,form").first())),t.opts.protect&&t.$content&&!t.hasError&&(t.$content.on("contextmenu.fb",function(t){return 2==t.button&&t.preventDefault(),!0}),"image"===t.type&&n('').appendTo(t.$content)),e.revealContent(t))},revealContent:function(t){var e,a,i,s,r,c=this,l=t.$slide,u=!1;return e=t.opts[c.firstRun?"animationEffect":"transitionEffect"],i=t.opts[c.firstRun?"animationDuration":"transitionDuration"],i=parseInt(t.forcedDuration===o?i:t.forcedDuration,10),!t.isMoved&&t.pos===c.currPos&&i||(e=!1),"zoom"!==e||t.pos===c.currPos&&i&&"image"===t.type&&!t.hasError&&(u=c.getThumbPos(t))||(e="fade"),"zoom"===e?(r=c.getFitPos(t),r.scaleX=r.width/u.width,r.scaleY=r.height/u.height,delete r.width,delete r.height,s=t.opts.zoomOpacity,"auto"==s&&(s=Math.abs(t.width/t.height-u.width/u.height)>.1),s&&(u.opacity=.1,r.opacity=1),n.fancybox.setTranslate(t.$content.removeClass("fancybox-is-hidden"),u),f(t.$content),void n.fancybox.animate(t.$content,r,i,function(){c.complete()})):(c.updateSlide(t),e?(n.fancybox.stop(l),a="fancybox-animated fancybox-slide--"+(t.pos>=c.prevPos?"next":"previous")+" fancybox-fx-"+e,l.removeAttr("style").removeClass("fancybox-slide--current fancybox-slide--next fancybox-slide--previous").addClass(a),t.$content.removeClass("fancybox-is-hidden"),f(l),void n.fancybox.animate(l,"fancybox-slide--current",i,function(e){l.removeClass(a).removeAttr("style"),t.pos===c.currPos&&c.complete()},!0)):(f(l),t.$content.removeClass("fancybox-is-hidden"),void(t.pos===c.currPos&&c.complete())))},getThumbPos:function(o){var a,i=this,s=!1,r=function(e){for(var o,a=e[0],i=a.getBoundingClientRect(),s=[];null!==a.parentElement;)"hidden"!==n(a.parentElement).css("overflow")&&"auto"!==n(a.parentElement).css("overflow")||s.push(a.parentElement.getBoundingClientRect()),a=a.parentElement;return o=s.every(function(t){var e=Math.min(i.right,t.right)-Math.max(i.left,t.left),n=Math.min(i.bottom,t.bottom)-Math.max(i.top,t.top);return e>0&&n>0}),o&&i.bottom>0&&i.right>0&&i.left=t.currPos-1&&o.pos<=t.currPos+1?a[o.pos]=o:o&&(n.fancybox.stop(o.$slide),o.$slide.off().remove())}),t.slides=a,t.updateCursor(),t.trigger("afterShow"),(n(e.activeElement).is("[disabled]")||o.opts.autoFocus&&"image"!=o.type&&"iframe"!==o.type)&&t.focus())},preload:function(){var t,e,n=this;n.group.length<2||(t=n.slides[n.currPos+1],e=n.slides[n.currPos-1],t&&"image"===t.type&&n.loadSlide(t),e&&"image"===e.type&&n.loadSlide(e))},focus:function(){var t,e=this.current;this.isClosing||(e&&e.isComplete&&(t=e.$slide.find("input[autofocus]:enabled:visible:first"),t.length||(t=e.$slide.find("button,:input,[tabindex],a").filter(":enabled:visible:first"))),t=t&&t.length?t:this.$refs.container,t.focus())},activate:function(){var t=this;n(".fancybox-container").each(function(){var e=n(this).data("FancyBox");e&&e.id!==t.id&&!e.isClosing&&(e.trigger("onDeactivate"),e.removeEvents(),e.isVisible=!1)}),t.isVisible=!0,(t.current||t.isIdle)&&(t.update(),t.updateControls()),t.trigger("onActivate"),t.addEvents()},close:function(t,e){var o,a,i,s,r,c,l=this,p=l.current,h=function(){l.cleanUp(t)};return!l.isClosing&&(l.isClosing=!0,l.trigger("beforeClose",t)===!1?(l.isClosing=!1,u(function(){l.update()}),!1):(l.removeEvents(),p.timouts&&clearTimeout(p.timouts),i=p.$content,o=p.opts.animationEffect,a=n.isNumeric(e)?e:o?p.opts.animationDuration:0,p.$slide.off(d).removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated"),p.$slide.siblings().trigger("onReset").remove(),a&&l.$refs.container.removeClass("fancybox-is-open").addClass("fancybox-is-closing"),l.hideLoading(p),l.hideControls(),l.updateCursor(),"zoom"!==o||t!==!0&&i&&a&&"image"===p.type&&!p.hasError&&(c=l.getThumbPos(p))||(o="fade"),"zoom"===o?(n.fancybox.stop(i),r=n.fancybox.getTranslate(i),r.width=r.width*r.scaleX,r.height=r.height*r.scaleY,s=p.opts.zoomOpacity,"auto"==s&&(s=Math.abs(p.width/p.height-c.width/c.height)>.1),s&&(c.opacity=0),r.scaleX=r.width/c.width,r.scaleY=r.height/c.height,r.width=c.width,r.height=c.height,n.fancybox.setTranslate(p.$content,r),f(p.$content),n.fancybox.animate(p.$content,c,a,h),!0):(o&&a?t===!0?setTimeout(h,a):n.fancybox.animate(p.$slide.removeClass("fancybox-slide--current"),"fancybox-animated fancybox-slide--previous fancybox-fx-"+o,a,h):h(),!0)))},cleanUp:function(t){var o,a,i=this,r=n("body");i.current.$slide.trigger("onReset"),i.$refs.container.empty().remove(),i.trigger("afterClose",t),i.$lastFocus&&i.current.opts.backFocus&&i.$lastFocus.focus(),i.current=null,o=n.fancybox.getInstance(),o?o.activate():(s.scrollTop(i.scrollTop).scrollLeft(i.scrollLeft),r.removeClass("fancybox-active compensate-for-scrollbar"),r.hasClass("fancybox-iosfix")&&(a=parseInt(e.body.style.top,10),r.removeClass("fancybox-iosfix").css("top","").scrollTop(a*-1)),n("#fancybox-style-noscroll").remove())},trigger:function(t,e){var o,a=Array.prototype.slice.call(arguments,1),i=this,s=e&&e.opts?e:i.current;return s?a.unshift(s):s=i,a.unshift(i),n.isFunction(s.opts[t])&&(o=s.opts[t].apply(s,a)),o===!1?o:void("afterClose"!==t&&i.$refs?i.$refs.container.trigger(t+".fb",a):r.trigger(t+".fb",a))},updateControls:function(t){var e=this,n=e.current,o=n.index,a=n.opts.caption,i=e.$refs.container,s=e.$refs.caption;n.$slide.trigger("refresh"),e.$caption=a&&a.length?s.html(a):null,e.isHiddenControls||e.isIdle||e.showControls(),i.find("[data-fancybox-count]").html(e.group.length),i.find("[data-fancybox-index]").html(o+1),i.find("[data-fancybox-prev]").prop("disabled",!n.opts.loop&&o<=0),i.find("[data-fancybox-next]").prop("disabled",!n.opts.loop&&o>=e.group.length-1),"image"===n.type?i.find("[data-fancybox-download]").attr("href",n.opts.image.src||n.src).show():i.find("[data-fancybox-download],[data-fancybox-zoom]").hide()},hideControls:function(){this.isHiddenControls=!0,this.$refs.container.removeClass("fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav")},showControls:function(){var t=this,e=t.current?t.current.opts:t.opts,n=t.$refs.container;t.isHiddenControls=!1,t.idleSecondsCounter=0,n.toggleClass("fancybox-show-toolbar",!(!e.toolbar||!e.buttons)).toggleClass("fancybox-show-infobar",!!(e.infobar&&t.group.length>1)).toggleClass("fancybox-show-nav",!!(e.arrows&&t.group.length>1)).toggleClass("fancybox-is-modal",!!e.modal),t.$caption?n.addClass("fancybox-show-caption "):n.removeClass("fancybox-show-caption")},toggleControls:function(){this.isHiddenControls?this.showControls():this.hideControls()}}),n.fancybox={version:"3.2.5",defaults:i,getInstance:function(t){var e=n('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"),o=Array.prototype.slice.call(arguments,1);return e instanceof p&&("string"===n.type(t)?e[t].apply(e,o):"function"===n.type(t)&&t.apply(e,o),e)},open:function(t,e,n){return new p(t,e,n)},close:function(t){var e=this.getInstance();e&&(e.close(),t===!0&&this.close())},destroy:function(){this.close(!0),r.off("click.fb-start")},isMobile:e.createTouch!==o&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),use3d:function(){var n=e.createElement("div");return t.getComputedStyle&&t.getComputedStyle(n).getPropertyValue("transform")&&!(e.documentMode&&e.documentMode<11)}(),getTranslate:function(t){var e;if(!t||!t.length)return!1;if(e=t.eq(0).css("transform"),e&&e.indexOf("matrix")!==-1?(e=e.split("(")[1],e=e.split(")")[0],e=e.split(",")):e=[],e.length)e=e.length>10?[e[13],e[12],e[0],e[5]]:[e[5],e[4],e[0],e[3]],e=e.map(parseFloat);else{e=[0,0,1,1];var n=/\.*translate\((.*)px,(.*)px\)/i,o=n.exec(t.eq(0).attr("style"));o&&(e[0]=parseFloat(o[2]),e[1]=parseFloat(o[1]))}return{top:e[0],left:e[1],scaleX:e[2],scaleY:e[3],opacity:parseFloat(t.css("opacity")),width:t.width(),height:t.height()}},setTranslate:function(t,e){var n="",a={};if(t&&e)return e.left===o&&e.top===o||(n=(e.left===o?t.position().left:e.left)+"px, "+(e.top===o?t.position().top:e.top)+"px",n=this.use3d?"translate3d("+n+", 0px)":"translate("+n+")"),e.scaleX!==o&&e.scaleY!==o&&(n=(n.length?n+" ":"")+"scale("+e.scaleX+", "+e.scaleY+")"),n.length&&(a.transform=n),e.opacity!==o&&(a.opacity=e.opacity),e.width!==o&&(a.width=e.width),e.height!==o&&(a.height=e.height),t.css(a)},animate:function(t,e,a,i,s){n.isFunction(a)&&(i=a,a=null),n.isPlainObject(e)||t.removeAttr("style"),t.on(d,function(a){(!a||!a.originalEvent||t.is(a.originalEvent.target)&&"z-index"!=a.originalEvent.propertyName)&&(n.fancybox.stop(t),n.isPlainObject(e)?e.scaleX!==o&&e.scaleY!==o&&(t.css("transition-duration",""),e.width=Math.round(t.width()*e.scaleX),e.height=Math.round(t.height()*e.scaleY),e.scaleX=1,e.scaleY=1,n.fancybox.setTranslate(t,e)):s!==!0&&t.removeClass(e),n.isFunction(i)&&i(a))}),n.isNumeric(a)&&t.css("transition-duration",a+"ms"),n.isPlainObject(e)?n.fancybox.setTranslate(t,e):t.addClass(e),e.scaleX&&t.hasClass("fancybox-image-wrap")&&t.parent().addClass("fancybox-is-scaling"),t.data("timer",setTimeout(function(){t.trigger("transitionend")},a+16))},stop:function(t){clearTimeout(t.data("timer")),t.off("transitionend").css("transition-duration",""),t.hasClass("fancybox-image-wrap")&&t.parent().removeClass("fancybox-is-scaling")}},n.fn.fancybox=function(t){var e;return t=t||{},e=t.selector||!1,e?n("body").off("click.fb-start",e).on("click.fb-start",e,{options:t},a):this.off("click.fb-start").on("click.fb-start",{items:this,options:t},a),this},r.on("click.fb-start","[data-fancybox]",a)}}(window,document,window.jQuery||jQuery),function(t){"use strict";var e=function(e,n,o){if(e)return o=o||"","object"===t.type(o)&&(o=t.param(o,!0)),t.each(n,function(t,n){e=e.replace("$"+t,n||"")}),o.length&&(e+=(e.indexOf("?")>0?"&":"?")+o),e},n={youtube:{matcher:/(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,params:{autoplay:1,autohide:1,fs:1,rel:0,hd:1,wmode:"transparent",enablejsapi:1,html5:1},paramPlace:8,type:"iframe",url:"//www.youtube.com/embed/$4",thumb:"//img.youtube.com/vi/$4/hqdefault.jpg"},vimeo:{matcher:/^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,params:{autoplay:1,hd:1,show_title:1,show_byline:1,show_portrait:0,fullscreen:1,api:1},paramPlace:3,type:"iframe",url:"//player.vimeo.com/video/$2"},metacafe:{matcher:/metacafe.com\/watch\/(\d+)\/(.*)?/,type:"iframe",url:"//www.metacafe.com/embed/$1/?ap=1"},dailymotion:{matcher:/dailymotion.com\/video\/(.*)\/?(.*)/,params:{additionalInfos:0,autoStart:1},type:"iframe",url:"//www.dailymotion.com/embed/video/$1"},vine:{matcher:/vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,type:"iframe",url:"//vine.co/v/$1/embed/simple"},instagram:{matcher:/(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,type:"image",url:"//$1/p/$2/media/?size=l"
+},gmap_place:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/?ll="+(t[9]?t[9]+"&z="+Math.floor(t[10])+(t[12]?t[12].replace(/^\//,"&"):""):t[12])+"&output="+(t[12]&&t[12].indexOf("layer=c")>0?"svembed":"embed")}},gmap_search:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/maps?q="+t[5].replace("query=","q=").replace("api=1","")+"&output=embed"}}};t(document).on("objectNeedsType.fb",function(o,a,i){var s,r,c,l,u,d,f,p=i.src||"",h=!1;s=t.extend(!0,{},n,i.opts.media),t.each(s,function(n,o){if(c=p.match(o.matcher)){if(h=o.type,d={},o.paramPlace&&c[o.paramPlace]){u=c[o.paramPlace],"?"==u[0]&&(u=u.substring(1)),u=u.split("&");for(var a=0;ae.clientHeight,i=("scroll"===o||"auto"===o)&&e.scrollWidth>e.clientWidth;return a||i},l=function(t){for(var e=!1;;){if(e=c(t.get(0)))break;if(t=t.parent(),!t.length||t.hasClass("fancybox-stage")||t.is("body"))break}return e},u=function(t){var e=this;e.instance=t,e.$bg=t.$refs.bg,e.$stage=t.$refs.stage,e.$container=t.$refs.container,e.destroy(),e.$container.on("touchstart.fb.touch mousedown.fb.touch",n.proxy(e,"ontouchstart"))};u.prototype.destroy=function(){this.$container.off(".fb.touch")},u.prototype.ontouchstart=function(o){var a=this,c=n(o.target),u=a.instance,d=u.current,f=d.$content,p="touchstart"==o.type;if(p&&a.$container.off("mousedown.fb.touch"),!d||a.instance.isAnimating||a.instance.isClosing)return o.stopPropagation(),void o.preventDefault();if((!o.originalEvent||2!=o.originalEvent.button)&&c.length&&!r(c)&&!r(c.parent())&&!(o.originalEvent.clientX>c[0].clientWidth+c.offset().left)&&(a.startPoints=i(o),a.startPoints&&!(a.startPoints.length>1&&u.isSliding))){if(a.$target=c,a.$content=f,a.canTap=!0,a.opts=d.opts.touch,n(e).off(".fb.touch"),n(e).on(p?"touchend.fb.touch touchcancel.fb.touch":"mouseup.fb.touch mouseleave.fb.touch",n.proxy(a,"ontouchend")),n(e).on(p?"touchmove.fb.touch":"mousemove.fb.touch",n.proxy(a,"ontouchmove")),!a.opts&&!u.canPan()||!c.is(a.$stage)&&!a.$stage.find(c).length)return void(c.is("img")&&o.preventDefault());o.stopPropagation(),n.fancybox.isMobile&&(l(a.$target)||l(a.$target.parent()))||o.preventDefault(),a.canvasWidth=Math.round(d.$slide[0].clientWidth),a.canvasHeight=Math.round(d.$slide[0].clientHeight),a.startTime=(new Date).getTime(),a.distanceX=a.distanceY=a.distance=0,a.isPanning=!1,a.isSwiping=!1,a.isZooming=!1,a.sliderStartPos=a.sliderLastPos||{top:0,left:0},a.contentStartPos=n.fancybox.getTranslate(a.$content),a.contentLastPos=null,1!==a.startPoints.length||a.isZooming||(a.canTap=!u.isSliding,"image"===d.type&&(a.contentStartPos.width>a.canvasWidth+1||a.contentStartPos.height>a.canvasHeight+1)?(n.fancybox.stop(a.$content),a.$content.css("transition-duration","0ms"),a.isPanning=!0):a.isSwiping=!0,a.$container.addClass("fancybox-controls--isGrabbing")),2!==a.startPoints.length||u.isAnimating||d.hasError||"image"!==d.type||!d.isLoaded&&!d.$ghost||(a.isZooming=!0,a.isSwiping=!1,a.isPanning=!1,n.fancybox.stop(a.$content),a.$content.css("transition-duration","0ms"),a.centerPointStartX=.5*(a.startPoints[0].x+a.startPoints[1].x)-n(t).scrollLeft(),a.centerPointStartY=.5*(a.startPoints[0].y+a.startPoints[1].y)-n(t).scrollTop(),a.percentageOfImageAtPinchPointX=(a.centerPointStartX-a.contentStartPos.left)/a.contentStartPos.width,a.percentageOfImageAtPinchPointY=(a.centerPointStartY-a.contentStartPos.top)/a.contentStartPos.height,a.startDistanceBetweenFingers=s(a.startPoints[0],a.startPoints[1]))}},u.prototype.ontouchmove=function(t){var e=this;if(e.newPoints=i(t),n.fancybox.isMobile&&(l(e.$target)||l(e.$target.parent())))return t.stopPropagation(),void(e.canTap=!1);if((e.opts||e.instance.canPan())&&e.newPoints&&e.newPoints.length&&(e.distanceX=s(e.newPoints[0],e.startPoints[0],"x"),e.distanceY=s(e.newPoints[0],e.startPoints[0],"y"),e.distance=s(e.newPoints[0],e.startPoints[0]),e.distance>0)){if(!e.$target.is(e.$stage)&&!e.$stage.find(e.$target).length)return;t.stopPropagation(),t.preventDefault(),e.isSwiping?e.onSwipe():e.isPanning?e.onPan():e.isZooming&&e.onZoom()}},u.prototype.onSwipe=function(){var e,i=this,s=i.isSwiping,r=i.sliderStartPos.left||0;s===!0?Math.abs(i.distance)>10&&(i.canTap=!1,i.instance.group.length<2&&i.opts.vertical?i.isSwiping="y":i.instance.isSliding||i.opts.vertical===!1||"auto"===i.opts.vertical&&n(t).width()>800?i.isSwiping="x":(e=Math.abs(180*Math.atan2(i.distanceY,i.distanceX)/Math.PI),i.isSwiping=e>45&&e<135?"y":"x"),i.instance.isSliding=i.isSwiping,i.startPoints=i.newPoints,n.each(i.instance.slides,function(t,e){n.fancybox.stop(e.$slide),e.$slide.css("transition-duration","0ms"),e.inTransition=!1,e.pos===i.instance.current.pos&&(i.sliderStartPos.left=n.fancybox.getTranslate(e.$slide).left)}),i.instance.SlideShow&&i.instance.SlideShow.isActive&&i.instance.SlideShow.stop()):("x"==s&&(i.distanceX>0&&(i.instance.group.length<2||0===i.instance.current.index&&!i.instance.current.opts.loop)?r+=Math.pow(i.distanceX,.8):i.distanceX<0&&(i.instance.group.length<2||i.instance.current.index===i.instance.group.length-1&&!i.instance.current.opts.loop)?r-=Math.pow(-i.distanceX,.8):r+=i.distanceX),i.sliderLastPos={top:"x"==s?0:i.sliderStartPos.top+i.distanceY,left:r},i.requestId&&(a(i.requestId),i.requestId=null),i.requestId=o(function(){i.sliderLastPos&&(n.each(i.instance.slides,function(t,e){var o=e.pos-i.instance.currPos;n.fancybox.setTranslate(e.$slide,{top:i.sliderLastPos.top,left:i.sliderLastPos.left+o*i.canvasWidth+o*e.opts.gutter})}),i.$container.addClass("fancybox-is-sliding"))}))},u.prototype.onPan=function(){var t,e,i,s=this;s.canTap=!1,t=s.contentStartPos.width>s.canvasWidth?s.contentStartPos.left+s.distanceX:s.contentStartPos.left,e=s.contentStartPos.top+s.distanceY,i=s.limitMovement(t,e,s.contentStartPos.width,s.contentStartPos.height),i.scaleX=s.contentStartPos.scaleX,i.scaleY=s.contentStartPos.scaleY,s.contentLastPos=i,s.requestId&&(a(s.requestId),s.requestId=null),s.requestId=o(function(){n.fancybox.setTranslate(s.$content,s.contentLastPos)})},u.prototype.limitMovement=function(t,e,n,o){var a,i,s,r,c=this,l=c.canvasWidth,u=c.canvasHeight,d=c.contentStartPos.left,f=c.contentStartPos.top,p=c.distanceX,h=c.distanceY;return a=Math.max(0,.5*l-.5*n),i=Math.max(0,.5*u-.5*o),s=Math.min(l-n,.5*l-.5*n),r=Math.min(u-o,.5*u-.5*o),n>l&&(p>0&&t>a&&(t=a-1+Math.pow(-a+d+p,.8)||0),p<0&&tu&&(h>0&&e>i&&(e=i-1+Math.pow(-i+f+h,.8)||0),h<0&&ei?(t=t>0?0:t,t=ts?(e=e>0?0:e,e=e50?(n.fancybox.animate(e.instance.current.$slide,{top:e.sliderStartPos.top+e.distanceY+150*e.velocityY,opacity:0},150),o=e.instance.close(!0,300)):"x"==t&&e.distanceX>50&&e.instance.group.length>1?o=e.instance.previous(e.speedX):"x"==t&&e.distanceX<-50&&e.instance.group.length>1&&(o=e.instance.next(e.speedX)),o!==!1||"x"!=t&&"y"!=t||e.instance.jumpTo(e.instance.current.index,150),e.$container.removeClass("fancybox-is-sliding")},u.prototype.endPanning=function(){var t,e,o,a=this;a.contentLastPos&&(a.opts.momentum===!1?(t=a.contentLastPos.left,e=a.contentLastPos.top):(t=a.contentLastPos.left+a.velocityX*a.speed,e=a.contentLastPos.top+a.velocityY*a.speed),o=a.limitPosition(t,e,a.contentStartPos.width,a.contentStartPos.height),o.width=a.contentStartPos.width,o.height=a.contentStartPos.height,n.fancybox.animate(a.$content,o,330))},u.prototype.endZooming=function(){var t,e,o,a,i=this,s=i.instance.current,r=i.newWidth,c=i.newHeight;i.contentLastPos&&(t=i.contentLastPos.left,e=i.contentLastPos.top,a={top:e,left:t,width:r,height:c,scaleX:1,scaleY:1},n.fancybox.setTranslate(i.$content,a),rs.width||c>s.height?i.instance.scaleToActual(i.centerPointStartX,i.centerPointStartY,150):(o=i.limitPosition(t,e,r,c),n.fancybox.setTranslate(i.content,n.fancybox.getTranslate(i.$content)),n.fancybox.animate(i.$content,o,150)))},u.prototype.onTap=function(t){var e,o=this,a=n(t.target),s=o.instance,r=s.current,c=t&&i(t)||o.startPoints,l=c[0]?c[0].x-o.$stage.offset().left:0,u=c[0]?c[0].y-o.$stage.offset().top:0,d=function(e){var a=r.opts[e];if(n.isFunction(a)&&(a=a.apply(s,[r,t])),a)switch(a){case"close":s.close(o.startEvent);break;case"toggleControls":s.toggleControls(!0);break;case"next":s.next();break;case"nextOrClose":s.group.length>1?s.next():s.close(o.startEvent);break;case"zoom":"image"==r.type&&(r.isLoaded||r.$ghost)&&(s.canPan()?s.scaleToFit():s.isScaledDown()?s.scaleToActual(l,u):s.group.length<2&&s.close(o.startEvent))}};if(!(t.originalEvent&&2==t.originalEvent.button||s.isSliding||l>a[0].clientWidth+a.offset().left)){if(a.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container"))e="Outside";else if(a.is(".fancybox-slide"))e="Slide";else{if(!s.current.$content||!s.current.$content.has(t.target).length)return;e="Content"}if(o.tapped){if(clearTimeout(o.tapped),o.tapped=null,Math.abs(l-o.tapX)>50||Math.abs(u-o.tapY)>50||s.isSliding)return this;d("dblclick"+e)}else o.tapX=l,o.tapY=u,r.opts["dblclick"+e]&&r.opts["dblclick"+e]!==r.opts["click"+e]?o.tapped=setTimeout(function(){o.tapped=null,d("click"+e)},300):d("click"+e);return this}},n(e).on("onActivate.fb",function(t,e){e&&!e.Guestures&&(e.Guestures=new u(e))}),n(e).on("beforeClose.fb",function(t,e){e&&e.Guestures&&e.Guestures.destroy()})}(window,document,window.jQuery||jQuery),function(t,e){"use strict";e.extend(!0,e.fancybox.defaults,{btnTpl:{slideShow:''},slideShow:{autoStart:!1,speed:3e3}});var n=function(t){this.instance=t,this.init()};e.extend(n.prototype,{timer:null,isActive:!1,$button:null,init:function(){var t=this;t.$button=t.instance.$refs.toolbar.find("[data-fancybox-play]").on("click",function(){t.toggle()}),(t.instance.group.length<2||!t.instance.group[t.instance.currIndex].opts.slideShow)&&t.$button.hide()},set:function(t){var e=this;e.instance&&e.instance.current&&(t===!0||e.instance.current.opts.loop||e.instance.currIndex'},fullScreen:{autoStart:!1}}),e(t).on({"onInit.fb":function(t,e){var n;e&&e.group[e.currIndex].opts.fullScreen?(n=e.$refs.container,n.on("click.fb-fullscreen","[data-fancybox-fullscreen]",function(t){t.stopPropagation(),t.preventDefault(),o.toggle(n[0])}),e.opts.fullScreen&&e.opts.fullScreen.autoStart===!0&&o.request(n[0]),e.FullScreen=o):e&&e.$refs.toolbar.find("[data-fancybox-fullscreen]").hide()},"afterKeydown.fb":function(t,e,n,o,a){e&&e.FullScreen&&70===a&&(o.preventDefault(),e.FullScreen.toggle(e.$refs.container[0]))},"beforeClose.fb":function(t){t&&t.FullScreen&&o.exit()}}),e(t).on(n.fullscreenchange,function(){var t=o.isFullscreen(),n=e.fancybox.getInstance();n&&(n.current&&"image"===n.current.type&&n.isAnimating&&(n.current.$content.css("transition","none"),n.isAnimating=!1,n.update(!0,!0,0)),n.trigger("onFullscreenChange",t),n.$refs.container.toggleClass("fancybox-is-fullscreen",t))})}(document,window.jQuery||jQuery),function(t,e){"use strict";e.fancybox.defaults=e.extend(!0,{btnTpl:{thumbs:''},thumbs:{autoStart:!1,hideOnClose:!0,parentEl:".fancybox-container",axis:"y"}},e.fancybox.defaults);var n=function(t){this.init(t)};e.extend(n.prototype,{$button:null,$grid:null,$list:null,isVisible:!1,isActive:!1,init:function(t){var e=this;e.instance=t,t.Thumbs=e;var n=t.group[0],o=t.group[1];e.opts=t.group[t.currIndex].opts.thumbs,e.$button=t.$refs.toolbar.find("[data-fancybox-thumbs]"),e.opts&&n&&o&&("image"==n.type||n.opts.thumb||n.opts.$thumb)&&("image"==o.type||o.opts.thumb||o.opts.$thumb)?(e.$button.show().on("click",function(){e.toggle()}),e.isActive=!0):e.$button.hide()},create:function(){var t,n,o=this,a=o.instance,i=o.opts.parentEl;o.$grid=e('').appendTo(a.$refs.container.find(i).addBack().filter(i)),t="",e.each(a.group,function(e,o){n=o.opts.thumb||(o.opts.$thumb?o.opts.$thumb.attr("src"):null),n||"image"!==o.type||(n=o.src),n&&n.length&&(t+='')}),t+="
",o.$list=e(t).appendTo(o.$grid).on("click","li",function(){a.jumpTo(e(this).data("index"))}),o.$list.find("img").hide().one("load",function(){var t,n,o,a,i=e(this).parent().removeClass("fancybox-thumbs-loading"),s=i.outerWidth(),r=i.outerHeight();t=this.naturalWidth||this.width,n=this.naturalHeight||this.height,o=t/s,a=n/r,o>=1&&a>=1&&(o>a?(t/=a,n=r):(t=s,n/=o)),e(this).css({width:Math.floor(t),height:Math.floor(n),"margin-top":n>r?Math.floor(.3*r-.3*n):Math.floor(.5*r-.5*n),"margin-left":Math.floor(.5*s-.5*t)}).show()}).each(function(){this.src=e(this).data("src")}),"x"===o.opts.axis&&o.$list.width(parseInt(o.$grid.css("padding-right"))+a.group.length*o.$list.children().eq(0).outerWidth(!0)+"px")},focus:function(t){var e,n,o=this,a=o.$list;o.instance.current&&(e=a.children().removeClass("fancybox-thumbs-active").filter('[data-index="'+o.instance.current.index+'"]').addClass("fancybox-thumbs-active"),n=e.position(),"y"===o.opts.axis&&(n.top<0||n.top>a.height()-e.outerHeight())?a.stop().animate({scrollTop:a.scrollTop()+n.top},t):"x"===o.opts.axis&&(n.lefta.parent().scrollLeft()+(a.parent().width()-e.outerWidth()))&&a.parent().stop().animate({scrollLeft:n.left},t))},update:function(){this.instance.$refs.container.toggleClass("fancybox-show-thumbs",this.isVisible),this.isVisible?(this.$grid||this.create(),this.instance.trigger("onThumbsShow"),this.focus(0)):this.$grid&&this.instance.trigger("onThumbsHide"),this.instance.update()},hide:function(){this.isVisible=!1,this.update()},show:function(){this.isVisible=!0,this.update()},toggle:function(){this.isVisible=!this.isVisible,this.update()}}),e(t).on({"onInit.fb":function(t,e){var o;e&&!e.Thumbs&&(o=new n(e),o.isActive&&o.opts.autoStart===!0&&o.show())},"beforeShow.fb":function(t,e,n,o){var a=e&&e.Thumbs;a&&a.isVisible&&a.focus(o?0:250)},"afterKeydown.fb":function(t,e,n,o,a){var i=e&&e.Thumbs;i&&i.isActive&&71===a&&(o.preventDefault(),i.toggle())},"beforeClose.fb":function(t,e){var n=e&&e.Thumbs;n&&n.isVisible&&n.opts.hideOnClose!==!1&&n.$grid.hide()}})}(document,window.jQuery),function(t,e){"use strict";function n(t){var e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};return String(t).replace(/[&<>"'`=\/]/g,function(t){return e[t]})}e.extend(!0,e.fancybox.defaults,{btnTpl:{share:''},share:{tpl:''}}),e(t).on("click","[data-fancybox-share]",function(){var t,o,a=e.fancybox.getInstance();a&&(t=a.current.opts.hash===!1?a.current.src:window.location,o=a.current.opts.share.tpl.replace(/\{\{src\}\}/g,encodeURIComponent(t)).replace(/\{\{src_raw\}\}/g,n(t)).replace(/\{\{descr\}\}/g,a.$caption?encodeURIComponent(a.$caption.text()):""),e.fancybox.open({src:a.translate(a,o),type:"html",opts:{animationEffect:"fade",animationDuration:250}}))})}(document,window.jQuery||jQuery),function(t,e,n){"use strict";function o(){var t=e.location.hash.substr(1),n=t.split("-"),o=n.length>1&&/^\+?\d+$/.test(n[n.length-1])?parseInt(n.pop(-1),10)||1:1,a=n.join("-");return o<1&&(o=1),{hash:t,index:o,gallery:a}}function a(t){var e;""!==t.gallery&&(e=n("[data-fancybox='"+n.escapeSelector(t.gallery)+"']").eq(t.index-1),e.length||(e=n("#"+n.escapeSelector(t.gallery))),e.length&&(s=!1,e.trigger("click")))}function i(t){var e;return!!t&&(e=t.current?t.current.opts:t.opts,e.hash||(e.$orig?e.$orig.data("fancybox"):""))}n.escapeSelector||(n.escapeSelector=function(t){var e=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,n=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t};return(t+"").replace(e,n)});var s=!0,r=null,c=null;n(function(){n.fancybox.defaults.hash!==!1&&(n(t).on({"onInit.fb":function(t,e){var n,a;e.group[e.currIndex].opts.hash!==!1&&(n=o(),a=i(e),a&&n.gallery&&a==n.gallery&&(e.currIndex=n.index-1))},"beforeShow.fb":function(n,o,a){var l;a&&a.opts.hash!==!1&&(l=i(o),l&&""!==l&&(e.location.hash.indexOf(l)<0&&(o.opts.origHash=e.location.hash),r=l+(o.group.length>1?"-"+(a.index+1):""),"replaceState"in e.history?(c&&clearTimeout(c),c=setTimeout(function(){e.history[s?"pushState":"replaceState"]({},t.title,e.location.pathname+e.location.search+"#"+r),c=null,s=!1},300)):e.location.hash=r))},"beforeClose.fb":function(o,a,s){var l,u;c&&clearTimeout(c),s.opts.hash!==!1&&(l=i(a),u=a&&a.opts.origHash?a.opts.origHash:"",l&&""!==l&&("replaceState"in history?e.history.replaceState({},t.title,e.location.pathname+e.location.search+u):(e.location.hash=u,n(e).scrollTop(a.scrollTop).scrollLeft(a.scrollLeft))),r=null)}}),n(e).on("hashchange.fb",function(){var t=o();n.fancybox.getInstance()?!r||r===t.gallery+"-"+t.index||1===t.index&&r==t.gallery||(r=null,n.fancybox.close()):""!==t.gallery&&a(t)}),setTimeout(function(){a(o())},50))})}(document,window,window.jQuery||jQuery);
\ No newline at end of file
diff --git a/source/lib/fancybox/source/jquery.fancybox.pack.js b/source/lib/fancybox/source/jquery.fancybox.pack.js
new file mode 100644
index 000000000..ac97c2cc9
--- /dev/null
+++ b/source/lib/fancybox/source/jquery.fancybox.pack.js
@@ -0,0 +1,5152 @@
+// ==================================================
+// fancyBox v3.2.5
+//
+// Licensed GPLv3 for open source use
+// or fancyBox Commercial License for commercial use
+//
+// http://fancyapps.com/fancybox/
+// Copyright 2017 fancyApps
+//
+// ==================================================
+;(function (window, document, $, undefined) {
+ 'use strict';
+
+ // If there's no jQuery, fancyBox can't work
+ // =========================================
+
+ if ( !$ ) {
+ return;
+ }
+
+ // Check if fancyBox is already initialized
+ // ========================================
+
+ if ( $.fn.fancybox ) {
+
+ if ( 'console' in window ) {
+ console.log( 'fancyBox already initialized' );
+ }
+
+ return;
+ }
+
+ // Private default settings
+ // ========================
+
+ var defaults = {
+
+ // Enable infinite gallery navigation
+ loop : false,
+
+ // Space around image, ignored if zoomed-in or viewport width is smaller than 800px
+ margin : [44, 0],
+
+ // Horizontal space between slides
+ gutter : 50,
+
+ // Enable keyboard navigation
+ keyboard : true,
+
+ // Should display navigation arrows at the screen edges
+ arrows : true,
+
+ // Should display infobar (counter and arrows at the top)
+ infobar : true,
+
+ // Should display toolbar (buttons at the top)
+ toolbar : true,
+
+ // What buttons should appear in the top right corner.
+ // Buttons will be created using templates from `btnTpl` option
+ // and they will be placed into toolbar (class="fancybox-toolbar"` element)
+ buttons : [
+ 'slideShow',
+ 'fullScreen',
+ 'thumbs',
+ 'share',
+ //'download',
+ //'zoom',
+ 'close'
+ ],
+
+ // Detect "idle" time in seconds
+ idleTime : 3,
+
+ // Should display buttons at top right corner of the content
+ // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
+ // Use template from `btnTpl.smallBtn` for customization
+ smallBtn : 'auto',
+
+ // Disable right-click and use simple image protection for images
+ protect : false,
+
+ // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
+ modal : false,
+
+ image : {
+
+ // Wait for images to load before displaying
+ // Requires predefined image dimensions
+ // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
+ preload : "auto"
+
+ },
+
+ ajax : {
+
+ // Object containing settings for ajax request
+ settings : {
+
+ // This helps to indicate that request comes from the modal
+ // Feel free to change naming
+ data : {
+ fancybox : true
+ }
+ }
+
+ },
+
+ iframe : {
+
+ // Iframe template
+ tpl : '',
+
+ // Preload iframe before displaying it
+ // This allows to calculate iframe content width and height
+ // (note: Due to "Same Origin Policy", you can't get cross domain data).
+ preload : true,
+
+ // Custom CSS styling for iframe wrapping element
+ // You can use this to set custom iframe dimensions
+ css : {},
+
+ // Iframe tag attributes
+ attr : {
+ scrolling : 'auto'
+ }
+
+ },
+
+ // Default content type if cannot be detected automatically
+ defaultType : 'image',
+
+ // Open/close animation type
+ // Possible values:
+ // false - disable
+ // "zoom" - zoom images from/to thumbnail
+ // "fade"
+ // "zoom-in-out"
+ //
+ animationEffect : "zoom",
+
+ // Duration in ms for open/close animation
+ animationDuration : 500,
+
+ // Should image change opacity while zooming
+ // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios
+ zoomOpacity : "auto",
+
+ // Transition effect between slides
+ //
+ // Possible values:
+ // false - disable
+ // "fade'
+ // "slide'
+ // "circular'
+ // "tube'
+ // "zoom-in-out'
+ // "rotate'
+ //
+ transitionEffect : "fade",
+
+ // Duration in ms for transition animation
+ transitionDuration : 366,
+
+ // Custom CSS class for slide element
+ slideClass : '',
+
+ // Custom CSS class for layout
+ baseClass : '',
+
+ // Base template for layout
+ baseTpl :
+ '' +
+ '' +
+ '' +
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '' +
+ ' ' +
+ '',
+
+ // Loading indicator template
+ spinnerTpl : '',
+
+ // Error message template
+ errorTpl : '{{ERROR}}
',
+
+ btnTpl : {
+
+ download : '' +
+ '' +
+ '',
+
+ zoom : '',
+
+ close : '',
+
+ // This small close button will be appended to your html/inline/ajax content by default,
+ // if "smallBtn" option is not set to false
+ smallBtn : '',
+
+ // Arrows
+ arrowLeft : '',
+
+ arrowRight : ''
+ },
+
+ // Container is injected into this element
+ parentEl : 'body',
+
+
+ // Focus handling
+ // ==============
+
+ // Try to focus on the first focusable element after opening
+ autoFocus : false,
+
+ // Put focus back to active element after closing
+ backFocus : true,
+
+ // Do not let user to focus on element outside modal content
+ trapFocus : true,
+
+
+ // Module specific options
+ // =======================
+
+ fullScreen : {
+ autoStart : false,
+ },
+
+ // Set `touch: false` to disable dragging/swiping
+ touch : {
+ vertical : true, // Allow to drag content vertically
+ momentum : true // Continue movement after releasing mouse/touch when panning
+ },
+
+ // Hash value when initializing manually,
+ // set `false` to disable hash change
+ hash : null,
+
+ // Customize or add new media types
+ // Example:
+ /*
+ media : {
+ youtube : {
+ params : {
+ autoplay : 0
+ }
+ }
+ }
+ */
+ media : {},
+
+ slideShow : {
+ autoStart : false,
+ speed : 4000
+ },
+
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true, // Hide thumbnail grid when closing animation starts
+ parentEl : '.fancybox-container', // Container is injected into this element
+ axis : 'y' // Vertical (y) or horizontal (x) scrolling
+ },
+
+ // Callbacks
+ //==========
+
+ // See Documentation/API/Events for more information
+ // Example:
+ /*
+ afterShow: function( instance, current ) {
+ console.info( 'Clicked element:' );
+ console.info( current.opts.$orig );
+ }
+ */
+
+ onInit : $.noop, // When instance has been initialized
+
+ beforeLoad : $.noop, // Before the content of a slide is being loaded
+ afterLoad : $.noop, // When the content of a slide is done loading
+
+ beforeShow : $.noop, // Before open animation starts
+ afterShow : $.noop, // When content is done loading and animating
+
+ beforeClose : $.noop, // Before the instance attempts to close. Return false to cancel the close.
+ afterClose : $.noop, // After instance has been closed
+
+ onActivate : $.noop, // When instance is brought to front
+ onDeactivate : $.noop, // When other instance has been activated
+
+
+ // Interaction
+ // ===========
+
+ // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
+ // each option can be string or method that returns value.
+ //
+ // Possible values:
+ // "close" - close instance
+ // "next" - move to next gallery item
+ // "nextOrClose" - move to next gallery item or close if gallery has only one item
+ // "toggleControls" - show/hide controls
+ // "zoom" - zoom image (if loaded)
+ // false - do nothing
+
+ // Clicked on the content
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+
+ // Clicked on the slide
+ clickSlide : 'close',
+
+ // Clicked on the background (backdrop) element
+ clickOutside : 'close',
+
+ // Same as previous two, but for double click
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false,
+
+
+ // Custom options when mobile device is detected
+ // =============================================
+
+ mobile : {
+ margin : 0,
+
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : false;
+ },
+ clickSlide : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : 'close';
+ },
+ dblclickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+ dblclickSlide : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ }
+ },
+
+
+ // Internationalization
+ // ============
+
+ lang : 'en',
+ i18n : {
+ 'en' : {
+ CLOSE : 'Close',
+ NEXT : 'Next',
+ PREV : 'Previous',
+ ERROR : 'The requested content cannot be loaded.
Please try again later.',
+ PLAY_START : 'Start slideshow',
+ PLAY_STOP : 'Pause slideshow',
+ FULL_SCREEN : 'Full screen',
+ THUMBS : 'Thumbnails',
+ DOWNLOAD : 'Download',
+ SHARE : 'Share',
+ ZOOM : 'Zoom'
+ },
+ 'de' : {
+ CLOSE : 'Schliessen',
+ NEXT : 'Weiter',
+ PREV : 'Zurück',
+ ERROR : 'Die angeforderten Daten konnten nicht geladen werden.
Bitte versuchen Sie es später nochmal.',
+ PLAY_START : 'Diaschau starten',
+ PLAY_STOP : 'Diaschau beenden',
+ FULL_SCREEN : 'Vollbild',
+ THUMBS : 'Vorschaubilder',
+ DOWNLOAD : 'Herunterladen',
+ SHARE : 'Teilen',
+ ZOOM : 'Maßstab'
+ }
+ }
+
+ };
+
+ // Few useful variables and methods
+ // ================================
+
+ var $W = $(window);
+ var $D = $(document);
+
+ var called = 0;
+
+
+ // Check if an object is a jQuery object and not a native JavaScript object
+ // ========================================================================
+
+ var isQuery = function ( obj ) {
+ return obj && obj.hasOwnProperty && obj instanceof $;
+ };
+
+
+ // Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
+ // ===============================================================================
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ // Detect the supported transition-end event property name
+ // =======================================================
+
+ var transitionEnd = (function () {
+ var t, el = document.createElement("fakeelement");
+
+ var transitions = {
+ "transition" : "transitionend",
+ "OTransition" : "oTransitionEnd",
+ "MozTransition" : "transitionend",
+ "WebkitTransition": "webkitTransitionEnd"
+ };
+
+ for (t in transitions) {
+ if (el.style[t] !== undefined){
+ return transitions[t];
+ }
+ }
+
+ return 'transitionend';
+ })();
+
+
+ // Force redraw on an element.
+ // This helps in cases where the browser doesn't redraw an updated element properly.
+ // =================================================================================
+
+ var forceRedraw = function( $el ) {
+ return ( $el && $el.length && $el[0].offsetHeight );
+ };
+
+
+ // Class definition
+ // ================
+
+ var FancyBox = function( content, opts, index ) {
+ var self = this;
+
+ self.opts = $.extend( true, { index : index }, $.fancybox.defaults, opts || {} );
+
+ if ( $.fancybox.isMobile ) {
+ self.opts = $.extend( true, {}, self.opts, self.opts.mobile );
+ }
+
+ // Exclude buttons option from deep merging
+ if ( opts && $.isArray( opts.buttons ) ) {
+ self.opts.buttons = opts.buttons;
+ }
+
+ self.id = self.opts.id || ++called;
+ self.group = [];
+
+ self.currIndex = parseInt( self.opts.index, 10 ) || 0;
+ self.prevIndex = null;
+
+ self.prevPos = null;
+ self.currPos = 0;
+
+ self.firstRun = null;
+
+ // Create group elements from original item collection
+ self.createGroup( content );
+
+ if ( !self.group.length ) {
+ return;
+ }
+
+ // Save last active element and current scroll position
+ self.$lastFocus = $(document.activeElement).blur();
+
+ // Collection of gallery objects
+ self.slides = {};
+
+ self.init();
+ };
+
+ $.extend(FancyBox.prototype, {
+
+ // Create DOM structure
+ // ====================
+
+ init : function() {
+ var self = this,
+ firstItem = self.group[ self.currIndex ],
+ firstItemOpts = firstItem.opts,
+ scrollbarWidth = $.fancybox.scrollbarWidth,
+ $scrollDiv,
+ $container,
+ buttonStr;
+
+ self.scrollTop = $D.scrollTop();
+ self.scrollLeft = $D.scrollLeft();
+
+
+ // Hide scrollbars
+ // ===============
+
+ if ( !$.fancybox.getInstance() ) {
+
+ $( 'body' ).addClass( 'fancybox-active' );
+
+ // iOS hack
+ if ( /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream ) {
+
+ // iOS has problems for input elements inside fixed containers,
+ // the workaround is to apply `position: fixed` to `` element,
+ // unfortunately, this makes it lose the scrollbars and forces address bar to appear.
+
+ if ( firstItem.type !== 'image' ) {
+ $( 'body' ).css( 'top', $( 'body' ).scrollTop() * -1 ).addClass( 'fancybox-iosfix' );
+ }
+
+ } else if ( !$.fancybox.isMobile && document.body.scrollHeight > window.innerHeight ) {
+
+ if ( scrollbarWidth === undefined ) {
+ $scrollDiv = $('').appendTo( 'body' );
+
+ scrollbarWidth = $.fancybox.scrollbarWidth = $scrollDiv[0].offsetWidth - $scrollDiv[0].clientWidth;
+
+ $scrollDiv.remove();
+ }
+
+ $( 'head' ).append( '' );
+ $( 'body' ).addClass( 'compensate-for-scrollbar' );
+ }
+ }
+
+
+ // Build html markup and set references
+ // ====================================
+
+ // Build html code for buttons and insert into main template
+ buttonStr = '';
+
+ $.each( firstItemOpts.buttons, function( index, value ) {
+ buttonStr += ( firstItemOpts.btnTpl[ value ] || '' );
+ });
+
+ // Create markup from base template, it will be initially hidden to
+ // avoid unnecessary work like painting while initializing is not complete
+ $container = $(
+ self.translate( self,
+ firstItemOpts.baseTpl
+ .replace( '\{\{buttons\}\}', buttonStr )
+ .replace( '\{\{arrows\}\}', firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight )
+ )
+ )
+ .attr( 'id', 'fancybox-container-' + self.id )
+ .addClass( 'fancybox-is-hidden' )
+ .addClass( firstItemOpts.baseClass )
+ .data( 'FancyBox', self )
+ .appendTo( firstItemOpts.parentEl );
+
+ // Create object holding references to jQuery wrapped nodes
+ self.$refs = {
+ container : $container
+ };
+
+ [ 'bg', 'inner', 'infobar', 'toolbar', 'stage', 'caption', 'navigation' ].forEach(function(item) {
+ self.$refs[ item ] = $container.find( '.fancybox-' + item );
+ });
+
+ self.trigger( 'onInit' );
+
+ // Enable events, deactive previous instances
+ self.activate();
+
+ // Build slides, load and reveal content
+ self.jumpTo( self.currIndex );
+ },
+
+
+ // Simple i18n support - replaces object keys found in template
+ // with corresponding values
+ // ============================================================
+
+ translate : function( obj, str ) {
+ var arr = obj.opts.i18n[ obj.opts.lang ];
+
+ return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
+ var value = arr[n];
+
+ if ( value === undefined ) {
+ return match;
+ }
+
+ return value;
+ });
+ },
+
+ // Create array of gally item objects
+ // Check if each object has valid type and content
+ // ===============================================
+
+ createGroup : function ( content ) {
+ var self = this;
+ var items = $.makeArray( content );
+
+ $.each(items, function( i, item ) {
+ var obj = {},
+ opts = {},
+ $item,
+ type,
+ src,
+ srcParts;
+
+ // Step 1 - Make sure we have an object
+ // ====================================
+
+ if ( $.isPlainObject( item ) ) {
+
+ // We probably have manual usage here, something like
+ // $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
+
+ obj = item;
+ opts = item.opts || item;
+
+ } else if ( $.type( item ) === 'object' && $( item ).length ) {
+
+ // Here we probably have jQuery collection returned by some selector
+ $item = $( item );
+
+ opts = $item.data();
+ opts = $.extend( {}, opts, opts.options || {} );
+
+ // Here we store clicked element
+ opts.$orig = $item;
+
+ obj.src = opts.src || $item.attr( 'href' );
+
+ // Assume that simple syntax is used, for example:
+ // `$.fancybox.open( $("#test"), {} );`
+ if ( !obj.type && !obj.src ) {
+ obj.type = 'inline';
+ obj.src = item;
+ }
+
+ } else {
+
+ // Assume we have a simple html code, for example:
+ // $.fancybox.open( 'Hi!
' );
+
+ obj = {
+ type : 'html',
+ src : item + ''
+ };
+
+ }
+
+ // Each gallery object has full collection of options
+ obj.opts = $.extend( true, {}, self.opts, opts );
+
+ // Do not merge buttons array
+ if ( $.isArray( opts.buttons ) ) {
+ obj.opts.buttons = opts.buttons;
+ }
+
+
+ // Step 2 - Make sure we have content type, if not - try to guess
+ // ==============================================================
+
+ type = obj.type || obj.opts.type;
+ src = obj.src || '';
+
+ if ( !type && src ) {
+ if ( src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i) ) {
+ type = 'image';
+
+ } else if ( src.match(/\.(pdf)((\?|#).*)?$/i) ) {
+ type = 'pdf';
+
+ } else if ( src.charAt(0) === '#' ) {
+ type = 'inline';
+ }
+ }
+
+ if ( type ) {
+ obj.type = type;
+
+ } else {
+ self.trigger( 'objectNeedsType', obj );
+ }
+
+
+ // Step 3 - Some adjustments
+ // =========================
+
+ obj.index = self.group.length;
+
+ // Check if $orig and $thumb objects exist
+ if ( obj.opts.$orig && !obj.opts.$orig.length ) {
+ delete obj.opts.$orig;
+ }
+
+ if ( !obj.opts.$thumb && obj.opts.$orig ) {
+ obj.opts.$thumb = obj.opts.$orig.find( 'img:first' );
+ }
+
+ if ( obj.opts.$thumb && !obj.opts.$thumb.length ) {
+ delete obj.opts.$thumb;
+ }
+
+ // "caption" is a "special" option, it can be used to customize caption per gallery item ..
+ if ( $.type( obj.opts.caption ) === 'function' ) {
+ obj.opts.caption = obj.opts.caption.apply( item, [ self, obj ] );
+ }
+
+ if ( $.type( self.opts.caption ) === 'function' ) {
+ obj.opts.caption = self.opts.caption.apply( item, [ self, obj ] );
+ }
+
+ // Make sure we have caption as a string or jQuery object
+ if ( !( obj.opts.caption instanceof $ ) ) {
+ obj.opts.caption = obj.opts.caption === undefined ? '' : obj.opts.caption + '';
+ }
+
+ // Check if url contains "filter" used to filter the content
+ // Example: "ajax.html #something"
+ if ( type === 'ajax' ) {
+ srcParts = src.split(/\s+/, 2);
+
+ if ( srcParts.length > 1 ) {
+ obj.src = srcParts.shift();
+
+ obj.opts.filter = srcParts.shift();
+ }
+ }
+
+ if ( obj.opts.smallBtn == 'auto' ) {
+
+ if ( $.inArray( type, ['html', 'inline', 'ajax'] ) > -1 ) {
+ obj.opts.toolbar = false;
+ obj.opts.smallBtn = true;
+
+ } else {
+ obj.opts.smallBtn = false;
+ }
+
+ }
+
+ // If the type is "pdf", then simply load file into iframe
+ if ( type === 'pdf' ) {
+ obj.type = 'iframe';
+
+ obj.opts.iframe.preload = false;
+ }
+
+ // Hide all buttons and disable interactivity for modal items
+ if ( obj.opts.modal ) {
+
+ obj.opts = $.extend(true, obj.opts, {
+ // Remove buttons
+ infobar : 0,
+ toolbar : 0,
+
+ smallBtn : 0,
+
+ // Disable keyboard navigation
+ keyboard : 0,
+
+ // Disable some modules
+ slideShow : 0,
+ fullScreen : 0,
+ thumbs : 0,
+ touch : 0,
+
+ // Disable click event handlers
+ clickContent : false,
+ clickSlide : false,
+ clickOutside : false,
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false
+ });
+
+ }
+
+ // Step 4 - Add processed object to group
+ // ======================================
+
+ self.group.push( obj );
+
+ });
+
+ },
+
+
+ // Attach an event handler functions for:
+ // - navigation buttons
+ // - browser scrolling, resizing;
+ // - focusing
+ // - keyboard
+ // - detect idle
+ // ======================================
+
+ addEvents : function() {
+ var self = this;
+
+ self.removeEvents();
+
+ // Make navigation elements clickable
+ self.$refs.container.on('click.fb-close', '[data-fancybox-close]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.close( e );
+
+ }).on( 'click.fb-prev touchend.fb-prev', '[data-fancybox-prev]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.previous();
+
+ }).on( 'click.fb-next touchend.fb-next', '[data-fancybox-next]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.next();
+
+ }).on( 'click.fb', '[data-fancybox-zoom]', function(e) {
+ // Click handler for zoom button
+ self[ self.isScaledDown() ? 'scaleToActual' : 'scaleToFit' ]();
+ });
+
+
+ // Handle page scrolling and browser resizing
+ $W.on('orientationchange.fb resize.fb', function(e) {
+
+ if ( e && e.originalEvent && e.originalEvent.type === "resize" ) {
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ } else {
+
+ self.$refs.stage.hide();
+
+ setTimeout(function() {
+ self.$refs.stage.show();
+
+ self.update();
+ }, 600);
+
+ }
+
+ });
+
+ // Trap keyboard focus inside of the modal, so the user does not accidentally tab outside of the modal
+ // (a.k.a. "escaping the modal")
+ $D.on('focusin.fb', function(e) {
+ var instance = $.fancybox ? $.fancybox.getInstance() : null;
+
+ if ( instance.isClosing || !instance.current || !instance.current.opts.trapFocus || $( e.target ).hasClass( 'fancybox-container' ) || $( e.target ).is( document ) ) {
+ return;
+ }
+
+ if ( instance && $( e.target ).css( 'position' ) !== 'fixed' && !instance.$refs.container.has( e.target ).length ) {
+ e.stopPropagation();
+
+ instance.focus();
+
+ // Sometimes page gets scrolled, set it back
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+ }
+ });
+
+
+ // Enable keyboard navigation
+ $D.on('keydown.fb', function (e) {
+ var current = self.current,
+ keycode = e.keyCode || e.which;
+
+ if ( !current || !current.opts.keyboard ) {
+ return;
+ }
+
+ if ( $(e.target).is('input') || $(e.target).is('textarea') ) {
+ return;
+ }
+
+ // Backspace and Esc keys
+ if ( keycode === 8 || keycode === 27 ) {
+ e.preventDefault();
+
+ self.close( e );
+
+ return;
+ }
+
+ // Left arrow and Up arrow
+ if ( keycode === 37 || keycode === 38 ) {
+ e.preventDefault();
+
+ self.previous();
+
+ return;
+ }
+
+ // Righ arrow and Down arrow
+ if ( keycode === 39 || keycode === 40 ) {
+ e.preventDefault();
+
+ self.next();
+
+ return;
+ }
+
+ self.trigger('afterKeydown', e, keycode);
+ });
+
+
+ // Hide controls after some inactivity period
+ if ( self.group[ self.currIndex ].opts.idleTime ) {
+ self.idleSecondsCounter = 0;
+
+ $D.on('mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle', function(e) {
+ self.idleSecondsCounter = 0;
+
+ if ( self.isIdle ) {
+ self.showControls();
+ }
+
+ self.isIdle = false;
+ });
+
+ self.idleInterval = window.setInterval(function() {
+ self.idleSecondsCounter++;
+
+ if ( self.idleSecondsCounter >= self.group[ self.currIndex ].opts.idleTime ) {
+ self.isIdle = true;
+ self.idleSecondsCounter = 0;
+
+ self.hideControls();
+ }
+
+ }, 1000);
+ }
+
+ },
+
+
+ // Remove events added by the core
+ // ===============================
+
+ removeEvents : function() {
+ var self = this;
+
+ $W.off( 'orientationchange.fb resize.fb' );
+ $D.off( 'focusin.fb keydown.fb .fb-idle' );
+
+ this.$refs.container.off( '.fb-close .fb-prev .fb-next' );
+
+ if ( self.idleInterval ) {
+ window.clearInterval( self.idleInterval );
+
+ self.idleInterval = null;
+ }
+ },
+
+
+ // Change to previous gallery item
+ // ===============================
+
+ previous : function( duration ) {
+ return this.jumpTo( this.currPos - 1, duration );
+ },
+
+
+ // Change to next gallery item
+ // ===========================
+
+ next : function( duration ) {
+ return this.jumpTo( this.currPos + 1, duration );
+ },
+
+
+ // Switch to selected gallery item
+ // ===============================
+
+ jumpTo : function ( pos, duration, slide ) {
+ var self = this,
+ firstRun,
+ loop,
+ current,
+ previous,
+ canvasWidth,
+ currentPos,
+ transitionProps;
+
+ var groupLen = self.group.length;
+
+ if ( self.isSliding || self.isClosing || ( self.isAnimating && self.firstRun ) ) {
+ return;
+ }
+
+ pos = parseInt( pos, 10 );
+ loop = self.current ? self.current.opts.loop : self.opts.loop;
+
+ if ( !loop && ( pos < 0 || pos >= groupLen ) ) {
+ return false;
+ }
+
+ firstRun = self.firstRun = ( self.firstRun === null );
+
+ if ( groupLen < 2 && !firstRun && !!self.isSliding ) {
+ return;
+ }
+
+ previous = self.current;
+
+ self.prevIndex = self.currIndex;
+ self.prevPos = self.currPos;
+
+ // Create slides
+ current = self.createSlide( pos );
+
+ if ( groupLen > 1 ) {
+ if ( loop || current.index > 0 ) {
+ self.createSlide( pos - 1 );
+ }
+
+ if ( loop || current.index < groupLen - 1 ) {
+ self.createSlide( pos + 1 );
+ }
+ }
+
+ self.current = current;
+ self.currIndex = current.index;
+ self.currPos = current.pos;
+
+ self.trigger( 'beforeShow', firstRun );
+
+ self.updateControls();
+
+ currentPos = $.fancybox.getTranslate( current.$slide );
+
+ current.isMoved = ( currentPos.left !== 0 || currentPos.top !== 0 ) && !current.$slide.hasClass( 'fancybox-animated' );
+ current.forcedDuration = undefined;
+
+ if ( $.isNumeric( duration ) ) {
+ current.forcedDuration = duration;
+ } else {
+ duration = current.opts[ firstRun ? 'animationDuration' : 'transitionDuration' ];
+ }
+
+ duration = parseInt( duration, 10 );
+
+ // Fresh start - reveal container, current slide and start loading content
+ if ( firstRun ) {
+
+ if ( current.opts.animationEffect && duration ) {
+ self.$refs.container.css( 'transition-duration', duration + 'ms' );
+ }
+
+ self.$refs.container.removeClass( 'fancybox-is-hidden' );
+
+ forceRedraw( self.$refs.container );
+
+ self.$refs.container.addClass( 'fancybox-is-open' );
+
+ // Make first slide visible (to display loading icon, if needed)
+ current.$slide.addClass( 'fancybox-slide--current' );
+
+ self.loadSlide( current );
+
+ self.preload();
+
+ return;
+ }
+
+ // Clean up
+ $.each(self.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+ });
+
+ // Make current that slide is visible even if content is still loading
+ current.$slide.removeClass( 'fancybox-slide--next fancybox-slide--previous' ).addClass( 'fancybox-slide--current' );
+
+ // If slides have been dragged, animate them to correct position
+ if ( current.isMoved ) {
+ canvasWidth = Math.round( current.$slide.width() );
+
+ $.each(self.slides, function( index, slide ) {
+ var pos = slide.pos - current.pos;
+
+ $.fancybox.animate( slide.$slide, {
+ top : 0,
+ left : ( pos * canvasWidth ) + ( pos * slide.opts.gutter )
+ }, duration, function() {
+
+ slide.$slide.removeAttr('style').removeClass( 'fancybox-slide--next fancybox-slide--previous' );
+
+ if ( slide.pos === self.currPos ) {
+ current.isMoved = false;
+
+ self.complete();
+ }
+ });
+ });
+
+ } else {
+ self.$refs.stage.children().removeAttr( 'style' );
+ }
+
+ // Start transition that reveals current content
+ // or wait when it will be loaded
+
+ if ( current.isLoaded ) {
+ self.revealContent( current );
+
+ } else {
+ self.loadSlide( current );
+ }
+
+ self.preload();
+
+ if ( previous.pos === current.pos ) {
+ return;
+ }
+
+ // Handle previous slide
+ // =====================
+
+ transitionProps = 'fancybox-slide--' + ( previous.pos > current.pos ? 'next' : 'previous' );
+
+ previous.$slide.removeClass( 'fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous' );
+
+ previous.isComplete = false;
+
+ if ( !duration || ( !current.isMoved && !current.opts.transitionEffect ) ) {
+ return;
+ }
+
+ if ( current.isMoved ) {
+ previous.$slide.addClass( transitionProps );
+
+ } else {
+
+ transitionProps = 'fancybox-animated ' + transitionProps + ' fancybox-fx-' + current.opts.transitionEffect;
+
+ $.fancybox.animate( previous.$slide, transitionProps, duration, function() {
+ previous.$slide.removeClass( transitionProps ).removeAttr( 'style' );
+ });
+
+ }
+
+ },
+
+
+ // Create new "slide" element
+ // These are gallery items that are actually added to DOM
+ // =======================================================
+
+ createSlide : function( pos ) {
+
+ var self = this;
+ var $slide;
+ var index;
+
+ index = pos % self.group.length;
+ index = index < 0 ? self.group.length + index : index;
+
+ if ( !self.slides[ pos ] && self.group[ index ] ) {
+ $slide = $('').appendTo( self.$refs.stage );
+
+ self.slides[ pos ] = $.extend( true, {}, self.group[ index ], {
+ pos : pos,
+ $slide : $slide,
+ isLoaded : false,
+ });
+
+ self.updateSlide( self.slides[ pos ] );
+ }
+
+ return self.slides[ pos ];
+ },
+
+
+ // Scale image to the actual size of the image
+ // ===========================================
+
+ scaleToActual : function( x, y, duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var imgPos, posX, posY, scaleX, scaleY;
+
+ var canvasWidth = parseInt( current.$slide.width(), 10 );
+ var canvasHeight = parseInt( current.$slide.height(), 10 );
+
+ var newImgWidth = current.width;
+ var newImgHeight = current.height;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ x = x === undefined ? canvasWidth * 0.5 : x;
+ y = y === undefined ? canvasHeight * 0.5 : y;
+
+ imgPos = $.fancybox.getTranslate( $what );
+
+ scaleX = newImgWidth / imgPos.width;
+ scaleY = newImgHeight / imgPos.height;
+
+ // Get center position for original image
+ posX = ( canvasWidth * 0.5 - newImgWidth * 0.5 );
+ posY = ( canvasHeight * 0.5 - newImgHeight * 0.5 );
+
+ // Make sure image does not move away from edges
+ if ( newImgWidth > canvasWidth ) {
+ posX = imgPos.left * scaleX - ( ( x * scaleX ) - x );
+
+ if ( posX > 0 ) {
+ posX = 0;
+ }
+
+ if ( posX < canvasWidth - newImgWidth ) {
+ posX = canvasWidth - newImgWidth;
+ }
+ }
+
+ if ( newImgHeight > canvasHeight) {
+ posY = imgPos.top * scaleY - ( ( y * scaleY ) - y );
+
+ if ( posY > 0 ) {
+ posY = 0;
+ }
+
+ if ( posY < canvasHeight - newImgHeight ) {
+ posY = canvasHeight - newImgHeight;
+ }
+ }
+
+ self.updateCursor( newImgWidth, newImgHeight );
+
+ $.fancybox.animate( $what, {
+ top : posY,
+ left : posX,
+ scaleX : scaleX,
+ scaleY : scaleY
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ // Stop slideshow
+ if ( self.SlideShow && self.SlideShow.isActive ) {
+ self.SlideShow.stop();
+ }
+ },
+
+
+ // Scale image to fit inside parent element
+ // ========================================
+
+ scaleToFit : function( duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+ var end;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ end = self.getFitPos( current );
+
+ self.updateCursor( end.width, end.height );
+
+ $.fancybox.animate( $what, {
+ top : end.top,
+ left : end.left,
+ scaleX : end.width / $what.width(),
+ scaleY : end.height / $what.height()
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ },
+
+ // Calculate image size to fit inside viewport
+ // ===========================================
+
+ getFitPos : function( slide ) {
+ var self = this;
+ var $what = slide.$content;
+
+ var imgWidth = slide.width;
+ var imgHeight = slide.height;
+
+ var margin = slide.opts.margin;
+
+ var canvasWidth, canvasHeight, minRatio, width, height;
+
+ if ( !$what || !$what.length || ( !imgWidth && !imgHeight) ) {
+ return false;
+ }
+
+ // Convert "margin to CSS style: [ top, right, bottom, left ]
+ if ( $.type( margin ) === "number" ) {
+ margin = [ margin, margin ];
+ }
+
+ if ( margin.length == 2 ) {
+ margin = [ margin[0], margin[1], margin[0], margin[1] ];
+ }
+
+ // We can not use $slide width here, because it can have different diemensions while in transiton
+ canvasWidth = parseInt( self.$refs.stage.width(), 10 ) - ( margin[ 1 ] + margin[ 3 ] );
+ canvasHeight = parseInt( self.$refs.stage.height(), 10 ) - ( margin[ 0 ] + margin[ 2 ] );
+
+ minRatio = Math.min(1, canvasWidth / imgWidth, canvasHeight / imgHeight );
+
+ width = Math.floor( minRatio * imgWidth );
+ height = Math.floor( minRatio * imgHeight );
+
+ // Use floor rounding to make sure it really fits
+ return {
+ top : Math.floor( ( canvasHeight - height ) * 0.5 ) + margin[ 0 ],
+ left : Math.floor( ( canvasWidth - width ) * 0.5 ) + margin[ 3 ],
+ width : width,
+ height : height
+ };
+
+ },
+
+
+ // Update position and content of all slides
+ // =========================================
+
+ update : function() {
+
+ var self = this;
+
+ $.each( self.slides, function( key, slide ) {
+ self.updateSlide( slide );
+ });
+
+ },
+
+
+ // Update slide position and scale content to fit
+ // ==============================================
+
+ updateSlide : function( slide ) {
+
+ var self = this;
+ var $what = slide.$content;
+
+ if ( $what && ( slide.width || slide.height ) ) {
+ self.isAnimating = false;
+
+ $.fancybox.stop( $what );
+
+ $.fancybox.setTranslate( $what, self.getFitPos( slide ) );
+
+ if ( slide.pos === self.currPos ) {
+ self.updateCursor();
+ }
+ }
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.trigger( 'onUpdate', slide );
+
+ },
+
+ // Update cursor style depending if content can be zoomed
+ // ======================================================
+
+ updateCursor : function( nextWidth, nextHeight ) {
+
+ var self = this;
+ var isScaledDown;
+
+ var $container = self.$refs.container.removeClass( 'fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut' );
+
+ if ( !self.current || self.isClosing ) {
+ return;
+ }
+
+ if ( self.isZoomable() ) {
+
+ $container.addClass( 'fancybox-is-zoomable' );
+
+ if ( nextWidth !== undefined && nextHeight !== undefined ) {
+ isScaledDown = nextWidth < self.current.width && nextHeight < self.current.height;
+
+ } else {
+ isScaledDown = self.isScaledDown();
+ }
+
+ if ( isScaledDown ) {
+
+ // If image is scaled down, then, obviously, it can be zoomed to full size
+ $container.addClass( 'fancybox-can-zoomIn' );
+
+ } else {
+
+ if ( self.current.opts.touch ) {
+
+ // If image size ir largen than available available and touch module is not disable,
+ // then user can do panning
+ $container.addClass( 'fancybox-can-drag' );
+
+ } else {
+ $container.addClass( 'fancybox-can-zoomOut' );
+ }
+
+ }
+
+ } else if ( self.current.opts.touch ) {
+ $container.addClass( 'fancybox-can-drag' );
+ }
+
+ },
+
+
+ // Check if current slide is zoomable
+ // ==================================
+
+ isZoomable : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var fitPos;
+
+ if ( !current || self.isClosing ) {
+ return;
+ }
+
+ // Assume that slide is zoomable if
+ // - image is loaded successfuly
+ // - click action is "zoom"
+ // - actual size of the image is smaller than available area
+ if ( current.type === 'image' && current.isLoaded && !current.hasError &&
+ ( current.opts.clickContent === 'zoom' || ( $.isFunction( current.opts.clickContent ) && current.opts.clickContent( current ) === "zoom" ) )
+ ) {
+
+ fitPos = self.getFitPos( current );
+
+ if ( current.width > fitPos.width || current.height > fitPos.height ) {
+ return true;
+ }
+
+ }
+
+ return false;
+
+ },
+
+
+ // Check if current image dimensions are smaller than actual
+ // =========================================================
+
+ isScaledDown : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = $.fancybox.getTranslate( $what );
+ rez = rez.width < current.width || rez.height < current.height;
+ }
+
+ return rez;
+
+ },
+
+
+ // Check if image dimensions exceed parent element
+ // ===============================================
+
+ canPan : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = self.getFitPos( current );
+ rez = Math.abs( $what.width() - rez.width ) > 1 || Math.abs( $what.height() - rez.height ) > 1;
+
+ }
+
+ return rez;
+
+ },
+
+
+ // Load content into the slide
+ // ===========================
+
+ loadSlide : function( slide ) {
+
+ var self = this, type, $slide;
+ var ajaxLoad;
+
+ if ( slide.isLoading ) {
+ return;
+ }
+
+ if ( slide.isLoaded ) {
+ return;
+ }
+
+ slide.isLoading = true;
+
+ self.trigger( 'beforeLoad', slide );
+
+ type = slide.type;
+ $slide = slide.$slide;
+
+ $slide
+ .off( 'refresh' )
+ .trigger( 'onReset' )
+ .addClass( 'fancybox-slide--' + ( type || 'unknown' ) )
+ .addClass( slide.opts.slideClass );
+
+ // Create content depending on the type
+
+ switch ( type ) {
+
+ case 'image':
+
+ self.setImage( slide );
+
+ break;
+
+ case 'iframe':
+
+ self.setIframe( slide );
+
+ break;
+
+ case 'html':
+
+ self.setContent( slide, slide.src || slide.content );
+
+ break;
+
+ case 'inline':
+
+ if ( $( slide.src ).length ) {
+ self.setContent( slide, $( slide.src ) );
+
+ } else {
+ self.setError( slide );
+ }
+
+ break;
+
+ case 'ajax':
+
+ self.showLoading( slide );
+
+ ajaxLoad = $.ajax( $.extend( {}, slide.opts.ajax.settings, {
+ url : slide.src,
+ success : function ( data, textStatus ) {
+
+ if ( textStatus === 'success' ) {
+ self.setContent( slide, data );
+ }
+
+ },
+ error : function ( jqXHR, textStatus ) {
+
+ if ( jqXHR && textStatus !== 'abort' ) {
+ self.setError( slide );
+ }
+
+ }
+ }));
+
+ $slide.one( 'onReset', function () {
+ ajaxLoad.abort();
+ });
+
+ break;
+
+ default:
+
+ self.setError( slide );
+
+ break;
+
+ }
+
+ return true;
+
+ },
+
+
+ // Use thumbnail image, if possible
+ // ================================
+
+ setImage : function( slide ) {
+
+ var self = this;
+ var srcset = slide.opts.srcset || slide.opts.image.srcset;
+
+ var found, temp, pxRatio, windowWidth;
+
+ // If we have "srcset", then we need to find matching "src" value.
+ // This is necessary, because when you set an src attribute, the browser will preload the image
+ // before any javascript or even CSS is applied.
+ if ( srcset ) {
+ pxRatio = window.devicePixelRatio || 1;
+ windowWidth = window.innerWidth * pxRatio;
+
+ temp = srcset.split(',').map(function ( el ) {
+ var ret = {};
+
+ el.trim().split(/\s+/).forEach(function ( el, i ) {
+ var value = parseInt( el.substring(0, el.length - 1), 10 );
+
+ if ( i === 0 ) {
+ return ( ret.url = el );
+ }
+
+ if ( value ) {
+ ret.value = value;
+ ret.postfix = el[ el.length - 1 ];
+ }
+
+ });
+
+ return ret;
+ });
+
+ // Sort by value
+ temp.sort(function (a, b) {
+ return a.value - b.value;
+ });
+
+ // Ok, now we have an array of all srcset values
+ for ( var j = 0; j < temp.length; j++ ) {
+ var el = temp[ j ];
+
+ if ( ( el.postfix === 'w' && el.value >= windowWidth ) || ( el.postfix === 'x' && el.value >= pxRatio ) ) {
+ found = el;
+ break;
+ }
+ }
+
+ // If not found, take the last one
+ if ( !found && temp.length ) {
+ found = temp[ temp.length - 1 ];
+ }
+
+ if ( found ) {
+ slide.src = found.url;
+
+ // If we have default width/height values, we can calculate height for matching source
+ if ( slide.width && slide.height && found.postfix == 'w' ) {
+ slide.height = ( slide.width / slide.height ) * found.value;
+ slide.width = found.value;
+ }
+ }
+ }
+
+ // This will be wrapper containing both ghost and actual image
+ slide.$content = $('')
+ .addClass( 'fancybox-is-hidden' )
+ .appendTo( slide.$slide );
+
+
+ // If we have a thumbnail, we can display it while actual image is loading
+ // Users will not stare at black screen and actual image will appear gradually
+ if ( slide.opts.preload !== false && slide.opts.width && slide.opts.height && ( slide.opts.thumb || slide.opts.$thumb ) ) {
+
+ slide.width = slide.opts.width;
+ slide.height = slide.opts.height;
+
+ slide.$ghost = $('')
+ .one('error', function() {
+
+ $(this).remove();
+
+ slide.$ghost = null;
+
+ self.setBigImage( slide );
+
+ })
+ .one('load', function() {
+
+ self.afterLoad( slide );
+
+ self.setBigImage( slide );
+
+ })
+ .addClass( 'fancybox-image' )
+ .appendTo( slide.$content )
+ .attr( 'src', slide.opts.thumb || slide.opts.$thumb.attr( 'src' ) );
+
+ } else {
+
+ self.setBigImage( slide );
+
+ }
+
+ },
+
+
+ // Create full-size image
+ // ======================
+
+ setBigImage : function ( slide ) {
+ var self = this;
+ var $img = $('');
+
+ slide.$image = $img
+ .one('error', function() {
+
+ self.setError( slide );
+
+ })
+ .one('load', function() {
+
+ // Clear timeout that checks if loading icon needs to be displayed
+ clearTimeout( slide.timouts );
+
+ slide.timouts = null;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.width = this.naturalWidth;
+ slide.height = this.naturalHeight;
+
+ if ( slide.opts.image.srcset ) {
+ $img.attr( 'sizes', '100vw' ).attr( 'srcset', slide.opts.image.srcset );
+ }
+
+ self.hideLoading( slide );
+
+ if ( slide.$ghost ) {
+
+ slide.timouts = setTimeout(function() {
+ slide.timouts = null;
+
+ slide.$ghost.hide();
+
+ }, Math.min( 300, Math.max( 1000, slide.height / 1600 ) ) );
+
+ } else {
+ self.afterLoad( slide );
+ }
+
+ })
+ .addClass( 'fancybox-image' )
+ .attr('src', slide.src)
+ .appendTo( slide.$content );
+
+ if ( ( $img[0].complete || $img[0].readyState == "complete" ) && $img[0].naturalWidth && $img[0].naturalHeight ) {
+ $img.trigger( 'load' );
+
+ } else if( $img[0].error ) {
+ $img.trigger( 'error' );
+
+ } else {
+
+ slide.timouts = setTimeout(function() {
+ if ( !$img[0].complete && !slide.hasError ) {
+ self.showLoading( slide );
+ }
+
+ }, 100);
+
+ }
+
+ },
+
+
+ // Create iframe wrapper, iframe and bindings
+ // ==========================================
+
+ setIframe : function( slide ) {
+ var self = this,
+ opts = slide.opts.iframe,
+ $slide = slide.$slide,
+ $iframe;
+
+ slide.$content = $('')
+ .css( opts.css )
+ .appendTo( $slide );
+
+ $iframe = $( opts.tpl.replace(/\{rnd\}/g, new Date().getTime()) )
+ .attr( opts.attr )
+ .appendTo( slide.$content );
+
+ if ( opts.preload ) {
+
+ self.showLoading( slide );
+
+ // Unfortunately, it is not always possible to determine if iframe is successfully loaded
+ // (due to browser security policy)
+
+ $iframe.on('load.fb error.fb', function(e) {
+ this.isReady = 1;
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.afterLoad( slide );
+ });
+
+ // Recalculate iframe content size
+ // ===============================
+
+ $slide.on('refresh.fb', function() {
+ var $wrap = slide.$content,
+ frameWidth = opts.css.width,
+ frameHeight = opts.css.height,
+ scrollWidth,
+ $contents,
+ $body;
+
+ if ( $iframe[0].isReady !== 1 ) {
+ return;
+ }
+
+ // Check if content is accessible,
+ // it will fail if frame is not with the same origin
+
+ try {
+ $contents = $iframe.contents();
+ $body = $contents.find('body');
+
+ } catch (ignore) {}
+
+ // Calculate dimensions for the wrapper
+ if ( $body && $body.length ) {
+
+ if ( frameWidth === undefined ) {
+ scrollWidth = $iframe[0].contentWindow.document.documentElement.scrollWidth;
+
+ frameWidth = Math.ceil( $body.outerWidth(true) + ( $wrap.width() - scrollWidth ) );
+ frameWidth += $wrap.outerWidth() - $wrap.innerWidth();
+ }
+
+ if ( frameHeight === undefined ) {
+ frameHeight = Math.ceil( $body.outerHeight(true) );
+ frameHeight += $wrap.outerHeight() - $wrap.innerHeight();
+ }
+
+ // Resize wrapper to fit iframe content
+ if ( frameWidth ) {
+ $wrap.width( frameWidth );
+ }
+
+ if ( frameHeight ) {
+ $wrap.height( frameHeight );
+ }
+ }
+
+ $wrap.removeClass( 'fancybox-is-hidden' );
+
+ });
+
+ } else {
+
+ this.afterLoad( slide );
+
+ }
+
+ $iframe.attr( 'src', slide.src );
+
+ if ( slide.opts.smallBtn === true ) {
+ slide.$content.prepend( self.translate( slide, slide.opts.btnTpl.smallBtn ) );
+ }
+
+ // Remove iframe if closing or changing gallery item
+ $slide.one( 'onReset', function () {
+
+ // This helps IE not to throw errors when closing
+ try {
+
+ $( this ).find( 'iframe' ).hide().attr( 'src', '//about:blank' );
+
+ } catch ( ignore ) {}
+
+ $( this ).empty();
+
+ slide.isLoaded = false;
+
+ });
+
+ },
+
+
+ // Wrap and append content to the slide
+ // ======================================
+
+ setContent : function ( slide, content ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ self.hideLoading( slide );
+
+ slide.$slide.empty();
+
+ if ( isQuery( content ) && content.parent().length ) {
+
+ // If content is a jQuery object, then it will be moved to the slide.
+ // The placeholder is created so we will know where to put it back.
+ // If user is navigating gallery fast, then the content might be already inside fancyBox
+ // =====================================================================================
+
+ // Make sure content is not already moved to fancyBox
+ content.parent( '.fancybox-slide--inline' ).trigger( 'onReset' );
+
+ // Create temporary element marking original place of the content
+ slide.$placeholder = $( '' ).hide().insertAfter( content );
+
+ // Make sure content is visible
+ content.css('display', 'inline-block');
+
+ } else if ( !slide.hasError ) {
+
+ // If content is just a plain text, try to convert it to html
+ if ( $.type( content ) === 'string' ) {
+ content = $('').append( $.trim( content ) ).contents();
+
+ // If we have text node, then add wrapping element to make vertical alignment work
+ if ( content[0].nodeType === 3 ) {
+ content = $('').html( content );
+ }
+ }
+
+ // If "filter" option is provided, then filter content
+ if ( slide.opts.filter ) {
+ content = $('').html( content ).find( slide.opts.filter );
+ }
+
+ }
+
+ slide.$slide.one('onReset', function () {
+
+ // Put content back
+ if ( slide.$placeholder ) {
+ slide.$placeholder.after( content.hide() ).remove();
+
+ slide.$placeholder = null;
+ }
+
+ // Remove custom close button
+ if ( slide.$smallBtn ) {
+ slide.$smallBtn.remove();
+
+ slide.$smallBtn = null;
+ }
+
+ // Remove content and mark slide as not loaded
+ if ( !slide.hasError ) {
+ $(this).empty();
+
+ slide.isLoaded = false;
+ }
+
+ });
+
+ slide.$content = $( content ).appendTo( slide.$slide );
+
+ this.afterLoad( slide );
+ },
+
+ // Display error message
+ // =====================
+
+ setError : function ( slide ) {
+
+ slide.hasError = true;
+
+ slide.$slide.removeClass( 'fancybox-slide--' + slide.type );
+
+ this.setContent( slide, this.translate( slide, slide.opts.errorTpl ) );
+
+ },
+
+
+ // Show loading icon inside the slide
+ // ==================================
+
+ showLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && !slide.$spinner ) {
+ slide.$spinner = $( self.opts.spinnerTpl ).appendTo( slide.$slide );
+ }
+
+ },
+
+ // Remove loading icon from the slide
+ // ==================================
+
+ hideLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && slide.$spinner ) {
+ slide.$spinner.remove();
+
+ delete slide.$spinner;
+ }
+
+ },
+
+
+ // Adjustments after slide content has been loaded
+ // ===============================================
+
+ afterLoad : function( slide ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.isLoading = false;
+ slide.isLoaded = true;
+
+ self.trigger( 'afterLoad', slide );
+
+ self.hideLoading( slide );
+
+ if ( slide.opts.smallBtn && !slide.$smallBtn ) {
+ slide.$smallBtn = $( self.translate( slide, slide.opts.btnTpl.smallBtn ) ).appendTo( slide.$content.filter('div,form').first() );
+ }
+
+ if ( slide.opts.protect && slide.$content && !slide.hasError ) {
+
+ // Disable right click
+ slide.$content.on( 'contextmenu.fb', function( e ) {
+ if ( e.button == 2 ) {
+ e.preventDefault();
+ }
+
+ return true;
+ });
+
+ // Add fake element on top of the image
+ // This makes a bit harder for user to select image
+ if ( slide.type === 'image' ) {
+ $( '' ).appendTo( slide.$content );
+ }
+
+ }
+
+ self.revealContent( slide );
+
+ },
+
+
+ // Make content visible
+ // This method is called right after content has been loaded or
+ // user navigates gallery and transition should start
+ // ============================================================
+
+ revealContent : function( slide ) {
+
+ var self = this;
+ var $slide = slide.$slide;
+
+ var effect, effectClassName, duration, opacity, end, start = false;
+
+ effect = slide.opts[ self.firstRun ? 'animationEffect' : 'transitionEffect' ];
+ duration = slide.opts[ self.firstRun ? 'animationDuration' : 'transitionDuration' ];
+
+ duration = parseInt( slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10 );
+
+ if ( slide.isMoved || slide.pos !== self.currPos || !duration ) {
+ effect = false;
+ }
+
+ // Check if can zoom
+ if ( effect === 'zoom' && !( slide.pos === self.currPos && duration && slide.type === 'image' && !slide.hasError && ( start = self.getThumbPos( slide ) ) ) ) {
+ effect = 'fade';
+ }
+
+ // Zoom animation
+ // ==============
+
+ if ( effect === 'zoom' ) {
+ end = self.getFitPos( slide );
+
+ end.scaleX = end.width / start.width;
+ end.scaleY = end.height / start.height;
+
+ delete end.width;
+ delete end.height;
+
+ // Check if we need to animate opacity
+ opacity = slide.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( slide.width / slide.height - start.width / start.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ start.opacity = 0.1;
+ end.opacity = 1;
+ }
+
+ // Draw image at start position
+ $.fancybox.setTranslate( slide.$content.removeClass( 'fancybox-is-hidden' ), start );
+
+ forceRedraw( slide.$content );
+
+ // Start animation
+ $.fancybox.animate( slide.$content, end, duration, function() {
+ self.complete();
+ });
+
+ return;
+ }
+
+ self.updateSlide( slide );
+
+
+ // Simply show content
+ // ===================
+
+ if ( !effect ) {
+ forceRedraw( $slide );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ return;
+ }
+
+ $.fancybox.stop( $slide );
+
+ effectClassName = 'fancybox-animated fancybox-slide--' + ( slide.pos >= self.prevPos ? 'next' : 'previous' ) + ' fancybox-fx-' + effect;
+
+ $slide.removeAttr( 'style' ).removeClass( 'fancybox-slide--current fancybox-slide--next fancybox-slide--previous' ).addClass( effectClassName );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ //Force reflow for CSS3 transitions
+ forceRedraw( $slide );
+
+ $.fancybox.animate( $slide, 'fancybox-slide--current', duration, function(e) {
+ $slide.removeClass( effectClassName ).removeAttr( 'style' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ }, true);
+
+ },
+
+
+ // Check if we can and have to zoom from thumbnail
+ //================================================
+
+ getThumbPos : function( slide ) {
+
+ var self = this;
+ var rez = false;
+
+ // Check if element is inside the viewport by at least 1 pixel
+ var isElementVisible = function( $el ) {
+ var element = $el[0];
+
+ var elementRect = element.getBoundingClientRect();
+ var parentRects = [];
+
+ var visibleInAllParents;
+
+ while ( element.parentElement !== null ) {
+ if ( $(element.parentElement).css('overflow') === 'hidden' || $(element.parentElement).css('overflow') === 'auto' ) {
+ parentRects.push(element.parentElement.getBoundingClientRect());
+ }
+
+ element = element.parentElement;
+ }
+
+ visibleInAllParents = parentRects.every(function(parentRect){
+ var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
+ var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
+
+ return visiblePixelX > 0 && visiblePixelY > 0;
+ });
+
+ return visibleInAllParents &&
+ elementRect.bottom > 0 && elementRect.right > 0 &&
+ elementRect.left < $(window).width() && elementRect.top < $(window).height();
+ };
+
+ var $thumb = slide.opts.$thumb;
+ var thumbPos = $thumb ? $thumb.offset() : 0;
+ var slidePos;
+
+ if ( thumbPos && $thumb[0].ownerDocument === document && isElementVisible( $thumb ) ) {
+ slidePos = self.$refs.stage.offset();
+
+ rez = {
+ top : thumbPos.top - slidePos.top + parseFloat( $thumb.css( "border-top-width" ) || 0 ),
+ left : thumbPos.left - slidePos.left + parseFloat( $thumb.css( "border-left-width" ) || 0 ),
+ width : $thumb.width(),
+ height : $thumb.height(),
+ scaleX : 1,
+ scaleY : 1
+ };
+ }
+
+ return rez;
+ },
+
+
+ // Final adjustments after current gallery item is moved to position
+ // and it`s content is loaded
+ // ==================================================================
+
+ complete : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var slides = {};
+
+ if ( current.isMoved || !current.isLoaded || current.isComplete ) {
+ return;
+ }
+
+ current.isComplete = true;
+
+ current.$slide.siblings().trigger( 'onReset' );
+
+ // Trigger any CSS3 transiton inside the slide
+ forceRedraw( current.$slide );
+
+ current.$slide.addClass( 'fancybox-slide--complete' );
+
+ // Remove unnecessary slides
+ $.each( self.slides, function( key, slide ) {
+ if ( slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1 ) {
+ slides[ slide.pos ] = slide;
+
+ } else if ( slide ) {
+
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.off().remove();
+ }
+ });
+
+ self.slides = slides;
+
+ self.updateCursor();
+
+ self.trigger( 'afterShow' );
+
+ // Try to focus on the first focusable element
+ if ( $( document.activeElement ).is( '[disabled]' ) || ( current.opts.autoFocus && !( current.type == 'image' || current.type === 'iframe' ) ) ) {
+ self.focus();
+ }
+
+ },
+
+
+ // Preload next and previous slides
+ // ================================
+
+ preload : function() {
+ var self = this;
+ var next, prev;
+
+ if ( self.group.length < 2 ) {
+ return;
+ }
+
+ next = self.slides[ self.currPos + 1 ];
+ prev = self.slides[ self.currPos - 1 ];
+
+ if ( next && next.type === 'image' ) {
+ self.loadSlide( next );
+ }
+
+ if ( prev && prev.type === 'image' ) {
+ self.loadSlide( prev );
+ }
+
+ },
+
+
+ // Try to find and focus on the first focusable element
+ // ====================================================
+
+ focus : function() {
+ var current = this.current;
+ var $el;
+
+ if ( this.isClosing ) {
+ return;
+ }
+
+ if ( current && current.isComplete ) {
+
+ // Look for first input with autofocus attribute
+ $el = current.$slide.find('input[autofocus]:enabled:visible:first');
+
+ if ( !$el.length ) {
+ $el = current.$slide.find('button,:input,[tabindex],a').filter(':enabled:visible:first');
+ }
+ }
+
+ $el = $el && $el.length ? $el : this.$refs.container;
+
+ $el.focus();
+ },
+
+
+ // Activates current instance - brings container to the front and enables keyboard,
+ // notifies other instances about deactivating
+ // =================================================================================
+
+ activate : function () {
+ var self = this;
+
+ // Deactivate all instances
+ $( '.fancybox-container' ).each(function () {
+ var instance = $(this).data( 'FancyBox' );
+
+ // Skip self and closing instances
+ if (instance && instance.id !== self.id && !instance.isClosing) {
+ instance.trigger( 'onDeactivate' );
+
+ instance.removeEvents();
+
+ instance.isVisible = false;
+ }
+
+ });
+
+ self.isVisible = true;
+
+ if ( self.current || self.isIdle ) {
+ self.update();
+
+ self.updateControls();
+ }
+
+ self.trigger( 'onActivate' );
+
+ self.addEvents();
+ },
+
+
+ // Start closing procedure
+ // This will start "zoom-out" animation if needed and clean everything up afterwards
+ // =================================================================================
+
+ close : function( e, d ) {
+
+ var self = this;
+ var current = self.current;
+
+ var effect, duration;
+ var $what, opacity, start, end;
+
+ var done = function() {
+ self.cleanUp( e );
+ };
+
+ if ( self.isClosing ) {
+ return false;
+ }
+
+ self.isClosing = true;
+
+ // If beforeClose callback prevents closing, make sure content is centered
+ if ( self.trigger( 'beforeClose', e ) === false ) {
+ self.isClosing = false;
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ return false;
+ }
+
+ // Remove all events
+ // If there are multiple instances, they will be set again by "activate" method
+ self.removeEvents();
+
+ if ( current.timouts ) {
+ clearTimeout( current.timouts );
+ }
+
+ $what = current.$content;
+ effect = current.opts.animationEffect;
+ duration = $.isNumeric( d ) ? d : ( effect ? current.opts.animationDuration : 0 );
+
+ // Remove other slides
+ current.$slide.off( transitionEnd ).removeClass( 'fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated' );
+
+ current.$slide.siblings().trigger( 'onReset' ).remove();
+
+ // Trigger animations
+ if ( duration ) {
+ self.$refs.container.removeClass( 'fancybox-is-open' ).addClass( 'fancybox-is-closing' );
+ }
+
+ // Clean up
+ self.hideLoading( current );
+
+ self.hideControls();
+
+ self.updateCursor();
+
+ // Check if possible to zoom-out
+ if ( effect === 'zoom' && !( e !== true && $what && duration && current.type === 'image' && !current.hasError && ( end = self.getThumbPos( current ) ) ) ) {
+ effect = 'fade';
+ }
+
+ if ( effect === 'zoom' ) {
+ $.fancybox.stop( $what );
+
+ start = $.fancybox.getTranslate( $what );
+
+ start.width = start.width * start.scaleX;
+ start.height = start.height * start.scaleY;
+
+ // Check if we need to animate opacity
+ opacity = current.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( current.width / current.height - end.width / end.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ end.opacity = 0;
+ }
+
+ start.scaleX = start.width / end.width;
+ start.scaleY = start.height / end.height;
+
+ start.width = end.width;
+ start.height = end.height;
+
+ $.fancybox.setTranslate( current.$content, start );
+
+ forceRedraw( current.$content );
+
+ $.fancybox.animate( current.$content, end, duration, done );
+
+ return true;
+ }
+
+ if ( effect && duration ) {
+
+ // If skip animation
+ if ( e === true ) {
+ setTimeout( done, duration );
+
+ } else {
+ $.fancybox.animate( current.$slide.removeClass( 'fancybox-slide--current' ), 'fancybox-animated fancybox-slide--previous fancybox-fx-' + effect, duration, done );
+ }
+
+ } else {
+ done();
+ }
+
+ return true;
+ },
+
+
+ // Final adjustments after removing the instance
+ // =============================================
+
+ cleanUp : function( e ) {
+ var self = this,
+ $body = $( 'body' ),
+ instance,
+ offset;
+
+ self.current.$slide.trigger( 'onReset' );
+
+ self.$refs.container.empty().remove();
+
+ self.trigger( 'afterClose', e );
+
+ // Place back focus
+ if ( self.$lastFocus && !!self.current.opts.backFocus ) {
+ self.$lastFocus.focus();
+ }
+
+ self.current = null;
+
+ // Check if there are other instances
+ instance = $.fancybox.getInstance();
+
+ if ( instance ) {
+ instance.activate();
+
+ } else {
+
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+
+ $body.removeClass( 'fancybox-active compensate-for-scrollbar' );
+
+ if ( $body.hasClass( 'fancybox-iosfix' ) ) {
+ offset = parseInt(document.body.style.top, 10);
+
+ $body.removeClass( 'fancybox-iosfix' ).css( 'top', '' ).scrollTop( offset * -1 );
+ }
+
+ $( '#fancybox-style-noscroll' ).remove();
+
+ }
+
+ },
+
+
+ // Call callback and trigger an event
+ // ==================================
+
+ trigger : function( name, slide ) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ self = this,
+ obj = slide && slide.opts ? slide : self.current,
+ rez;
+
+ if ( obj ) {
+ args.unshift( obj );
+
+ } else {
+ obj = self;
+ }
+
+ args.unshift( self );
+
+ if ( $.isFunction( obj.opts[ name ] ) ) {
+ rez = obj.opts[ name ].apply( obj, args );
+ }
+
+ if ( rez === false ) {
+ return rez;
+ }
+
+ if ( name === 'afterClose' || !self.$refs ) {
+ $D.trigger( name + '.fb', args );
+
+ } else {
+ self.$refs.container.trigger( name + '.fb', args );
+ }
+
+ },
+
+
+ // Update infobar values, navigation button states and reveal caption
+ // ==================================================================
+
+ updateControls : function ( force ) {
+
+ var self = this;
+
+ var current = self.current,
+ index = current.index,
+ caption = current.opts.caption,
+ $container = self.$refs.container,
+ $caption = self.$refs.caption;
+
+ // Recalculate content dimensions
+ current.$slide.trigger( 'refresh' );
+
+ self.$caption = caption && caption.length ? $caption.html( caption ) : null;
+
+ if ( !self.isHiddenControls && !self.isIdle ) {
+ self.showControls();
+ }
+
+ // Update info and navigation elements
+ $container.find('[data-fancybox-count]').html( self.group.length );
+ $container.find('[data-fancybox-index]').html( index + 1 );
+
+ $container.find('[data-fancybox-prev]').prop( 'disabled', ( !current.opts.loop && index <= 0 ) );
+ $container.find('[data-fancybox-next]').prop( 'disabled', ( !current.opts.loop && index >= self.group.length - 1 ) );
+
+ if ( current.type === 'image' ) {
+
+ // Update download button source
+ $container.find('[data-fancybox-download]').attr( 'href', current.opts.image.src || current.src ).show();
+
+ } else {
+ $container.find('[data-fancybox-download],[data-fancybox-zoom]').hide();
+ }
+ },
+
+ // Hide toolbar and caption
+ // ========================
+
+ hideControls : function () {
+
+ this.isHiddenControls = true;
+
+ this.$refs.container.removeClass( 'fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav' );
+
+ },
+
+ showControls : function() {
+ var self = this;
+ var opts = self.current ? self.current.opts : self.opts;
+ var $container = self.$refs.container;
+
+ self.isHiddenControls = false;
+ self.idleSecondsCounter = 0;
+
+ $container
+ .toggleClass( 'fancybox-show-toolbar', !!( opts.toolbar && opts.buttons ) )
+ .toggleClass( 'fancybox-show-infobar', !!( opts.infobar && self.group.length > 1 ) )
+ .toggleClass( 'fancybox-show-nav', !!( opts.arrows && self.group.length > 1 ) )
+ .toggleClass( 'fancybox-is-modal', !!opts.modal );
+
+ if ( self.$caption ) {
+ $container.addClass( 'fancybox-show-caption ');
+
+ } else {
+ $container.removeClass( 'fancybox-show-caption' );
+ }
+
+ },
+
+
+ // Toggle toolbar and caption
+ // ==========================
+
+ toggleControls : function() {
+ if ( this.isHiddenControls ) {
+ this.showControls();
+
+ } else {
+ this.hideControls();
+ }
+
+ },
+
+
+ });
+
+
+ $.fancybox = {
+
+ version : "3.2.5",
+ defaults : defaults,
+
+
+ // Get current instance and execute a command.
+ //
+ // Examples of usage:
+ //
+ // $instance = $.fancybox.getInstance();
+ // $.fancybox.getInstance().jumpTo( 1 );
+ // $.fancybox.getInstance( 'jumpTo', 1 );
+ // $.fancybox.getInstance( function() {
+ // console.info( this.currIndex );
+ // });
+ // ======================================================
+
+ getInstance : function ( command ) {
+ var instance = $('.fancybox-container:not(".fancybox-is-closing"):last').data( 'FancyBox' );
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ if ( instance instanceof FancyBox ) {
+
+ if ( $.type( command ) === 'string' ) {
+ instance[ command ].apply( instance, args );
+
+ } else if ( $.type( command ) === 'function' ) {
+ command.apply( instance, args );
+ }
+
+ return instance;
+ }
+
+ return false;
+
+ },
+
+
+ // Create new instance
+ // ===================
+
+ open : function ( items, opts, index ) {
+ return new FancyBox( items, opts, index );
+ },
+
+
+ // Close current or all instances
+ // ==============================
+
+ close : function ( all ) {
+ var instance = this.getInstance();
+
+ if ( instance ) {
+ instance.close();
+
+ // Try to find and close next instance
+
+ if ( all === true ) {
+ this.close();
+ }
+ }
+
+ },
+
+ // Close instances and unbind all events
+ // ==============================
+
+ destroy : function() {
+
+ this.close( true );
+
+ $D.off( 'click.fb-start' );
+
+ },
+
+
+ // Try to detect mobile devices
+ // ============================
+
+ isMobile : document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
+
+
+ // Detect if 'translate3d' support is available
+ // ============================================
+
+ use3d : (function() {
+ var div = document.createElement('div');
+
+ return window.getComputedStyle && window.getComputedStyle( div ).getPropertyValue('transform') && !(document.documentMode && document.documentMode < 11);
+ }()),
+
+ // Helper function to get current visual state of an element
+ // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
+ // =====================================================================
+
+ getTranslate : function( $el ) {
+ var matrix;
+
+ if ( !$el || !$el.length ) {
+ return false;
+ }
+
+ matrix = $el.eq( 0 ).css('transform');
+
+ if ( matrix && matrix.indexOf( 'matrix' ) !== -1 ) {
+ matrix = matrix.split('(')[1];
+ matrix = matrix.split(')')[0];
+ matrix = matrix.split(',');
+ } else {
+ matrix = [];
+ }
+
+ if ( matrix.length ) {
+
+ // If IE
+ if ( matrix.length > 10 ) {
+ matrix = [ matrix[13], matrix[12], matrix[0], matrix[5] ];
+
+ } else {
+ matrix = [ matrix[5], matrix[4], matrix[0], matrix[3]];
+ }
+
+ matrix = matrix.map(parseFloat);
+
+ } else {
+ matrix = [ 0, 0, 1, 1 ];
+
+ var transRegex = /\.*translate\((.*)px,(.*)px\)/i;
+ var transRez = transRegex.exec( $el.eq( 0 ).attr('style') );
+
+ if ( transRez ) {
+ matrix[ 0 ] = parseFloat( transRez[2] );
+ matrix[ 1 ] = parseFloat( transRez[1] );
+ }
+ }
+
+ return {
+ top : matrix[ 0 ],
+ left : matrix[ 1 ],
+ scaleX : matrix[ 2 ],
+ scaleY : matrix[ 3 ],
+ opacity : parseFloat( $el.css('opacity') ),
+ width : $el.width(),
+ height : $el.height()
+ };
+
+ },
+
+
+ // Shortcut for setting "translate3d" properties for element
+ // Can set be used to set opacity, too
+ // ========================================================
+
+ setTranslate : function( $el, props ) {
+ var str = '';
+ var css = {};
+
+ if ( !$el || !props ) {
+ return;
+ }
+
+ if ( props.left !== undefined || props.top !== undefined ) {
+ str = ( props.left === undefined ? $el.position().left : props.left ) + 'px, ' + ( props.top === undefined ? $el.position().top : props.top ) + 'px';
+
+ if ( this.use3d ) {
+ str = 'translate3d(' + str + ', 0px)';
+
+ } else {
+ str = 'translate(' + str + ')';
+ }
+ }
+
+ if ( props.scaleX !== undefined && props.scaleY !== undefined ) {
+ str = (str.length ? str + ' ' : '') + 'scale(' + props.scaleX + ', ' + props.scaleY + ')';
+ }
+
+ if ( str.length ) {
+ css.transform = str;
+ }
+
+ if ( props.opacity !== undefined ) {
+ css.opacity = props.opacity;
+ }
+
+ if ( props.width !== undefined ) {
+ css.width = props.width;
+ }
+
+ if ( props.height !== undefined ) {
+ css.height = props.height;
+ }
+
+ return $el.css( css );
+ },
+
+
+ // Simple CSS transition handler
+ // =============================
+
+ animate : function ( $el, to, duration, callback, leaveAnimationName ) {
+ if ( $.isFunction( duration ) ) {
+ callback = duration;
+ duration = null;
+ }
+
+ if ( !$.isPlainObject( to ) ) {
+ $el.removeAttr('style');
+ }
+
+ $el.on( transitionEnd, function(e) {
+
+ // Skip events from child elements and z-index change
+ if ( e && e.originalEvent && ( !$el.is( e.originalEvent.target ) || e.originalEvent.propertyName == 'z-index' ) ) {
+ return;
+ }
+
+ $.fancybox.stop( $el );
+
+ if ( $.isPlainObject( to ) ) {
+
+ if ( to.scaleX !== undefined && to.scaleY !== undefined ) {
+ $el.css( 'transition-duration', '' );
+
+ to.width = Math.round( $el.width() * to.scaleX );
+ to.height = Math.round( $el.height() * to.scaleY );
+
+ to.scaleX = 1;
+ to.scaleY = 1;
+
+ $.fancybox.setTranslate( $el, to );
+ }
+
+ } else if ( leaveAnimationName !== true ) {
+ $el.removeClass( to );
+ }
+
+ if ( $.isFunction( callback ) ) {
+ callback( e );
+ }
+
+ });
+
+ if ( $.isNumeric( duration ) ) {
+ $el.css( 'transition-duration', duration + 'ms' );
+ }
+
+ if ( $.isPlainObject( to ) ) {
+ $.fancybox.setTranslate( $el, to );
+
+ } else {
+ $el.addClass( to );
+ }
+
+ if ( to.scaleX && $el.hasClass( 'fancybox-image-wrap' ) ) {
+ $el.parent().addClass( 'fancybox-is-scaling' );
+ }
+
+ // Make sure that `transitionend` callback gets fired
+ $el.data("timer", setTimeout(function() {
+ $el.trigger( 'transitionend' );
+ }, duration + 16));
+
+ },
+
+ stop : function( $el ) {
+ clearTimeout( $el.data("timer") );
+
+ $el.off( 'transitionend' ).css( 'transition-duration', '' );
+
+ if ( $el.hasClass( 'fancybox-image-wrap' ) ) {
+ $el.parent().removeClass( 'fancybox-is-scaling' );
+ }
+ }
+
+ };
+
+
+ // Default click handler for "fancyboxed" links
+ // ============================================
+
+ function _run( e ) {
+ var $target = $( e.currentTarget ),
+ opts = e.data ? e.data.options : {},
+ value = $target.attr( 'data-fancybox' ) || '',
+ index = 0,
+ items = [];
+
+ // Avoid opening multiple times
+ if ( e.isDefaultPrevented() ) {
+ return;
+ }
+
+ e.preventDefault();
+
+ // Get all related items and find index for clicked one
+ if ( value ) {
+ items = opts.selector ? $( opts.selector ) : ( e.data ? e.data.items : [] );
+ items = items.length ? items.filter( '[data-fancybox="' + value + '"]' ) : $( '[data-fancybox="' + value + '"]' );
+
+ index = items.index( $target );
+
+ // Sometimes current item can not be found
+ // (for example, when slider clones items)
+ if ( index < 0 ) {
+ index = 0;
+ }
+
+ } else {
+ items = [ $target ];
+ }
+
+ $.fancybox.open( items, opts, index );
+ }
+
+
+ // Create a jQuery plugin
+ // ======================
+
+ $.fn.fancybox = function (options) {
+ var selector;
+
+ options = options || {};
+ selector = options.selector || false;
+
+ if ( selector ) {
+
+ $( 'body' ).off( 'click.fb-start', selector ).on( 'click.fb-start', selector, {
+ options : options
+ }, _run );
+
+ } else {
+
+ this.off( 'click.fb-start' ).on( 'click.fb-start', {
+ items : this,
+ options : options
+ }, _run);
+
+ }
+
+ return this;
+ };
+
+
+ // Self initializing plugin
+ // ========================
+
+ $D.on( 'click.fb-start', '[data-fancybox]', _run );
+
+}( window, document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Media
+// Adds additional media type support
+//
+// ==========================================================================
+;(function ($) {
+
+ 'use strict';
+
+ // Formats matching url to final form
+
+ var format = function (url, rez, params) {
+ if ( !url ) {
+ return;
+ }
+
+ params = params || '';
+
+ if ( $.type(params) === "object" ) {
+ params = $.param(params, true);
+ }
+
+ $.each(rez, function (key, value) {
+ url = url.replace('$' + key, value || '');
+ });
+
+ if (params.length) {
+ url += (url.indexOf('?') > 0 ? '&' : '?') + params;
+ }
+
+ return url;
+ };
+
+ // Object containing properties for each media type
+
+ var defaults = {
+ youtube : {
+ matcher : /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
+ params : {
+ autoplay : 1,
+ autohide : 1,
+ fs : 1,
+ rel : 0,
+ hd : 1,
+ wmode : 'transparent',
+ enablejsapi : 1,
+ html5 : 1
+ },
+ paramPlace : 8,
+ type : 'iframe',
+ url : '//www.youtube.com/embed/$4',
+ thumb : '//img.youtube.com/vi/$4/hqdefault.jpg'
+ },
+
+ vimeo : {
+ matcher : /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
+ params : {
+ autoplay : 1,
+ hd : 1,
+ show_title : 1,
+ show_byline : 1,
+ show_portrait : 0,
+ fullscreen : 1,
+ api : 1
+ },
+ paramPlace : 3,
+ type : 'iframe',
+ url : '//player.vimeo.com/video/$2'
+ },
+
+ metacafe : {
+ matcher : /metacafe.com\/watch\/(\d+)\/(.*)?/,
+ type : 'iframe',
+ url : '//www.metacafe.com/embed/$1/?ap=1'
+ },
+
+ dailymotion : {
+ matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
+ params : {
+ additionalInfos : 0,
+ autoStart : 1
+ },
+ type : 'iframe',
+ url : '//www.dailymotion.com/embed/video/$1'
+ },
+
+ vine : {
+ matcher : /vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,
+ type : 'iframe',
+ url : '//vine.co/v/$1/embed/simple'
+ },
+
+ instagram : {
+ matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
+ type : 'image',
+ url : '//$1/p/$2/media/?size=l'
+ },
+
+ // Examples:
+ // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
+ // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
+ // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
+ gmap_place : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/?ll=' + ( rez[9] ? rez[9] + '&z=' + Math.floor( rez[10] ) + ( rez[12] ? rez[12].replace(/^\//, "&") : '' ) : rez[12] ) + '&output=' + ( rez[12] && rez[12].indexOf('layer=c') > 0 ? 'svembed' : 'embed' );
+ }
+ },
+
+ // Examples:
+ // https://www.google.com/maps/search/Empire+State+Building/
+ // https://www.google.com/maps/search/?api=1&query=centurylink+field
+ // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
+ gmap_search : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/maps?q=' + rez[5].replace('query=', 'q=').replace('api=1', '') + '&output=embed';
+ }
+ }
+ };
+
+ $(document).on('objectNeedsType.fb', function (e, instance, item) {
+
+ var url = item.src || '',
+ type = false,
+ media,
+ thumb,
+ rez,
+ params,
+ urlParams,
+ paramObj,
+ provider;
+
+ media = $.extend( true, {}, defaults, item.opts.media );
+
+ // Look for any matching media type
+ $.each(media, function ( providerName, providerOpts ) {
+ rez = url.match( providerOpts.matcher );
+
+ if ( !rez ) {
+ return;
+ }
+
+ type = providerOpts.type;
+ paramObj = {};
+
+ if ( providerOpts.paramPlace && rez[ providerOpts.paramPlace ] ) {
+ urlParams = rez[ providerOpts.paramPlace ];
+
+ if ( urlParams[ 0 ] == '?' ) {
+ urlParams = urlParams.substring(1);
+ }
+
+ urlParams = urlParams.split('&');
+
+ for ( var m = 0; m < urlParams.length; ++m ) {
+ var p = urlParams[ m ].split('=', 2);
+
+ if ( p.length == 2 ) {
+ paramObj[ p[0] ] = decodeURIComponent( p[1].replace(/\+/g, " ") );
+ }
+ }
+ }
+
+ params = $.extend( true, {}, providerOpts.params, item.opts[ providerName ], paramObj );
+
+ url = $.type( providerOpts.url ) === "function" ? providerOpts.url.call( this, rez, params, item ) : format( providerOpts.url, rez, params );
+ thumb = $.type( providerOpts.thumb ) === "function" ? providerOpts.thumb.call( this, rez, params, item ) : format( providerOpts.thumb, rez );
+
+ if ( providerName === 'vimeo' ) {
+ url = url.replace('&%23', '#');
+ }
+
+ return false;
+ });
+
+ // If it is found, then change content type and update the url
+
+ if ( type ) {
+ item.src = url;
+ item.type = type;
+
+ if ( !item.opts.thumb && !( item.opts.$thumb && item.opts.$thumb.length ) ) {
+ item.opts.thumb = thumb;
+ }
+
+ if ( type === 'iframe' ) {
+ $.extend(true, item.opts, {
+ iframe : {
+ preload : false,
+ attr : {
+ scrolling : "no"
+ }
+ }
+ });
+
+ item.contentProvider = provider;
+
+ item.opts.slideClass += ' fancybox-slide--' + ( provider == 'gmap_place' || provider == 'gmap_search' ? 'map' : 'video' );
+ }
+
+ } else if ( url ) {
+ item.type = item.opts.defaultType;
+ }
+
+ });
+
+}( window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Guestures
+// Adds touch guestures, handles click and tap events
+//
+// ==========================================================================
+;(function (window, document, $) {
+ 'use strict';
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ var cancelAFrame = (function () {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.mozCancelAnimationFrame ||
+ window.oCancelAnimationFrame ||
+ function (id) {
+ window.clearTimeout(id);
+ };
+ })();
+
+
+ var pointers = function( e ) {
+ var result = [];
+
+ e = e.originalEvent || e || window.e;
+ e = e.touches && e.touches.length ? e.touches : ( e.changedTouches && e.changedTouches.length ? e.changedTouches : [ e ] );
+
+ for ( var key in e ) {
+
+ if ( e[ key ].pageX ) {
+ result.push( { x : e[ key ].pageX, y : e[ key ].pageY } );
+
+ } else if ( e[ key ].clientX ) {
+ result.push( { x : e[ key ].clientX, y : e[ key ].clientY } );
+ }
+ }
+
+ return result;
+ };
+
+ var distance = function( point2, point1, what ) {
+ if ( !point1 || !point2 ) {
+ return 0;
+ }
+
+ if ( what === 'x' ) {
+ return point2.x - point1.x;
+
+ } else if ( what === 'y' ) {
+ return point2.y - point1.y;
+ }
+
+ return Math.sqrt( Math.pow( point2.x - point1.x, 2 ) + Math.pow( point2.y - point1.y, 2 ) );
+ };
+
+ var isClickable = function( $el ) {
+
+ if ( $el.is('a,area,button,[role="button"],input,label,select,summary,textarea') || $.isFunction( $el.get(0).onclick ) || $el.data('selectable') ) {
+ return true;
+ }
+
+ // Check for attributes like data-fancybox-next or data-fancybox-close
+ for ( var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++ ) {
+ if ( atts[i].nodeName.substr(0, 14) === 'data-fancybox-' ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ var hasScrollbars = function( el ) {
+ var overflowY = window.getComputedStyle( el )['overflow-y'];
+ var overflowX = window.getComputedStyle( el )['overflow-x'];
+
+ var vertical = (overflowY === 'scroll' || overflowY === 'auto') && el.scrollHeight > el.clientHeight;
+ var horizontal = (overflowX === 'scroll' || overflowX === 'auto') && el.scrollWidth > el.clientWidth;
+
+ return vertical || horizontal;
+ };
+
+ var isScrollable = function ( $el ) {
+ var rez = false;
+
+ while ( true ) {
+ rez = hasScrollbars( $el.get(0) );
+
+ if ( rez ) {
+ break;
+ }
+
+ $el = $el.parent();
+
+ if ( !$el.length || $el.hasClass( 'fancybox-stage' ) || $el.is( 'body' ) ) {
+ break;
+ }
+ }
+
+ return rez;
+ };
+
+
+ var Guestures = function ( instance ) {
+ var self = this;
+
+ self.instance = instance;
+
+ self.$bg = instance.$refs.bg;
+ self.$stage = instance.$refs.stage;
+ self.$container = instance.$refs.container;
+
+ self.destroy();
+
+ self.$container.on( 'touchstart.fb.touch mousedown.fb.touch', $.proxy(self, 'ontouchstart') );
+ };
+
+ Guestures.prototype.destroy = function() {
+ this.$container.off( '.fb.touch' );
+ };
+
+ Guestures.prototype.ontouchstart = function( e ) {
+ var self = this;
+
+ var $target = $( e.target );
+ var instance = self.instance;
+ var current = instance.current;
+ var $content = current.$content;
+
+ var isTouchDevice = ( e.type == 'touchstart' );
+
+ // Do not respond to both events
+ if ( isTouchDevice ) {
+ self.$container.off( 'mousedown.fb.touch' );
+ }
+
+ // Ignore clicks while zooming or closing
+ if ( !current || self.instance.isAnimating || self.instance.isClosing ) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ return;
+ }
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Ignore taping on links, buttons, input elements
+ if ( !$target.length || isClickable( $target ) || isClickable( $target.parent() ) ) {
+ return;
+ }
+
+ // Ignore clicks on the scrollbar
+ if ( e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ self.startPoints = pointers( e );
+
+ // Prevent zooming if already swiping
+ if ( !self.startPoints || ( self.startPoints.length > 1 && instance.isSliding ) ) {
+ return;
+ }
+
+ self.$target = $target;
+ self.$content = $content;
+ self.canTap = true;
+ self.opts = current.opts.touch;
+
+ $(document).off( '.fb.touch' );
+
+ $(document).on( isTouchDevice ? 'touchend.fb.touch touchcancel.fb.touch' : 'mouseup.fb.touch mouseleave.fb.touch', $.proxy(self, "ontouchend"));
+ $(document).on( isTouchDevice ? 'touchmove.fb.touch' : 'mousemove.fb.touch', $.proxy(self, "ontouchmove"));
+
+ if ( !(self.opts || instance.canPan() ) || !( $target.is( self.$stage ) || self.$stage.find( $target ).length ) ) {
+
+ // Prevent ghosting
+ if ( $target.is('img') ) {
+ e.preventDefault();
+ }
+
+ return;
+ }
+
+ e.stopPropagation();
+
+ if ( !( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) ) {
+ e.preventDefault();
+ }
+
+ self.canvasWidth = Math.round( current.$slide[0].clientWidth );
+ self.canvasHeight = Math.round( current.$slide[0].clientHeight );
+
+ self.startTime = new Date().getTime();
+ self.distanceX = self.distanceY = self.distance = 0;
+
+ self.isPanning = false;
+ self.isSwiping = false;
+ self.isZooming = false;
+
+ self.sliderStartPos = self.sliderLastPos || { top: 0, left: 0 };
+ self.contentStartPos = $.fancybox.getTranslate( self.$content );
+ self.contentLastPos = null;
+
+ if ( self.startPoints.length === 1 && !self.isZooming ) {
+ self.canTap = !instance.isSliding;
+
+ if ( current.type === 'image' && ( self.contentStartPos.width > self.canvasWidth + 1 || self.contentStartPos.height > self.canvasHeight + 1 ) ) {
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.isPanning = true;
+
+ } else {
+
+ self.isSwiping = true;
+ }
+
+ self.$container.addClass('fancybox-controls--isGrabbing');
+ }
+
+ if ( self.startPoints.length === 2 && !instance.isAnimating && !current.hasError && current.type === 'image' && ( current.isLoaded || current.$ghost ) ) {
+ self.isZooming = true;
+
+ self.isSwiping = false;
+ self.isPanning = false;
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.centerPointStartX = ( ( self.startPoints[0].x + self.startPoints[1].x ) * 0.5 ) - $(window).scrollLeft();
+ self.centerPointStartY = ( ( self.startPoints[0].y + self.startPoints[1].y ) * 0.5 ) - $(window).scrollTop();
+
+ self.percentageOfImageAtPinchPointX = ( self.centerPointStartX - self.contentStartPos.left ) / self.contentStartPos.width;
+ self.percentageOfImageAtPinchPointY = ( self.centerPointStartY - self.contentStartPos.top ) / self.contentStartPos.height;
+
+ self.startDistanceBetweenFingers = distance( self.startPoints[0], self.startPoints[1] );
+ }
+
+ };
+
+ Guestures.prototype.ontouchmove = function( e ) {
+
+ var self = this;
+
+ self.newPoints = pointers( e );
+
+ if ( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) {
+ e.stopPropagation();
+
+ self.canTap = false;
+
+ return;
+ }
+
+ if ( !( self.opts || self.instance.canPan() ) || !self.newPoints || !self.newPoints.length ) {
+ return;
+ }
+
+ self.distanceX = distance( self.newPoints[0], self.startPoints[0], 'x' );
+ self.distanceY = distance( self.newPoints[0], self.startPoints[0], 'y' );
+
+ self.distance = distance( self.newPoints[0], self.startPoints[0] );
+
+ // Skip false ontouchmove events (Chrome)
+ if ( self.distance > 0 ) {
+
+ if ( !( self.$target.is( self.$stage ) || self.$stage.find( self.$target ).length ) ) {
+ return;
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ if ( self.isSwiping ) {
+ self.onSwipe();
+
+ } else if ( self.isPanning ) {
+ self.onPan();
+
+ } else if ( self.isZooming ) {
+ self.onZoom();
+ }
+
+ }
+
+ };
+
+ Guestures.prototype.onSwipe = function() {
+
+ var self = this;
+
+ var swiping = self.isSwiping;
+ var left = self.sliderStartPos.left || 0;
+ var angle;
+
+ if ( swiping === true ) {
+
+ if ( Math.abs( self.distance ) > 10 ) {
+
+ self.canTap = false;
+
+ if ( self.instance.group.length < 2 && self.opts.vertical ) {
+ self.isSwiping = 'y';
+
+ } else if ( self.instance.isSliding || self.opts.vertical === false || ( self.opts.vertical === 'auto' && $( window ).width() > 800 ) ) {
+ self.isSwiping = 'x';
+
+ } else {
+ angle = Math.abs( Math.atan2( self.distanceY, self.distanceX ) * 180 / Math.PI );
+
+ self.isSwiping = ( angle > 45 && angle < 135 ) ? 'y' : 'x';
+ }
+
+ self.instance.isSliding = self.isSwiping;
+
+ // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
+ self.startPoints = self.newPoints;
+
+ $.each(self.instance.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.css( 'transition-duration', '0ms' );
+
+ slide.inTransition = false;
+
+ if ( slide.pos === self.instance.current.pos ) {
+ self.sliderStartPos.left = $.fancybox.getTranslate( slide.$slide ).left;
+ }
+ });
+
+ //self.instance.current.isMoved = true;
+
+ // Stop slideshow
+ if ( self.instance.SlideShow && self.instance.SlideShow.isActive ) {
+ self.instance.SlideShow.stop();
+ }
+ }
+
+ } else {
+
+ if ( swiping == 'x' ) {
+
+ // Sticky edges
+ if ( self.distanceX > 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === 0 && !self.instance.current.opts.loop ) ) ) {
+ left = left + Math.pow( self.distanceX, 0.8 );
+
+ } else if ( self.distanceX < 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop ) ) ) {
+ left = left - Math.pow( -self.distanceX, 0.8 );
+
+ } else {
+ left = left + self.distanceX;
+ }
+
+ }
+
+ self.sliderLastPos = {
+ top : swiping == 'x' ? 0 : self.sliderStartPos.top + self.distanceY,
+ left : left
+ };
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+
+ if ( self.sliderLastPos ) {
+ $.each(self.instance.slides, function( index, slide ) {
+ var pos = slide.pos - self.instance.currPos;
+
+ $.fancybox.setTranslate( slide.$slide, {
+ top : self.sliderLastPos.top,
+ left : self.sliderLastPos.left + ( pos * self.canvasWidth ) + ( pos * slide.opts.gutter )
+ });
+ });
+
+ self.$container.addClass( 'fancybox-is-sliding' );
+ }
+
+ });
+
+ }
+
+ };
+
+ Guestures.prototype.onPan = function() {
+
+ var self = this;
+
+ var newOffsetX, newOffsetY, newPos;
+
+ self.canTap = false;
+
+ if ( self.contentStartPos.width > self.canvasWidth ) {
+ newOffsetX = self.contentStartPos.left + self.distanceX;
+
+ } else {
+ newOffsetX = self.contentStartPos.left;
+ }
+
+ newOffsetY = self.contentStartPos.top + self.distanceY;
+
+ newPos = self.limitMovement( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.scaleX = self.contentStartPos.scaleX;
+ newPos.scaleY = self.contentStartPos.scaleY;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+ };
+
+ // Make panning sticky to the edges
+ Guestures.prototype.limitMovement = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var distanceX = self.distanceX;
+ var distanceY = self.distanceY;
+
+ // Slow down proportionally to traveled distance
+
+ minTranslateX = Math.max(0, canvasWidth * 0.5 - newWidth * 0.5 );
+ minTranslateY = Math.max(0, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ maxTranslateX = Math.min( canvasWidth - newWidth, canvasWidth * 0.5 - newWidth * 0.5 );
+ maxTranslateY = Math.min( canvasHeight - newHeight, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ if ( newWidth > canvasWidth ) {
+
+ // ->
+ if ( distanceX > 0 && newOffsetX > minTranslateX ) {
+ newOffsetX = minTranslateX - 1 + Math.pow( -minTranslateX + currentOffsetX + distanceX, 0.8 ) || 0;
+ }
+
+ // <-
+ if ( distanceX < 0 && newOffsetX < maxTranslateX ) {
+ newOffsetX = maxTranslateX + 1 - Math.pow( maxTranslateX - currentOffsetX - distanceX, 0.8 ) || 0;
+ }
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+
+ // \/
+ if ( distanceY > 0 && newOffsetY > minTranslateY ) {
+ newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8 ) || 0;
+ }
+
+ // /\
+ if ( distanceY < 0 && newOffsetY < maxTranslateY ) {
+ newOffsetY = maxTranslateY + 1 - Math.pow ( maxTranslateY - currentOffsetY - distanceY, 0.8 ) || 0;
+ }
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+
+ Guestures.prototype.limitPosition = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ if ( newWidth > canvasWidth ) {
+ newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
+ newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
+
+ } else {
+
+ // Center horizontally
+ newOffsetX = Math.max( 0, canvasWidth / 2 - newWidth / 2 );
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+ newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
+ newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
+
+ } else {
+
+ // Center vertically
+ newOffsetY = Math.max( 0, canvasHeight / 2 - newHeight / 2 );
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+ Guestures.prototype.onZoom = function() {
+
+ var self = this;
+
+ // Calculate current distance between points to get pinch ratio and new width and height
+
+ var currentWidth = self.contentStartPos.width;
+ var currentHeight = self.contentStartPos.height;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var endDistanceBetweenFingers = distance( self.newPoints[0], self.newPoints[1] );
+
+ var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
+
+ var newWidth = Math.floor( currentWidth * pinchRatio );
+ var newHeight = Math.floor( currentHeight * pinchRatio );
+
+ // This is the translation due to pinch-zooming
+ var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
+ var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
+
+ //Point between the two touches
+
+ var centerPointEndX = ((self.newPoints[0].x + self.newPoints[1].x) / 2) - $(window).scrollLeft();
+ var centerPointEndY = ((self.newPoints[0].y + self.newPoints[1].y) / 2) - $(window).scrollTop();
+
+ // And this is the translation due to translation of the centerpoint
+ // between the two fingers
+
+ var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
+ var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
+
+ // The new offset is the old/current one plus the total translation
+
+ var newOffsetX = currentOffsetX + ( translateFromZoomingX + translateFromTranslatingX );
+ var newOffsetY = currentOffsetY + ( translateFromZoomingY + translateFromTranslatingY );
+
+ var newPos = {
+ top : newOffsetY,
+ left : newOffsetX,
+ scaleX : self.contentStartPos.scaleX * pinchRatio,
+ scaleY : self.contentStartPos.scaleY * pinchRatio
+ };
+
+ self.canTap = false;
+
+ self.newWidth = newWidth;
+ self.newHeight = newHeight;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+
+ };
+
+ Guestures.prototype.ontouchend = function( e ) {
+
+ var self = this;
+ var dMs = Math.max( (new Date().getTime() ) - self.startTime, 1);
+
+ var swiping = self.isSwiping;
+ var panning = self.isPanning;
+ var zooming = self.isZooming;
+
+ self.endPoints = pointers( e );
+
+ self.$container.removeClass( 'fancybox-controls--isGrabbing' );
+
+ $(document).off( '.fb.touch' );
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.isSwiping = false;
+ self.isPanning = false;
+ self.isZooming = false;
+
+ if ( self.canTap ) {
+ return self.onTap( e );
+ }
+
+ self.speed = 366;
+
+ // Speed in px/ms
+ self.velocityX = self.distanceX / dMs * 0.5;
+ self.velocityY = self.distanceY / dMs * 0.5;
+
+ self.speedX = Math.max( self.speed * 0.5, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityX ) ) * self.speed ) );
+
+ if ( panning ) {
+ self.endPanning();
+
+ } else if ( zooming ) {
+ self.endZooming();
+
+ } else {
+ self.endSwiping( swiping );
+ }
+
+ return;
+ };
+
+ Guestures.prototype.endSwiping = function( swiping ) {
+
+ var self = this;
+ var ret = false;
+
+ self.instance.isSliding = false;
+ self.sliderLastPos = null;
+
+ // Close if swiped vertically / navigate if horizontally
+ if ( swiping == 'y' && Math.abs( self.distanceY ) > 50 ) {
+
+ // Continue vertical movement
+ $.fancybox.animate( self.instance.current.$slide, {
+ top : self.sliderStartPos.top + self.distanceY + ( self.velocityY * 150 ),
+ opacity : 0
+ }, 150 );
+
+ ret = self.instance.close( true, 300 );
+
+ } else if ( swiping == 'x' && self.distanceX > 50 && self.instance.group.length > 1 ) {
+ ret = self.instance.previous( self.speedX );
+
+ } else if ( swiping == 'x' && self.distanceX < -50 && self.instance.group.length > 1 ) {
+ ret = self.instance.next( self.speedX );
+ }
+
+ if ( ret === false && ( swiping == 'x' || swiping == 'y' ) ) {
+ self.instance.jumpTo( self.instance.current.index, 150 );
+ }
+
+ self.$container.removeClass( 'fancybox-is-sliding' );
+
+ };
+
+ // Limit panning from edges
+ // ========================
+
+ Guestures.prototype.endPanning = function() {
+
+ var self = this;
+ var newOffsetX, newOffsetY, newPos;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ if ( self.opts.momentum === false ) {
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ } else {
+
+ // Continue movement
+ newOffsetX = self.contentLastPos.left + ( self.velocityX * self.speed );
+ newOffsetY = self.contentLastPos.top + ( self.velocityY * self.speed );
+ }
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.width = self.contentStartPos.width;
+ newPos.height = self.contentStartPos.height;
+
+ $.fancybox.animate( self.$content, newPos, 330 );
+ };
+
+
+ Guestures.prototype.endZooming = function() {
+
+ var self = this;
+
+ var current = self.instance.current;
+
+ var newOffsetX, newOffsetY, newPos, reset;
+
+ var newWidth = self.newWidth;
+ var newHeight = self.newHeight;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ reset = {
+ top : newOffsetY,
+ left : newOffsetX,
+ width : newWidth,
+ height : newHeight,
+ scaleX : 1,
+ scaleY : 1
+ };
+
+ // Reset scalex/scaleY values; this helps for perfomance and does not break animation
+ $.fancybox.setTranslate( self.$content, reset );
+
+ if ( newWidth < self.canvasWidth && newHeight < self.canvasHeight ) {
+ self.instance.scaleToFit( 150 );
+
+ } else if ( newWidth > current.width || newHeight > current.height ) {
+ self.instance.scaleToActual( self.centerPointStartX, self.centerPointStartY, 150 );
+
+ } else {
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, newWidth, newHeight );
+
+ // Switch from scale() to width/height or animation will not work correctly
+ $.fancybox.setTranslate( self.content, $.fancybox.getTranslate( self.$content ) );
+
+ $.fancybox.animate( self.$content, newPos, 150 );
+ }
+
+ };
+
+ Guestures.prototype.onTap = function(e) {
+ var self = this;
+ var $target = $( e.target );
+
+ var instance = self.instance;
+ var current = instance.current;
+
+ var endPoints = ( e && pointers( e ) ) || self.startPoints;
+
+ var tapX = endPoints[0] ? endPoints[0].x - self.$stage.offset().left : 0;
+ var tapY = endPoints[0] ? endPoints[0].y - self.$stage.offset().top : 0;
+
+ var where;
+
+ var process = function ( prefix ) {
+
+ var action = current.opts[ prefix ];
+
+ if ( $.isFunction( action ) ) {
+ action = action.apply( instance, [ current, e ] );
+ }
+
+ if ( !action) {
+ return;
+ }
+
+ switch ( action ) {
+
+ case "close" :
+
+ instance.close( self.startEvent );
+
+ break;
+
+ case "toggleControls" :
+
+ instance.toggleControls( true );
+
+ break;
+
+ case "next" :
+
+ instance.next();
+
+ break;
+
+ case "nextOrClose" :
+
+ if ( instance.group.length > 1 ) {
+ instance.next();
+
+ } else {
+ instance.close( self.startEvent );
+ }
+
+ break;
+
+ case "zoom" :
+
+ if ( current.type == 'image' && ( current.isLoaded || current.$ghost ) ) {
+
+ if ( instance.canPan() ) {
+ instance.scaleToFit();
+
+ } else if ( instance.isScaledDown() ) {
+ instance.scaleToActual( tapX, tapY );
+
+ } else if ( instance.group.length < 2 ) {
+ instance.close( self.startEvent );
+ }
+ }
+
+ break;
+ }
+
+ };
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Skip if current slide is not in the center
+ if ( instance.isSliding ) {
+ return;
+ }
+
+ // Skip if clicked on the scrollbar
+ if ( tapX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ // Check where is clicked
+ if ( $target.is( '.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container' ) ) {
+ where = 'Outside';
+
+ } else if ( $target.is( '.fancybox-slide' ) ) {
+ where = 'Slide';
+
+ } else if ( instance.current.$content && instance.current.$content.has( e.target ).length ) {
+ where = 'Content';
+
+ } else {
+ return;
+ }
+
+ // Check if this is a double tap
+ if ( self.tapped ) {
+
+ // Stop previously created single tap
+ clearTimeout( self.tapped );
+ self.tapped = null;
+
+ // Skip if distance between taps is too big
+ if ( Math.abs( tapX - self.tapX ) > 50 || Math.abs( tapY - self.tapY ) > 50 || instance.isSliding ) {
+ return this;
+ }
+
+ // OK, now we assume that this is a double-tap
+ process( 'dblclick' + where );
+
+ } else {
+
+ // Single tap will be processed if user has not clicked second time within 300ms
+ // or there is no need to wait for double-tap
+ self.tapX = tapX;
+ self.tapY = tapY;
+
+ if ( current.opts[ 'dblclick' + where ] && current.opts[ 'dblclick' + where ] !== current.opts[ 'click' + where ] ) {
+ self.tapped = setTimeout(function() {
+ self.tapped = null;
+
+ process( 'click' + where );
+
+ }, 300);
+
+ } else {
+ process( 'click' + where );
+ }
+
+ }
+
+ return this;
+ };
+
+ $(document).on('onActivate.fb', function (e, instance) {
+ if ( instance && !instance.Guestures ) {
+ instance.Guestures = new Guestures( instance );
+ }
+ });
+
+ $(document).on('beforeClose.fb', function (e, instance) {
+ if ( instance && instance.Guestures ) {
+ instance.Guestures.destroy();
+ }
+ });
+
+
+}( window, document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// SlideShow
+// Enables slideshow functionality
+//
+// Example of usage:
+// $.fancybox.getInstance().SlideShow.start()
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ $.extend(true, $.fancybox.defaults, {
+ btnTpl : {
+ slideShow :
+ ''
+ },
+ slideShow : {
+ autoStart : false,
+ speed : 3000
+ }
+ });
+
+ var SlideShow = function( instance ) {
+ this.instance = instance;
+ this.init();
+ };
+
+ $.extend( SlideShow.prototype, {
+ timer : null,
+ isActive : false,
+ $button : null,
+
+ init : function() {
+ var self = this;
+
+ self.$button = self.instance.$refs.toolbar.find('[data-fancybox-play]').on('click', function() {
+ self.toggle();
+ });
+
+ if ( self.instance.group.length < 2 || !self.instance.group[ self.instance.currIndex ].opts.slideShow ) {
+ self.$button.hide();
+ }
+ },
+
+ set : function( force ) {
+ var self = this;
+
+ // Check if reached last element
+ if ( self.instance && self.instance.current && (force === true || self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
+ self.timer = setTimeout(function() {
+ if ( self.isActive ) {
+ self.instance.jumpTo( (self.instance.currIndex + 1) % self.instance.group.length );
+ }
+
+ }, self.instance.current.opts.slideShow.speed);
+
+ } else {
+ self.stop();
+ self.instance.idleSecondsCounter = 0;
+ self.instance.showControls();
+ }
+ },
+
+ clear : function() {
+ var self = this;
+
+ clearTimeout( self.timer );
+
+ self.timer = null;
+ },
+
+ start : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ if ( current ) {
+ self.isActive = true;
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_STOP )
+ .removeClass( 'fancybox-button--play' )
+ .addClass( 'fancybox-button--pause' );
+
+ self.set( true );
+ }
+ },
+
+ stop : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ self.clear();
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_START )
+ .removeClass( 'fancybox-button--pause' )
+ .addClass( 'fancybox-button--play' );
+
+ self.isActive = false;
+ },
+
+ toggle : function() {
+ var self = this;
+
+ if ( self.isActive ) {
+ self.stop();
+
+ } else {
+ self.start();
+ }
+ }
+
+ });
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ if ( instance && !instance.SlideShow ) {
+ instance.SlideShow = new SlideShow( instance );
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, current, firstRun) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( firstRun ) {
+
+ if ( SlideShow && current.opts.slideShow.autoStart ) {
+ SlideShow.start();
+ }
+
+ } else if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.clear();
+ }
+ },
+
+ 'afterShow.fb' : function(e, instance, current) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.set();
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var SlideShow = instance && instance.SlideShow;
+
+ // "P" or Spacebar
+ if ( SlideShow && current.opts.slideShow && ( keycode === 80 || keycode === 32 ) && !$(document.activeElement).is( 'button,a,input' ) ) {
+ keypress.preventDefault();
+
+ SlideShow.toggle();
+ }
+ },
+
+ 'beforeClose.fb onDeactivate.fb' : function(e, instance) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow ) {
+ SlideShow.stop();
+ }
+ }
+ });
+
+ // Page Visibility API to pause slideshow when window is not active
+ $(document).on("visibilitychange", function() {
+ var instance = $.fancybox.getInstance();
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ if ( document.hidden ) {
+ SlideShow.clear();
+
+ } else {
+ SlideShow.set();
+ }
+ }
+ });
+
+}( document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// FullScreen
+// Adds fullscreen functionality
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ // Collection of methods supported by user browser
+ var fn = (function () {
+
+ var fnMap = [
+ [
+ 'requestFullscreen',
+ 'exitFullscreen',
+ 'fullscreenElement',
+ 'fullscreenEnabled',
+ 'fullscreenchange',
+ 'fullscreenerror'
+ ],
+ // new WebKit
+ [
+ 'webkitRequestFullscreen',
+ 'webkitExitFullscreen',
+ 'webkitFullscreenElement',
+ 'webkitFullscreenEnabled',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ // old WebKit (Safari 5.1)
+ [
+ 'webkitRequestFullScreen',
+ 'webkitCancelFullScreen',
+ 'webkitCurrentFullScreenElement',
+ 'webkitCancelFullScreen',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ [
+ 'mozRequestFullScreen',
+ 'mozCancelFullScreen',
+ 'mozFullScreenElement',
+ 'mozFullScreenEnabled',
+ 'mozfullscreenchange',
+ 'mozfullscreenerror'
+ ],
+ [
+ 'msRequestFullscreen',
+ 'msExitFullscreen',
+ 'msFullscreenElement',
+ 'msFullscreenEnabled',
+ 'MSFullscreenChange',
+ 'MSFullscreenError'
+ ]
+ ];
+
+ var val;
+ var ret = {};
+ var i, j;
+
+ for ( i = 0; i < fnMap.length; i++ ) {
+ val = fnMap[ i ];
+
+ if ( val && val[ 1 ] in document ) {
+ for ( j = 0; j < val.length; j++ ) {
+ ret[ fnMap[ 0 ][ j ] ] = val[ j ];
+ }
+
+ return ret;
+ }
+ }
+
+ return false;
+ })();
+
+ // If browser does not have Full Screen API, then simply unset default button template and stop
+ if ( !fn ) {
+
+ if ( $ && $.fancybox ) {
+ $.fancybox.defaults.btnTpl.fullScreen = false;
+ }
+
+ return;
+ }
+
+ var FullScreen = {
+
+ request : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ elem[ fn.requestFullscreen ]( elem.ALLOW_KEYBOARD_INPUT );
+
+ },
+ exit : function () {
+
+ document[ fn.exitFullscreen ]();
+
+ },
+ toggle : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ if ( this.isFullscreen() ) {
+ this.exit();
+
+ } else {
+ this.request( elem );
+ }
+
+ },
+ isFullscreen : function() {
+
+ return Boolean( document[ fn.fullscreenElement ] );
+
+ },
+ enabled : function() {
+
+ return Boolean( document[ fn.fullscreenEnabled ] );
+
+ }
+ };
+
+ $.extend(true, $.fancybox.defaults, {
+ btnTpl : {
+ fullScreen :
+ ''
+ },
+ fullScreen : {
+ autoStart : false
+ }
+ });
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ var $container;
+
+ if ( instance && instance.group[ instance.currIndex ].opts.fullScreen ) {
+ $container = instance.$refs.container;
+
+ $container.on('click.fb-fullscreen', '[data-fancybox-fullscreen]', function(e) {
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ FullScreen.toggle( $container[ 0 ] );
+
+ });
+
+ if ( instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true ) {
+ FullScreen.request( $container[ 0 ] );
+ }
+
+ // Expose API
+ instance.FullScreen = FullScreen;
+
+ } else if ( instance ) {
+ instance.$refs.toolbar.find('[data-fancybox-fullscreen]').hide();
+ }
+
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+
+ // "P" or Spacebar
+ if ( instance && instance.FullScreen && keycode === 70 ) {
+ keypress.preventDefault();
+
+ instance.FullScreen.toggle( instance.$refs.container[ 0 ] );
+ }
+
+ },
+
+ 'beforeClose.fb' : function( instance ) {
+ if ( instance && instance.FullScreen ) {
+ FullScreen.exit();
+ }
+ }
+ });
+
+ $(document).on(fn.fullscreenchange, function() {
+ var isFullscreen = FullScreen.isFullscreen(),
+ instance = $.fancybox.getInstance();
+
+ if ( instance ) {
+
+ // If image is zooming, then force to stop and reposition properly
+ if ( instance.current && instance.current.type === 'image' && instance.isAnimating ) {
+ instance.current.$content.css( 'transition', 'none' );
+
+ instance.isAnimating = false;
+
+ instance.update( true, true, 0 );
+ }
+
+ instance.trigger( 'onFullscreenChange', isFullscreen );
+
+ instance.$refs.container.toggleClass( 'fancybox-is-fullscreen', isFullscreen );
+ }
+
+ });
+
+}( document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Thumbs
+// Displays thumbnails in a grid
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ // Make sure there are default values
+ $.fancybox.defaults = $.extend(true, {
+ btnTpl : {
+ thumbs :
+ ''
+ },
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true, // Hide thumbnail grid when closing animation starts
+ parentEl : '.fancybox-container', // Container is injected into this element
+ axis : 'y' // Vertical (y) or horizontal (x) scrolling
+ }
+ }, $.fancybox.defaults);
+
+ var FancyThumbs = function( instance ) {
+ this.init( instance );
+ };
+
+ $.extend( FancyThumbs.prototype, {
+
+ $button : null,
+ $grid : null,
+ $list : null,
+ isVisible : false,
+ isActive : false,
+
+ init : function( instance ) {
+ var self = this;
+
+ self.instance = instance;
+
+ instance.Thumbs = self;
+
+ // Enable thumbs if at least two group items have thumbnails
+ var first = instance.group[0],
+ second = instance.group[1];
+
+ self.opts = instance.group[ instance.currIndex ].opts.thumbs;
+
+ self.$button = instance.$refs.toolbar.find( '[data-fancybox-thumbs]' );
+
+ if ( self.opts && first && second && (
+ ( first.type == 'image' || first.opts.thumb || first.opts.$thumb ) &&
+ ( second.type == 'image' || second.opts.thumb || second.opts.$thumb )
+ )) {
+
+ self.$button.show().on('click', function() {
+ self.toggle();
+ });
+
+ self.isActive = true;
+
+ } else {
+ self.$button.hide();
+ }
+ },
+
+ create : function() {
+ var self = this,
+ instance = self.instance,
+ parentEl = self.opts.parentEl,
+ list,
+ src;
+
+ self.$grid = $('').appendTo( instance.$refs.container.find( parentEl ).addBack().filter( parentEl ) );
+
+ // Build list HTML
+ list = '';
+
+ $.each(instance.group, function( i, item ) {
+ src = item.opts.thumb || ( item.opts.$thumb ? item.opts.$thumb.attr( 'src' ) : null );
+
+ if ( !src && item.type === 'image' ) {
+ src = item.src;
+ }
+
+ if ( src && src.length ) {
+ list += '';
+ }
+ });
+
+ list += '
';
+
+ self.$list = $( list ).appendTo( self.$grid ).on('click', 'li', function() {
+ instance.jumpTo( $(this).data('index') );
+ });
+
+ self.$list.find( 'img' ).hide().one('load', function() {
+ var $parent = $(this).parent().removeClass( 'fancybox-thumbs-loading' ),
+ thumbWidth = $parent.outerWidth(),
+ thumbHeight = $parent.outerHeight(),
+ width,
+ height,
+ widthRatio,
+ heightRatio;
+
+ width = this.naturalWidth || this.width;
+ height = this.naturalHeight || this.height;
+
+ // Calculate thumbnail dimensions; center vertically and horizontally
+ widthRatio = width / thumbWidth;
+ heightRatio = height / thumbHeight;
+
+ if (widthRatio >= 1 && heightRatio >= 1) {
+ if (widthRatio > heightRatio) {
+ width = width / heightRatio;
+ height = thumbHeight;
+
+ } else {
+ width = thumbWidth;
+ height = height / widthRatio;
+ }
+ }
+
+ $(this).css({
+ width : Math.floor(width),
+ height : Math.floor(height),
+ 'margin-top' : height > thumbHeight ? ( Math.floor(thumbHeight * 0.3 - height * 0.3 ) ) : Math.floor(thumbHeight * 0.5 - height * 0.5 ),
+ 'margin-left' : Math.floor(thumbWidth * 0.5 - width * 0.5 )
+ }).show();
+
+ })
+ .each(function() {
+ this.src = $( this ).data( 'src' );
+ });
+
+ if ( self.opts.axis === 'x' ) {
+ self.$list.width( parseInt( self.$grid.css("padding-right") ) + ( instance.group.length * self.$list.children().eq(0).outerWidth(true) ) + 'px' );
+ }
+ },
+
+ focus : function( duration ) {
+ var self = this,
+ $list = self.$list,
+ thumb,
+ thumbPos;
+
+ if ( self.instance.current ) {
+ thumb = $list.children()
+ .removeClass( 'fancybox-thumbs-active' )
+ .filter('[data-index="' + self.instance.current.index + '"]')
+ .addClass('fancybox-thumbs-active');
+
+ thumbPos = thumb.position();
+
+ // Check if need to scroll to make current thumb visible
+ if ( self.opts.axis === 'y' && ( thumbPos.top < 0 || thumbPos.top > ( $list.height() - thumb.outerHeight() ) ) ) {
+ $list.stop().animate({ 'scrollTop' : $list.scrollTop() + thumbPos.top }, duration);
+
+ } else if ( self.opts.axis === 'x' && (
+ thumbPos.left < $list.parent().scrollLeft() ||
+ thumbPos.left > ( $list.parent().scrollLeft() + ( $list.parent().width() - thumb.outerWidth() ) )
+ )
+ ) {
+ $list.parent().stop().animate({ 'scrollLeft' : thumbPos.left }, duration);
+ }
+ }
+ },
+
+ update : function() {
+ this.instance.$refs.container.toggleClass( 'fancybox-show-thumbs', this.isVisible );
+
+ if ( this.isVisible ) {
+ if ( !this.$grid ) {
+ this.create();
+ }
+
+ this.instance.trigger( 'onThumbsShow' );
+
+ this.focus( 0 );
+
+ } else if ( this.$grid ) {
+ this.instance.trigger( 'onThumbsHide' );
+ }
+
+ // Update content position
+ this.instance.update();
+ },
+
+ hide : function() {
+ this.isVisible = false;
+ this.update();
+ },
+
+ show : function() {
+ this.isVisible = true;
+ this.update();
+ },
+
+ toggle : function() {
+ this.isVisible = !this.isVisible;
+ this.update();
+ }
+ });
+
+ $(document).on({
+
+ 'onInit.fb' : function(e, instance) {
+ var Thumbs;
+
+ if ( instance && !instance.Thumbs ) {
+ Thumbs = new FancyThumbs( instance );
+
+ if ( Thumbs.isActive && Thumbs.opts.autoStart === true ) {
+ Thumbs.show();
+ }
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, item, firstRun) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( Thumbs && Thumbs.isVisible ) {
+ Thumbs.focus( firstRun ? 0 : 250 );
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var Thumbs = instance && instance.Thumbs;
+
+ // "G"
+ if ( Thumbs && Thumbs.isActive && keycode === 71 ) {
+ keypress.preventDefault();
+
+ Thumbs.toggle();
+ }
+ },
+
+ 'beforeClose.fb' : function( e, instance ) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false ) {
+ Thumbs.$grid.hide();
+ }
+ }
+
+ });
+
+}(document, window.jQuery));
+
+//// ==========================================================================
+//
+// Share
+// Displays simple form for sharing current url
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ $.extend(true, $.fancybox.defaults, {
+ btnTpl : {
+ share :
+ ''
+ },
+ share : {
+ tpl :
+ '' +
+ '{{SHARE}}
' +
+ '' +
+ '' +
+ '' +
+ 'Facebook' +
+ '' +
+ '' +
+ '' +
+ 'Pinterest' +
+ '' +
+ '' +
+ '' +
+ 'Twitter' +
+ '' +
+ '
' +
+ '' +
+ ''
+ }
+ });
+
+ function escapeHtml(string) {
+ var entityMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/',
+ '`': '`',
+ '=': '='
+ };
+
+ return String(string).replace(/[&<>"'`=\/]/g, function (s) {
+ return entityMap[s];
+ });
+ }
+
+ $(document).on('click', '[data-fancybox-share]', function() {
+ var f = $.fancybox.getInstance(),
+ url,
+ tpl;
+
+ if ( f ) {
+ url = f.current.opts.hash === false ? f.current.src : window.location;
+ tpl = f.current.opts.share.tpl
+ .replace( /\{\{src\}\}/g, encodeURIComponent( url ) )
+ .replace( /\{\{src_raw\}\}/g, escapeHtml( url ) )
+ .replace( /\{\{descr\}\}/g, f.$caption ? encodeURIComponent( f.$caption.text() ) : '' );
+
+ $.fancybox.open({
+ src : f.translate( f, tpl ),
+ type : 'html',
+ opts : {
+ animationEffect : "fade",
+ animationDuration : 250
+ }
+ });
+ }
+
+ });
+
+}( document, window.jQuery || jQuery ));
+
+// ==========================================================================
+//
+// Hash
+// Enables linking to each modal
+//
+// ==========================================================================
+;(function (document, window, $) {
+ 'use strict';
+
+ // Simple $.escapeSelector polyfill (for jQuery prior v3)
+ if ( !$.escapeSelector ) {
+ $.escapeSelector = function( sel ) {
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
+ var fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ };
+
+ return ( sel + "" ).replace( rcssescape, fcssescape );
+ };
+ }
+
+ // Create new history entry only once
+ var shouldCreateHistory = true;
+
+ // Variable containing last hash value set by fancyBox
+ // It will be used to determine if fancyBox needs to close after hash change is detected
+ var currentHash = null;
+
+ // Throttling the history change
+ var timerID = null;
+
+ // Get info about gallery name and current index from url
+ function parseUrl() {
+ var hash = window.location.hash.substr( 1 );
+ var rez = hash.split( '-' );
+ var index = rez.length > 1 && /^\+?\d+$/.test( rez[ rez.length - 1 ] ) ? parseInt( rez.pop( -1 ), 10 ) || 1 : 1;
+ var gallery = rez.join( '-' );
+
+ // Index is starting from 1
+ if ( index < 1 ) {
+ index = 1;
+ }
+
+ return {
+ hash : hash,
+ index : index,
+ gallery : gallery
+ };
+ }
+
+ // Trigger click evnt on links to open new fancyBox instance
+ function triggerFromUrl( url ) {
+ var $el;
+
+ if ( url.gallery !== '' ) {
+
+ // If we can find element matching 'data-fancybox' atribute, then trigger click event for that ..
+ $el = $( "[data-fancybox='" + $.escapeSelector( url.gallery ) + "']" ).eq( url.index - 1 );
+
+ if ( !$el.length ) {
+ // .. if not, try finding element by ID
+ $el = $( "#" + $.escapeSelector( url.gallery ) + "" );
+ }
+
+ if ( $el.length ) {
+ shouldCreateHistory = false;
+
+ $el.trigger( 'click' );
+ }
+
+ }
+ }
+
+ // Get gallery name from current instance
+ function getGalleryID( instance ) {
+ var opts;
+
+ if ( !instance ) {
+ return false;
+ }
+
+ opts = instance.current ? instance.current.opts : instance.opts;
+
+ return opts.hash || ( opts.$orig ? opts.$orig.data( 'fancybox' ) : '' );
+ }
+
+ // Start when DOM becomes ready
+ $(function() {
+
+ // Check if user has disabled this module
+ if ( $.fancybox.defaults.hash === false ) {
+ return;
+ }
+
+ // Update hash when opening/closing fancyBox
+ $(document).on({
+ 'onInit.fb' : function( e, instance ) {
+ var url, gallery;
+
+ if ( instance.group[ instance.currIndex ].opts.hash === false ) {
+ return;
+ }
+
+ url = parseUrl();
+ gallery = getGalleryID( instance );
+
+ // Make sure gallery start index matches index from hash
+ if ( gallery && url.gallery && gallery == url.gallery ) {
+ instance.currIndex = url.index - 1;
+ }
+ },
+
+ 'beforeShow.fb' : function( e, instance, current ) {
+ var gallery;
+
+ if ( !current || current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGalleryID( instance );
+
+ // Update window hash
+ if ( gallery && gallery !== '' ) {
+
+ if ( window.location.hash.indexOf( gallery ) < 0 ) {
+ instance.opts.origHash = window.location.hash;
+ }
+
+ currentHash = gallery + ( instance.group.length > 1 ? '-' + ( current.index + 1 ) : '' );
+
+ if ( 'replaceState' in window.history ) {
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ timerID = setTimeout(function() {
+ window.history[ shouldCreateHistory ? 'pushState' : 'replaceState' ]( {} , document.title, window.location.pathname + window.location.search + '#' + currentHash );
+
+ timerID = null;
+
+ shouldCreateHistory = false;
+
+ }, 300);
+
+ } else {
+ window.location.hash = currentHash;
+ }
+
+ }
+
+ },
+
+ 'beforeClose.fb' : function( e, instance, current ) {
+ var gallery, origHash;
+
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ if ( current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGalleryID( instance );
+ origHash = instance && instance.opts.origHash ? instance.opts.origHash : '';
+
+ // Remove hash from location bar
+ if ( gallery && gallery !== '' ) {
+
+ if ( 'replaceState' in history ) {
+ window.history.replaceState( {} , document.title, window.location.pathname + window.location.search + origHash );
+
+ } else {
+ window.location.hash = origHash;
+
+ // Keep original scroll position
+ $( window ).scrollTop( instance.scrollTop ).scrollLeft( instance.scrollLeft );
+ }
+ }
+
+ currentHash = null;
+ }
+ });
+
+ // Check if need to close after url has changed
+ $(window).on('hashchange.fb', function() {
+ var url = parseUrl();
+
+ if ( $.fancybox.getInstance() ) {
+ if ( currentHash && currentHash !== url.gallery + '-' + url.index && !( url.index === 1 && currentHash == url.gallery ) ) {
+ currentHash = null;
+
+ $.fancybox.close();
+ }
+
+ } else if ( url.gallery !== '' ) {
+ triggerFromUrl( url );
+ }
+ });
+
+ // Check current hash and trigger click event on matching element to start fancyBox, if needed
+ setTimeout(function() {
+ triggerFromUrl( parseUrl() );
+ }, 50);
+ });
+
+}( document, window, window.jQuery || jQuery ));
diff --git a/source/lib/font-awesome/.bower.json b/source/lib/font-awesome/.bower.json
new file mode 100644
index 000000000..fb98b1d6d
--- /dev/null
+++ b/source/lib/font-awesome/.bower.json
@@ -0,0 +1,36 @@
+{
+ "name": "font-awesome",
+ "description": "Font Awesome",
+ "keywords": [],
+ "homepage": "http://fontawesome.io",
+ "dependencies": {},
+ "devDependencies": {},
+ "license": [
+ "OFL-1.1",
+ "MIT",
+ "CC-BY-3.0"
+ ],
+ "main": [
+ "less/font-awesome.less",
+ "scss/font-awesome.scss"
+ ],
+ "ignore": [
+ "*/.*",
+ "*.json",
+ "src",
+ "*.yml",
+ "Gemfile",
+ "Gemfile.lock",
+ "*.md"
+ ],
+ "version": "4.7.0",
+ "_release": "4.7.0",
+ "_resolution": {
+ "type": "version",
+ "tag": "v4.7.0",
+ "commit": "a3fe90fa5f6fac55d197f9cbd18e3f57dafb716c"
+ },
+ "_source": "https://github.com/FortAwesome/Font-Awesome.git",
+ "_target": "*",
+ "_originalSource": "fontawesome"
+}
\ No newline at end of file
diff --git a/source/lib/font-awesome/.gitignore b/source/lib/font-awesome/.gitignore
new file mode 100644
index 000000000..39c4f20b7
--- /dev/null
+++ b/source/lib/font-awesome/.gitignore
@@ -0,0 +1,33 @@
+*.pyc
+*.egg-info
+*.db
+*.db.old
+*.swp
+*.db-journal
+
+.coverage
+.DS_Store
+.installed.cfg
+_gh_pages/*
+
+.idea/*
+.svn/*
+src/website/static/*
+src/website/media/*
+
+bin
+cfcache
+develop-eggs
+dist
+downloads
+eggs
+parts
+tmp
+.sass-cache
+node_modules
+
+src/website/settingslocal.py
+stunnel.log
+
+.ruby-version
+.bundle
diff --git a/source/lib/font-awesome/.npmignore b/source/lib/font-awesome/.npmignore
new file mode 100644
index 000000000..54a691f81
--- /dev/null
+++ b/source/lib/font-awesome/.npmignore
@@ -0,0 +1,42 @@
+*.pyc
+*.egg-info
+*.db
+*.db.old
+*.swp
+*.db-journal
+
+.coverage
+.DS_Store
+.installed.cfg
+_gh_pages/*
+
+.idea/*
+.svn/*
+src/website/static/*
+src/website/media/*
+
+bin
+cfcache
+develop-eggs
+dist
+downloads
+eggs
+parts
+tmp
+.sass-cache
+node_modules
+
+src/website/settingslocal.py
+stunnel.log
+
+.ruby-version
+
+# don't need these in the npm package.
+src/
+_config.yml
+bower.json
+component.json
+composer.json
+CONTRIBUTING.md
+Gemfile
+Gemfile.lock
diff --git a/source/lib/font-awesome/HELP-US-OUT.txt b/source/lib/font-awesome/HELP-US-OUT.txt
new file mode 100644
index 000000000..83d083dd7
--- /dev/null
+++ b/source/lib/font-awesome/HELP-US-OUT.txt
@@ -0,0 +1,7 @@
+I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project,
+Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome,
+comprehensive icon sets or copy and paste your own.
+
+Please. Check it out.
+
+-Dave Gandy
diff --git a/source/lib/font-awesome/bower.json b/source/lib/font-awesome/bower.json
new file mode 100644
index 000000000..9e2112659
--- /dev/null
+++ b/source/lib/font-awesome/bower.json
@@ -0,0 +1,22 @@
+{
+ "name": "font-awesome",
+ "description": "Font Awesome",
+ "keywords": [],
+ "homepage": "http://fontawesome.io",
+ "dependencies": {},
+ "devDependencies": {},
+ "license": ["OFL-1.1", "MIT", "CC-BY-3.0"],
+ "main": [
+ "less/font-awesome.less",
+ "scss/font-awesome.scss"
+ ],
+ "ignore": [
+ "*/.*",
+ "*.json",
+ "src",
+ "*.yml",
+ "Gemfile",
+ "Gemfile.lock",
+ "*.md"
+ ]
+}
diff --git a/source/lib/font-awesome/css/font-awesome.css b/source/lib/font-awesome/css/font-awesome.css
new file mode 100644
index 000000000..ee906a819
--- /dev/null
+++ b/source/lib/font-awesome/css/font-awesome.css
@@ -0,0 +1,2337 @@
+/*!
+ * 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 PATH
+ * -------------------------- */
+@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;
+}
+/* makes the font 33% larger relative to the icon container */
+.fa-lg {
+ font-size: 1.33333333em;
+ line-height: 0.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: 0.14285714em;
+ text-align: center;
+}
+.fa-li.fa-lg {
+ left: -1.85714286em;
+}
+.fa-border {
+ padding: .2em .25em .15em;
+ border: solid 0.08em #eeeeee;
+ 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;
+}
+/* Deprecated as of 4.4.0 */
+.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: #ffffff;
+}
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+ readers do not read off random characters that represent icons */
+.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/source/lib/font-awesome/css/font-awesome.css.map b/source/lib/font-awesome/css/font-awesome.css.map
new file mode 100644
index 000000000..60763a864
--- /dev/null
+++ b/source/lib/font-awesome/css/font-awesome.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": ";;;;;;;AAGA,UAUC;EATC,WAAW,EAAE,aAAa;EAC1B,GAAG,EAAE,+CAAgE;EACrE,GAAG,EAAE,ySAAmG;EAKxG,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;ACTpB,GAAmB;EACjB,OAAO,EAAE,YAAY;EACrB,IAAI,EAAE,uCAAwD;EAC9D,SAAS,EAAE,OAAO;EAClB,cAAc,EAAE,IAAI;EACpB,sBAAsB,EAAE,WAAW;EACnC,uBAAuB,EAAE,SAAS;EAClC,SAAS,EAAE,eAAe;;;ACN5B,MAAsB;EACpB,SAAS,EAAE,SAAS;EACpB,WAAW,EAAE,MAAS;EACtB,cAAc,EAAE,IAAI;;AAEtB,MAAsB;EAAE,SAAS,EAAE,GAAG;;AACtC,MAAsB;EAAE,SAAS,EAAE,GAAG;;AACtC,MAAsB;EAAE,SAAS,EAAE,GAAG;;AACtC,MAAsB;EAAE,SAAS,EAAE,GAAG;;ACVtC,MAAsB;EACpB,KAAK,EAAE,SAAW;EAClB,UAAU,EAAE,MAAM;;ACDpB,MAAsB;EACpB,YAAY,EAAE,CAAC;EACf,WAAW,ECKU,SAAS;EDJ9B,eAAe,EAAE,IAAI;EACrB,WAAK;IAAE,QAAQ,EAAE,QAAQ;;AAE3B,MAAsB;EACpB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,UAAa;EACnB,KAAK,ECFgB,SAAS;EDG9B,GAAG,EAAE,SAAU;EACf,UAAU,EAAE,MAAM;EAClB,YAAuB;IACrB,IAAI,EAAE,UAA0B;;AEbpC,UAA0B;EACxB,OAAO,EAAE,gBAAgB;EACzB,MAAM,EAAE,iBAA4B;EACpC,aAAa,EAAE,IAAI;;AAGrB,WAAY;EAAE,KAAK,EAAE,KAAK;;AAC1B,UAAW;EAAE,KAAK,EAAE,IAAI;;AAGtB,aAAY;EAAE,YAAY,EAAE,IAAI;AAChC,cAAa;EAAE,WAAW,EAAE,IAAI;;ACXlC,QAAwB;EACtB,iBAAiB,EAAE,0BAA0B;EACrC,SAAS,EAAE,0BAA0B;;AAG/C,SAAyB;EACvB,iBAAiB,EAAE,4BAA4B;EACvC,SAAS,EAAE,4BAA4B;;AAGjD,0BASC;EARC,EAAG;IACD,iBAAiB,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;EAEjC,IAAK;IACH,iBAAiB,EAAE,cAAc;IACzB,SAAS,EAAE,cAAc;AAIrC,kBASC;EARC,EAAG;IACD,iBAAiB,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;EAEjC,IAAK;IACH,iBAAiB,EAAE,cAAc;IACzB,SAAS,EAAE,cAAc;AC5BrC,aAA8B;ECY5B,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,aAAgB;EAC/B,aAAa,EAAE,aAAgB;EAC3B,SAAS,EAAE,aAAgB;;ADdrC,cAA8B;ECW5B,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,cAAgB;EAC/B,aAAa,EAAE,cAAgB;EAC3B,SAAS,EAAE,cAAgB;;ADbrC,cAA8B;ECU5B,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,cAAgB;EAC/B,aAAa,EAAE,cAAgB;EAC3B,SAAS,EAAE,cAAgB;;ADXrC,mBAAmC;ECejC,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,YAAoB;EACnC,aAAa,EAAE,YAAoB;EAC/B,SAAS,EAAE,YAAoB;;ADjBzC,iBAAmC;ECcjC,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,YAAoB;EACnC,aAAa,EAAE,YAAoB;EAC/B,SAAS,EAAE,YAAoB;;ADZzC;;;;uBAIuC;EACrC,MAAM,EAAE,IAAI;;AEfd,SAAyB;EACvB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,GAAG;EACX,WAAW,EAAE,GAAG;EAChB,cAAc,EAAE,MAAM;;AAExB,0BAAyD;EACvD,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;;AAEpB,YAA4B;EAAE,WAAW,EAAE,OAAO;;AAClD,YAA4B;EAAE,SAAS,EAAE,GAAG;;AAC5C,WAA2B;EAAE,KAAK,ELVZ,IAAI;;;;AMN1B,gBAAgC;EAAE,OAAO,ENoQ1B,GAAO;;AMnQtB,gBAAgC;EAAE,OAAO,EN0W1B,GAAO;;AMzWtB,iBAAiC;EAAE,OAAO,ENmb1B,GAAO;;AMlbvB,qBAAqC;EAAE,OAAO,ENmL1B,GAAO;;AMlL3B,gBAAgC;EAAE,OAAO,ENkR1B,GAAO;;AMjRtB,eAA+B;EAAE,OAAO,ENke1B,GAAO;;AMjerB,iBAAiC;EAAE,OAAO,ENse1B,GAAO;;AMrevB,eAA+B;EAAE,OAAO,EN+iB1B,GAAO;;AM9iBrB,eAA+B;EAAE,OAAO,ENyN1B,GAAO;;AMxNrB,mBAAmC;EAAE,OAAO,ENggB1B,GAAO;;AM/fzB,aAA6B;EAAE,OAAO,EN8f1B,GAAO;;AM7fnB,kBAAkC;EAAE,OAAO,EN+f1B,GAAO;;AM9fxB,gBAAgC;EAAE,OAAO,ENoG1B,GAAO;;AMnGtB;;gBAEgC;EAAE,OAAO,ENkgB1B,GAAO;;AMjgBtB,sBAAsC;EAAE,OAAO,ENua1B,GAAO;;AMta5B,uBAAuC;EAAE,OAAO,ENqa1B,GAAO;;AMpa7B,oBAAoC;EAAE,OAAO,EN+X1B,GAAO;;AM9X1B,iBAAiC;EAAE,OAAO,ENsb1B,GAAO;;AMrbvB;cAC8B;EAAE,OAAO,ENwH1B,GAAO;;AMvHpB,kBAAkC;EAAE,OAAO,ENygB1B,GAAO;;AMxgBxB,eAA+B;EAAE,OAAO,ENmQ1B,GAAO;;AMlQrB,iBAAiC;EAAE,OAAO,EN6L1B,GAAO;;AM5LvB,kBAAkC;EAAE,OAAO,EN0G1B,GAAO;;AMzGxB,eAA+B;EAAE,OAAO,EN+Y1B,GAAO;;AM9YrB,mBAAmC;EAAE,OAAO,ENiJ1B,GAAO;;AMhJzB,8BAA8C;EAAE,OAAO,ENI1B,GAAO;;AMHpC,4BAA4C;EAAE,OAAO,ENM1B,GAAO;;AMLlC,gBAAgC;EAAE,OAAO,ENkQ1B,GAAO;;AMjQtB,wBAAwC;EAAE,OAAO,EN4W1B,GAAO;;AM3W9B;iBACiC;EAAE,OAAO,ENmY1B,GAAO;;AMlYvB,kBAAkC;EAAE,OAAO,EN8X1B,GAAO;;AM7XxB,mBAAmC;EAAE,OAAO,ENiS1B,GAAO;;AMhSzB,eAA+B;EAAE,OAAO,ENoS1B,GAAO;;AMnSrB,eAA+B;EAAE,OAAO,ENgM1B,GAAO;;AM/LrB,qBAAqC;EAAE,OAAO,EN+O1B,GAAO;;AM9O3B,qBAAqC;EAAE,OAAO,EN8hB1B,GAAO;;AM7hB3B,sBAAsC;EAAE,OAAO,EN4hB1B,GAAO;;AM3hB5B,oBAAoC;EAAE,OAAO,EN6hB1B,GAAO;;AM5hB1B,iBAAiC;EAAE,OAAO,EN2W1B,GAAO;;AM1WvB,kBAAkC;EAAE,OAAO,ENW1B,GAAO;;AMVxB,cAA8B;EAAE,OAAO,ENod1B,GAAO;;AMndpB,eAA+B;EAAE,OAAO,ENod1B,GAAO;;AMndrB,eAA+B;EAAE,OAAO,EN2B1B,GAAO;;AM1BrB,mBAAmC;EAAE,OAAO,EN2B1B,GAAO;;AM1BzB,gBAAgC;EAAE,OAAO,ENkW1B,GAAO;;AMjWtB,iBAAiC;EAAE,OAAO,ENwC1B,GAAO;;AMvCvB,eAA+B;EAAE,OAAO,EN8L1B,GAAO;;AM7LrB,eAA+B;EAAE,OAAO,ENmB1B,GAAO;;AMlBrB,iBAAiC;EAAE,OAAO,ENoP1B,GAAO;;AMnPvB,sBAAsC;EAAE,OAAO,ENid1B,GAAO;;AMhd5B,qBAAqC;EAAE,OAAO,ENid1B,GAAO;;AMhd3B,qBAAqC;EAAE,OAAO,EN1C1B,GAAO;;AM2C3B,uBAAuC;EAAE,OAAO,EN7C1B,GAAO;;AM8C7B,sBAAsC;EAAE,OAAO,EN3C1B,GAAO;;AM4C5B,wBAAwC;EAAE,OAAO,EN9C1B,GAAO;;AM+C9B,eAA+B;EAAE,OAAO,ENwQ1B,GAAO;;AMvQrB;kBACkC;EAAE,OAAO,ENmT1B,GAAO;;AMlTxB,iBAAiC;EAAE,OAAO,ENmO1B,GAAO;;AMlOvB,uBAAuC;EAAE,OAAO,ENigB1B,GAAO;;AMhgB7B;;oBAEoC;EAAE,OAAO,EN+T1B,GAAO;;AM9T1B,iBAAiC;EAAE,OAAO,ENwT1B,GAAO;;AMvTvB,qBAAqC;EAAE,OAAO,EN+Q1B,GAAO;;AM9Q3B,iBAAiC;EAAE,OAAO,EN5D1B,GAAO;;AM6DvB,eAA+B;EAAE,OAAO,EN8c1B,GAAO;;AM7crB;0BAC0C;EAAE,OAAO,ENqT1B,GAAO;;AMpThC,yBAAyC;EAAE,OAAO,ENuX1B,GAAO;;AMtX/B,yBAAyC;EAAE,OAAO,EN0C1B,GAAO;;AMzC/B,iBAAiC;EAAE,OAAO,ENjC1B,GAAO;;AMkCvB,wBAAwC;EAAE,OAAO,ENma1B,GAAO;;AMla9B,wBAAwC;EAAE,OAAO,EN4H1B,GAAO;;AM3H9B,mBAAmC;EAAE,OAAO,EN7B1B,GAAO;;AM8BzB,eAA+B;EAAE,OAAO,EN0T1B,GAAO;;AMzTrB,gBAAgC;EAAE,OAAO,ENwS1B,GAAO;;AMvStB,eAA+B;EAAE,OAAO,ENia1B,GAAO;;AMharB,kBAAkC;EAAE,OAAO,ENgK1B,GAAO;;AM/JxB,uBAAuC;EAAE,OAAO,ENuH1B,GAAO;;AMtH7B,uBAAuC;EAAE,OAAO,EN4Z1B,GAAO;;AM3Z7B,gBAAgC;EAAE,OAAO,EN4F1B,GAAO;;AM3FtB,uBAAuC;EAAE,OAAO,ENoC1B,GAAO;;AMnC7B,wBAAwC;EAAE,OAAO,ENoC1B,GAAO;;AMnC9B,sBAAsC;EAAE,OAAO,ENsT1B,GAAO;;AMrT5B,uBAAuC;EAAE,OAAO,ENyQ1B,GAAO;;AMxQ7B,uBAAuC;EAAE,OAAO,ENwb1B,GAAO;;AMvb7B,uBAAuC;EAAE,OAAO,ENsB1B,GAAO;;AMrB7B,0BAA0C;EAAE,OAAO,EN2T1B,GAAO;;AM1ThC,sBAAsC;EAAE,OAAO,ENsM1B,GAAO;;AMrM5B,qBAAqC;EAAE,OAAO,EN6D1B,GAAO;;AM5D3B,yBAAyC;EAAE,OAAO,ENob1B,GAAO;;AMnb/B,yBAAyC;EAAE,OAAO,ENkB1B,GAAO;;AMjB/B,cAA8B;EAAE,OAAO,EN/C1B,GAAO;;AMgDpB,qBAAqC;EAAE,OAAO,EN3D1B,GAAO;;AM4D3B,sBAAsC;EAAE,OAAO,EN3D1B,GAAO;;AM4D5B,mBAAmC;EAAE,OAAO,EN3D1B,GAAO;;AM4DzB,qBAAqC;EAAE,OAAO,EN/D1B,GAAO;;AMgE3B;gBACgC;EAAE,OAAO,ENqV1B,GAAO;;AMpVtB,iBAAiC;EAAE,OAAO,ENuF1B,GAAO;;AMtFvB,mBAAmC;EAAE,OAAO,EN4C1B,GAAO;;AM3CzB,eAA+B;EAAE,OAAO,ENmS1B,GAAO;;AMlSrB,gBAAgC;EAAE,OAAO,ENsP1B,GAAO;;AMrPtB,mBAAmC;EAAE,OAAO,EN9D1B,GAAO;;AM+DzB,6BAA6C;EAAE,OAAO,ENgF1B,GAAO;;AM/EnC,eAA+B;EAAE,OAAO,EN+I1B,GAAO;;AM9IrB,eAA+B;EAAE,OAAO,ENoM1B,GAAO;;AMnMrB,eAA+B;EAAE,OAAO,ENmH1B,GAAO;;AMlHrB,cAA8B;EAAE,OAAO,ENiF1B,GAAO;;AMhFpB,oBAAoC;EAAE,OAAO,ENiF1B,GAAO;;AMhF1B;+BAC+C;EAAE,OAAO,EN0E1B,GAAO;;AMzErC,gBAAgC;EAAE,OAAO,ENmR1B,GAAO;;AMlRtB,mBAAmC;EAAE,OAAO,EN/B1B,GAAO;;AMgCzB,iBAAiC;EAAE,OAAO,ENoS1B,GAAO;;AMnSvB,kBAAkC;EAAE,OAAO,ENwB1B,GAAO;;AMvBxB,iBAAiC;EAAE,OAAO,ENqN1B,GAAO;;AMpNvB,qBAAqC;EAAE,OAAO,ENE1B,GAAO;;AMD3B,uBAAuC;EAAE,OAAO,ENF1B,GAAO;;AMG7B,kBAAkC;EAAE,OAAO,EN2S1B,GAAO;;AM1SxB,wBAAwC;EAAE,OAAO,ENyU1B,GAAO;;AMxU9B,iBAAiC;EAAE,OAAO,EN8G1B,GAAO;;AM7GvB,sBAAsC;EAAE,OAAO,EN+G1B,GAAO;;AM9G5B,mBAAmC;EAAE,OAAO,ENnF1B,GAAO;;AMoFzB,mBAAmC;EAAE,OAAO,ENrF1B,GAAO;;AMsFzB;oBACoC;EAAE,OAAO,EN/E1B,GAAO;;AMgF1B,yBAAyC;EAAE,OAAO,ENua1B,GAAO;;AMta/B,0BAA0C;EAAE,OAAO,ENmE1B,GAAO;;AMlEhC,uBAAuC;EAAE,OAAO,EN5C1B,GAAO;;AM6C7B,cAA8B;EAAE,OAAO,ENqK1B,GAAO;;AMpKpB;eAC+B;EAAE,OAAO,ENK1B,GAAO;;AMJrB,mBAAmC;EAAE,OAAO,ENQ1B,GAAO;;AMPzB,sBAAsC;EAAE,OAAO,ENmY1B,GAAO;;AMlY5B,wBAAwC;EAAE,OAAO,ENiY1B,GAAO;;AMhY9B,oBAAoC;EAAE,OAAO,EN2V1B,GAAO;;AM1V1B,kBAAkC;EAAE,OAAO,ENyI1B,GAAO;;AMxIxB,mBAAmC;EAAE,OAAO,ENyT1B,GAAO;;AMxTzB,0BAA0C;EAAE,OAAO,ENiL1B,GAAO;;AMhLhC,qBAAqC;EAAE,OAAO,EN0X1B,GAAO;;AMzX3B,wBAAwC;EAAE,OAAO,EN8C1B,GAAO;;AM7C9B,kBAAkC;EAAE,OAAO,ENoT1B,GAAO;;AMnTxB,iBAAiC;EAAE,OAAO,EN8Y1B,GAAO;;AM7YvB,wBAAwC;EAAE,OAAO,EN6G1B,GAAO;;AM5G9B,iBAAiC;EAAE,OAAO,EN8Z1B,GAAO;;AM7ZvB,kBAAkC;EAAE,OAAO,EN+J1B,GAAO;;AM9JxB,gBAAgC;EAAE,OAAO,ENsO1B,GAAO;;AMrOtB,mBAAmC;EAAE,OAAO,EN2U1B,GAAO;;AM1UzB,qBAAqC;EAAE,OAAO,EN/E1B,GAAO;;AMgF3B,uBAAuC;EAAE,OAAO,ENoO1B,GAAO;;AMnO7B,kBAAkC;EAAE,OAAO,EN8Y1B,GAAO;;AM7YxB;mBACmC;EAAE,OAAO,ENuC1B,GAAO;;AMtCzB,iBAAiC;EAAE,OAAO,ENiG1B,GAAO;;AMhGvB,iBAAiC;EAAE,OAAO,ENiZ1B,GAAO;;AMhZvB,sBAAsC;EAAE,OAAO,ENR1B,GAAO;;AMS5B,cAA8B;EAAE,OAAO,EN4Q1B,GAAO;;AM3QpB,gBAAgC;EAAE,OAAO,ENgH1B,GAAO;;AM/GtB,mBAAmC;EAAE,OAAO,ENnF1B,GAAO;;AMoFzB,eAA+B;EAAE,OAAO,ENzG1B,GAAO;;AM0GrB,sBAAsC;EAAE,OAAO,ENzD1B,GAAO;;AM0D5B,uBAAuC;EAAE,OAAO,EN0G1B,GAAO;;AMzG7B,sBAAsC;EAAE,OAAO,ENwG1B,GAAO;;AMvG5B,oBAAoC;EAAE,OAAO,ENyG1B,GAAO;;AMxG1B,sBAAsC;EAAE,OAAO,ENqG1B,GAAO;;AMpG5B,4BAA4C;EAAE,OAAO,EN5I1B,GAAO;;AM6IlC,6BAA6C;EAAE,OAAO,ENxI1B,GAAO;;AMyInC,0BAA0C;EAAE,OAAO,ENxI1B,GAAO;;AMyIhC,4BAA4C;EAAE,OAAO,ENhJ1B,GAAO;;AMiJlC,gBAAgC;EAAE,OAAO,ENsF1B,GAAO;;AMrFtB,iBAAiC;EAAE,OAAO,ENia1B,GAAO;;AMhavB,gBAAgC;EAAE,OAAO,ENiV1B,GAAO;;AMhVtB,iBAAiC;EAAE,OAAO,ENgD1B,GAAO;;AM/CvB,oBAAoC;EAAE,OAAO,ENvG1B,GAAO;;AMwG1B,qBAAqC;EAAE,OAAO,ENzI1B,GAAO;;AM0I3B;gBACgC;EAAE,OAAO,ENqY1B,GAAO;;AMpYtB;eAC+B;EAAE,OAAO,ENuI1B,GAAO;;AMtIrB,gBAAgC;EAAE,OAAO,ENpD1B,GAAO;;AMqDtB,gBAAgC;EAAE,OAAO,EN+C1B,GAAO;;AM9CtB;mBACmC;EAAE,OAAO,ENwP1B,GAAO;;AMvPzB;kBACkC;EAAE,OAAO,ENkC1B,GAAO;;AMjCxB,oBAAoC;EAAE,OAAO,ENsL1B,GAAO;;AMrL1B;mBACmC;EAAE,OAAO,EN0C1B,GAAO;;AMzCzB,iBAAiC;EAAE,OAAO,ENiS1B,GAAO;;AMhSvB;;eAE+B;EAAE,OAAO,EN9I1B,GAAO;;AM+IrB,kBAAkC;EAAE,OAAO,ENgI1B,GAAO;;AM/HxB,kBAAkC;EAAE,OAAO,EN8H1B,GAAO;;AM7HxB,wBAAwC;EAAE,OAAO,EN4S1B,GAAO;;AM3S9B,oBAAoC;EAAE,OAAO,ENoW1B,GAAO;;AMnW1B,gBAAgC;EAAE,OAAO,ENmT1B,GAAO;;AMlTtB,gBAAgC;EAAE,OAAO,ENkI1B,GAAO;;AMjItB,gBAAgC;EAAE,OAAO,ENuV1B,GAAO;;AMtVtB,oBAAoC;EAAE,OAAO,ENwL1B,GAAO;;AMvL1B,2BAA2C;EAAE,OAAO,ENyL1B,GAAO;;AMxLjC,6BAA6C;EAAE,OAAO,ENyD1B,GAAO;;AMxDnC,sBAAsC;EAAE,OAAO,ENuD1B,GAAO;;AMtD5B,gBAAgC;EAAE,OAAO,ENsJ1B,GAAO;;AMrJtB,qBAAqC;EAAE,OAAO,ENtH1B,GAAO;;AMuH3B,mBAAmC;EAAE,OAAO,ENhH1B,GAAO;;AMiHzB,qBAAqC;EAAE,OAAO,ENvH1B,GAAO;;AMwH3B,sBAAsC;EAAE,OAAO,ENvH1B,GAAO;;AMwH5B,kBAAkC;EAAE,OAAO,ENvE1B,GAAO;;AMwExB;eAC+B;EAAE,OAAO,EN2P1B,GAAO;;AM1PrB;oBACoC;EAAE,OAAO,EN+P1B,GAAO;;AM9P1B;mBACmC;EAAE,OAAO,EN4P1B,GAAO;;AM3PzB,mBAAmC;EAAE,OAAO,ENxC1B,GAAO;;AMyCzB,mBAAmC;EAAE,OAAO,ENkG1B,GAAO;;AMjGzB;eAC+B;EAAE,OAAO,EN8U1B,GAAO;;AM7UrB;gBACgC;EAAE,OAAO,ENqB1B,GAAO;;AMpBtB;qBACqC;EAAE,OAAO,EN2R1B,GAAO;;AM1R3B,oBAAoC;EAAE,OAAO,ENpF1B,GAAO;;AMqF1B,qBAAqC;EAAE,OAAO,ENnF1B,GAAO;;AMoF3B;eAC+B;EAAE,OAAO,ENjK1B,GAAO;;AMkKrB,kBAAkC;EAAE,OAAO,ENkO1B,GAAO;;AMjOxB,mBAAmC;EAAE,OAAO,ENkU1B,GAAO;;AMjUzB;oBACoC;EAAE,OAAO,EN1G1B,GAAO;;AM2G1B,sBAAsC;EAAE,OAAO,ENgF1B,GAAO;;AM/E5B,mBAAmC;EAAE,OAAO,ENnD1B,GAAO;;AMoDzB,yBAAyC;EAAE,OAAO,ENzG1B,GAAO;;AM0G/B,uBAAuC;EAAE,OAAO,ENzG1B,GAAO;;AM0G7B,kBAAkC;EAAE,OAAO,ENsU1B,GAAO;;AMrUxB,sBAAsC;EAAE,OAAO,EN+P1B,GAAO;;AM9P5B,mBAAmC;EAAE,OAAO,ENsQ1B,GAAO;;AMrQzB,iBAAiC;EAAE,OAAO,ENvL1B,GAAO;;AMwLvB,iBAAiC;EAAE,OAAO,ENzG1B,GAAO;;AM0GvB,kBAAkC;EAAE,OAAO,ENtF1B,GAAO;;AMuFxB,sBAAsC;EAAE,OAAO,EN3B1B,GAAO;;AM4B5B,qBAAqC;EAAE,OAAO,ENxK1B,GAAO;;AMyK3B,qBAAqC;EAAE,OAAO,ENkC1B,GAAO;;AMjC3B,oBAAoC;EAAE,OAAO,EN3O1B,GAAO;;AM4O1B,iBAAiC;EAAE,OAAO,ENiG1B,GAAO;;AMhGvB,sBAAsC;EAAE,OAAO,EN/C1B,GAAO;;AMgD5B,eAA+B;EAAE,OAAO,ENpM1B,GAAO;;AMqMrB,mBAAmC;EAAE,OAAO,ENe1B,GAAO;;AMdzB,sBAAsC;EAAE,OAAO,ENgJ1B,GAAO;;AM/I5B,4BAA4C;EAAE,OAAO,EN5O1B,GAAO;;AM6OlC,6BAA6C;EAAE,OAAO,EN5O1B,GAAO;;AM6OnC,0BAA0C;EAAE,OAAO,EN5O1B,GAAO;;AM6OhC,4BAA4C;EAAE,OAAO,ENhP1B,GAAO;;AMiPlC,qBAAqC;EAAE,OAAO,EN5O1B,GAAO;;AM6O3B,sBAAsC;EAAE,OAAO,EN5O1B,GAAO;;AM6O5B,mBAAmC;EAAE,OAAO,EN5O1B,GAAO;;AM6OzB,qBAAqC;EAAE,OAAO,ENhP1B,GAAO;;AMiP3B,kBAAkC;EAAE,OAAO,ENlG1B,GAAO;;AMmGxB,iBAAiC;EAAE,OAAO,ENuC1B,GAAO;;AMtCvB,iBAAiC;EAAE,OAAO,ENoP1B,GAAO;;AMnPvB;iBACiC;EAAE,OAAO,ENyF1B,GAAO;;AMxFvB,mBAAmC;EAAE,OAAO,EN9I1B,GAAO;;AM+IzB,qBAAqC;EAAE,OAAO,EN0I1B,GAAO;;AMzI3B,sBAAsC;EAAE,OAAO,EN0I1B,GAAO;;AMzI5B,kBAAkC;EAAE,OAAO,ENgN1B,GAAO;;AM/MxB,iBAAiC;EAAE,OAAO,ENnJ1B,GAAO;;AMoJvB;gBACgC;EAAE,OAAO,ENkJ1B,GAAO;;AMjJtB,qBAAqC;EAAE,OAAO,ENnB1B,GAAO;;AMoB3B,mBAAmC;EAAE,OAAO,ENxC1B,GAAO;;AMyCzB,wBAAwC;EAAE,OAAO,ENvC1B,GAAO;;AMwC9B,kBAAkC;EAAE,OAAO,EN0L1B,GAAO;;AMzLxB,kBAAkC;EAAE,OAAO,ENpC1B,GAAO;;AMqCxB,gBAAgC;EAAE,OAAO,ENoE1B,GAAO;;AMnEtB,kBAAkC;EAAE,OAAO,ENpC1B,GAAO;;AMqCxB,qBAAqC;EAAE,OAAO,ENkB1B,GAAO;;AMjB3B,iBAAiC;EAAE,OAAO,ENrD1B,GAAO;;AMsDvB,yBAAyC;EAAE,OAAO,ENvD1B,GAAO;;AMwD/B,mBAAmC;EAAE,OAAO,ENuO1B,GAAO;;AMtOzB,eAA+B;EAAE,OAAO,ENtJ1B,GAAO;;AMuJrB;oBACoC;EAAE,OAAO,ENqI1B,GAAO;;AMpI1B;;sBAEsC;EAAE,OAAO,ENuM1B,GAAO;;AMtM5B,yBAAyC;EAAE,OAAO,ENkC1B,GAAO;;AMjC/B,eAA+B;EAAE,OAAO,EN5I1B,GAAO;;AM6IrB,oBAAoC;EAAE,OAAO,EN7J1B,GAAO;;AM8J1B;uBACuC;EAAE,OAAO,EN1L1B,GAAO;;AM2L7B,mBAAmC;EAAE,OAAO,EN4G1B,GAAO;;AM3GzB,eAA+B;EAAE,OAAO,ENT1B,GAAO;;AMUrB,sBAAsC;EAAE,OAAO,ENhH1B,GAAO;;AMiH5B,sBAAsC;EAAE,OAAO,EN8M1B,GAAO;;AM7M5B,oBAAoC;EAAE,OAAO,ENyM1B,GAAO;;AMxM1B,iBAAiC;EAAE,OAAO,ENvH1B,GAAO;;AMwHvB,uBAAuC;EAAE,OAAO,ENmG1B,GAAO;;AMlG7B,qBAAqC;EAAE,OAAO,EN8C1B,GAAO;;AM7C3B,2BAA2C;EAAE,OAAO,EN8C1B,GAAO;;AM7CjC,iBAAiC;EAAE,OAAO,ENgJ1B,GAAO;;AM/IvB,qBAAqC;EAAE,OAAO,EN5N1B,GAAO;;AM6N3B,4BAA4C;EAAE,OAAO,ENjF1B,GAAO;;AMkFlC,iBAAiC;EAAE,OAAO,ENoH1B,GAAO;;AMnHvB,iBAAiC;EAAE,OAAO,ENkC1B,GAAO;;AMjCvB,8BAA8C;EAAE,OAAO,ENlM1B,GAAO;;AMmMpC,+BAA+C;EAAE,OAAO,ENlM1B,GAAO;;AMmMrC,4BAA4C;EAAE,OAAO,ENlM1B,GAAO;;AMmMlC,8BAA8C;EAAE,OAAO,ENtM1B,GAAO;;AMuMpC,gBAAgC;EAAE,OAAO,EN/B1B,GAAO;;AMgCtB,eAA+B;EAAE,OAAO,ENjK1B,GAAO;;AMkKrB,iBAAiC;EAAE,OAAO,EN9S1B,GAAO;;AM+SvB,qBAAqC;EAAE,OAAO,ENmP1B,GAAO;;AMlP3B,mBAAmC;EAAE,OAAO,EN9O1B,GAAO;;AM+OzB,qBAAqC;EAAE,OAAO,EN/I1B,GAAO;;AMgJ3B,qBAAqC;EAAE,OAAO,EN/I1B,GAAO;;AMgJ3B,qBAAqC;EAAE,OAAO,EN4G1B,GAAO;;AM3G3B,sBAAsC;EAAE,OAAO,ENsE1B,GAAO;;AMrE5B,iBAAiC;EAAE,OAAO,EN2M1B,GAAO;;AM1MvB,uBAAuC;EAAE,OAAO,EN6B1B,GAAO;;AM5B7B,yBAAyC;EAAE,OAAO,EN6B1B,GAAO;;AM5B/B,mBAAmC;EAAE,OAAO,ENhB1B,GAAO;;AMiBzB,qBAAqC;EAAE,OAAO,ENlB1B,GAAO;;AMmB3B,uBAAuC;EAAE,OAAO,ENvN1B,GAAO;;AMwN7B,wBAAwC;EAAE,OAAO,ENiD1B,GAAO;;AMhD9B,+BAA+C;EAAE,OAAO,EN3I1B,GAAO;;AM4IrC,uBAAuC;EAAE,OAAO,ENkH1B,GAAO;;AMjH7B,kBAAkC;EAAE,OAAO,EN1L1B,GAAO;;AM2LxB;8BAC8C;EAAE,OAAO,ENjP1B,GAAO;;AMkPpC;4BAC4C;EAAE,OAAO,ENhP1B,GAAO;;AMiPlC;+BAC+C;EAAE,OAAO,ENnP1B,GAAO;;AMoPrC;cAC8B;EAAE,OAAO,EN7J1B,GAAO;;AM8JpB,cAA8B;EAAE,OAAO,EN/F1B,GAAO;;AMgGpB;cAC8B;EAAE,OAAO,EN4N1B,GAAO;;AM3NpB;cAC8B;EAAE,OAAO,ENvD1B,GAAO;;AMwDpB;;;cAG8B;EAAE,OAAO,ENrD1B,GAAO;;AMsDpB;;cAE8B;EAAE,OAAO,EN8E1B,GAAO;;AM7EpB;cAC8B;EAAE,OAAO,ENtD1B,GAAO;;AMuDpB;cAC8B;EAAE,OAAO,ENzR1B,GAAO;;AM0RpB,eAA+B;EAAE,OAAO,ENzJ1B,GAAO;;AM0JrB,oBAAoC;EAAE,OAAO,EN7I1B,GAAO;;AM8I1B,yBAAyC;EAAE,OAAO,EN2G1B,GAAO;;AM1G/B,0BAA0C;EAAE,OAAO,EN2G1B,GAAO;;AM1GhC,0BAA0C;EAAE,OAAO,EN2G1B,GAAO;;AM1GhC,2BAA2C;EAAE,OAAO,EN2G1B,GAAO;;AM1GjC,2BAA2C;EAAE,OAAO,EN8G1B,GAAO;;AM7GjC,4BAA4C;EAAE,OAAO,EN8G1B,GAAO;;AM7GlC,oBAAoC;EAAE,OAAO,ENgK1B,GAAO;;AM/J1B,sBAAsC;EAAE,OAAO,EN4J1B,GAAO;;AM3J5B,yBAAyC;EAAE,OAAO,ENwO1B,GAAO;;AMvO/B,kBAAkC;EAAE,OAAO,ENqO1B,GAAO;;AMpOxB,eAA+B;EAAE,OAAO,EN+N1B,GAAO;;AM9NrB,sBAAsC;EAAE,OAAO,EN+N1B,GAAO;;AM9N5B,uBAAuC;EAAE,OAAO,ENmO1B,GAAO;;AMlO7B,kBAAkC;EAAE,OAAO,ENxM1B,GAAO;;AMyMxB,yBAAyC;EAAE,OAAO,EN+G1B,GAAO;;AM9G/B,oBAAoC;EAAE,OAAO,ENnF1B,GAAO;;AMoF1B,iBAAiC;EAAE,OAAO,EN/I1B,GAAO;;AMgJvB,cAA8B;EAAE,OAAO,ENhX1B,GAAO;;AMiXpB,oBAAoC;EAAE,OAAO,ENxT1B,GAAO;;AMyT1B,2BAA2C;EAAE,OAAO,ENxT1B,GAAO;;AMyTjC,iBAAiC;EAAE,OAAO,ENyK1B,GAAO;;AMxKvB,wBAAwC;EAAE,OAAO,ENyK1B,GAAO;;AMxK9B,0BAA0C;EAAE,OAAO,ENtD1B,GAAO;;AMuDhC,wBAAwC;EAAE,OAAO,ENpD1B,GAAO;;AMqD9B,0BAA0C;EAAE,OAAO,ENvD1B,GAAO;;AMwDhC,2BAA2C;EAAE,OAAO,ENvD1B,GAAO;;AMwDjC,gBAAgC;EAAE,OAAO,ENxW1B,GAAO;;AMyWtB,kBAAkC;EAAE,OAAO,EN0M1B,GAAO;;AMzMxB,kBAAkC;EAAE,OAAO,ENpX1B,GAAO;;AMqXxB,gBAAgC;EAAE,OAAO,ENpE1B,GAAO;;AMqEtB,mBAAmC;EAAE,OAAO,EN1N1B,GAAO;;AM2NzB,gBAAgC;EAAE,OAAO,ENqE1B,GAAO;;AMpEtB,qBAAqC;EAAE,OAAO,ENtJ1B,GAAO;;AMuJ3B,iBAAiC;EAAE,OAAO,ENuJ1B,GAAO;;AMtJvB,iBAAiC;EAAE,OAAO,EN/L1B,GAAO;;AMgMvB,eAA+B;EAAE,OAAO,EN1D1B,GAAO;;AM2DrB;mBACmC;EAAE,OAAO,ENnI1B,GAAO;;AMoIzB,gBAAgC;EAAE,OAAO,EN2G1B,GAAO;;AM1GtB,iBAAiC;EAAE,OAAO,ENxC1B,GAAO;;AMyCvB,kBAAkC;EAAE,OAAO,ENrX1B,GAAO;;AMsXxB,cAA8B;EAAE,OAAO,ENpU1B,GAAO;;AMqUpB,aAA6B;EAAE,OAAO,ENgL1B,GAAO;;AM/KnB,gBAAgC;EAAE,OAAO,ENqL1B,GAAO;;AMpLtB,iBAAiC;EAAE,OAAO,ENa1B,GAAO;;AMZvB,oBAAoC;EAAE,OAAO,ENrC1B,GAAO;;AMsC1B,yBAAyC;EAAE,OAAO,EN8E1B,GAAO;;AM7E/B,+BAA+C;EAAE,OAAO,ENtX1B,GAAO;;AMuXrC,8BAA8C;EAAE,OAAO,ENxX1B,GAAO;;AMyXpC;8BAC8C;EAAE,OAAO,EN3T1B,GAAO;;AM4TpC,uBAAuC;EAAE,OAAO,ENjP1B,GAAO;;AMkP7B,qBAAqC;EAAE,OAAO,EN+K1B,GAAO;;AM9K3B,uBAAuC;EAAE,OAAO,ENmK1B,GAAO;;AMlK7B;cAC8B;EAAE,OAAO,ENoI1B,GAAO;;AMnIpB,wBAAwC;EAAE,OAAO,ENjB1B,GAAO;;AMkB9B,wBAAwC;EAAE,OAAO,EN6D1B,GAAO;;AM5D9B,gBAAgC;EAAE,OAAO,EN2C1B,GAAO;;AM1CtB,0BAA0C;EAAE,OAAO,EN7O1B,GAAO;;AM8OhC,oBAAoC;EAAE,OAAO,EN2K1B,GAAO;;AM1K1B,iBAAiC;EAAE,OAAO,ENvD1B,GAAO;;AMwDvB;;qBAEqC;EAAE,OAAO,ENsI1B,GAAO;;AMrI3B;yBACyC;EAAE,OAAO,ENjK1B,GAAO;;AMkK/B,gBAAgC;EAAE,OAAO,ENwK1B,GAAO;;AMvKtB,iBAAiC;EAAE,OAAO,ENvK1B,GAAO;;AMwKvB,iBAAiC;EAAE,OAAO,ENhB1B,GAAO;;AMiBvB,wBAAwC;EAAE,OAAO,ENhB1B,GAAO;;AMiB9B,6BAA6C;EAAE,OAAO,ENsE1B,GAAO;;AMrEnC,sBAAsC;EAAE,OAAO,ENoE1B,GAAO;;AMnE5B,oBAAoC;EAAE,OAAO,EN7Q1B,GAAO;;AM8Q1B,eAA+B;EAAE,OAAO,EN1Q1B,GAAO;;AM2QrB,qBAAqC;EAAE,OAAO,ENjD1B,GAAO;;AMkD3B,yBAAyC;EAAE,OAAO,ENjD1B,GAAO;;AMkD/B,iBAAiC;EAAE,OAAO,ENvQ1B,GAAO;;AMwQvB,iBAAiC;EAAE,OAAO,EN9I1B,GAAO;;AM+IvB,mBAAmC;EAAE,OAAO,ENzI1B,GAAO;;AM0IzB,cAA8B;EAAE,OAAO,EN9O1B,GAAO;;AM+OpB,mBAAmC;EAAE,OAAO,EN3W1B,GAAO;;AM4WzB,gBAAgC;EAAE,OAAO,EN9T1B,GAAO;;AM+TtB,cAA8B;EAAE,OAAO,ENnE1B,GAAO;;AMoEpB,gBAAgC;EAAE,OAAO,ENoC1B,GAAO;;AMnCtB,eAA+B;EAAE,OAAO,ENjS1B,GAAO;;AMkSrB,gBAAgC;EAAE,OAAO,ENjS1B,GAAO;;AMkStB,kBAAkC;EAAE,OAAO,ENtY1B,GAAO;;AMuYxB,yBAAyC;EAAE,OAAO,ENtY1B,GAAO;;AMuY/B,gBAAgC;EAAE,OAAO,EN2C1B,GAAO;;AM1CtB,uBAAuC;EAAE,OAAO,EN2C1B,GAAO;;AM1C7B,kBAAkC;EAAE,OAAO,ENvC1B,GAAO;;AMwCxB;cAC8B;EAAE,OAAO,EN3W1B,GAAO;;AM4WpB;eAC+B;EAAE,OAAO,EN2D1B,GAAO;;AM1DrB,eAA+B;EAAE,OAAO,ENuF1B,GAAO;;AMtFrB,kBAAkC;EAAE,OAAO,ENwB1B,GAAO;;AMvBxB,qBAAqC;EAAE,OAAO,ENpS1B,GAAO;;AMqS3B,qBAAqC;EAAE,OAAO,ENkB1B,GAAO;;AMjB3B,mBAAmC;EAAE,OAAO,EN1S1B,GAAO;;AM2SzB,qBAAqC;EAAE,OAAO,ENxP1B,GAAO;;AMyP3B,sBAAsC;EAAE,OAAO,ENjP1B,GAAO;;AMkP5B,uBAAuC;EAAE,OAAO,EN9P1B,GAAO;;AM+P7B,4BAA4C;EAAE,OAAO,ENxP1B,GAAO;;AMyPlC;;uBAEuC;EAAE,OAAO,ENjQ1B,GAAO;;AMkQ7B;yBACyC;EAAE,OAAO,ENvQ1B,GAAO;;AMwQ/B;uBACuC;EAAE,OAAO,ENxQ1B,GAAO;;AMyQ7B;uBACuC;EAAE,OAAO,EN7P1B,GAAO;;AM8P7B,sBAAsC;EAAE,OAAO,EN1Q1B,GAAO;;AM2Q5B,eAA+B;EAAE,OAAO,ENsG1B,GAAO;;AMrGrB,kBAAkC;EAAE,OAAO,ENlV1B,GAAO;;AMmVxB,mBAAmC;EAAE,OAAO,ENnL1B,GAAO;;AMoLzB;;;;oBAIoC;EAAE,OAAO,ENxK1B,GAAO;;AMyK1B,yBAAyC;EAAE,OAAO,ENpW1B,GAAO;;AMqW/B;gBACgC;EAAE,OAAO,EN1E1B,GAAO;;AM2EtB;iBACiC;EAAE,OAAO,ENpT1B,GAAO;;AMqTvB,qBAAqC;EAAE,OAAO,EN1O1B,GAAO;;AM2O3B,cAA8B;EAAE,OAAO,EN5O1B,GAAO;;AM6OpB,sBAAsC;EAAE,OAAO,EN7N1B,GAAO;;AM8N5B,wBAAwC;EAAE,OAAO,ENwB1B,GAAO;;AMvB9B,aAA6B;EAAE,OAAO,ENzF1B,GAAO;;AM0FnB;iBACiC;EAAE,OAAO,EN2F1B,GAAO;;AM1FvB;sBACsC;EAAE,OAAO,EN9H1B,GAAO;;AM+H5B;wBACwC;EAAE,OAAO,EN/H1B,GAAO;;AMgI9B,kBAAkC;EAAE,OAAO,EN3N1B,GAAO;;AM4NxB;sBACsC;EAAE,OAAO,ENrX1B,GAAO;;AMsX5B,iBAAiC;EAAE,OAAO,ENnO1B,GAAO;;AMoOvB,oBAAoC;EAAE,OAAO,ENlI1B,GAAO;;AMmI1B,kBAAkC;EAAE,OAAO,EN1C1B,GAAO;;AM2CxB,oBAAoC;EAAE,OAAO,EN7D1B,GAAO;;AM8D1B,2BAA2C;EAAE,OAAO,EN7D1B,GAAO;;AM8DjC,eAA+B;EAAE,OAAO,ENpb1B,GAAO;;AMqbrB;mBACmC;EAAE,OAAO,ENzQ1B,GAAO;;AM0QzB,cAA8B;EAAE,OAAO,ENsC1B,GAAO;;AMrCpB,qBAAqC;EAAE,OAAO,EN/b1B,GAAO;;AMgc3B,eAA+B;EAAE,OAAO,ENrH1B,GAAO;;AMsHrB,qBAAqC;EAAE,OAAO,ENlD1B,GAAO;;AMmD3B,iBAAiC;EAAE,OAAO,ENsC1B,GAAO;;AMrCvB,eAA+B;EAAE,OAAO,ENiF1B,GAAO;;AMhFrB,sBAAsC;EAAE,OAAO,ENvJ1B,GAAO;;AMwJ5B,eAA+B;EAAE,OAAO,ENuE1B,GAAO;;AMtErB,qBAAqC;EAAE,OAAO,ENjb1B,GAAO;;AMkb3B,iBAAiC;EAAE,OAAO,EN9I1B,GAAO;;AM+IvB,wBAAwC;EAAE,OAAO,ENhQ1B,GAAO;;AMiQ9B,kBAAkC;EAAE,OAAO,EN9Z1B,GAAO;;AM+ZxB,wBAAwC;EAAE,OAAO,ENla1B,GAAO;;AMma9B,sBAAsC;EAAE,OAAO,ENpa1B,GAAO;;AMqa5B,kBAAkC;EAAE,OAAO,ENta1B,GAAO;;AMuaxB,oBAAoC;EAAE,OAAO,ENpa1B,GAAO;;AMqa1B,oBAAoC;EAAE,OAAO,ENpa1B,GAAO;;AMqa1B,qBAAqC;EAAE,OAAO,ENld1B,GAAO;;AMmd3B,uBAAuC;EAAE,OAAO,ENld1B,GAAO;;AMmd7B,gBAAgC;EAAE,OAAO,ENY1B,GAAO;;AMXtB,oBAAoC;EAAE,OAAO,EN3X1B,GAAO;;AM4X1B,aAA6B;EAAE,OAAO,ENre1B,GAAO;;AMsenB,qBAAqC;EAAE,OAAO,ENjV1B,GAAO;;AMkV3B,sBAAsC;EAAE,OAAO,ENpK1B,GAAO;;AMqK5B,wBAAwC;EAAE,OAAO,ENrd1B,GAAO;;AMsd9B,qBAAqC;EAAE,OAAO,EN3f1B,GAAO;;AM4f3B,oBAAoC;EAAE,OAAO,ENvJ1B,GAAO;;AMwJ1B,qBAAqC;EAAE,OAAO,EN5N1B,GAAO;;AM6N3B,iBAAiC;EAAE,OAAO,EN1O1B,GAAO;;AM2OvB,wBAAwC;EAAE,OAAO,EN1O1B,GAAO;;AM2O9B,qBAAqC;EAAE,OAAO,ENN1B,GAAO;;AMO3B,oBAAoC;EAAE,OAAO,ENN1B,GAAO;;AMO1B,kBAAkC;EAAE,OAAO,EN/d1B,GAAO;;AMgexB,cAA8B;EAAE,OAAO,EN7c1B,GAAO;;AM8cpB,kBAAkC;EAAE,OAAO,EN1P1B,GAAO;;AM2PxB,oBAAoC;EAAE,OAAO,ENhhB1B,GAAO;;AMihB1B,aAA6B;EAAE,OAAO,EN7b1B,GAAO;;AM8bnB;;cAE8B;EAAE,OAAO,ENxQ1B,GAAO;;AMyQpB,mBAAmC;EAAE,OAAO,EN7M1B,GAAO;;AM8MzB,qBAAqC;EAAE,OAAO,ENpd1B,GAAO;;AMqd3B,yBAAyC;EAAE,OAAO,ENnZ1B,GAAO;;AMoZ/B,mBAAmC;EAAE,OAAO,ENxY1B,GAAO;;AMyYzB,mBAAmC;EAAE,OAAO,EN1T1B,GAAO;;AM2TzB,kBAAkC;EAAE,OAAO,ENxP1B,GAAO;;AMyPxB,iBAAiC;EAAE,OAAO,ENrH1B,GAAO;;AMsHvB,uBAAuC;EAAE,OAAO,ENzG1B,GAAO;;AM0G7B,sBAAsC;EAAE,OAAO,ENrG1B,GAAO;;AMsG5B,mBAAmC;EAAE,OAAO,ENpG1B,GAAO;;AMqGzB,oBAAoC;EAAE,OAAO,EN5c1B,GAAO;;AM6c1B,0BAA0C;EAAE,OAAO,EN9c1B,GAAO;;AM+chC,kBAAkC;EAAE,OAAO,EN3Y1B,GAAO;;AM4YxB,eAA+B;EAAE,OAAO,ENhH1B,GAAO;;AMiHrB,sBAAsC;EAAE,OAAO,ENI1B,GAAO;;AMH5B,qBAAqC;EAAE,OAAO,EN5M1B,GAAO;;AM6M3B,sBAAsC;EAAE,OAAO,ENpE1B,GAAO;;AMqE5B,oBAAoC;EAAE,OAAO,ENhS1B,GAAO;;AMiS1B,gBAAgC;EAAE,OAAO,ENG1B,GAAO;;AMFtB,eAA+B;EAAE,OAAO,ENtO1B,GAAO;;AMuOrB,kBAAkC;EAAE,OAAO,EN7N1B,GAAO;;AM8NxB,sBAAsC;EAAE,OAAO,ENhC1B,GAAO;;AMiC5B,0BAA0C;EAAE,OAAO,ENhC1B,GAAO;;AMiChC,uBAAuC;EAAE,OAAO,END1B,GAAO;;AME7B,sBAAsC;EAAE,OAAO,EN1O1B,GAAO;;AM2O5B,qBAAqC;EAAE,OAAO,ENF1B,GAAO;;AMG3B,sBAAsC;EAAE,OAAO,EN3O1B,GAAO;;AM4O5B,wBAAwC;EAAE,OAAO,EN1O1B,GAAO;;AM2O9B,wBAAwC;EAAE,OAAO,EN5O1B,GAAO;;AM6O9B,iBAAiC;EAAE,OAAO,ENvN1B,GAAO;;AMwNvB,4BAA4C;EAAE,OAAO,EN9X1B,GAAO;;AM+XlC,sBAAsC;EAAE,OAAO,ENhM1B,GAAO;;AMiM5B,mBAAmC;EAAE,OAAO,ENI1B,GAAO;;AMHzB,iBAAiC;EAAE,OAAO,EN7I1B,GAAO;;AM8IvB,oBAAoC;EAAE,OAAO,ENjB1B,GAAO;;AMkB1B,qBAAqC;EAAE,OAAO,ENhB1B,GAAO;;AMiB3B;cAC8B;EAAE,OAAO,ENphB1B,GAAO;;AMqhBpB,kBAAkC;EAAE,OAAO,ENd1B,GAAO;;AMexB,gBAAgC;EAAE,OAAO,ENnD1B,GAAO;;AMoDtB,iBAAiC;EAAE,OAAO,ENvF1B,GAAO;;AMwFvB,iBAAiC;EAAE,OAAO,ENrP1B,GAAO",
+"sources": ["../scss/_path.scss","../scss/_core.scss","../scss/_larger.scss","../scss/_fixed-width.scss","../scss/_list.scss","../scss/_variables.scss","../scss/_bordered-pulled.scss","../scss/_animated.scss","../scss/_rotated-flipped.scss","../scss/_mixins.scss","../scss/_stacked.scss","../scss/_icons.scss"],
+"names": [],
+"file": "font-awesome.css"
+}
diff --git a/source/lib/font-awesome/css/font-awesome.min.css b/source/lib/font-awesome/css/font-awesome.min.css
new file mode 100644
index 000000000..540440ce8
--- /dev/null
+++ b/source/lib/font-awesome/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/source/lib/font-awesome/fonts/fontawesome-webfont.eot b/source/lib/font-awesome/fonts/fontawesome-webfont.eot
new file mode 100644
index 000000000..e9f60ca95
Binary files /dev/null and b/source/lib/font-awesome/fonts/fontawesome-webfont.eot differ
diff --git a/source/lib/font-awesome/fonts/fontawesome-webfont.woff b/source/lib/font-awesome/fonts/fontawesome-webfont.woff
new file mode 100644
index 000000000..400014a4b
Binary files /dev/null and b/source/lib/font-awesome/fonts/fontawesome-webfont.woff differ
diff --git a/source/lib/font-awesome/fonts/fontawesome-webfont.woff2 b/source/lib/font-awesome/fonts/fontawesome-webfont.woff2
new file mode 100644
index 000000000..4d13fc604
Binary files /dev/null and b/source/lib/font-awesome/fonts/fontawesome-webfont.woff2 differ
diff --git a/source/lib/jquery/index.js b/source/lib/jquery/index.js
new file mode 100644
index 000000000..25714ed29
--- /dev/null
+++ b/source/lib/jquery/index.js
@@ -0,0 +1,4 @@
+/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)
+},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
+},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec=/#.*$/,fc=/([?&])_=[^&]*/,gc=/^(.*?):[ \t]*([^\r\n]*)$/gm,hc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ic=/^(?:GET|HEAD)$/,jc=/^\/\//,kc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lc={},mc={},nc="*/".concat("*"),oc=a.location.href,pc=kc.exec(oc.toLowerCase())||[];function qc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rc(a,b,c,d){var e={},f=a===mc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function uc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:oc,type:"GET",isLocal:hc.test(pc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sc(sc(a,n.ajaxSettings),b):sc(n.ajaxSettings,a)},ajaxPrefilter:qc(lc),ajaxTransport:qc(mc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gc.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||oc)+"").replace(ec,"").replace(jc,pc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pc[1]&&h[2]===pc[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pc[3]||("http:"===pc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rc(lc,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ic.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fc.test(d)?d.replace(fc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rc(mc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tc(k,v,f)),u=uc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vc=/%20/g,wc=/\[\]$/,xc=/\r?\n/g,yc=/^(?:submit|button|image|reset|file)$/i,zc=/^(?:input|select|textarea|keygen)/i;function Ac(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wc.test(a)?d(a,e):Ac(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ac(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ac(c,a[c],b,e);return d.join("&").replace(vc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zc.test(this.nodeName)&&!yc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xc,"\r\n")}}):{name:b.name,value:c.replace(xc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bc=0,Cc={},Dc={0:200,1223:204},Ec=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cc)Cc[a]()}),k.cors=!!Ec&&"withCredentials"in Ec,k.ajax=Ec=!!Ec,n.ajaxTransport(function(a){var b;return k.cors||Ec&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Dc[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("